Search code examples
pythonprologchatbot

Simple Chatbot in Prolog - translate python to prolog


I'm trying to do a simple chatbot in prolog, which basically does what this python script does ... could someone help me?

question = input('Hello, can i help you?')

questions = ["what is ipv4", "what is router", "what is osi"]

answers = [
    "Internet Protocol version 4 is the fourth version of the Internet Protocol.",
    "A router is a device that forwards data packets between computer networks."
    "The OSI Model is an ISO reference computer network model divided into layers of functions."
]

question = question.lower().replace("?", "").strip()

idx = questions.index(question) if question in questions else -1
response = answers[idx] if idx > -1 else "Sorry, answer not found."

print(response)

I am blocked here:

:- initialization(main).


list_of_questions(['what is ipv4', 'what is router']).


in_list_of_questions(X) :- 
    list_of_questions(L),
    member(X, L).
    
Res :- in_my_list_of_elements('what is ipv4 ?').

%write(list_of_questions).

main :- write(Res).

this doesnt work :(


Solution

  • How about this.

    Note the following:

    This is for SWI-Prolog.

    • It has predicate read_line_to_codes/2. If another Prolog is used, a subsitute predicate may have to be found.
    • SWI-Prolog distinguishes between strings ("foo") and atoms ('foo' or foo). Strings should be used for "text elements" as opposed to "identifier-like" elements. In this case, we use atoms throughout, although the answer and question for example are use cases for strings.
    • I have noticed there is no trim/2 predicate as such to trim an atom (i.e. remove blanks from the atom's start and end). So I added one. It's not very efficient due to the way append/3 generates candidates but good enough for short atoms. (Is the SWI-Prolog preferred way to transform everything into a string and then apply a particular form of split_string/4? I hope trim/2 gets added soon.)
    • Processing of atoms may be done by transforming them into "lists of codes", as here (the codes are Unicode codepoints in SWI-Prolog, which is the one and only sane decision, but other Prologs may differ). Alternatively, processing of atoms may be done by transforming them into "lists of chars", i.e. lists of atoms of length 1, which is done in the trimming predicate.
    question_answer('what is ipv4'   , 'Internet Protocol version 4 is the fourth version of the Internet Protocol.').
    question_answer('what is router' , 'A router is a device that forwards data packets between computer networks.').
    question_answer('what is osi'    , 'The OSI Model is an ISO reference computer network model divided into layers of functions.').
    
    main :-
       format('Hello, can i help you?~n',[]),
       read_line_to_codes(user_input,QCodes1),
       exclude(=(0'?),QCodes1,QCodes2),   
       atom_codes(QAtom1,QCodes2),
       downcase_atom(QAtom1,QAtom2),
       trim(QAtom2,TrimmedAtom),
       (
          question_answer(TrimmedAtom,Answer) 
          -> 
          format('~s~n',[Answer])
          ;
          format('~s~n',['Sorry, answer not found'])
       ),
       !,
       main.
    
    
    % That additional
    % trim(Chars,TrimmedChars)
    
    is_blank(X) :- 
       memberchk(X,[' ','\n','\r','\t']). % should be extended to the whole unicode "blank" class
    
    trim(Atom,TrimmedAtom) :-
       atom_chars(Atom,Chars),
       trim_chars(Chars,TrimmedChars),
       atom_chars(TrimmedAtom,TrimmedChars).
    
    trim_chars(Chars,TrimmedChars) :- 
       append([Prefix,TrimmedChars,Suffix],Chars),
       forall(member(X,Prefix),is_blank(X)),
       forall(member(X,Suffix),is_blank(X)),
       (
          TrimmedChars == [];
          (TrimmedChars = [First|_], \+is_blank(First), last(TrimmedChars,Last), \+is_blank(Last))
       ).
    

    Test run:

    ?- [q].
    true.
    
    ?- main.
    Hello, can i help you?
    |:     What is IPv4 ?
    Internet Protocol version 4 is the fourth version of the Internet Protocol.
    Hello, can i help you?
    |: What is ROUTER
    A router is a device that forwards data packets between computer networks.
    Hello, can i help you?
    |: Who is Iwakura Lain?
    Sorry, answer not found
    Hello, can i help you?
    |: ^Dfalse.