2008-09-10 290 views
32

我想建立一个bot,根据答案向某人提出一些简单的问题和分支。我意识到从人类的反应中解析意义是具有挑战性的,但是如何设置程序来处理对话的“状态”?如何编程一个简单的聊天机器人AI?

这将是一个人与机器人之间的一对一对话。

+4

我并不完全相信现有的聊天机器人甚至有'国家'这样的东西。他们的回答似乎只取决于你问的最后一个问题。人类会问一系列相关问题,这只是巧合。 – 2008-09-10 19:05:38

+0

http://search.cpan.org/search?query=bot&mode=all – 2008-09-15 16:00:32

回答

22

你可能想看看Markov Chains作为机器人AI的基础知识。我写的东西很久以前(的代码,我一点儿也不感到骄傲,并且需要一些MODS的关于Python> 1.5上运行)可能对你有用的起点:http://sourceforge.net/projects/benzo/

编辑:下面是一个马尔可夫链Python的最小例子,它接受来自stdin的输入,并根据输入中相互成功的单词的概率输出文本。它的IRC风格的聊天记录了优化,但运行任何体面的文字通过它应该表现出概念:

import random, sys 

NONWORD = "\n" 
STARTKEY = NONWORD, NONWORD 
MAXGEN=1000 

class MarkovChainer(object): 
    def __init__(self): 
     self.state = dict() 

    def input(self, input): 
     word1, word2 = STARTKEY 
     for word3 in input.split(): 
      self.state.setdefault((word1, word2), list()).append(word3) 
      word1, word2 = word2, word3 
     self.state.setdefault((word1, word2), list()).append(NONWORD) 

    def output(self): 
     output = list() 
     word1, word2 = STARTKEY 
     for i in range(MAXGEN): 
      word3 = random.choice(self.state[(word1,word2)]) 
      if word3 == NONWORD: break 
      output.append(word3) 
      word1, word2 = word2, word3 
     return " ".join(output) 

if __name__ == "__main__": 
    c = MarkovChainer() 
    c.input(sys.stdin.read()) 
    print c.output() 

离这里很容易在持久性和一个IRC库堵塞和有型的基础你正在谈论的bot。

0

我会建议看看贝叶斯概率。然后只监视聊天室一段时间来创建概率树。

3

我想你可以看看Kooky的代码,而IIRC它也使用马尔可夫链。

还检查了kooky quotes,他们在不久前编码恐怖片特色,有些是热闹。

2

我认为要开始这个项目,最好能有一个有问题的数据库(组织成一棵树,每个节点有一个或多个问题)。 这些问题应该回答“是”或“否”。

如果机器人开始质疑,它可以从yuor数据库中的任何问题开始,标记为开始问题。答案是到树中下一个节点的路径。

编辑:这是用Ruby编写的一个somple一个你可以开始:rubyBOT

0

我不知道这是你在找什么,但有一个叫ELIZA旧的程序可以存放谈话通过采取你所说的话并在执行一些简单的文本转换之后将它吐出来。

如果我没有记错的话,很多人都确信他们正在与一个真人对话,并与他们进行长时间的精心对话。

14

有人提到已经是有状态不是典型的聊天机器人的一大组成部分:

  • 纯马尔可夫实现,如果它正在扩大其词汇和表实时可以表达一种状态非常宽松人类对话者先前的话语可能会在稍后的谈话中偶然反刍—,但马尔可夫模型没有任何选择或产生这种反应的内在机制。

  • 一个基于分析的机器人(例如,ELIZA)通常会尝试对来自用户的最近输入的(某些)语义内容做出响应,而不重视先前的交换。

这就是说,你肯定可以状态的一定量添加到聊天机器人,无论您使用的输入解析和声明合成模型。如何做到这一点很大程度上取决于你想用你的状态完成什么,而这从你的问题来看并不是很清楚。然而,一些一般想法:

  • 创建关键字堆栈。当你的人提供输入时,从他们的陈述/问题中解析出关键字,并将这些关键字放入某种类型的堆栈中。当你的聊天机器人在最近的输入—或者随机的时候没有提出一些令人信服的回应时,可以将它们混合起来—回到你的堆栈,抓住一个以前的关键字,并用它来播种你的下一个合成。对于奖励积分,让机器人明确地确认它将返回到先前的主题,例如, “等等,人类,早些时候你提到foo。[由foo播种的句子]”。

  • 在机器人中构建类似RPG的对话逻辑。作为解析人的输入,切换特定会话提示的标志或来自用户的内容,并有条件地改变聊天机器人可以谈论的内容或其如何通信。例如,用粗言秽语(或骂或笑)是相当普遍的;一个聊天机器人将得到het,并有条件地仍然如此,直到道歉,将是一个有趣的状态变化。输出切换到全部大写,扔在对峙言辞或要求或哭泣,等

    你想要的状态,以帮助你完成

