[HELP] a GW Basic chatbot with database that is buggy

Started by ron77, November 13, 2023, 16:56:54

Previous topic - Next topic

ron77

Hello... :/
I got a GW-Basic program of a chatbot that uses a DATABASE.TXT for keywords/replies - default replies - it works, however, the replies are not the for the right keywords - any idea what is wrong? or how to fix it?

DATABASE.TXT file
============= GW BASIC CHATBOT DATABASE =============

========= TESTS ROUTINE ===========

k:hello
k:hi

r:hi hello how are you?
r:good day nice to talk to you
r:how are you doing this lovely day?

k:sad
k:lonely

r:well i'm here with you let's talk?
r:what's sitting on your mind?

k:bad day

r:it's just a feeling that will pass cheer up
r:it's just a bad day not a bad life...

d:go on i'l listening
d:i see
d:i think i can understand
d:can you explain more?

GWCHAT.BAS file
10 REM A CHATBOT WITH A DATABASE OF KEYWORDS AND REPLIES AND DEFAULT REPLIES
20 REM BY RON77
30 REM 2023
40 REM PROGRAM INITIALIZATION
50 DIM K$(100),R$(100),D$(20): KCOUNT=0: RCOUNT=0: DCOUNT=0:FLINE$=""
60 DIM KCS(100),RCS(100),DCS(20),KCE(100),RCE(100)
70 DATAFILE$="DATABASE.TXT"
80 REM LOAD DATABASE
82 ISKEYWORD = 0: KEYWORDNUM = 1: REPLYNUM = 1
90 OPEN "I",#1,DATAFILE$
100 WHILE NOT EOF(1)
110 LINE INPUT #1,FLINE$
120 IF LEN(FLINE$)>0 THEN TAGP = INSTR(FLINE$,":")
130 IF TAGP>0 THEN TAG$=LEFT$(FLINE$,1) : STEXT$=MID$(FLINE$,TAGP+1)
140 REM
150 IF TAG$="k" AND ISKEYWORD = 0 THEN ISKEYWORD=1 : RCE(RCOUNT)= REPLYNUM : RCOUNT=RCOUNT+1 : RCS(RCOUNT) = REPLYNUM
160 IF TAG$="k" AND ISKEYWORD = 1 THEN K$(KEYWORDNUM)=" "+STEXT$+" " : KEYWORDNUM=KEYWORDNUM+1
165 IF TAG$="r" AND ISKEYWORD = 1 THEN ISKEYWORD=0 : KCE(KCOUNT)= KEYWORDNUM : KCOUNT=KCOUNT+1 : KCS(KCOUNT) = KEYWORDNUM
170 IF TAG$="r" AND ISKEYWORD = 0 THEN R$(REPLYNUM)=STEXT$ : REPLYNUM=REPLYNUM+1
175 IF TAG$="k" AND ISKEYWORD = 0 THEN ISKEYWORD=1 : RCE(RCOUNT)= REPLYNUM : RCOUNT=RCOUNT+1 : RCS(RCOUNT) = REPLYNUM
180 IF TAG$="d" THEN D$(DCOUNT)=STEXT$ : DCOUNT=DCOUNT+1
190 WEND
200 CLOSE #1

250 PRINT "Hello! How can I assist you today?"
260 INPUT "YOU: ", USERINPUT$
270 REM
280 found = 0
290 FOR I = 1 TO KCOUNT
300   FOR J = KCS(I) TO KCE(I)
310     IF INSTR(USERINPUT$, K$(J)) > 0 THEN PRINT "BOT: ";R$(RCS(I) + INT(RND * (RCE(I) - RCS(I) + 1))): found = 1
320       REM
330       REM
340     REM
350   NEXT J
360 NEXT I
370 IF found = 0 THEN PRINT D$(INT(RND * DCOUNT) + 1)
380 GOTO 260

Dan

Hi

the problematic line is this:

310     IF INSTR(USERINPUT$, K$(J))

you can get better results with

310     IF INSTR(K$(J),  USERINPUT$) 
because instr is not case sensitive, you should convert the USERINPUT$ to lowercase (and eventually the keywords as well).

(p.s. i have used QB64 and PCBasic to test this on windows)
65536 GOTO Back2Basic

ron77

Hello @Dan i wish to thank you for trying to help me solve this buggy code, and i don't wish to sound ungrateful or anything, but the bug I think is somewhere else...
i'll try to explain - the database.txt file consists of pairs of multi keywords-replies pairs... so for instance, if we input the first keywords "hi" "hello" the output should only be the paired Replies to those keywords either "hi hello how are you?" or "good day nice to talk to you" or "how are you doing this lovely day?" same goes with the second pair of keywords-replies and so on and if there are no keywords in the input we suppose to get one of the default replies..
But what happens with this code is that as output for, say the first pair of keywords - we get the replies of the second or third pair of keywords or the default replies or even an empty string.
i guess the bug is in the "read database.txt file and load arrays" code and maybe in the main loop of the chatbot too...

