this script was open source and used to work in sl and iwz. but now that i am trying to use it again, here... it errors out. Many years ago i coulda fixed it, but unfortunately i am no longer one with brain power. Can anyone fix it?
// 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 responses 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;
// used to rephrase input into responses
list conjugations = [
"are", "am",
"were", "was",
"you", "i",
"your", "my",
"ive", "youve",
"im", "youre",
"you", "me"
];
// 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 still processing last input
string say; // response to user input
initialize()
{
lastLine = -1;
replyLine = 0;
replyLines = -1;
showProgress();
keywords = [];
matchCount = [];
matchStart = [];
replyCountId = llGetNumberOfNotecardLines(replyNote);
}
string conjugateWord(string word)
{
// 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);
}
respondTo(integer keywordIndex)
{
// determine what keyword to response 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);
}
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;
// itterate through keywords
integer n = llGetListLength(keywords);
integer i;
for(i = 0; i < n; i++)
{
// padd 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)
{
// remove punctuation and change everything to lowercase
string message = llToLower(message);
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 + " ";
}
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);
}
readReplies()
{
// at end of notecard?
if(replyLine >= replyLines)
{
startSession();
return;
}
showProgress();
// read next line
replyLineId = llGetNotecardLine(replyNote, replyLine++);
}
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();
}
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)
{
// finding reply count
if(queryId == replyCountId)
{
replyLines = (integer)data;
readReplies();
return;
}
// initializing keywords/replies
if(queryId == replyLineId)
{
initializeReply(data);
return;
}
// retrieving response template
if(queryId == responseId)
{
processResponse(data);
return;
}
}
listen(integer channel, string name, key id, string message)
{
if(ignoreObjects && llGetOwnerKey(id) != id) return;
processMessage(message);
}
touch_start(integer count)
{
llSay(0, introduction);
}
timer()
{
// say what we previously decided to say
llSay(PUBLIC_CHANNEL, say);
llSetTimerEvent(0);
// listen for next input
processing = FALSE;
}
}
thanks in advance
eliza chatbot
- Gregg Legendary
- Posts: 126
- Joined: Sun Jun 22, 2014 10:22 am
- Has thanked: 215 times
- Been thanked: 225 times
-
- Posts: 1314
- Joined: Sun Dec 23, 2012 2:26 pm
- Has thanked: 1134 times
- Been thanked: 1142 times
Re: eliza chatbot
I think this should work. Bear in mind it needs a notecard named Chatbot.Eliza.txt.
Code: Select all
// 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 responses 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;
// used to rephrase input into responses
list conjugations = [
"are", "am",
"were", "was",
"you", "i",
"your", "my",
"ive", "youve",
"im", "youre",
"you", "me"
];
// 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 still processing last input
string say; // response to user input
initialize()
{
lastLine = -1;
replyLine = 0;
replyLines = -1;
showProgress();
keywords = [];
matchCount = [];
matchStart = [];
replyCountId = llGetNumberOfNotecardLines(replyNote);
}
string conjugateWord(string word)
{
// 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);
}
respondTo(integer keywordIndex)
{
// determine what keyword to response 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);
}
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;
// itterate through keywords
integer n = llGetListLength(keywords);
integer i;
for(i = 0; i < n; i++)
{
// padd 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 msg)
{
// remove punctuation and change everything to lowercase
string message = llToLower(msg);
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 + " ";
}
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);
}
readReplies()
{
// at end of notecard?
if(replyLine >= replyLines)
{
startSession();
return;
}
showProgress();
// read next line
replyLineId = llGetNotecardLine(replyNote, replyLine++);
}
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();
}
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)
{
// finding reply count
if(queryId == replyCountId)
{
replyLines = (integer)data;
readReplies();
return;
}
// initializing keywords/replies
if(queryId == replyLineId)
{
initializeReply(data);
return;
}
// retrieving response template
if(queryId == responseId)
{
processResponse(data);
return;
}
}
listen(integer channel, string name, key id, string message)
{
if(ignoreObjects && llGetOwnerKey(id) != id) return;
processMessage(message);
}
touch_start(integer count)
{
llSay(0, introduction);
}
timer()
{
// say what we previously decided to say
llSay(PUBLIC_CHANNEL, say);
llSetTimerEvent(0);
// listen for next input
processing = FALSE;
}
}
- These users thanked the author Graham Mills for the post (total 3):
- Ilan Tochner • Gregg Legendary • Gusher Castaignede
- Gregg Legendary
- Posts: 126
- Joined: Sun Jun 22, 2014 10:22 am
- Has thanked: 215 times
- Been thanked: 225 times
Re: eliza chatbot
THANK YOU SOOO MUCH
- These users thanked the author Gregg Legendary for the post (total 3):
- Graham Mills • Shandon Loring • Chris Namaste
- Shandon Loring
- Posts: 1369
- Joined: Sat Oct 26, 2013 3:25 am
- Has thanked: 1019 times
- Been thanked: 1615 times
- Contact:
Re: eliza chatbot
Very cool! I set this up in an NPC at our Spaceworld but never really got it tuned in and working right...
Will give this a shot.. thanks all!
Will give this a shot.. thanks all!
- Lewis Moten
- Posts: 1
- Joined: Sun Oct 20, 2024 2:28 am
- Has thanked: 0
- Been thanked: 2 times
Re: eliza chatbot
Hello. I'm the "Dedric Mauriac" that ported Eliza to Second Life. Graham Mills is correct, in that the script needs to read a notecard. I've just posted everything - scripts, images, notecards, etc. to my GitHub account (lewismoten)
There is also a Voice Box that can be hooked up to it for voice synthesis from the 80's using about 60 sound files. I'm working on archiving the various versions that it went though.
Chatbot.Eliza.txt
There is also a Voice Box that can be hooked up to it for voice synthesis from the 80's using about 60 sound files. I'm working on archiving the various versions that it went though.
Chatbot.Eliza.txt
Code: Select all
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?
- These users thanked the author Lewis Moten for the post (total 2):
- Ilan Tochner • Chris Namaste
- Shandon Loring
- Posts: 1369
- Joined: Sat Oct 26, 2013 3:25 am
- Has thanked: 1019 times
- Been thanked: 1615 times
- Contact:
Re: eliza chatbot
THE Lewis Moten?? Very cool! Thank you noble sir!
Tons of fun stuff on Lewis' github in addition to Eliza, what a fun cool expedition!!
https://github.com/lewismoten?tab=repositories
Tons of fun stuff on Lewis' github in addition to Eliza, what a fun cool expedition!!
https://github.com/lewismoten?tab=repositories
- These users thanked the author Shandon Loring for the post:
- Chris Namaste