你能澄清一下吗?

5

想象一下每个节点或神经元都具有解析能力的神经网络。根据规则和解析结果,神经元会激发。如果某些神经元发生火灾,您可以对该问题的主题和语义有个好主意,因此可以给出一个很好的答案。

记忆是通过在会话中讨论话题,添加到下一个问题的发射,并因此指导最终可能的答案的选择过程。

将您的规则和模式保存在知识库中,但在开始时将它们编译到内存中,并按照规则使用神经元。您可以使用听众或事件功能等工具来设计突触。

0

如果你只是涉猎,我相信Pidgin允许你脚本聊天风格的行为。框架的一部分可能会影响谁在什么时候发送消息的状态,并且您希望为每个最近的N条消息记录您的机器人的内部状态。未来的状态决策可以基于对先前状态的检查和最近几条消息的内容进行硬编码。或者你可以做一些讨论的马尔可夫链,并将它用于解析和生成。

0

如果你不需要学习机器人,使用AIML(http://www.aiml.net/)很可能会产生你想要的结果,至少就bot解析输入和基于它的应答而言。

您可以重用或创建由XML构成的“大脑”(采用AIML格式),并在程序(解析器)中解析/运行它们。有几种不同语言的解析器可供选择,并且据我所知,在大多数情况下,代码似乎是开源的。

1

naive chatbot program。没有解析,没有聪明,只是一个培训文件和输出。

它首先根据文本进行自我训练,然后使用该训练的数据生成对话者输入的响应。训练过程会创建一个字典,其中每个键都是一个单词,并且该值是在训练文本中的任意位置顺序跟随该单词的所有单词的列表。如果一个单词在这个列表中不止一次具有特征,那么它就会反映出来,而且它更有可能被机器人选中,因此不需要概率性的东西只是用列表来完成。

机器人从您的输入中选择一个随机单词,并通过选择另一个随机单词来生成响应,该单词已被视为其保留单词的后继单词。然后通过依次找到该单词的继承者并重复进行,直到它认为它已足够。它通过停止训练文本中标点符号之前的单词来达到该结论。然后它会再次返回到输入模式以让您作出回应,依此类推。

这不是很现实,但我特此挑战任何人在71行代码中做得更好!对于任何萌芽的Python主义者来说,这是一个巨大的挑战,我只希望我能向更广泛的受众展示挑战,而不是我访问该博客的少量访问者。要编写一个始终保证语法的机器人必须接近几百行,我简单地简化一下,试图想到最简单的规则,让计算机不得不说有话要说。

至少可以说它的反应相当写意!你也必须把你说的单引号。

我用战争与和平这花了几个小时的跑步训练我的“文集”,使用更短的文件,如果你不耐烦......

这里是教练

#lukebot-trainer.py 
import pickle 
b=open('war&peace.txt') 
text=[] 
for line in b: 
    for word in line.split(): 
     text.append (word) 
b.close() 
textset=list(set(text)) 
follow={} 
for l in range(len(textset)): 
    working=[] 
    check=textset[l] 
    for w in range(len(text)-1): 
     if check==text[w] and text[w][-1] not in '(),.?!': 
      working.append(str(text[w+1])) 
    follow[check]=working 
a=open('lexicon-luke','wb') 
pickle.dump(follow,a,2) 
a.close() 

这里是机器人

#lukebot.py 
import pickle,random 
a=open('lexicon-luke','rb') 
successorlist=pickle.load(a) 
a.close() 
def nextword(a): 
    if a in successorlist: 
     return random.choice(successorlist[a]) 
    else: 
     return 'the' 
speech='' 
while speech!='quit': 
    speech=raw_input('>') 
    s=random.choice(speech.split()) 
    response='' 
    while True: 
     neword=nextword(s) 
     response+=' '+neword 
     s=neword 
     if neword[-1] in ',?!.': 
      break 
    print response 

当你说出某种看起来部分有意义的东西时,你往往会有一种不可思议的感觉。