最近打算弄一個智能客服的東西,就是輔助客服講述幫助用戶如何安裝電視機的流程。
現在記錄下吧:
一開始查了很多rnn,lstm,s2s等模型,發現都是那種生成式模型。
而且需要大量訓練集,效果不是很理想。
對於此任務應該是一個task-oriented。
一般有三種方法:
樣板式模型 (Rule-based model)
檢索式模型 (Retrieval-based model)
生成式模型 (Generative model)
這裏主要講樣板式(Rule-based model),從簡單的開始。
通過AIML這種提供編寫類似XML的高科技來完成任務。
有一個很明顯的缺點就是需要大量的寫規則,累。但是這種東西有提供詞槽(slot),下面記錄下AIML的使用過程。
通過AIML包,用Python很容易寫出人工智能的聊天機器人。AIML代表人工智能修飾語言,但它僅是一個簡單的XML。下面這些代碼樣例將帶你瞭解如何使用Python創造你自己的人工智能聊天機器人。
AIML是什麼?
AIML是由Richard Wallace開發的。他製作了一個叫做A.L.I.C.E.(人工語言學網絡計算機實體)的機器人,並獲得了一些人工智能的獎項。有趣的是,找尋人工智能的圖靈測試中的一項是,讓一個人通過文字接口與一個機器人對話幾分鐘,然後看看他們是否把它當做一個人。AIML以XML的形式來定義匹配模式規則,然後決定應答。
獲得完整的AIML入門,查看Alice Bot’s AIML Primer。你將學到更多關於AIML的東西,以及在AIML Wikipedia page上看到它能夠做什麼。我們將首先創建AIML文件,然後使用Python給它賦予活力。
創建標準啓動文件
標準的做法是,創建一個名爲std-startup.xml的啓動文件,作爲加載AIML文件的主入口點。在這個例子中,我們將創建一個基礎的文件,它匹配一個模式,並且返回一個相應。我們想要匹配模式load aiml b,然後讓它加載我們的aiml大腦作爲響應。我們將在一分鐘內創建basic_chat.aiml文件。
<aiml version="1.0.1" encoding="UTF-8">
<!-- std-startup.xml -->
<!-- Category是一個自動的AIML單元 -->
<category>
<!-- Pattern用來匹配用戶輸入 -->
<!-- 如果用戶輸入 "LOAD AIML B" -->
<pattern>LOAD AIML B</pattern>
<!-- Template是模式的響應 -->
<!-- 這裏學習一個aiml文件 -->
<template>
<learn>basic_chat.aiml</learn>
<!-- 你可以在這裏添加更多的aiml文件 -->
<!--<learn>more_aiml.aiml</learn>-->
</template>
</category>
</aiml>
創建一個AIML文件
在上面,我們創建的AIML文件只能處理一個模式:load aiml b。當我們向機器人輸入那個命令時,它將會嘗試加載basic_chat.aiml。除非我們真的創建了它,否則無效。下面是你可以寫進basic_chat.aiml的內容。我們將匹配兩個基本的模式和響應。
<aiml version="1.0.1" encoding="UTF-8">
<!-- basic_chat.aiml -->
<aiml>
<category>
<pattern>HELLO</pattern>
<template>
Well, hello!
</template>
</category>
<category>
<pattern>WHAT ARE YOU</pattern>
<template>
I'm a bot, silly!
</template>
</category>
</aiml>
隨機響應
你也可以像下面這樣添加隨機響應。它將在接受到一個以”One time I”開頭的消息的時候隨機響應。*是一個匹配任何東西的通配符。
<category>
<pattern>ONE TIME I *</pattern>
<template>
<random>
<li>Go on.</li>
<li>How old are you?</li>
<li>Be more specific.</li>
<li>I did not know that.</li>
<li>Are you telling the truth?</li>
<li>I don't know what that means.</li>
<li>Try to tell me that another way.</li>
<li>Are you talking about an animal, vegetable or mineral?</li>
<li>What is it?</li>
</random>
</template>
</category>
使用已存在的AIML文件
編寫你自己的AIML文件是一個很有趣的事,但是它將花費很大的功夫。我覺得它需要大概10,000個模式纔會開始變得真實起來。幸運的是,ALICE基金會提供了大量免費的AIML文件。在Alice Bot website上瀏覽AIML文件。在調用std-65percent.xml(它包含了65%最常用的短語)前,有一個浮動值。還有一個文件允許你和機器人玩BlackJack遊戲。
最簡單的Python程序
import aiml
# 創建核心,並學習AIML文件
kernel = aiml.Kernel()
kernel.learn("std-startup.xml")
kernel.respond("load aiml b")
# 按住CTRL-C來終止這個循環
while True:
print kernel.respond(raw_input("Enter your message >> "))
加速Brain加載
當你開始擁有很多AIML文件時,它將花費很長的時間來學習。這就是brain文件從何而來。在機器人學習所有的AIML文件後,它可以直接將它的大腦保存到一個文件中,這個文件將會在後續的運行中動態加速加載時間。
import aiml
import os
kernel = aiml.Kernel()
if os.path.isfile("bot_brain.brn"):
kernel.bootstrap(brainFile = "bot_brain.brn")
else:
kernel.bootstrap(learnFiles = "std-startup.xml", commands = "load aiml b")
kernel.saveBrain("bot_brain.brn")
# kernel now ready for use
while True:
print kernel.respond(raw_input("Enter your message >> "))
在運行的時候重新加載AIML
你可以在機器人運行的時候發送加載消息,然後它將加載AIML文件。記住,如果你使用了上面寫的brain方法,在運行的時候加載並不會將新增改變保存到brain中。你將需要刪除brain文件以便於它在下一次啓動的時候重建,或者需要修改代碼,使得它在重新加載後的某個時間點保存brain。關於爲機器人創建可以執行的Python命令,查看下一章節。
load aiml b
增加Python命令 如果你想要爲你的機器人提供一些特殊的運行Python函數的命令,那麼,你應該爲機器人捕獲輸入消息,然後在將它發送給kernel.respond()之前處理它。在上面的例子中,我們從raw_input中獲得了用戶的輸入。然而,我們可以從任何地方獲取輸入。可能是一個TCP socket,或者是一個語音識別源碼。在它進入到AIML之前處理這個消息。你可能想要在某些特定的消息上跳過AIML處理。
while True:
message = raw_input("Enter your message to the bot: ")
if message == "quit":
exit()
elif message == "save":
kernel.saveBrain("bot_brain.brn")
else:
bot_response = kernel.respond(message)
# Do something with bot_response
會話和斷言
通過指定一個會話,AIML可以爲不同的人剪裁不同的會話。例如,如果某個人告訴機器人,他的名字是Alice,而另一個人告訴機器人他的名字是Bob,機器人可以區分不同的人。爲了指定你所使用的會話,將其作爲第二個參數傳給respond()
sessionId = 12345
kernel.respond(raw_input(">>>"), sessionId)
這對於爲每一個客戶端定製個性化的對話是很有幫助的。你將必須以某種形式生成自己的會話ID,並且跟蹤它。注意,保存brain文件不會保存所有的會話值。
sessionId = 12345
# 會話信息作爲字典獲取. 包含輸入輸出歷史,
# 以及任何已知斷言
sessionData = kernel.getSessionData(sessionId)
# 每一個會話ID需要時一個唯一值。
# 斷言名是機器人在與你的會話中瞭解到的某些/某個名字
# 機器人可能知道,你是"Billy",而你的狗的名字是"Brandy"
kernel.setPredicate("dog", "Brandy", sessionId)
clients_dogs_name = kernel.getPredicate("dog", sessionId)
kernel.setBotPredicate("hometown", "127.0.0.1")
bot_hometown = kernel.getBotPredicate("hometown")
在AIML中,我們可以使用模板中的set響應來設置斷言
<aiml version="1.0.1" encoding="UTF-8">
<category>
<pattern>MY DOGS NAME IS *</pattern>
<template>
That is interesting that you have a dog named <set name="dog"><star/></set>
</template>
</category>
<category>
<pattern>WHAT IS MY DOGS NAME</pattern>
<template>
Your dog's name is <get name="dog"/>.
</template>
</category>
</aiml>
使用上面的AIML,你可以告訴機器人:
My dogs name is Max
而機器人會回答你:
That is interesting that you have a dog named Max
然後,如果你問機器人:
What is my dogs name?
機器人將會回答:
Your dog's name is Max.