Difference between revisions of "User:Toady Nakamura/ELIZA chatbot"

From Second Life Wiki
Jump to navigation Jump to search
m (<source lang="lsl2">)
m (formatt)
Line 3: Line 3:
About ELIZA
About ELIZA


ELIZA is a famous 1966 computer program by Joseph Weizenbaum
ELIZA is a famous 1966 computer program by Joseph Weizenbaum.
ELIZA is a parody of a Rogerian therapist
 
ELIZA rephrases many of the patient's statements as questions and posing them to the patient.
ELIZA is a parody of a Rogerian therapist who rephrases many of the patient's statements as questions and poses them to the patient.


'''Transcript of a sample conversation:'''
'''Transcript of a sample conversation:'''


''You: hi
You: hi
 
Eliza Doolittle: how do you do--please state your problem.
Eliza Doolittle: how do you do--please state your problem.
You: i don't have a problem
 
You: I don't have a problem
 
Eliza Doolittle: does that trouble you?
Eliza Doolittle: does that trouble you?
You: no
You: no
Eliza Doolittle: you are being a bit negative.
Eliza Doolittle: you are being a bit negative.
You: does that trouble you?
You: does that trouble you?
Eliza Doolittle: we were discussing you-- not me.
Eliza Doolittle: we were discussing you-- not me.
You: you have the problem.
You: you have the problem.
Eliza Doolittle: oh, i have the problem
 
Eliza Doolittle: oh, I have the problem
 
You: yes
You: yes
Eliza Doolittle: i see.''
 
Eliza Doolittle: I see.




Line 548: Line 559:
COME COME ELUCIDATE YOUR THOUGHTS.
COME COME ELUCIDATE YOUR THOUGHTS.
CAN YOU ELABORATE ON THAT?
CAN YOU ELABORATE ON THAT?
</ source>
</source>
---- This ends the notecard, be sure there are no blank lines at the end of your card!
---- This ends the notecard, be sure there are no blank lines at the end of your card!
 
