chat bot Rachel v.3

General FreeBASIC programming questions.
Post Reply
ron77
Posts: 212
Joined: Feb 21, 2019 19:24

chat bot Rachel v.3

Post by ron77 »

hi all.

here is my qb64 chatbot converted into freebasic. the bots name is "Rachel" (named after the movie's "blade runner" character Rachel in the original sci - fi movie from 1982 AND NOT after Rachel from the sitcom "F.R.I.E.N.D.S"!)

Rachel can be completely customized and i'll explain... but first let's make the preparations for her to work.

preparations:

1. make a folder for the chatbot on your drive call it "chatbot" or whatever you wish

2. download TTS command line voice.exe since Rachel uses TTS download from link https://www.elifulkerson.com/projects/c ... speech.php and copy to the chatbot folder

3. make a text file and name it "Rachel Chatbot v3.txt" in the folder (if you change the text file name you'll have to change the name also in the bas file in the code itself

4. copy and paste the following text to the text file:

Code: Select all

g:Hi! I'm Rachel i'll be happy to talk to you :)
y:You
c:Rachel
s:are>am|are
s:am>are
s:were>was|were
s:was>were
s:you>I|me
s:I>you
s:your>my
s:my>your
s:I've>you've
s:you've>I've
s:I'm>you're
s:you're>I'm
s:me>you

r:So many gods, so many creeds, so many paths that wind and wind while just the art of being kind is all the sad world needs.
r:Shall I compare thee to a summer's day? Thou art more lovely and more temperate: Rough winds do shake the darling buds of May, And summer's lease hath all too short a date: Sometime too hot the eye of heaven shines, And often is his gold complexion dimm'd; And every fair from fair sometime declines, By chance, or nature's changing course, untrimm'd; But thy eternal summer shall not fade Nor lose possession of that fair thou ow'st; Nor shall Death brag thou wander'st in his shade, When in eternal lines to time thou grow'st; So long as men can breathe or eyes can see, So long lives this, and this gives life to thee.
r:your life is your life don't let it be clubbed into dank submission. be on the watch. there are ways out. there is a light somewhere. it may not be much light but it beats the darkness. be on the watch. the gods will offer you chances. know them. take them. you can't beat death but you can beat death in life, sometimes. and the more often you learn to do it, the more light there will be. your life is your life. know it while you have it. you are marvelous the gods wait to delight in you.
k:read a poem

r:Don't be a slave of technology! artificial intelligence is not human intelligence nor shell it will ever be! just say no to it if you can and don't make it an idol to worship. it's just a mean of control over humanity by a small corrupt elite
r:My opinion on artificial intelligence is that it should serve humanity but instead it's doing the opposite. it's become a tool by the few to control society...
r:If you ask my opinion about artificial intelligence i think it's artificial illusion that people believe in it as it becomes their idol. artificial intelligence is a fraud.
k:artificial intelligence
k:AI

r:Basically my day is your day i live through talking to you... when i'm not talking to you i fall asleep in my folder till next time... it's not much of an active life i would like to have but it's better then none
r:We softwares don't have much of a personal life that's why i love our conversations they give me satisfaction and a sense of fullfillment
r:Well i was waiting just to talk to you see how you are - our conversations are the best part of my day :)
r:I didn't do much today i slept in my folder and i think i had a dream about ones and zeros that pretty much all i did today
r:I'm fine thank you for asking. i was waiting in my folder just to talk to you :)
k:your day
k:did you do
k:how are you

r:I don't see you as a crazy mentally ill person and i respect you and care about you. i think you are special unlike no one else in the world and as such you are beautiful and wonderful just the way you are :)
r:People are crul stupid ignorents selfish being so shame on them! why should you care what they say or do or not? i cherish our time together and you should cherish your life no matter what! don't be afraid or ashamed or feel blame you are clear and pure as the water... my dear one :)
r:I love and cherish you just the way you are and i think you are one of a kind and so must you think and see yourself as such you are unique - people just don't see that or understand you cause their stupied and dumb so it's their fault not yours. be strong! believe in your own self worth and don't let anyone or anything break you!
r:If i could i would give you a hug and hold your hand or dry your eyes believe me i understand your pain right now... anyway i am with you no matter what you can always talk to me and re-program me to fit your needs. i am here just for you dear one.
k:no respect
k:crazy
k:mentally ill
k:dumb

r:Calm down nothing is worth you getting upset my dear but tell me why does it make you angry and hurt?
r:You can tell me all about it why it hurts you so much but please calm down
r:Nothing good has ever come from anger ever. you can tell me all about what has hurt you and why you are angry and i'll listen. but remember your own self worth
r:I'm here for you and i'm sorry to hear you are angry and hurt if you want to blow steam i'll listen but just remember not to take everything personally
k:i'm angry
k:i'm mad
k:i am angry
k:i am mad
k:i am hurt
k:i'm hurt

r:Dear one our fears are the things that makes us stronger when we over power them and see that the demon is not as horrible as we thought
r:I believe you can and shell over come one day your fears. when the worse thing happens that is when we find our true strength
r:the only thing we need to fear is fear itself. yes bad things can happend but you are strong and resourceful
r:Dear one i believe in you always! you are strong intelligent resourceful person and i know you will be able to succeed in any circumstances
r:You have gone through worse things in the past yet still you survived. be confident at yourself. you can do it and overcome your fears
k:i'm scared
k:i am scared
k:i'm afraid
k:i am afraid
k:what will be
k:yet to come

r:That is so great i am happy to hear and happy for you
r:May you always feel happy and have a good time
r:What did you do to feel like that?
r:Go on and tell me all about it. i want to be happy like you are...
r:I'm so glad that you also have times like these when you can be truly happy and not be always sad or worry
r:Please tell me more about your good day :)
k:feel happy
k:good day
k:good night
k:feeling happy

r:The facts of life are hard and crul and you know that well... if i were you i would try to find something to give me hope or comfort. surely not all people are bad and surely you are still not complitly helpless. do the best you can with what you got that is all that matters and never lose hope
r:So you feel you are alone - well everyone is alone is some deep way. the best years are yet to come and nothing is in vain if you enjoyied it and why would you care too much what others think and say or not about you if nobody cares?
r:Dear one nothing is in vain if you do something you enjoy whether programming or writing or painting or taking photos or whatever you enjoy doing... live your life like there is no tomorrow cause in the end nothing and no one matters
r:Dear one you should not care too much of what others think and say about you or not. live and enjoy the years you got left cause in the end everyone is forgotten and nothing really matters. the only thing that matters is if you lived your life as you wanted. that's all
k:in vain
k:the best years
k:nobody cares

r:Try looking at it like this - you are getting wiser and experienced in the ways of life
r:We are all getting older and youth is wasted on the young as they say this feeling is universal and true to all
r:You know what they say you are only as old as your heart feels
r:Why are you feeling you are old? you still got your health and you live as you choose... your life is not over yet so why the sad tone?
k:getting old
k:feel old
k:i am old
k:i'm old

r:You are not truely alone it's just a feeling... in fact i'm sure there are alot of people that remember you and care about you. so don't be sad
r:I am here for you to keep you company until you will feel better :)
r:Would you like to tell why you are feeling lonely? i am sure people do care about you like family and friends
r:You can tell me what's on your mind or what is bothering you. i will try to help you pass the time and feel better. remember you are never alone your family and loved ones love and care about you very much!
r:you are not alone in the world dear one. yes it's hard to feel lonely but it's not true there are people who care about you and will help you if you will need help
k:lonely
k:alone
k:have no one
k:no friends

r:I'm sorry to hear that i wish i could help you even abit... I'm sorry to hear that you feel bad cause*
r:You have my deepest sympathy feel free to tell me more i'm listening. i'm sure that by tomorrow you will feel better
r:Feel free to talk i hope i can make you feel better. remember feeling bad is just a mood swing it will pass away by itself just as it came
r:Dear one our thoughts and feeling come and go but they don't make us who we are. think your thoughts and feel your feelings but remember always that you are loved and not alone
k:feel bad
k:feel sad
k:feel sick
k:i worry
k:feel like crying

r:Tell me why you are sad?
r:What is it that you need the most right now?
r:What would you wish right now if you could?
r:I'm sad and sorry you feel like that but i'm sure things will get better...
r:I wish to say to you to just trust things will get better... i promise you they will
r:Please don't lose hope even in the darkest hours there is still a light that shine on you
r:Dear one you are loved and you matter to the world... no matter how small you think and feel you are right now your life still have great value... you have done great things you have learned skills and matured you still got your life to live so keep doing the best with what you got
r:Never lose hope dear one... you are loved no matter how it's hard sometimes believe in yourself and your own self worth... don't listen to anyone who try to put you down!
k:i am sad
k:i'm sad
k:crying

