Jump to content

Trying to make an "artificial intelligence"


Pullamies
 Share

You are about to reply to a thread that has been inactive for 448 days.

Please take a moment to consider if this thread is worth bumping.

Recommended Posts

I have a script that listens to public chat word inputs and gives an answer with the keywords and replies I've specified in a notecard.

The question is, how to make it stop replying to words that are not specified in the notecard? It will reply the last word reply in the notecard to the keywords it doesnt recognize instead of just doing nothing.

For ecample let's say, 

the keywords "gift / gifts" will trigger a response: "They are on the table!"

and if that response is the last one in the notecard... it will reply it to every single input in the chat.
 

float delay = 1.5; 

// name of notecard containing patterns and responses
string replyNote = "talk";

// stated when end-user repeats themselves
string repeatReply = "";

// greeting
string introduction = "";

// 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 llList2String(conjugations, i - 1);
    
    // 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;
    }
}

 

Edited by Pullamies
  • Thanks 1
Link to comment
Share on other sites

I've tried it. It doesn't effect it. Feel free to try the script. The is the example notecard configuration:

The number infront is the possible lines of outcomes. Words after the number are keywords that trigger the lines.

The problem is that when it doesnt match a keyword, it "uses the "NOKEYFOUND" line". Actually it just answers with the last line of the configuration instead of just not answering.

1;NAME;name
MY NAME IS ROBOT, I'M A ROBOT NOT A PERSON

3;ROBOT;robot;boot
YES, I AM
TOTALLY THERE IS NOT A PERSON BEHIND ME*
YES, YOU BETTER GO TO HELP ISLAND FOR HELP, LOOK IN THE SEARCH BAR*

2;work;WORK;job;JOB
ONLY MODELING TOUCH ME TO GET THE NOTE FOR MODEL
NO WORK HERE AT THE MOMENT

3;money;MONEY;LINDEN;LINDENS;linden;lindens
YOU HAVE THE ATM IN THERE TO GET LINDENS
THE ONLY WAY TO GET ANY IS WITH YOUR CREDIT OR DEBIT CARD IN THE ATM THERE
CLICK IN THE TOP RIGHT WHERE YOU SEE THE l$ SIGN IN BLUE AND BUY LINDENS

2;SEX
GO TO HELP ISLAND FOR HELP WITH THAT.

2;SORRY
PLEASE DON'T APOLOGIZE I AM A ROBOT.
APOLOGIES ARE NOT NECESSARY THERE IS NOBODY BEHIND ME.

2;HELP;INFORMATION
I AM A ROBOT BUT HAVE SOME INFORMATION, TRY ME

1;HELLO;HI;hey;oi;salut;hi;hola;Hi;hello;Hello
HOW DO YOU DO--I AM A ROBOT BUT HAVE SOME INFORMATION, WHAT DO YOU NEED?

1;FREEBIES
WE DON'T HAVE FREEBIES HERE, THIS IS AN EXCLUSIVE BOUTIQUE.

1;FRIEND
THIS IS NOT A GOOD PLACE FOR FRIENDS IS A STORE TO SHOP, LOOK IN SEARCH FOR CLUBS INSTEAD.

1;THANK YOU;TKS
YOU ARE WELCOME, GLAD TO BE A ROBOT OF SERVICE

2;EVENT
PLEASE READ THE AD IN THE EVENTS PAGE AGAIN AND FOLLOW INSTRUCTIONS
FOLLOW THE INSTRUCTIONS IN THE AD OF THE EVENTS PAGE

1;shoes;lingerie;stilettos;hair;skin;shapes;boots;men;gown;pants;skirts;micro;mini;beach wear;bathing suit;suit;hud;poses;sexywalk
YES, WE HAVE THAT ITS A SMALL BOUTIQUE JUST WALK A LITTLE AND YOU'LL SEE.

2;NOKEYFOUND
I'M NOT SURE I UNDERSTAND YOU FULLY.
I DON'T HAVE AN ANSWER FOR THAT

 

Link to comment
Share on other sites

5 hours ago, Love Zhaoying said:

I would guess it is this after your for() loop:

    // since keyword not found, response with last keywords replies (not understood)
    respondTo(n - 1);

Try commenting out that line perhaps.

I've tried this again it completely breaks the script.

Link to comment
Share on other sites

You are about to reply to a thread that has been inactive for 448 days.

Please take a moment to consider if this thread is worth bumping.

Please sign in to comment

You will be able to leave a comment after signing in



Sign In Now
 Share

×
×
  • Create New...