'''External references'''
[https://www.chegg.com/homework-help/questions-and-answers/eliza-famous-1966-computer-program-written-joseph-weizenbaum-imitates-psychologist-specifi-q24553990 about ELIZA]
[https://www.chegg.com/homework-help/questions-and-answers/eliza-famous-1966-computer-program-written-joseph-weizenbaum-imitates-psychologist-specifi-q24553990 about ELIZA]
[https://en.wikipedia.org/wiki/ELIZA Wikipedia ELIZA]
[https://en.wikipedia.org/wiki/ELIZA Wikipedia ELIZA]
[http://lslwiki.digiworldz.com/lslwiki/wakka.php?wakka=LibraryElizaChatbot Defunct Wiki.wakka source]
[http://lslwiki.digiworldz.com/lslwiki/wakka.php?wakka=LibraryElizaChatbot Defunct Wiki.wakka source]
   
   
Visit my LSL wiki page for my library of scripts !  [[User:Toady Nakamura|Toady Nakamura]]
Visit my LSL wiki page for my library of scripts !  [[User:Toady Nakamura|Toady Nakamura]]

Revision as of 13:08, 3 March 2021

Eliza Chatbot Sources & links at bottom of page! About ELIZA

ELIZA is a famous 1966 computer program by Joseph Weizenbaum.

ELIZA is a parody of a Rogerian therapist who rephrases many of the patient's statements as questions and poses them to the patient.

Transcript of a sample conversation:

You: hi

Eliza Doolittle: how do you do--please state your problem.

You: I don't have a problem

Eliza Doolittle: does that trouble you?

You: no

Eliza Doolittle: you are being a bit negative.

You: does that trouble you?

Eliza Doolittle: we were discussing you-- not me.

You: you have the problem.

Eliza Doolittle: oh, I have the problem

You: yes

Eliza Doolittle: I see.


// ELIZA is a famous 1966 computer program by Joseph Weizenbaum
// ELIZA is a parody of a Rogerian therapist
// ELIZA rephrases many of the patient's statements as questions and posing them to the patient.

// This LSL version was originally ported by Dedric Mauriac
// This LSL version is a port from a BASIC implementation written by John Schugg in January 1985.

// Data Setup:
// Keywords and patterns are contained in a seperate notecard
// a keyword set appears on a line delimited with semi-colon and prefixed with number of responses
// each response is written on its own line
// if more then one response follows a set of keywords, a random response will be chosen
// the last keyword in the notecard will always be used for responses that are not understood
// blank lines should only appear before keywords or after the last response.
// blank lines are optional and only used for easier management of data

// how long to wait before responding and listening for next user input
float delay = 7.5; 

// name of notecard containing patterns and responses
string replyNote = "Chatbot.Eliza.txt";

// stated when end-user repeats themselves
string repeatReply = "please do not repeat yourself";

// greeting
string introduction = "Have any problems?  Let me help you.";

// don't listen to objects?
integer ignoreObjects = TRUE;

list keywords;   // recognized keywords
list matchStart; // start position in notecard for responses to each keyword
list matchCount; // number of responses for each keyword
integer lastLine;

// number of lines in reply notecard
integer replyLines;

// id of request for notecard line count
key replyCountId;

// current line number being requested from notecard
integer replyLine;

// id of request for text in notecard for initialization
key replyLineId;

// characters recognized from user input
string recognized = "abcdefghijklmnopqrstuvwxyz ";

// id of listener for user input
integer listener;

// id of request for text in notecard as a response to input
key responseId;

string said;    // what the user said
string matched; // keyword/phrase the program understood

integer processing = FALSE; // state if program is still processing last input

string say; // response to user input

initialize()
{
    lastLine = -1;
    replyLine = 0;
    replyLines = -1;
    showProgress();
    keywords = [];
    matchCount = [];
    matchStart = [];
    replyCountId = llGetNumberOfNotecardLines(replyNote);
}
        
readReplies()
{
    // at end of notecard?
    if(replyLine >= replyLines)
    {
        startSession();
    }
    else
    { 
        showProgress();        
        replyLineId = llGetNotecardLine(replyNote, replyLine++); // read next line
    }
}
    
initializeReply(string data)
{
    data = llToLower(data);
    
    // is this a pattern?
    if(llSubStringIndex(data, ";") != -1)
    {
        list patterns = llParseString2List(data, [";"], []);
        integer count = llList2Integer(patterns, 0);
        keywords += llDeleteSubList(patterns, 0, 0);
        replyLine++;
        setMatchStart();
        setMatchLength(count);
        replyLine += count;
    }
    
    readReplies();
}
    
processMessage(string message)
{
    // don't process if we are still working on the last message
    if(processing) return;
    processing = TRUE;
    
    message = formatMessage(message);

    // do not bother with repeat input
    if(said == message)
    {
        say = repeatReply;
        llSetTimerEvent(delay);
        return;
    }
    
    // remember what user said last
    said = message;
    
    // iterate through keywords
    integer n = llGetListLength(keywords);
    integer i;
    for(i = 0; i < n; i++)
    {
        // pad keyword with spaces
        string keyword = " " + llList2String(keywords, i) + " ";
        
        // if keyword in user-input, respond to it.
        if(llSubStringIndex(message, keyword) != -1)
        {
            respondTo(i);
            return;
        }
    }
    
    // since keyword not found, response with last keywords replies (not understood)
    respondTo(n - 1);
}
    
string formatMessage(string message)
{    
    message = llToLower(message); // remove punctuation and change everything to lowercase
    string format = " ";
    integer i;
    integer n = llStringLength(message);
    
    for(i = 0; i < n; i++)
    {
        string char = llGetSubString(message, i, i);
        if(llSubStringIndex(recognized, char) != -1) format += char;
    }
    
    return format + " ";
}
    
respondTo(integer keywordIndex)
{
    // determine what keyword to respond to
    matched = llList2String(keywords, keywordIndex);
    
    // determine what to respond with
    integer start = llList2Integer(matchStart, keywordIndex);
    integer count = llList2Integer(matchCount, keywordIndex);
    integer line = start + llFloor(llFrand(count));
    
    // prevent repeat response
    while(line == lastLine && count != 1)
    {
        line = start + llFloor(llFrand(count));
    }
    
    lastLine = line;
    
    // request text for chosen response
    responseId = llGetNotecardLine(replyNote, line);
}
    
string conjugateWord(string word)
{
    // used to rephrase input into responses
    list conjugations = ["are", "am", 
                         "were", "was", 
                         "you", "i", 
                         "your", "my", 
                         "ive", "youve", 
                         "im", "youre", 
                         "you", "me"];

    // find word to replace
    integer i = llListFindList(conjugations, [word]);
    
    // not found
    if(i == -1) return word;
    
    // word found.  opposites in pairs.
    if(i % 2 == 0) return llList2String(conjugations, i + 1);
    return llList2String(conjugations, i - 1);
}
    
string processConjugates()
{
    // rephrase what user said after the matched keyword.
    
    integer i = llSubStringIndex(said, matched);
    string text = llGetSubString(said, i + llStringLength(matched), -1);
    list words = llParseString2List(text, [" "], []);
    text = "";
    
    integer n = llGetListLength(words);

    for(i = 0; i < n; i++)
    {
        text += " " + conjugateWord(llList2String(words, i));
    }
    
    return text;
}
        
processResponse(string message)
{
    // format response
    message = llToLower(message);
        
    // if wildcard in response, rephrase what user said
    integer i = llSubStringIndex(message, "*");
    if(i != -1)
    {
        message = llDeleteSubString(message, i, i);
        message = llInsertString(message, i, processConjugates());
    }
    
    // prepare to respond
    say = message;
    llSetTimerEvent(delay);
}
        
showProgress()
{
    // determine how much is done
    integer percent = (integer)(((float)replyLine / (float)replyLines) * 100);
    
    // build a text based progress bar - 59% [|||||......]
    string progress = (string)percent + "%\n[";
    integer i = 0;
    for(i = 0; i < 100; i+= 3)
    {
        if(i <= percent) progress += "|"; 
        else progress += ".";
    }
    progress += "]";

    llSetText("Initializing\n" + progress, <1,1,1>, 1);
}
        
setMatchStart()
{
    // set starting index for all keywords that do not yet have it set
    integer count = llGetListLength(keywords);
    integer i = llGetListLength(matchStart);
    for(; i < count; i++) matchStart += [replyLine - 1];
}
    
setMatchLength(integer length)
{
    // determine number of replies for keyword set
    integer count = llGetListLength(keywords);
    integer i = llGetListLength(matchCount);
    for(; i < count; i++) matchCount += [length];
}
    
startSession()
{
    // start listening
    llSetText("", ZERO_VECTOR, 0);
    if(listener != 0) llListenRemove(listener);
    listener = llListen(PUBLIC_CHANNEL, "", NULL_KEY, "");
    llSay(0, introduction);
}
    
default
{
    state_entry()
    {
        initialize();
    }

    on_rez(integer start_param)
    {
        initialize();
    }
    
    changed(integer change)
    {
        if(change & CHANGED_INVENTORY) initialize();
    }
    
    dataserver(key queryId, string data) 
    {
        if(queryId == replyCountId)     // finding reply count
        {
            replyLines = (integer)data;
            readReplies();
        }
        else if(queryId == replyLineId) // initializing keywords/replies
        {
            initializeReply(data);
        }
        else if(queryId == responseId)  // retrieving response template
        {
            processResponse(data);
        }
    }
            
    listen(integer channel, string name, key id, string message)
    {
        if(!ignoreObjects && llGetOwnerKey(id) == id)
        {
            processMessage(message);
        }
    }
    
    touch_start(integer count)
    {
        llSay(0, introduction);
    }
    
    timer()
    {
        // say what we previously decided to say
        llSay(PUBLIC_CHANNEL, say);
        llSetTimerEvent(0);
                
        processing = FALSE; // listen for next input
    }
}



Make a notecard and put the following text into it for a sample!

3;CAN YOU
DON'T YOU BELIEVE THAT I CAN*
PERHAPS YOU WOULD LIKE TO BE ABLE TO*
YOU WANT ME TO BE ABLE TO*

2;CAN I
PERHAPS YOU DON'T WANT TO*
DO YOU WANT TO BE ABLE TO*

4;YOU ARE;YOURE
WHAT MAKES YOU THINK I AM*
DOES IT PLEASE YOU TO BELIEVE I AM*
PERHAPS YOU WOULD LIKE TO BE*
DO YOU SOMETIMES WISH YOU WERE*

4;I DONT
DON'T YOU REALLY*
WHY DON'T YOU*
DO YOU WISH TO BE ABLE TO*
DOES THAT TROUBLE YOU?

3;I FEEL
TELL ME MORE ABOUT SUCH FEELINGS.
DO YOU OFTEN FEEL*
DO YOU ENJOY FEELING*

3;WHY DONT YOU
DO YOU REALLY BELIEVE I DON'T*
PERHAPS IN GOOD TIME I WILL*
DO YOU WANT ME TO*

2;WHY CANT I
DO YOU THINK YOU SHOULD BE ABLE TO*
WHY CAN'T YOU*

3;ARE YOU
WHY ARE YOU INTERESTED IN WHETHER OR NOT I AM*
WOULD YOU PREFER IF I WERE NOT*
PERHAPS IN YOUR FANTASIES I AM*

3;I CANT
HOW DO YOU KNOW YOU CAN'T*
HAVE YOU TRIED?
PERHAPS YOU CAN NOW*

4;I AM;IM
DID YOU COME TO ME BECAUSE YOU ARE*
HOW LONG HAVE YOU BEEN*
DO YOU BELIEVE IT IS NORMAL TO BE*
DO YOU ENJOY BEING*

3;YOU
WE WERE DISCUSSING YOU-- NOT ME.
OH, I*
YOU'RE NOT REALLY TALKING ABOUT ME, ARE YOU?

5;I WANT
WHY DO YOU WANT*
WHAT IF YOU NEVER GOT*
I SOMETIMES ALSO WANT*
WHAT WOULD IT MEAN TO YOU IF YOU GOT*
SUPPOSE YOU SOON GOT*

9;WHAT;HOW;WHO;WHERE;WHEN;WHY
WHY DO YOU ASK?
DOES THAT QUESTION INTEREST YOU?
WHAT ANSWER WOULD PLEASE YOU THE MOST?
WHAT DO YOU THINK?
ARE SUCH QUESTIONS ON YOUR MIND OFTEN?
WHAT IS IT THAT YOU REALLY WANT TO KNOW?
HAVE YOU ASKED ANYONE ELSE?
HAVE YOU ASKED SUCH QUESTIONS BEFORE?
WHAT ELSE COMES TO MIND WHEN YOU ASK THAT?

2;NAME
NAMES DON'T INTEREST ME.
I DON'T CARE ABOUT NAMES-- PLEASE GO ON.

4;CAUSE
IS THAT THE REAL REASON?
DON'T ANY OTHER REASONS COME TO MIND?
DOES THAT REASON EXPLAIN ANY THING ELSE?
WHAT OTHER REASONS MIGHT THERE BE?

4;SORRY
PLEASE DON'T APOLOGIZE.
APOLOGIES ARE NOT NECESSARY.
WHAT FEELINGS DO YOU HAVE WHEN YOU APOLOGIZE?
DON'T BE SO DEFENSIVE!

4;DREAM
WHAT DOES THAT DREAM SUGGEST TO YOU?
DO YOU DREAM OFTEN?
WHAT PERSONS APPEAR IN YOUR DREAMS?
ARE YOU DISTURBED BY YOUR DREAMS?

1;HELLO;HI
HOW DO YOU DO--PLEASE STATE YOUR PROBLEM.

5;MAYBE
YOU DON'T SEEM QUITE CERTAIN.
WHY THE UNCERTAIN TONE?
CAN'T YOU BE MORE POSITIVE?
YOU AREN'T SURE?
DON'T YOU KNOW?

5;NO
ARE YOU SAYING NO JUST TO BE NEGATIVE?
YOU ARE BEING A BIT NEGATIVE.
WHY NOT?
ARE YOU SURE?
WHY NO?

2;YOUR
WHY ARE YOU CONCERNED ABOUT MY*
WHAT ABOUT YOUR OWN*

4;ALWAYS
CAN YOU THINK OF A SPECIFIC EXAMPLE?
WHEN?
WHAT ARE YOU THINKING OF?
REALLY, ALWAYS?

3;THINK
DO YOU REALLY THINK SO?
BUT YOU ARE NOT SURE YOU*
DO YOU DOUBT YOU*

7;ALIKE
IN WHAT WAY?
WHAT RESEMBLANCE DO YOU SEE?
WHAT DOES THE SIMILARITY SUGGEST TO YOU?
WHAT OTHER CONNECTIONS DO YOU SEE?
COULD THERE REALLY BE SOME CONNECTION?
HOW?
YOU SEEM QUITE POSITIVE.

3;YES
ARE YOU SURE?
I SEE.
I UNDERSTAND.

6;FRIEND
WHY DO YOU BRING UP THE TOPIC OF FRIENDS?
DO YOUR FRIENDS WORRY YOU?
DO YOUR FRIENDS PICK ON YOU?
ARE YOU SURE YOU HAVE ANY FRIENDS?
DO YOU IMPOSE ON YOUR FRIENDS?
PERHAPS YOUR LOVE FOR FRIENDS WORRIES YOU?

7;COMPUTER
DO COMPUTERS WORRY YOU?
ARE YOU TALKING ABOUT ME IN PARTICULAR?
ARE YOU FRIGHTENED BY MACHINES?
WHY DO YOU MENTION COMPUTERS?
WHAT DO YOU THINK MACHINES HAVE TO DO WITH YOUR PROBLEM?
DON'T YOU THINK COMPUTERS CAN HELP PEOPLE?
WHAT IS IT ABOUT MACHINES THAT WORRIES YOU?

5;CAR
OH, DO YOU LIKE CARS?
MY FAVORITE CAR IS A LAMBORGINI COUNTACH. WHAT IS YOUR FAVORITE CAR?
MY FAVORITE CAR COMPANY IS FERRARI.  WHAT IS YOURS?
DO YOU LIKE PORSCHES?
DO YOU LIKE PORSCHE TURBO CARRERAS?

6;NOKEYFOUND
SAY, DO YOU HAVE ANY PSYCHOLOGICAL PROBLEMS?
WHAT DOES THAT SUGGEST TO YOU?
I SEE.
I'M NOT SURE I UNDERSTAND YOU FULLY.
COME COME ELUCIDATE YOUR THOUGHTS.
CAN YOU ELABORATE ON THAT?

This ends the notecard, be sure there are no blank lines at the end of your card!

External references about ELIZA

Wikipedia ELIZA

Defunct Wiki.wakka source

Visit my LSL wiki page for my library of scripts ! Toady Nakamura