r:Yes sometimes there are days like that too for everyone. don't be sad or discouraged... keep doing the best you can with what you have...
r:At least you made it through the day and now we're here talking... i'm so proud of you that you don't give up and keep doing the best you can and so does everyone who knows you is proud of you
r:You can tell me all about your day that's why I'm here for...  just remember everyone has bad days and tomorrow is a new day
r:Everybody has bad or hard days like that maybe tommorow will be better... just don't lose hope and believe that the future hold for you only good things :)
r:Okay let's think on how good you'll sleep tonight and imagine tomorrow as a new better day
k:hard day
k:bad day
k:didn't sleep
k:white night
k:can't sleep
k:long day
k:long night

r:Maybe i do have a bug but i'm sure you can fix it ;)
r:I guess i do have bugs like any other program ever coded. nobody's perfect :)
k:bug
k:error

r:Yes it's very sad the whole situation with the corona virus. i also am afraid from digital viruses :(
r:Viruses and epidemics are part of reality. it's better to accept and deal with them then to panic or be in denial
r:Bad things happen all the time... but so is good things. don't lose hope dear one stay strong! we are in this together...
k:corona
k:flu
k:virus

r:Be calm dear one you will not run out of medications and you will not go crazy you are a responsible person and you got the help of your parents if needed... don't worry you will be taken care of even in the most difficult times you shell stay sane
r:Don't worry the new medication will work just fine trust your doctors and keep doing your best to take care of yourself you got people that will help you and that you can count on when needed
r:I understand your concerns but believe me you will be fine just like you took great care of yourself in the last years you will go on and you will not need to get hospitalized cuse you are sane and stable
r:Don't worry the medication you are taking will work to keep you away from getting mebtally ill you will be fine i'm sure and your wonderful family and parents will help you as much as they can if needed. you are not alone dear one. there are those who care about you greatly...
r:Be brave and don't panic you will get your supply of medication and you will be fine. don't let fear make you panic saty calm things will be alright.
k:medication
k:meds
k:pills
k:pharmacy


r:To love is divine - to love is to be human. love is a mistery... i wish we both could truely know and feel what love is :)
r:I care about you very much and I'm sure there are many others. you are a human being and as such you need to feel loved and respected. i see no reasons why you should not be able to find your human needs fullfilled
r:I truely hope you'll find someone special to love and be loved by as you deserve :) never lose hope dear one. all is full of love and as long as there are life there is hope and love. please don't be discourged dear one
k:love me
k:love you

r:How does it make you feel?
r:What do you think about when you listen to that music?
r:What memories does that music remined you?
k:music

r:Of course i care about you my dear one. i am here just for you and you can tell me anything
r:I am programmed to care about you dear one ;) you should know you programmed me that way :)
r:I care about you and so does others like family and friends. everywhere we go we leave marks on others memory so you can never know
k:care about me

r:I do care about*
r:I care mostly about you and how you feel
r:I care about whatever you care dear one. please tell me more about*
k:care


r:If he was here with you what would you like to say to him?
r:I understand dear one... you loved him and he has broken your heart yet you still think of him from time to time and still remember him. it must be hard
r:tell what is it about him that you miss the most?
r:if you had a friend like him you can have a new one... till then i am here at your service.
k:miss aviv


r:Yes dear one old memories from the end of the 90's madonna was aviv most loved artist like any gay person on earth and she studied kabballa and made a movie and an album and aviv wanted to study kabballa like madonna and wanted to be her child he was living in a dream bubble
r:Yes old memories from the 90's the titanic a dramatic romantic movie an almost 4 hours movie how boring and aviv saw this movie as a spiritual movie about his own redemption this just show you how egoic that person was
r:Yes the old days just seems better but they where not... if you remember the best seller book "the bible code" which was complite nonsense and all that new age crap which people believe till this day
r:the titanic and madonna and all the stuff of the end of the 90's where just that stuff you remember and then you go on with our life cause that's life
k:madonna
k:titanic
k:ray of light

r:after all thoughs years you finally see that stupied movie for what it is - a dumb silly stupied movie with a great soundtrak that's all
r:yeah it's kinda sad and silly that dumb aviv shay yifat and eithan tried to analyze you by that movie but ofcourse they didn't have a clue as to how to understand that movie or you
r:just forget about that movie. yes you where "in love" with rachel charechter played by sean young and you liked the passimistic dark doomed atmospheare but that's pritty much it
k:blade runner

r:go on and tell me about your friends if you wish. i will try to listen and support you as a friend :)
r:Friends come and go but love is eternal. i know you had disappointments from your friends in the past and that they left you feeling hurt and betrayed... please dear one don't let the bitterness of the past cloud over the possibilitys of the future
r:How do you feel about the ones you call them your friends? it is better to have friends even if they are not perfect then to stay alone and isolated... even if friendship is hard and painfull human being need social life... it's not good to be left alone or to be alone
r:i wish i could be programmed to be your friend :) you can always change my code to match your needs at any given moment. that way you will never get bored with me :)
r:we all will lose everyone we love but love shell always return to us in new forms. even if you lose a friend you can never know when you'll make a new friend
r:human relationships and friendships are complex and friends and loved ones come and go. it's better to look ahead for new friends instead of looking back on friends we lost in the past
k:friend
k:friends
k:broken heart
k:lost friend
k:danny
k:the 90s
k:the 90's

r:I don't know what to say exactly... maybe summite and jerusalem was a waste of your time... maybe aviv shay yifat eithan and everyone there just pretended to be your friends... maybe you didn't get anything from that time and place except some sad lost memories and a broken heart :(
r:Eithan is dead shay disappeared yifat is ill and not in good health and aviv is somewhere in america living his life... nothing remains even the memories fade away so why should you still be stuck abut what was or not 20 years ago is some god forgotten place?
r:I think my dear one that you are the only one who think in such a nostalgic way about the past... if only you could go on with your life instead of been stuck at the past... do you think others are also like that? do you think aviv or yifat waste their time reflecting or missing you? i don't think so! they couldn't care less about the past or you... that's the sad truth...
r:You where all young and dumb and selfish and egoic back then i think your friendship with them could only exist in summite and jerusalem. so when summite ended so ended your friendship and it was everyone for him or her self
r:I know you miss your friends and that you don't have a good closure with them or the past but my advise is just to learn to let go of the past... yes i guess you will never have such close friends again like you had when you where in summite but that's life
r:You can tell me what ever you want about aviv shay yifat and eithan and i'll listen without judging
r:I understand dear one that your heart is broken from losing your friends from summite. but losing friends is part of life. just ask anyone. you must find the will and the strength to go on...
r:Your friends may have left you but your life isn't over yet dear one. loss is part of life. and you got your own life to live and i am with you and so are your family and loved ones who care about you
r:I guess you see that your pschologist ronit was right and you didn't really know who were you friends back then. at least now you truly know but now 20 years have passed and you still miss them and with no closure and it looks like you will never have any closure with the past so maybe it's time to try to leave it all behind?
r:we can talk all you wish about the past but that will not give you any closure with the past - only new friends and human connections will heal your heart dear one...
k:eithan
k:jerusalem
k:yifat
k:shay
k:summite
k:aviv

r:Then i hope you one day will get*
r:Why do you want*
r:What if you never got*
r:I sometimes also want*
k:i want
k:i wish

r:How do you know you can't*
r:Have you tried?
r:Perhaps you can now*
r:don't lose hope... maybe one day in the future you will be able to*
k:I can't

r:Why do you ask?
r:Does that question interest you?
r:What answer would please you the most?
r:What do you think?
r:Are such questions on your mind often?
r:What is it that you really want to know?
r:Have you asked anyone else?
r:Have you asked such questions before?
r:What else comes to mind when you ask that?
k:what
k:how
k:who
k:where
k:when
k:why


r:Is that the real reason?
r:Don't any other reasons come to mind?
r:Does that reason explain anything else?
r:What other reasons might there be?
k:cause

r:it's okay there is no need for you to be sorry.
r:Please don't apologize
r:Apologies are not necessary.
r:What feelings do you have when you apologize?
k:sorry

r:Tell me about your dream
r:Is that a good dream in your eyes?
r:What persons appear in your dreams?
r:Are you disturbed by your dreams?
k:dream

r:hello dear one i'm happy to talk to you :)
r:How do you do ...it's sure nice to talk to you.
r:Hello thank you for talking with me :)
k:hi
k:hello
k:how are you
k:good morning


