我想在酒吧的上下文中实现一个人机口语对话系统,它将用户的文本短语作为输入(对给定产品的请求:薯片、可乐、水、咖啡等) .) 并返回相应的响应作为输出(超出操作范围,但这并不重要)。
我想达到的对话示例:
U: Hi, how are you?
S: Hey there. I'm good. How may I help you?
U: I would like to have a coffee and a Croissant with jam"
S: Sure. Here your order!
U: Thank you! bye.
S: Thank to you, too. Have a good day!
也就是说,现在我只想在他们之间就酒吧的秩序进行简单的对话。
有人知道一些关于如何实现对话系统的教程,最好是用 Prolog 吗?
无论如何,任何其他语言对我来说都是有好处的,至少可以理解这样的系统是如何实现的。
我在互联网上搜索,但发现了很多让我困惑的材料,而且没有一个给出如何实现对话系统的示例。
最后我只想将它作为我的 PC 上的软件(而不是网络应用程序或类似应用程序)。
ELIZA 这是典型的聊天机器人。
它并没有真正“理解”对话框的语法结构,但可能是一个好的开始。
SWISH 中有一个非常简单的例子。这是我的 HD 上的一些代码(IIRC,来自 Clocksin - Mellish,移植到 SWI-Prolog)。
eliza :-
write('? '), read_word_list(Input), eliza(Input), !.
eliza([bye]) :-
write('Goodbye. I hope I have helped you'), nl.
eliza(Input) :-
pattern(Stimulus, Response),
match(Stimulus, Dictionary, Input),
match(Response, Dictionary, Output),
reply(Output),
!, eliza.
match([N|Pattern], Dictionary, Target) :-
integer(N), lookup(N, Dictionary, LeftTarget),
append(LeftTarget, RightTarget, Target),
match(Pattern, Dictionary, RightTarget).
match([Word | Pattern], Dictionary, [Word | Target]) :-
atom(Word), match(Pattern, Dictionary, Target).
match([], _Dictionary, []).
pattern([i,am,1],[how,long,have,you,been,1,'?']).
pattern([1,you,2,me],[what,makes,you,think,i,2,you,'?']).
pattern([i,like,1],[does,anyone,else,in,your,family,like,1,'?']).
pattern([i,feel,1],[do,you,often,feel,that,way,'?']).
pattern([1,X,2],[can,you,tell,me,more,about,your,X,'?']) :- important(X).
pattern([1],[please,go,on]).
important(father).
important(mother).
important(son).
important(sister).
important(brother).
important(daughter).
reply([Head | Tail]) :-
write(Head), write(' '), reply(Tail).
reply([]) :- nl.
lookup(Key, [(Key, Value) | _Dict], Value).
lookup(Key, [(Key1, _Val1) | Dictionary], Value) :-
Key \= Key1, lookup(Key, Dictionary, Value).
read_word_list(Ws) :-
read_line_to_codes(user_input, Cs),
atom_codes(A, Cs),
tokenize_atom(A, Ws).
编辑回复评论...
好吧,该代码是由 Prolog 大师编写的,而不是我:) 所以,我们应该尝试理解它...这两个子句使用不完整的数据结构实现了一个“增量字典”。它们在刺激和响应之间绑定任意短语,并且是 ELIZA 如此紧凑的编码的关键(尽管原始程序并不那么简单......)。为了跟踪用法,可以进行 Prolog 调试:
?- leash(-all),spy(lookup).
?- eliza.
? i am happy
* Call: (12) lookup(1, _G4620, _G4621)
* Exit: (12) lookup(1, [(1, _G4616)|_G4613], _G4616)
* Call: (15) lookup(1, [(1, [happy])|_G4613], _G4645)
* Exit: (15) lookup(1, [(1, [happy])|_G4613], [happy])
how long have you been happy ?
? i think you hate me
* Call: (14) lookup(1, _G4821, _G4822)
* Exit: (14) lookup(1, [(1, _G4817)|_G4814], _G4817)
* Call: (16) lookup(2, [(1, [i, think])|_G4814], _G4834)
* Call: (17) lookup(2, _G4814, _G4834)
* Exit: (17) lookup(2, [(2, _G4829)|_G4826], _G4829)
* Exit: (16) lookup(2, [(1, [i, think]), (2, _G4829)|_G4826], _G4829)
* Call: (19) lookup(2, [(1, [i, think]), (2, [hate])|_G4826], _G4858)
* Call: (20) lookup(2, [(2, [hate])|_G4826], _G4858)
* Exit: (20) lookup(2, [(2, [hate])|_G4826], [hate])
* Exit: (19) lookup(2, [(1, [i, think]), (2, [hate])|_G4826], [hate])
what makes you think i hate you ?
...
您可以看到关联列表的尾部在退出时是空闲的,因此字典根据需要进行扩展。不完整数据结构的巧妙运用。请参阅《Prolog 的艺术》第 15 章