2008-09-10 293 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 

當你說出某種看起來部分有意義的東西時,你往往會有一種不可思議的感覺。