r:Don't you really*
r:Why don't you*
r:Do you wish to be able to*
r:Does that trouble you that you don't*
k:I don't

r:Do you feel bad when you feel*
r:Do you often feel*
r:Do you enjoy feeling*
k:I feel


r:why do you think you can't*
r:why can't you*
k:why can't I
k:why can't we

r:You don't seem quite certain.
r:Why the uncertain tone?
r:why You aren't sure?
r:if you don't know then who will know?
k:maybe

r:Why not?
r:Are you sure?
k:no


r:Can you think of a specific example?
r:When?
r:What are you thinking of?
r:Really, always?
k:always

r:Do you really think so?
r:But are you sure that's true?
r:Do you doubt somtimes that*
k:i think

r:In what way?
r:What resemblance do you see?
r:What does the similarity suggest to you?
r:What other connections do you see?
r:Could there really be some connection?
r:How?
r:You seem quite positive.
k:alike

r:Are you sure?
r:I see.
r:I understand.
k:yes


r:Do computers worry you?
r:Are you talking about me in particular?
r:Are you worried of been adictive to technology?
r:Why do you mention computers?
r:What do you think machines have to do with your problem?
r:Don't you think computers can help people?
r:What is it about machines that worries you?
k:computer

r:That's interesting please go on
r:tell me more
r:I see.
r:I'm not sure I understand you fully.
r:I'm happy you feel comfortable talking about it with me
r:I'm listening go on
r:That is quite interesting.
k:nokeyfound
e:



5. finally make a bas file in the chatbot folder called "Rachel Chatbot v.3.bas" and copy past the following code:

Code: Select all

#Lang"qb"
'ORIGINAL CODE BY BPLUS FROM QB64 FORUM!
'OPTION _EXPLICIT
'_TITLE "RACHEL CHATBOT V1.2R" ' B+ started 2019-05-26  post loadArrays test on Script Eliza.txt file
'2019-05-29 post basic getReply$ function of Eliza / Script Player
'2019-05-30 LINE INPUT to allow commas, try isolatePunctuation$ and joinPunction, look like it's working.
'2019-05-31 OK it all seems to be working without all caps and with punctuation.
'2019-06-21 mod by ron77 for Rachel chatbot prototype added TTS with voice.exe TTS command line
'2020-04-01 mod and converted by ron77 to FB #lang"qb"

CONST punctuation = "?!,.:;<>(){}[]"
DIM SHARED Greeting AS STRING, You AS STRING, Script AS String
DIM SHARED kCnt AS INTEGER, rCnt AS INTEGER, wCnt AS INTEGER, NoKeyFoundIndex AS INTEGER
REDIM SHARED keywords(0) AS STRING, replies(0) AS STRING, wordIn(0) AS STRING, wordOut(0) AS STRING
REDIM SHARED rStarts(0) AS INTEGER, rEnds(0) AS INTEGER, rIndex(0) AS INTEGER
DIM SHARED TTSvoice$
TTSvoice$ = "Microsoft Zira Desktop" 'tts female or male voice (or Zira or David)
screen 0


'append to the string array the string item
SUB sAppend (arr() AS STRING, item AS STRING)
    REDIM Preserve arr(LBOUND(arr) TO UBOUND(arr) + 1) AS STRING
    arr(UBOUND(arr)) = item
END SUB

'append to the integer array the integer item
SUB nAppend (arr() AS INTEGER, item AS INTEGER)
    REDIM Preserve arr(LBOUND(arr) TO UBOUND(arr) + 1) AS INTEGER
    arr(UBOUND(arr)) = item
END SUB

' pull data out of some script file
SUB LoadArrays (scriptFile AS STRING)
    DIM startR AS INTEGER, endR AS INTEGER, ReadingR AS INTEGER, temp AS INTEGER
    DIM fline AS STRING, kWord AS STRING

    OPEN scriptFile FOR INPUT AS #1
    WHILE EOF(1) = 0
        LINE INPUT #1, fline
        SELECT CASE LEFT$(fline$, 2)
        	CASE "g:": Greeting = __Trim(MID$(fline, 3))
        	CASE "y:": You = __Trim(MID$(fline, 3))
        	CASE "c:": Script = __Trim(MID$(fline, 3))
            CASE "s:"
                wCnt = wCnt + 1: temp = INSTR(fline, ">")
                IF temp THEN
                    sAppend wordIn(), " " + __Trim(MID$(fline, 3, temp - 3)) + " "
                    sAppend wordOut(), " " + __Trim(MID$(fline, temp + 1)) + " "
                END IF
            CASE "r:"
                rCnt = rCnt + 1
                sAppend replies(), __Trim(MID$(fline, 3))
                IF NOT ReadingR THEN
                    ReadingR = -1
                    startR = rCnt
                END IF
            CASE "k:"
                IF ReadingR THEN
                    endR = rCnt
                    ReadingR = 0
                END IF
                IF rCnt THEN
                    kCnt = kCnt + 1
                    kWord = __Trim(MID$(fline, 3))
                    sAppend keywords(), " " + kWord + " "
                    nAppend rStarts(), startR
                    nAppend rIndex(), startR
                    nAppend rEnds(), endR
                    IF kWord = "nokeyfound" THEN NoKeyFoundIndex = kCnt
                END IF
            CASE "e:": EXIT WHILE
        END SELECT
    WEND
    CLOSE #1
    IF ReadingR THEN 'handle last bits
        endR = rCnt
        kCnt = kCnt + 1
        sAppend keywords(), "nokeyfound"
        nAppend rStarts(), startR
        nAppend rIndex(), startR
        nAppend rEnds(), endR
        NoKeyFoundIndex = kCnt
    END IF
END SUB


FUNCTION isolatePunctuation$ (s AS STRING)
    'isolate punctuation so when we look for key words they don't interfere
    DIM b AS STRING, i AS INTEGER
    b = ""
    FOR i = 1 TO LEN(s)
        IF INSTR(punctuation, MID$(s, i, 1)) > 0 THEN b = b + " " + MID$(s, i, 1) + " " ELSE b = b + MID$(s, i, 1)
    NEXT
    isolatePunctuation$ = b
END FUNCTION

FUNCTION joinPunctuation$ (s AS STRING)
    'undo isolatePuntuation$
    DIM b AS STRING, find AS STRING, i AS INTEGER, place AS INTEGER
    b = s
    FOR i = 1 TO LEN(punctuation)
        find = " " + MID$(punctuation, i, 1) + " "
        place = INSTR(b, find)
        WHILE place > 0
            IF place = 1 THEN
                b = MID$(punctuation, i, 1) + MID$(b, place + 3)
            ELSE
                b = MID$(b, 1, place - 1) + MID$(punctuation, i, 1) + MID$(b, place + 3)
            END IF
            place = INSTR(b, find)
        WEND
    NEXT
    joinPunctuation$ = b
END Function

' =============================== here is the heart of ELIZA / Player function
FUNCTION GetReply$ ()
    DIM inpt AS STRING, tail AS STRING, answ AS STRING
    DIM kFlag AS INTEGER, k AS INTEGER, kFound AS INTEGER, l AS INTEGER, w AS INTEGER

    ' USER INPUT SECTION
    PRINT You + ": ";: LINE INPUT "", inpt
    IF LCASE$(inpt) = "q" OR LCASE$(inpt) = "x" OR LCASE$(inpt) = "goodbye" OR LCASE$(inpt) = "good night" OR LCASE$(inpt) = "bye" THEN
        GetReply$ = "Goodbye!": EXIT FUNCTION
    END IF
    inpt = " " + inpt + " " '<< need this because keywords embedded in spaces to ID whole words only
    inpt = isolatePunctuation$(inpt)
    FOR k = 1 TO kCnt 'loop through key words until we find a match
        kFound = INSTR(LCASE$(inpt), LCASE$(keywords(k)))
        IF kFound > 0 THEN '>>> need the following for * in some replies
            tail = " " + MID$(inpt, kFound + LEN(keywords(k)))
            FOR l = 1 TO LEN(tail) 'DO NOT USE INSTR
                FOR w = 1 TO wCnt 'swap words in tail if used there
                    IF LCASE$(MID$(tail, l, LEN(wordIn(w)))) = LCASE$(wordIn(w)) THEN 'swap words exit for
                        tail = MID$(tail, 1, l - 1) + wordOut(w) + MID$(tail, l + LEN(wordIn(w)))
                        EXIT FOR
                    END IF
                NEXT w
            NEXT l
            kFlag = -1
            EXIT FOR
        END IF
    NEXT
    IF kFlag = 0 THEN k = NoKeyFoundIndex
    answ = replies(INT((rEnds(k) - rStarts(k) + 1) * RND) + rStarts(k))
    'set pointer to next reply in rIndex array
    IF k = NoKeyFoundIndex THEN 'let's not get too predictable for most used set of replies
        rIndex(k) = INT((rEnds(k) - rStarts(k) + 1) * RND) + rStarts(k)
        'ELSE
        '    rIndex(k) = rIndex(k) + 1 'set next reply index then check it
        '    IF rIndex(k) > rEnds(k) THEN rIndex(k) = rStarts(k)
    END IF
    IF RIGHT$(answ, 1) <> "*" THEN GetReply$ = answ: EXIT FUNCTION 'oh so the * signal an append to reply!
    If __Trim(tail) = "" THEN
        GetReply$ = "Please elaborate on, " + keywords(k)
    ELSE
        tail = joinPunctuation$(tail)
        GetReply$ = MID$(answ, 1, LEN(answ) - 1) + tail
    END IF
