聊天機器人開發思路(樣板式模型)

最近打算弄一個智能客服的東西,就是輔助客服講述幫助用戶如何安裝電視機的流程。

現在記錄下吧:
一開始查了很多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.
發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章