anyway, I'm grateful that you took a look at this code - for what's it worth...

DaiHard

Is the issue that your arrays are 0-based, but most of your requests are 1-based (as an example, your default array d$ seems to store the first answer in d$(0), but when you call it in line 370 you generate a random number (which can presumably be 0 - dcount), and then add 1 - so you can never use the first entry?

If all your responses are stored in the same r$ array, this kind of approach will often mean the entry you use is one beyond the one you intend?

I haven't worked through all your "marker" arrays, but there may be a similar issue there.

Would it be easier to use a 2D array with two columns to store the responses, where the first column stores a marker for the key word it corresponds to (or even just the keyword itself!), and the second column stores the actual response? That way when you detect a keyword, you can search your responses array based on the keyword [index], and select one at random?

ron77

hello - well i decided to simplify the database and the code - made another database.txt file with a rule of "one keyword = three replies" no multi keywords and replies pairs but just 1 keyword = 3 replies

so here is DATABASE.TXT:
======== DATABASE GW CHATBOT 2 =============

=========ONE KEYWORD THREE REPLIES==========

======== TEST DRIVE ==============

k:hi

r:hello
r:hi there
r:how are you?

k:hello

r:hi hello how are you?
r:hi nice to meet you
r:hello how is your day coming along?

k:sad

r:don't be sad it will be alright
r:why are you sad?
r:whats wrong? you can yell me...

k:lonely day

r:yes we are all alone in the wrold
r:is that how you feel? just remember this too shell pass
r:i'm sorry you feel like that i wish i could help

k:day day

r:i hope your day gets better
r:everyone has bad bays tomorrow will be better
r:hang on i'm sure tomorrow will be better

d:i see
d:go on please
d:i'm listening
d:i think i understand

and here is the code :
10 REM A CHATBOT 2 WITH A DATABASE OF KEYWORDS AND REPLIES AND DEFAULT REPLIES - FIXED DATABASE 1 KEYWORD = 3 REPLIES EACH
20 REM BY RON77
30 REM 2023
40 REM PROGRAM INITIALIZATION
50 DIM K$(100),R$(100, 3),D$(20): DCOUNT=1:FLINE$="":TAG$="":STEXT$="":TAGP=0
60 REM
70 DATAFILE$="DATABASE.TXT": RANDOMIZE TIMER
80 REM LOAD DATABASE
82 KEYWORDNUM = 1: REPLYNUM = 1
90 OPEN "I",#1,DATAFILE$
100 WHILE NOT EOF(1)
110 LINE INPUT #1,FLINE$
120 IF LEN(FLINE$)>0 THEN TAGP = INSTR(FLINE$,":")
130 IF TAGP>0 THEN TAG$=LEFT$(FLINE$,1) : STEXT$=MID$(FLINE$,TAGP+1) ELSE TAGP$=""
140 IF TAG$="k" THEN KEYWORDNUM=KEYWORDNUM+1: K$(KEYWORDNUM)=" "+ STEXT$+ " ": REPLYNUM = 1
150 IF TAG$="r" THEN R$(KEYWORDNUM, REPLYNUM)=STEXT$: REPLYNUM=REPLYNUM+1
160 IF TAG$="d" THEN DCOUNT=DCOUNT+1: D$(DCOUNT)=STEXT$
170 WEND
180 CLOSE #1
190 REM MAIN LOOP
200 PRINT "============================="
210 INPUT "YOU: ", USERINPUT$
211 USERINPUT$ = " " + USERINPUT$ + " "
220 IF USERINPUT$ = " BYE " THEN GOTO 500
230 KFOUND = 0
240 FOR I = 1 TO KEYWORDNUM
250   IF INSTR(USERINPUT$,K$(I)) > 0 THEN KFOUND = 1: KNUM = I: GOTO 300
260 NEXT I
270 IF KFOUND = 0 THEN GOTO 400
300 REM KEYWORD FOUND, SELECT A RANDOM REPLY
310 RNUM = INT(RND * 3) + 1
320 PRINT "BOT: " + R$(KNUM, RNUM)
390 GOTO 190
400 REM KEYWORD NOT FOUND, USE DEFAULT REPLY
410 DNUM = INT(RND * DCOUNT) + 1
420 PRINT "BOT: " + D$(DNUM)
430 GOTO 190
500 REM EXIT
510 PRINT "BOT: GOODBYE!"
520 END
 and it still not working i get empty strings as output or is i tweak with the code i get wrong replies to the keyword
any idea what is wrong...

ron77

okay i succeeded in fixing the code and now it works as intended...

the issue (bug) was seems to be with the order of operations in line 140. The keyword is being stored in `K$` at index `KEYWORDNUM`, and then `KEYWORDNUM` is being incremented. However, in line 150, the reply is being stored in `R$` at index `KEYWORDNUM`, which is now one more than it was when the keyword was stored. This means that the first reply for each keyword is being stored at the next keyword's index, which could cause the first keyword to have an empty reply.

here is the correct code:
10 REM A CHATBOT 2 WITH A DATABASE OF KEYWORDS AND REPLIES AND DEFAULT REPLIES - FIXED DATABASE 1 KEYWORD = 3 REPLIES EACH
20 REM BY RON77
30 REM 2023
40 REM PROGRAM INITIALIZATION
50 DIM K$(100),R$(100, 3),D$(20): DCOUNT=1:FLINE$="":TAG$="":STEXT$="":TAGP=0:KNUM=0
60 REM
70 DATAFILE$="DATABASE.TXT": RANDOMIZE TIMER
80 REM LOAD DATABASE
82 KEYWORDNUM = 1: REPLYNUM = 1
90 OPEN "I",#1,DATAFILE$
100 WHILE NOT EOF(1)
110 LINE INPUT #1,FLINE$
120 IF LEN(FLINE$)>0 THEN TAGP = INSTR(FLINE$,":")
130 IF TAGP>0 THEN TAG$=LEFT$(FLINE$,1) : STEXT$=MID$(FLINE$,TAGP+1) ELSE TAG$=""
140 IF TAG$="k" THEN K$(KEYWORDNUM)=" "+ STEXT$+ " ": REPLYNUM = 1: KEYWORDNUM=KEYWORDNUM+1
150 IF TAG$="r" THEN R$(KEYWORDNUM - 1, REPLYNUM)=STEXT$: REPLYNUM=REPLYNUM+1
160 IF TAG$="d" THEN DCOUNT=DCOUNT+1: D$(DCOUNT)=STEXT$
170 WEND
180 CLOSE #1
190 REM MAIN LOOP
200 PRINT "============================="
210 INPUT "YOU: ", USERINPUT$
211 USERINPUT$ = " " + USERINPUT$ + " "
220 IF USERINPUT$ = " BYE " THEN GOTO 500
230 KFOUND = 0
240 FOR I = 1 TO KEYWORDNUM - 1
250   IF INSTR(USERINPUT$,K$(I)) > 0 THEN KFOUND = 1: KNUM = I: GOTO 300
260 NEXT I
270 IF KFOUND = 0 THEN GOTO 400
300 REM KEYWORD FOUND, SELECT A RANDOM REPLY
310 RNUM = INT(RND * 3) + 1
320 PRINT "BOT: " + R$(KNUM, RNUM)
390 GOTO 190
400 REM KEYWORD NOT FOUND, USE DEFAULT REPLY
410 DNUM = INT(RND * DCOUNT) + 1
420 PRINT "BOT: " + D$(DNUM)
430 GOTO 190
500 REM EXIT
510 PRINT "BOT: GOODBYE!"
520 END

DATABASE.TXT (corrected spelling)
======== DATABASE GW CHATBOT 2 =============

=========ONE KEYWORD THREE REPLIES==========

======== TEST DRIVE ==============

k:hi

r:hello
r:hi there
r:how are you?

k:hello

r:hi hello how are you?
r:hi nice to meet you
r:hello how is your day coming along?

k:sad

r:don't be sad it will be alright
r:why are you sad?
r:whats wrong? you can tell me...

k:lonely day

r:yes we are all alone in the world
r:is that how you feel? just remember this too shell pass
r:i'm sorry you feel like that i wish i could help

k:bad day

r:i hope your day gets better
r:everyone has bad bays tomorrow will be better
r:hang on i'm sure tomorrow will be better

d:i see
d:go on please
d:i'm listening
d:i think i understand

Dan

...
65536 GOTO Back2Basic

ron77

#7
hi @Dan yes this is how i intended it to work - for every keyword the right paired replies as output

thanks for trying it and showing how it works on your screen :)

making this code work was important to me since i plan to code a gw basic text game and use this as a feature in the game

Dan

...
65536 GOTO Back2Basic

ron77

nice @Dan try to ask it "hi there how are you doing?" or "it's a lonely day this week" or "i'm sad cause it's autumn" i wonder what it will reply :)

Dan

65536 GOTO Back2Basic