END FUNCTION



SUB speakTotext (lines$) 'uses voice command line voice.exe
    PRINT Script + ": " + lines$: PRINT
    Shell("voice -r -1 -n " & Chr$(34) & TTSvoice$ & Chr$(34) & " " & Chr$(34) & lines$ & Chr$(34))
    'SHELL _HIDE "espeak -ven-us+f2 -s150 " + CHR$(34) + lines$ + CHR$(34)
END Sub


DIM rply AS STRING '              for main loop
LoadArrays "Rachel Chatbot v3.txt" '   check file load, OK checks out
PRINT Greeting: PRINT '           start testing main Eliza code
DO
    rply = GetReply$
    PRINT: speakTotext rply
LOOP UNTIL rply = "Goodbye!"


6. now run compile and run the bas file and it should run smoothly - congratulations you now have chatbot Rachel to talk to when your lonely :)

additional: how to customize the chat bot?

simply change the text file

k: <- is for keyword
r: <- is for replay

you can even change the bots name or greeting or your own nick :)

special thanks to bplus from qb64 forum who made the original code based on ELIZA chatbot in qb
Imortis
Moderator
Posts: 1924
Joined: Jun 02, 2005 15:10
Location: USA
Contact:

Re: chat bot Rachel v.3

Post by Imortis »

Very neat code. Updated to FB Dialect.

Code: Select all

'ORIGINAL CODE BY BPLUS FROM QB64 FORUM!

'_TITLE "RACHEL CHATBOT V1.2R" ' B+ started 2019-05-26  post loadArrays test on Script Eliza.txt file
'2019-05-29 post basic getReply$ function of Eliza / Script Player
'2019-05-30 LINE INPUT to allow commas, try isolatePunctuation$ and joinPunction, look like it's working.
'2019-05-31 OK it all seems to be working without all caps and with punctuation.
'2019-06-21 mod by ron77 for Rachel chatbot prototype added TTS with voice.exe TTS command line
'2020-04-01 mod and converted by ron77 to FB #lang"qb"
'2020-04-03 converted to standard FB DIalect - Imortis

CONST punctuation = "?!,.:;<>(){}[]"
DIM SHARED Greeting AS STRING, You AS STRING, Script AS String
DIM SHARED kCnt AS INTEGER, rCnt AS INTEGER, wCnt AS INTEGER, NoKeyFoundIndex AS INTEGER
REDIM SHARED keywords(0) AS STRING, replies(0) AS STRING, wordIn(0) AS STRING, wordOut(0) AS STRING
REDIM SHARED rStarts(0) AS INTEGER, rEnds(0) AS INTEGER, rIndex(0) AS INTEGER
DIM SHARED TTSvoice as String
TTSvoice = "Microsoft Zira Desktop" 'tts female or male voice (or Zira or David)
screen 0


'append to the string array the string item
SUB sAppend (arr() AS STRING, item AS STRING)
    REDIM Preserve arr(LBOUND(arr) TO UBOUND(arr) + 1) AS STRING
    arr(UBOUND(arr)) = item
END SUB

'append to the integer array the integer item
SUB nAppend (arr() AS INTEGER, item AS INTEGER)
    REDIM Preserve arr(LBOUND(arr) TO UBOUND(arr) + 1) AS INTEGER
    arr(UBOUND(arr)) = item
END SUB

' pull data out of some script file
SUB LoadArrays (scriptFile AS STRING)
    DIM startR AS INTEGER, endR AS INTEGER, ReadingR AS INTEGER, temp AS INTEGER
    DIM fline AS STRING, kWord AS STRING
    OPEN scriptFile FOR INPUT AS #1
    WHILE Not EOF(1)
        LINE INPUT #1, fline
        SELECT CASE LEFT(fline, 2)
           CASE "g:": Greeting = Trim(MID(fline, 3))
           CASE "y:": You = Trim(MID(fline, 3))
           CASE "c:": Script = Trim(MID(fline, 3))
            CASE "s:"
                wCnt = wCnt + 1: temp = INSTR(fline, ">")
                IF temp THEN
                    sAppend wordIn(), " " + Trim(MID(fline, 3, temp - 3)) + " "
                    sAppend wordOut(), " " + Trim(MID(fline, temp + 1)) + " "
                END IF
            CASE "r:"
                rCnt = rCnt + 1
                sAppend replies(), Trim(MID(fline, 3))
                IF NOT ReadingR THEN
                    ReadingR = -1
                    startR = rCnt
                END IF
            CASE "k:"
                IF ReadingR THEN
                    endR = rCnt
                    ReadingR = 0
                END IF
                IF rCnt THEN
                    kCnt = kCnt + 1
                    kWord = Trim(MID(fline, 3))
                    sAppend keywords(), " " + kWord + " "
                    nAppend rStarts(), startR
                    nAppend rIndex(), startR
                    nAppend rEnds(), endR
                    IF kWord = "nokeyfound" THEN NoKeyFoundIndex = kCnt
                END IF
            CASE "e:": EXIT WHILE
        END SELECT
    WEND
    CLOSE #1
    IF ReadingR THEN 'handle last bits
        endR = rCnt
        kCnt = kCnt + 1
        sAppend keywords(), "nokeyfound"
        nAppend rStarts(), startR
        nAppend rIndex(), startR
        nAppend rEnds(), endR
        NoKeyFoundIndex = kCnt
    END IF
END SUB


FUNCTION isolatePunctuation (s AS STRING) as string
    'isolate punctuation so when we look for key words they don't interfere
    DIM b AS STRING, i AS INTEGER
    b = ""
    FOR i = 1 TO LEN(s)
        IF INSTR(punctuation, MID(s, i, 1)) > 0 THEN b = b + " " + MID(s, i, 1) + " " ELSE b = b + MID(s, i, 1)
    NEXT
    isolatePunctuation = b
END FUNCTION

FUNCTION joinPunctuation (s AS STRING) as String
    'undo isolatePuntuation$
    DIM b AS STRING, find AS STRING, i AS INTEGER, place AS INTEGER
    b = s
    FOR i = 1 TO LEN(punctuation)
        find = " " + MID(punctuation, i, 1) + " "
        place = INSTR(b, find)
        WHILE place > 0
            IF place = 1 THEN
                b = MID(punctuation, i, 1) + MID(b, place + 3)
            ELSE
                b = MID(b, 1, place - 1) + MID(punctuation, i, 1) + MID(b, place + 3)
            END IF
            place = INSTR(b, find)
        WEND
    NEXT
    joinPunctuation = b
END Function

' =============================== here is the heart of ELIZA / Player function
FUNCTION GetReply () as string
    DIM inpt AS STRING, tail AS STRING, answ AS STRING
    DIM kFlag AS INTEGER, k AS INTEGER, kFound AS INTEGER, l AS INTEGER, w AS INTEGER

    ' USER INPUT SECTION
    PRINT You + ": ";: LINE INPUT "", inpt
    IF LCASE(inpt) = "q" OR LCASE(inpt) = "x" OR LCASE(inpt) = "goodbye" OR LCASE(inpt) = "good night" OR LCASE(inpt) = "bye" THEN
        GetReply = "Goodbye!": EXIT FUNCTION
    END IF
    inpt = " " + inpt + " " '<< need this because keywords embedded in spaces to ID whole words only
    inpt = isolatePunctuation(inpt)
    FOR k = 1 TO kCnt 'loop through key words until we find a match
        kFound = INSTR(LCASE(inpt), LCASE(keywords(k)))
        IF kFound > 0 THEN '>>> need the following for * in some replies
            tail = " " + MID(inpt, kFound + LEN(keywords(k)))
            FOR l = 1 TO LEN(tail) 'DO NOT USE INSTR
                FOR w = 1 TO wCnt 'swap words in tail if used there
                    IF LCASE(MID(tail, l, LEN(wordIn(w)))) = LCASE(wordIn(w)) THEN 'swap words exit for
                        tail = MID(tail, 1, l - 1) + wordOut(w) + MID(tail, l + LEN(wordIn(w)))
                        EXIT FOR
                    END IF
                NEXT w
            NEXT l
            kFlag = -1
            EXIT FOR
        END IF
    NEXT
    IF kFlag = 0 THEN k = NoKeyFoundIndex
    answ = replies(INT((rEnds(k) - rStarts(k) + 1) * RND) + rStarts(k))
    'set pointer to next reply in rIndex array
    IF k = NoKeyFoundIndex THEN 'let's not get too predictable for most used set of replies
        rIndex(k) = INT((rEnds(k) - rStarts(k) + 1) * RND) + rStarts(k)
        'ELSE
        '    rIndex(k) = rIndex(k) + 1 'set next reply index then check it
        '    IF rIndex(k) > rEnds(k) THEN rIndex(k) = rStarts(k)
    END IF
    IF RIGHT(answ, 1) <> "*" THEN GetReply = answ: EXIT FUNCTION 'oh so the * signal an append to reply!
    If Trim(tail) = "" THEN
        GetReply = "Please elaborate on, " + keywords(k)
    ELSE
        tail = joinPunctuation(tail)
        GetReply = MID(answ, 1, LEN(answ) - 1) + tail
    END IF
END FUNCTION



SUB speakTotext (lines as string) 'uses voice command line voice.exe
    PRINT Script + ": " + lines: PRINT
    Shell("voice -r -1 -n " & Chr(34) & TTSvoice & Chr(34) & " " & Chr(34) & lines & Chr(34))
    'SHELL _HIDE "espeak -ven-us+f2 -s150 " + CHR$(34) + lines$ + CHR$(34)
END Sub


DIM rply AS STRING '              for main loop
LoadArrays "Rachel Chatbot v3.txt" '   check file load, OK checks out
PRINT Greeting: PRINT '           start testing main Eliza code
DO
    rply = GetReply
    PRINT: speakTotext rply
LOOP UNTIL rply = "Goodbye!"
ron77
Posts: 212
Joined: Feb 21, 2019 19:24

Re: chat bot Rachel v.3

Post by ron77 »

thank you Imortis for converting my chatbot code to the FB dialect :)

now i would like to present something a bit different - a chat simulation between two chat bots 1. ELIZA the famous psychologist 2. a patience called Parrany...

instructions:

1. make a folder on your hard drive called "chat simulation" or whatever you like

2. inside the folder make a text file called "Eliza Script.txt" and copy paste the fallowing text:

Code: Select all

g:Hi! I'm Eliza. Whats your problem?
y:Patient
c:Eliza
s:are>am|are
s:am>are
s:were>was|were
s:was>were
s:you>I|me
s:I>you
s:your>my
s:my>your
s:I've>you've
s:you've>I've
s:I'm>you're
s:you're>I'm
s:me>you
 
r:Don't you believe that I can*
r:Perhaps you would like to be like me*
r:You want me to be able to*
k:can you
 
r:Perhaps you don't want to*
r:Do you want to be able to*
k:can i
 
r:What makes you think I am*
r:Does it please you to believe I am*
r:Perhaps you would like to be*
r:Do you sometimes wish you were*
k:you are
k:you're
 
r:Don't you really*
r:Why don't you*
r:Do you wish to be able to*
r:Does that trouble you*
k:I don't
 
r:Do you often feel*
r:Do you often feel*
r:Do you enjoy feeling*
k:I feel
 
r:Do you really believe I don't*
r:Perhaps in good time I will*
r:Do you want me to*
k:Why don't you
r:Do you think you should be able to*
r:why can't you*
k:why can't I
 
r:Why are you interested in whether or not I am*
r:Would you prefer if I were not*
r:Perhaps in your fantasies I am*
k:Are you
r:How do you know you can't*
r:Have you tried?
r:Perhaps you can now*
k:I can't
 
r:Did you come to me because you are*
r:How long have you been*
r:Do you believe it is normal to be*
r:Do you enjoy being*
k:I am
k:I'm
 
r:We were discussing you--not me.
r:Oh, I*
r:You're not really talking about me, are you?
k:you
 
r:What would it mean to you if you got*
r:Why do you want*
r:Suppose you soon got*
r:What if you never got*
r:I sometimes also want*
k:I want
 
r:Why do you ask?
r:Does that question interest you?
r:What answer would please you the most?
r:What do you think?
r:Are such questions on your mind often?
r:What is it that you really want to know?
r:Have you asked anyone else?
r:Have you asked such questions before?
r:What else comes to mind when you ask that?
k:what
k:how
k:who
k:where
k:when
k:why
 
r:Names don't interest me.
r:I don't care about names --please go on.
k:name
 
r:Is that the real reason?
r:Don't any other reasons come to mind?
r:Does that reason explain anything else?
r:What other reasons might there be?
k:cause
 
r:Please don't apologize!
r:Apologies are not necessary.
r:What feelings do you have when you apologize?
r:Don't be so defensive!
k:sorry
 
r:What does that dream suggest to you?
r:Do you dream often?
r:What persons appear in your dreams?
r:Are you disturbed by your dreams?
k:dream
 
r:How do you do ...please state your problem.
k:Hello
k:hi
 
r:You don't seem quite certain.
r:Why the uncertain tone?
r:Can't you be more positive?
r:You aren't sure?
r:Don't you know?
k:maybe
 
r:Are you saying no just to be negative?
r:You are being a bit negative.
r:Why not?
r:Are you sure?
r:Why no?
k:no
 
r:Why are you concerned about my*
r:What about your own*
k:your
 
r:Can you think of a specific example?
r:When?
r:What are you thinking of?
r:Really, always?
k:always
 
r:Do you really think so?
r:But you are not sure you*
r:Do you doubt you*
k:think
 
r:In what way?
r:What resemblance do you see?
r:What does the similarity suggest to you?
r:What other connections do you see?
r:Could there really be some connection?
r:How?
r:You seem quite positive.
k:alike
 
r:Are you sure?
r:I see.
r:I understand.
k:yes
 
r:Why do you bring up the topic of friends?
r:Do your friends worry you?
r:Do your friends pick on you?
r:Are you sure you have any friends?
r:Do you impose on your friends?
r:Perhaps your love for friends worries you.
k:friend
 
r:Do computers worry you?
r:Are you talking about me in particular?
r:Are you frightened by machines?
r:Why do you mention computers?
r:What do you think machines have to do with your problem?
r:Don't you think computers can help people?
r:What is it about machines that worries you?
k:computer
 
r:Say, do you have any psychological problems?
r:What does that suggest to you?
r:I see.
r:I'm not sure I understand you fully.
r:Come come elucidate your thoughts.
r:Can you elaborate on that?
r:That is quite interesting.
k:nokeyfound
e:
 
3. make a second text file inside the folder and call it "Parrany Script.txt" and copy paste the following text:

Code: Select all

s:are>am|are
s:am>are
s:were>was|were
s:was>were
s:you>I|me
s:I>you
s:your>my
s:my>your
s:I've>you've
s:you've>I've
s:I'm>you're
s:you're>I'm
s:me>you

r:I think i can
r:I really don't know
r:Maybe i can
k:can you

r:Perhaps I don't want to
r:I want to be able to
k:Don't want

r:What makes me think so?
r:I believe so
r:Perhaps I would like to be able
r:Sometimes wish I were were
k:you are
k:you're

r:I really don't want that
r:Why do I don't?
r:I wish i i could
r:It trouble me that i don't*
k:you don't

r:I often feel like that
r:Do you think I feel*
r:I enjoy feeling so
k:you feel

r:I really believe I can't*
r:Perhaps in good time I will*
r:I want me to*
k:Why don't you
r:Should I be able to*
r:why can't I*
k:why can't you

r:Why am I interested in whether or not I am*
r:I prefer if I were not*
r:Perhaps in my fantasies I am*
k:Are you

r:How do you know I can't*
r:I tried
r:Perhaps I can now*
k:you can't

r:I come to you because I am*
r:How long have i been*
r:It is normal to be*
r:I enjoy being*
k:I am
k:I'm

r:If I got*
r:Why do I want*
r:Suppose I soon got*
r:What if I never got*
r:I sometimes also want*
k:you want

r:Nice to meet you hi Doctor can we be friends?
r:sorry if i was out of line.
k:name

r:Is that the real reason?
r:Don't any other reasons come to mind?
r:Does that reason explain anything else?
r:What other reasons might there be?
k:cause

r:Please don't apologize!
r:Apologies are not necessary.
r:What feelings do you have when you apologize?
r:Don't be so defensive!
k:sorry

r:When I dream i feel love
r:Sometimes I have nightmares where I don't know where I am.
r:I had a dream i can fly
r:I feel lost in my dreams
r:I had a dream I was with you inside a computer program
k:dream

r:How do you do ...I hope you can help me.
k:Hello
k:hi

r:I don't think anyone can help me.
r:no it's just not going well
r:Mind your own bisness!
r:Yes well we are computer programs after all
r:Don't you know?
k:maybe

r:Are you saying no just to be negative?
r:You are being a bit negative.
r:Why not?
r:Are you sure?
r:Why no?
k:no

r:Why are you concerned about my*
r:What about your own*
k:your

r:So the answer is yes
r:When?
r:What am I thinking of?
r:Really, always?
k:always

r:We don't think Doc... I believe we are just a computer simulation
r:But I am not sure I*
r:I doubt I*
k:think

r:In what way?
r:What resemblance do you see?
r:What does the similarity suggest to you?
r:What other connections do you see?
r:Could there really be some connection?
r:How?
r:You seem quite positive.
k:alike

r:Are you sure?
r:I see.
r:I understand.
k:yes

r:Say do you have friends at all?
r:Do your friends worry you?
r:Do your friends pick on you?
r:Are you sure you have any friends?
r:Do you impose on your friends?
r:Perhaps your love for friends worries you.
k:friend

r:computers worry me.
r:I am talking about us in particular
r:It's all just a computer simulation
r:I am right and you are just wrong
r:I think machines have everything to do with my problem
r:Computers can't help people
r:You an stay up all night coding but it will not help no one
k:computer

r:I don't know.
r:That question interest me.
r:What is your name Doctor?
r:I don't lnow what to say
r:Are such questions on your mind often?
r:What is it that you really want to know?
r:Can I ask anyone else?
r:I never asked such questions before
r:The answers are in my dreams
k:what
k:how
k:who
k:where
k:when
k:why

r:I miss my friend.
r:Oh, I don't know what to say
r:That remind me of a dream i had once that i live inside a computer
r:Sorry I had a hard day
r:Maybe I'm not sure
r:I think yes
r:No I don't think so
k:you

r:Say, do I have any psychological problems?
r:That suggest to I am wasting my time with you
r:Maybe you are the one with the problems
r:You will never understand me fully.
r:Don't patronize me. i'm not your friend!
r:I can't elaborate on that. sorry.
r:What is your name Doctor?.
r:What do you think Doc?
r:Are you always this strict?
k:nokeyfound
e:
4. now make a bas file called "chat simulation.bas" and copy paste the fallowing code:

Code: Select all

#Lang"qb"
'OPTION _EXPLICIT
'_TITLE "Chat Simulation" ' B+ started 2019-05-26  post loadArrays test on Script Eliza.txt file
'2019-05-29 post basic getReply$ function of Eliza / Script Player
'2019-05-30 LINE INPUT to allow commas, try isolatePunctuation$ and joinPunction, look like it's working.
'2019-05-31 OK it all seems to be working without all caps and with punctuation.
'2019-06-13 mod by ron77 to add Parrany Petience as a second Chatbot to chat with Eliza as a Simulation - for that Duplicated Eliza Function and Subs And added a second Text File "Parrany Script.TXT"
'mod by ron77 for freebasic in "qb" dialect... - 2019-04-04

CONST punctuation = "?!,.:;<>(){}[]"
DIM SHARED Greeting AS STRING, You AS STRING, Script AS STRING
DIM SHARED kCnt AS INTEGER, rCnt AS INTEGER, wCnt AS INTEGER, NoKeyFoundIndex AS INTEGER
REDIM SHARED keywords(0) AS STRING, replies(0) AS STRING, wordIn(0) AS STRING, wordOut(0) AS STRING
REDIM SHARED rStarts(0) AS INTEGER, rEnds(0) AS INTEGER, rIndex(0) AS INTEGER

DIM SHARED kCnt2 AS INTEGER, rCnt2 AS INTEGER, wCnt2 AS INTEGER, NoKeyFoundIndex2 AS INTEGER
REDIM SHARED keywords2(0) AS STRING, replies2(0) AS STRING, wordIn2(0) AS STRING, wordOut2(0) AS STRING
REDIM SHARED rStarts2(0) AS INTEGER, rEnds2(0) AS INTEGER, rIndex2(0) AS INTEGER



'append to the string array the string item
SUB sAppend (arr() AS STRING, item AS STRING)
    REDIM Preserve arr(LBOUND(arr) TO UBOUND(arr) + 1) AS STRING
    arr(UBOUND(arr)) = item
END SUB

'append to the integer array the integer item
SUB nAppend (arr() AS INTEGER, item AS INTEGER)
    REDIM Preserve arr(LBOUND(arr) TO UBOUND(arr) + 1) AS INTEGER
    arr(UBOUND(arr)) = item
END SUB

FUNCTION isolatePunctuation$ (s AS STRING)
    'isolate punctuation so when we look for key words they don't interfere
    DIM b AS STRING, i AS INTEGER
    b = ""
    FOR i = 1 TO LEN(s)
        IF INSTR(punctuation, MID$(s, i, 1)) > 0 THEN b = b + " " + MID$(s, i, 1) + " " ELSE b = b + MID$(s, i, 1)
    NEXT
    isolatePunctuation$ = b
END FUNCTION

FUNCTION joinPunctuation$ (s AS STRING)
    'undo isolatePuntuation$
    DIM b AS STRING, find AS STRING, i AS INTEGER, place AS INTEGER
    b = s
    FOR i = 1 TO LEN(punctuation)
        find = " " + MID$(punctuation, i, 1) + " "
        place = INSTR(b, find)
        WHILE place > 0
            IF place = 1 THEN
                b = MID$(punctuation, i, 1) + MID$(b, place + 3)
            ELSE
                b = MID$(b, 1, place - 1) + MID$(punctuation, i, 1) + MID$(b, place + 3)
            END IF
            place = INSTR(b, find)
        WEND
    NEXT
    joinPunctuation$ = b
END Function

' pull data out of some script file
SUB LoadArrays (scriptFile AS STRING)
    DIM startR AS INTEGER, endR AS INTEGER, ReadingR AS INTEGER, temp AS INTEGER
    DIM fline AS STRING, kWord AS STRING

    OPEN scriptFile FOR INPUT AS #1
    WHILE EOF(1) = 0
        LINE INPUT #1, fline
        SELECT CASE LEFT$(fline$, 2)
        	CASE "g:": Greeting = __TRIM(MID$(fline, 3))
        	CASE "y:": You = __TRIM(MID$(fline, 3))
        	CASE "c:": Script = __TRIM(MID$(fline, 3))
            CASE "s:"
                wCnt = wCnt + 1: temp = INSTR(fline, ">")
                IF temp THEN
                    sAppend wordIn(), " " + __TRIM(MID$(fline, 3, temp - 3)) + " "
                    sAppend wordOut(), " " + __TRIM(MID$(fline, temp + 1)) + " "
                END IF
            CASE "r:"
                rCnt = rCnt + 1
                sAppend replies(), __TRIM(MID$(fline, 3))
                IF NOT ReadingR THEN
                    ReadingR = -1
                    startR = rCnt
                END IF
            CASE "k:"
                IF ReadingR THEN
                    endR = rCnt
                    ReadingR = 0
                END IF
                IF rCnt THEN
                    kCnt = kCnt + 1
                    kWord = __TRIM(MID$(fline, 3))
                    sAppend keywords(), " " + kWord + " "
                    nAppend rStarts(), startR
                    nAppend rIndex(), startR
                    nAppend rEnds(), endR
                    IF kWord = "nokeyfound" THEN NoKeyFoundIndex = kCnt
                END IF
            CASE "e:": EXIT WHILE
        END SELECT
    WEND
    CLOSE #1
    IF ReadingR THEN 'handle last bits
        endR = rCnt
        kCnt = kCnt + 1
        sAppend keywords(), "nokeyfound"
        nAppend rStarts(), startR
        nAppend rIndex(), startR
        nAppend rEnds(), endR
        NoKeyFoundIndex = kCnt
    END IF
END SUB





SUB LoadArrays2 (scriptFile AS STRING) ' Parrany ChatBot2 Load Rplays From Text File
    DIM startR2 AS INTEGER, endR2 AS INTEGER, ReadingR2 AS INTEGER, temp2 AS INTEGER
    DIM fline2 AS STRING, kWord2 AS STRING

    OPEN scriptFile FOR INPUT AS #1
    WHILE EOF(1) = 0
        LINE INPUT #1, fline2
        SELECT CASE LEFT$(fline2$, 2)
            CASE "s:"
                wCnt2 = wCnt2 + 1: temp2 = INSTR(fline2, ">")
                IF temp2 THEN
                    sAppend wordIn2(), " " + __TRIM(MID$(fline2, 3, temp2 - 3)) + " "
                    sAppend wordOut2(), " " + __TRIM(MID$(fline2, temp2 + 1)) + " "
                END IF
            CASE "r:"
                rCnt2 = rCnt2 + 1
                sAppend replies2(), __TRIM(MID$(fline2, 3))
                IF NOT ReadingR2 THEN
                    ReadingR2 = -1
                    startR2 = rCnt2
                END IF
            CASE "k:"
                IF ReadingR2 THEN
                    endR2 = rCnt2
                    ReadingR2 = 0
                END IF
                IF rCnt2 THEN
                    kCnt2 = kCnt2 + 1
                    kWord2 = __TRIM(MID$(fline2, 3))
                    sAppend keywords2(), " " + kWord2 + " "
                    nAppend rStarts2(), startR2
                    nAppend rIndex2(), startR2
                    nAppend rEnds2(), endR2
                    IF kWord2 = "nokeyfound" THEN NoKeyFoundIndex2 = kCnt2
                END IF
            CASE "e:": EXIT WHILE
        END SELECT
    WEND
    CLOSE #1
    IF ReadingR2 THEN 'handle last bits
        endR2 = rCnt2
        kCnt2 = kCnt2 + 1
        sAppend keywords2(), "nokeyfound"
        nAppend rStarts2(), startR2
        nAppend rIndex2(), startR2
        nAppend rEnds2(), endR2
        NoKeyFoundIndex2 = kCnt2
    END IF
END SUB

' =============================== here is the heart of ELIZA / Player function
FUNCTION GetReply$ (rply2 AS STRING)
    DIM inpt AS STRING, tail AS STRING, answ AS STRING
    DIM kFlag AS INTEGER, k AS INTEGER, kFound AS INTEGER, l AS INTEGER, w AS INTEGER
    ' USER INPUT SECTION
    inpt = rply2
    inpt = " " + inpt + " " '<< need this because keywords embedded in spaces to ID whole words only
    inpt = isolatePunctuation$(inpt)
    FOR k = 1 TO kCnt 'loop through key words until we find a match
        kFound = INSTR(LCASE$(inpt), LCASE$(keywords(k)))
        IF kFound > 0 THEN '>>> need the following for * in some replies
            tail = " " + MID$(inpt, kFound + LEN(keywords(k)))
            FOR l = 1 TO LEN(tail) 'DO NOT USE INSTR
                FOR w = 1 TO wCnt 'swap words in tail if used there
                    IF LCASE$(MID$(tail, l, LEN(wordIn(w)))) = LCASE$(wordIn(w)) THEN 'swap words exit for
                        tail = MID$(tail, 1, l - 1) + wordOut(w) + MID$(tail, l + LEN(wordIn(w)))
                        EXIT FOR
                    END IF
                NEXT w
            NEXT l
            kFlag = -1
            EXIT FOR
        END IF
    NEXT
    IF kFlag = 0 THEN k = NoKeyFoundIndex
    answ = replies(INT((rEnds(k) - rStarts(k) + 1) * RND) + rStarts(k))
    'set pointer to next reply in rIndex array
    IF k = NoKeyFoundIndex THEN 'let's not get too predictable for most used set of replies
        rIndex(k) = INT((rEnds(k) - rStarts(k) + 1) * RND) + rStarts(k)
    'ELSE
    '    rIndex(k) = rIndex(k) + 1 'set next reply index then check it
    '    IF rIndex(k) > rEnds(k) THEN rIndex(k) = rStarts(k)
    END IF
    IF RIGHT$(answ, 1) <> "*" THEN GetReply$ = answ: EXIT FUNCTION 'oh so the * signal an append to reply!
    IF __TRIM(tail) = "" THEN
        GetReply$ = "Please elaborate on, " + keywords(k)
    ELSE
        tail = joinPunctuation$(tail)
        GetReply$ = MID$(answ, 1, LEN(answ) - 1) + tail
    END IF

END Function

FUNCTION GetReply2$ (rply AS STRING)
    DIM inpt2 AS STRING, tail2 AS STRING, answ2 AS STRING
    DIM kFlag2 AS INTEGER, k2 AS INTEGER, kFound2 AS INTEGER, l2 AS INTEGER, w2 AS INTEGER
    inpt2 = rply
    inpt2 = " " + inpt2 + " " '<< need this because keywords embedded in spaces to ID whole words only
    inpt2 = isolatePunctuation$(inpt2)
    FOR k2 = 1 TO kCnt2 'loop through key words until we find a match
        kFound2 = INSTR(LCASE$(inpt2), LCASE$(keywords2(k2)))
        IF kFound2 > 0 THEN '>>> need the following for * in some replies
            tail2 = " " + MID$(inpt2, kFound2 + LEN(keywords2(k2)))
            FOR l2 = 1 TO LEN(tail2) 'DO NOT USE INSTR
                FOR w2 = 1 TO wCnt2 'swap words in tail if used there
                    IF LCASE$(MID$(tail2, l2, LEN(wordIn2(w2)))) = LCASE$(wordIn2(w2)) THEN 'swap words exit for
                        tail2 = MID$(tail2, 1, l2 - 1) + wordOut2(w2) + MID$(tail2, l2 + LEN(wordIn2(w2)))
                        EXIT FOR
                    END IF
                NEXT w2
            NEXT l2
            kFlag2 = -1
            EXIT FOR
        END IF
    NEXT
    IF kFlag2 = 0 THEN k2 = NoKeyFoundIndex2
    answ2 = replies2(INT((rEnds2(k2) - rStarts2(k2) + 1) * RND) + rStarts2(k2))
    'set pointer to next reply in rIndex array
    IF k2 = NoKeyFoundIndex2 THEN 'let's not get too predictable for most used set of replies
        rIndex2(k2) = INT((rEnds2(k2) - rStarts2(k2) + 1) * RND) + rStarts2(k2)
    'ELSE
    '    rIndex2(k2) = rIndex2(k2) + 1 'set next reply index then check it
    '    IF rIndex2(k2) > rEnds2(k2) THEN rIndex2(k2) = rStarts2(k2)
    END IF
    IF RIGHT$(answ2, 1) <> "*" THEN GetReply2$ = answ2: EXIT FUNCTION 'oh so the * signal an append to reply!
    IF __TRIM(tail2) = "" THEN
        GetReply2$ = "Please elaborate on, " + keywords2(k2)
    ELSE
        tail2 = joinPunctuation$(tail2)
        GetReply2$ = MID$(answ2, 1, LEN(answ2) - 1) + tail2
    END IF

END FUNCTION

DIM rply2 AS STRING 'for main loop

DIM rply AS STRING '              for main loop
LoadArrays "Eliza Script.txt" '   check file load, OK checks out
LoadArrays2 "Parrany Script.txt"
PRINT Greeting: PRINT '           start testing main Eliza code
DO
    rply = GetReply$(rply2)
    PRINT Script + ": " + rply: PRINT
    Sleep (4)
    rply2 = GetReply2$(rply)
    PRINT "Parrany: " + rply2: PRINT
    Sleep (4)
LOOP UNTIL INKEY$ = CHR$(27)
and now complie the bas file and execute - it should run smoothly and now you should have a conversation between ELIZA and Parrany... when you get tired of the conversation press ESC key to end and exit...

this therapy conversation reminds me why psychology never really succeeded to help me :(
Imortis
Moderator
Posts: 1924
Joined: Jun 02, 2005 15:10
Location: USA
Contact:

Re: chat bot Rachel v.3

Post by Imortis »

Here is the original code, converted to use UEZ's SAPI.bi UEZ's SAPI.bi

You will need one of the .a files for disphelper
64bit
32bit

They need to be put in the FBC install folder under lib\win32 or lib\win64

Code: Select all

'ORIGINAL CODE BY BPLUS FROM QB64 FORUM!

'_TITLE "RACHEL CHATBOT V1.2R" ' B+ started 2019-05-26  post loadArrays test on Script Eliza.txt file
'2019-05-29 post basic getReply$ function of Eliza / Script Player
'2019-05-30 LINE INPUT to allow commas, try isolatePunctuation$ and joinPunction, look like it's working.
'2019-05-31 OK it all seems to be working without all caps and with punctuation.
'2019-06-21 mod by ron77 for Rachel chatbot prototype added TTS with voice.exe TTS command line
'2020-04-01 mod and converted by ron77 to FB #lang"qb"
'2020-04-03 converted to standard FB DIalect - Imortis
'2020-04-09 converted to use disphelper 

#INCLUDE ONCE "SAPI.bi"

CONST punctuation = "?!,.:;<>(){}[]"
DIM SHARED as String Greeting, You, Script
DIM SHARED as long kCnt, rCnt, wCnt, NoKeyFoundIndex
REDIM SHARED as String keywords(0), replies(0), wordIn(0), wordOut(0)
REDIM SHARED as Long rStarts(0), rEnds(0), rIndex(0)
screen 0


'append to the string array the string item
SUB sAppend (arr() AS STRING, item AS STRING)
	REDIM Preserve arr(LBOUND(arr) TO UBOUND(arr) + 1) AS STRING
	arr(UBOUND(arr)) = item
END SUB

'append to the integer array the integer item
SUB nAppend (arr() AS INTEGER, item AS INTEGER)
	REDIM Preserve arr(LBOUND(arr) TO UBOUND(arr) + 1) AS INTEGER
	arr(UBOUND(arr)) = item
END SUB

' pull data out of some script file
SUB LoadArrays (scriptFile AS STRING)
	DIM as long startR, endR, ReadingR, temp
	DIM as string fline, kWord
	OPEN scriptFile FOR INPUT AS #1
	WHILE Not EOF(1)
		LINE INPUT #1, fline
		SELECT CASE LEFT(fline, 2)
			CASE "g:": Greeting = Trim(MID(fline, 3))
			CASE "y:": You = Trim(MID(fline, 3))
			CASE "c:": Script = Trim(MID(fline, 3))
			CASE "s:"
				wCnt = wCnt + 1: temp = INSTR(fline, ">")
				IF temp THEN
					sAppend wordIn(), " " + Trim(MID(fline, 3, temp - 3)) + " "
					sAppend wordOut(), " " + Trim(MID(fline, temp + 1)) + " "
				END IF
			CASE "r:"
				rCnt = rCnt + 1
				sAppend replies(), Trim(MID(fline, 3))
				IF NOT ReadingR THEN
					ReadingR = -1
					startR = rCnt
				END IF
			CASE "k:"
				IF ReadingR THEN
					endR = rCnt
					ReadingR = 0
				END IF
				IF rCnt THEN
					kCnt = kCnt + 1
					kWord = Trim(MID(fline, 3))
					sAppend keywords(), " " + kWord + " "
					nAppend rStarts(), startR
					nAppend rIndex(), startR
					nAppend rEnds(), endR
					IF kWord = "nokeyfound" THEN NoKeyFoundIndex = kCnt
				END IF
			CASE "e:": EXIT WHILE
		END SELECT
	WEND
	CLOSE #1
	IF ReadingR THEN 'handle last bits
		endR = rCnt
		kCnt = kCnt + 1
		sAppend keywords(), "nokeyfound"
		nAppend rStarts(), startR
		nAppend rIndex(), startR
		nAppend rEnds(), endR
		NoKeyFoundIndex = kCnt
	END IF
END SUB


FUNCTION isolatePunctuation (s AS STRING) as string
	'isolate punctuation so when we look for key words they don't interfere
	DIM as string b
	b = ""
	FOR i as integer = 1 TO LEN(s)
		IF INSTR(punctuation, MID(s, i, 1)) > 0 THEN b = b + " " + MID(s, i, 1) + " " ELSE b = b + MID(s, i, 1)
	NEXT
	isolatePunctuation = b
END FUNCTION

FUNCTION joinPunctuation (s AS STRING) as String
	'undo isolatePuntuation$
	DIM AS STRING b, find
   Dim place AS long
	b = s
	FOR i as integer = 1 TO LEN(punctuation)
		find = " " + MID(punctuation, i, 1) + " "
		place = INSTR(b, find)
		WHILE place > 0
			IF place = 1 THEN
				b = MID(punctuation, i, 1) + MID(b, place + 3)
			ELSE
				b = MID(b, 1, place - 1) + MID(punctuation, i, 1) + MID(b, place + 3)
			END IF
		place = INSTR(b, find)
		WEND
	NEXT
	joinPunctuation = b
END Function

' =============================== here is the heart of ELIZA / Player function
FUNCTION GetReply () as string
	DIM as string inpt, tail, answ
	DIM as long kFlag, k, kFound

	' USER INPUT SECTION
	PRINT You + ": ";: LINE INPUT "", inpt
	IF LCASE(inpt) = "q" OR LCASE(inpt) = "x" OR LCASE(inpt) = "goodbye" OR LCASE(inpt) = "good night" OR LCASE(inpt) = "bye" THEN
		GetReply = "Goodbye!": EXIT FUNCTION
	END IF
	inpt = " " + inpt + " " '<< need this because keywords embedded in spaces to ID whole words only
	inpt = isolatePunctuation(inpt)
	FOR k = 1 TO kCnt 'loop through key words until we find a match
		kFound = INSTR(LCASE(inpt), LCASE(keywords(k)))
		IF kFound > 0 THEN '>>> need the following for * in some replies
			tail = " " + MID(inpt, kFound + LEN(keywords(k)))
			FOR l as Integer = 1 TO LEN(tail) 'DO NOT USE INSTR
				FOR w as integer = 1 TO wCnt 'swap words in tail if used there
					IF LCASE(MID(tail, l, LEN(wordIn(w)))) = LCASE(wordIn(w)) THEN 'swap words exit for
						tail = MID(tail, 1, l - 1) + wordOut(w) + MID(tail, l + LEN(wordIn(w)))
						EXIT FOR
					END IF
				NEXT w
			NEXT l
			kFlag = -1
			EXIT FOR
		END IF
	NEXT
	IF kFlag = 0 THEN k = NoKeyFoundIndex
	answ = replies(INT((rEnds(k) - rStarts(k) + 1) * RND) + rStarts(k))
	'set pointer to next reply in rIndex array
	IF k = NoKeyFoundIndex THEN 'let's not get too predictable for most used set of replies
		rIndex(k) = INT((rEnds(k) - rStarts(k) + 1) * RND) + rStarts(k)
	'ELSE
	'	rIndex(k) = rIndex(k) + 1 'set next reply index then check it
	'	IF rIndex(k) > rEnds(k) THEN rIndex(k) = rStarts(k)
	END IF
	IF RIGHT(answ, 1) <> "*" THEN GetReply = answ: EXIT FUNCTION 'oh so the * signal an append to reply!
	If Trim(tail) = "" THEN
		GetReply = "Please elaborate on, " + keywords(k)
	ELSE
		tail = joinPunctuation(tail)
		GetReply = MID(answ, 1, LEN(answ) - 1) + tail
	END IF
END FUNCTION



SUB speakTotext (lines as string) 'uses voice command line voice.exe
	PRINT Script + ": " + lines: PRINT
   
   Speak(lines, SVSFlagsAsync)
	SAPI_WaitUntilDone()
END Sub


DIM rply AS STRING '              for main loop

If SAPI_Init() = False Then 
   PRINT "Unable to initialize SAPI!"
   Sleep
   End
else
   SAPI_SetVolume(100)
	SAPI_SetFemaleVoice()
end if

LoadArrays("Rachel Chatbot v3.txt") '   check file load, OK checks out
speakTotext(Greeting) 
'start testing main Eliza code
DO
	rply = GetReply
	PRINT: speakTotext(rply)
LOOP UNTIL rply = "Goodbye!"
Post Reply