聊天機器人教學(xué):使用Dialogflow (API.AI)開發(fā) iOS Chatbot App

image

隨著蘋果Core ML的最新版本發(fā)佈,開發(fā)人員更容易構(gòu)建人工智能應(yīng)用程式,除了圖像識別和文本檢測是利用AI建置APP的好例子,另一種善于展現(xiàn)機器學(xué)習(xí)Power的應(yīng)用程式類型則是chatbots。在本教程中,我們將使用Google的Dialogflow(以前稱為API.AI)構(gòu)建在iOS上運行的chatbot應(yīng)用程式!

聽起來很酷吧!接下來開始進入本教程的重點。

Intents(意圖)和Entities(關(guān)鍵字)快速概覽

在開始之前,我先解釋Dialogflow和chatbots的一般基本知識。 在構(gòu)建chatbots時,你必須知道兩個術(shù)語:Intents(意圖)Entities(關(guān)鍵字)。

An entity represents a term or object in the user’s input that provides clarification or specific context for a particular intent.
(entity表示用戶輸入中的術(shù)語或?qū)ο?/em>,為intent提供說明或使用情境。)

An intent, on the other hand, represents something that the user wants to do. If intents represent verbs, then entities represent nouns.
(另一方面,intent代表用戶想要做的事情,如果intent代表動詞,則entities代表名詞。)

來看一個例子,在我們的項目中,可能會告訴我們的機器人以下聲明:

“Book me a room at the La Grande Hotel”(替我在La Grande Hotel訂一間房)

在這句話中,我們的intent(意圖)是”預(yù)定一個房間”,entity(關(guān)鍵字)是”La Grande Hotel”,現(xiàn)在,自然語言處理(NLP)算法可以計算兩種不同類型的對話內(nèi)容。

  1. 基于意圖(Intent-based)的對話:這是當(dāng)NLP算法使用intents和entities進行對話時,通過識別用戶聲明中的名詞和動詞,然后與它的dictionary交叉引用,讓bot可以執(zhí)行有效的操作,這種類型的對話是Dialogflow使用的。
  2. 基于流程(Flow-based)的對話:基于流程的對話是智能通信的下一個級別。在這里,我們會給予兩個人之間對話的許多不同樣本的RNN(循環(huán)神經(jīng)網(wǎng)絡(luò)),創(chuàng)建的機器人將根據(jù)你訓(xùn)練的ML模型進行響應(yīng)。Wit.ai是在這個領(lǐng)域取得巨大進展的少數(shù)網(wǎng)站之一,不用擔(dān)心,我們不需要做到這個程度。

注意:如果想了解更多有關(guān)Intent-based和Flow-based的對話信息,可以查看這篇文章。

在本教程中,我們將創(chuàng)建一個可幫助你預(yù)訂hotel的機器人。

One of the most important rules when developing a chatbot is that it MUST have a personna. This means that it must behave like a real person. Therefore, let’s name out bot – Chip!
(開發(fā)chatbot最重要的規(guī)則之一,就是它必須有一個personna,意味著它必須像真人一樣行事。 因此,讓我們來替bot命名 – Chip!)

接下來,就進入本文重點!

熟悉Dialogflow

進入到Dialogflow,在右上角點擊”Go to Console(前往控制臺)”。

Dialogflow

系統(tǒng)會要求你使用Google帳戶登錄,并授權(quán)使用Dialogflow在Google云端平臺服務(wù)中查看和管理你的資訊,接受條款,你應(yīng)該看到一個初始啟動頁面。

Dialogflow-console

觀看介紹影片可以讓你更快速了解Dialogflow,但如果你不想花時間看也沒關(guān)係!點擊”Create Agent”按鈕,在Dialogflow中,一個agent(代理)意味著iOS應(yīng)用將使用chatbot通過無線方式進行通訊以接收回應(yīng)。

填寫代理名稱(比如Chip),然后點擊Create按鈕進行下一步,Dialogflow將為你創(chuàng)建agent?,F(xiàn)在,讓我們來確認(rèn)一下,你應(yīng)該有2個預(yù)設(shè)intents:”Default Welcome Intent”和”Default Fallback Intent”。在左側(cè)欄位中,你應(yīng)該可以看到Intents和Entities的tabs(選項)。

Create Agent in Dialogflow

我們也會在下方看到其他tabs?,F(xiàn)在,該開始創(chuàng)建機器人了!

添加Entities

首先,讓我們開始添加entities,如果你還記得,entities就像NLP算法可以理解的名詞,拿出一個可能經(jīng)常用于我們機器人的entities名單,我已經(jīng)把我整理的list放在下面,并且隨時可以添加它。

  • Hotel
  • Room
  • Payment

選擇entities選項,然后點擊”Create Entity”按鈕。并將這個entity命名為”Hotel”,并點擊第一行,輸入”Hotel”當(dāng)做參考值,當(dāng)用戶使用你的機器人時,他們可能會使用Hotel以外的其他名稱。 因此,應(yīng)該輸入關(guān)鍵字的一些同義詞,即使用戶使用”Hotel”以外的字,機器人仍然可以理解用戶在說什么,看下面的圖片,我使用了一些同義詞。

Dialogflow-add-entity

現(xiàn)在,儲存你的entity,并按照剛才建置Hotel entity的步驟創(chuàng)建以下的entities。

Dialogflow-entity-payment
Dialogflow-entity-room

小建議:要查找單詞的同義詞,只需Google搜尋”synonyms of [word]”。

現(xiàn)在我們已經(jīng)創(chuàng)建了entities,接著來討論intents。

添加Intents

進入Intents頁面并點擊Default Welcome Intent,這個intent就是我們機器人在第一次啟動時會抓取的東西,你應(yīng)該看到網(wǎng)頁呈現(xiàn)如下:

Dialogflow-intent

我們可以制定用戶應(yīng)該說出哪個字去觸發(fā)intent。在本頁面的最底部,我們也可以制定回應(yīng)的文本內(nèi)容,由于這是一個Welcome intent,用戶可能會說”Hello!”或”How’s it going?” 因此,讓我們將這些短語(和任何類似的同義詞)添加到’User says’部分,以下是一些范例,你可以隨意地添加更多的訊息,設(shè)定你的用戶可能會對機器人說的字匯。

Dialogflow-welcome-intent

如果向下滾動,會找到* Response *部分。intent帶有一些內(nèi)置的回應(yīng),我們添加一個follow up question(關(guān)聯(lián)性問題):”What can I do for you?”,我們最終Welcome intent應(yīng)該是這樣的:

Dialogflow-welcome-intent-response

在我們開始創(chuàng)建下一個intent之前,如果你想在任何時候測試你的agent,請查看右側(cè)欄位,你可以輸入想要的任何內(nèi)容,然后查看你的agent是否回應(yīng)。輸入”Hello”,然后檢查agent是否回應(yīng)了預(yù)期的回應(yīng)。

到目前為止,agent只有一個intent,由于我們的機器人是為處理預(yù)訂hotel而設(shè)計的,因此我們必須創(chuàng)建另一個處理intent這些查詢,用戶可能會問:“能替我預(yù)訂一家旅館嗎?” 或類似的問句。

讓我們創(chuàng)建一個新的intent,并將其命名Begin Order。在User says欄位中,添加上面的表達式然后按下enter。一旦你輸入了這個表達式,將會看到agent已經(jīng)在該語句中識別了一個@Hotel關(guān)鍵字。與entities類似,用戶不會只用這個問句來表達預(yù)訂酒店的需求。所以這里添加一些變化,以agent理可以了解用戶的意思,增加的變化越多,agent也就越聰明,以下是一個范例展示。

Dialogflow Begin Order Intent

agent應(yīng)該做的下一件事是搜索附近的hotel,并詢問用戶他/她需要幾間房。但是,如果我們要真正搜尋附近的酒店,則需要調(diào)用API并使用JavaScript將webhook與api.ai整合在一起,這超出了本教程的范圍,所以讓我們在Response欄位創(chuàng)建一些虛擬酒店,這是我創(chuàng)建的回應(yīng)內(nèi)容:

Dialogflow-begin-order-response

儲存intent并返回到主頁面,在右側(cè)欄位中測試你的agent,到目前為止,如果讀者有跟著前面的步驟,它應(yīng)該按預(yù)期工作!正如你所看到的,不必提出確切的問題,Dialogflow將從你的陳述中學(xué)習(xí)并理解變化。

test-agent

現(xiàn)在,我們來添加一些follow-up intent,將鼠標(biāo)移動在你剛創(chuàng)建的intent上,你應(yīng)該看到一個選項”Add follow-up intent”,選擇它并點擊Custom,將產(chǎn)生一個新的intent,并顯示”Begin Order – custom”,讓我們編輯這個intent!

Dialogflow-add-follow-intent

請記住,我們agent對我們說的最后一件事情是”How many rooms do we want?”,用戶可能會回覆一個數(shù)字,他/她可能會說:”I would like 1 room”或簡單地回答”4″,你應(yīng)該要預(yù)測用戶會說什么,并填寫所有可能的答案,請參考以下我填寫的范例:

begin-order-followup-intent

正如你所看到的,Dialogflow有一個內(nèi)置的數(shù)字entity,不管你輸入一個數(shù)字還是一個單詞,它都能夠處理它并理解它的含義。

接下來,我們要讓機器人回應(yīng)確認(rèn)價格總額,并詢問用戶喜歡什么付款方式。同樣的,于這些是hotel虛擬資料,我們可以在機器人的反應(yīng)中添加虛擬的價格。

begin-order-followup-response

保存這個intent,現(xiàn)在給讀者一個挑戰(zhàn),創(chuàng)建最后一個intent,即詢問用戶使用何種付款方式付款,這應(yīng)該是非常簡單的,因為我們已經(jīng)做了兩次!

所以我們將回到intent的主頁面,然后點擊Create Intent。

注意: 沒有創(chuàng)建另一個follow-up intent,因為當(dāng)機器人第一次觸發(fā)時,用戶不太可能會說出付款方式的名稱,這就是為什么我要創(chuàng)造一個normal intent,就像我們在剛開始時所做的。

將這個intent命名為Payment并添加用戶可能會說的內(nèi)容,這是我們的Payment關(guān)鍵字(entity)使用的地方!

Dialogflow-payment-intent

最后,讓機器人回應(yīng)一些確認(rèn)訊息。以下是一些范例:

  • Done! You have rent the rooms!
  • Success! We received your payment.

就是這樣!請記住保存Payment意圖,Chip現(xiàn)在可以使用了,在我們轉(zhuǎn)到本教程的iOS端之前,你可以在右側(cè)欄位中對其進行測試。

還有幾件事

在開始真正的編程之前,讓我花點時間來解釋Dialogflow控制臺左側(cè)欄位中的其他tabs,在Entities下,有一個名為Training的tab,如果點擊此選項,你將收到所有發(fā)送給agent的回覆訊息以及agent回覆的內(nèi)容,如果你告訴你的agent一些回應(yīng)文本,但它回應(yīng)你不喜歡的輸出,這就非常有用,若你稍后意識到忘記了某個關(guān)鍵字的同義詞,并且用戶正在使用這個關(guān)鍵字,那么也可能會有所幫助,可以去告訴你的代理在這種情況下應(yīng)該做什么。

在Training下方,你可以看到Integrations。在這里,可以管理你的agent去串接不同的服務(wù),例如Google Assistant,Twitter,Slack,Messenger,Cortana,Alexa等等。Integrations之后,還有Analytics,基本上用來顯示建議名稱,之后還有Fulfillment,如果你要調(diào)用一個API并實現(xiàn)一個webhook,這就是你會需要來的地方。

Dialogflow-integration

最后兩個選項功能非常簡單,但很有用。第一個是Prebuilt Agents,在這里,你可以import一個預(yù)先存在的代理框架,有很多例子,如食物傳遞機器人,音樂機器人,甚至(抱歉,但你真的需要知道這個)hotel預(yù)訂機器人! 最后一個選項是Small Talk,如果你將代理設(shè)計為像Siri或Google Assistant這樣的每日伙伴(daily companion),這個選項非常有用,Small Talk允許你添加常見問題的答案,我們都喜歡問我們的機器人,如”你幾歲?”或”你住哪里?”,以及更熱門的問題”你愿意嫁給我嗎?”

現(xiàn)在你已經(jīng)知道Dialogflow是什么,并且對于如何操作有很好的觀念了,現(xiàn)在是時候移動到另一端,開始編寫Swift代碼!

使用API.AI SDK連接到Dialogflow

現(xiàn)在我們移動到本教程Swift的部分,首先[下載初始項目](https://github.com/appcoda/ChatbotHotel/raw/master/ChatbotStarter.zip),我已經(jīng)構(gòu)建了基本的UI并綁定了API.AI SDK。如果你從頭構(gòu)建應(yīng)用程序,則可以使用CocoaPods安裝API.AI SDK(這是用于連接到Dialogflow的SDK),只需在Podfile中添加以下訊息:

pod  'ApiAI'

一旦你unzip初始項目,確保你打開了Chatbot Starter Project.xcworkspace文件。進入Main.storyboard,已經(jīng)有一個UILabel,UIButtonUITextField,它們的outlets也連接到ViewController.swift。

demo-app-main-storyboard

先來看看AppDelegate.swift,我們需要讓APP連接到Dialogflow的servers,在import UIKit的正下方,輸入以下代碼來導(dǎo)入framework:

import  ApiAI

現(xiàn)在,需要使用client access token來初始化我們的配置,請參照下面范例更新didFinishLaunchingWithOptions方法:

func  application(_  application:  UIApplication,  didFinishLaunchingWithOptions launchOptions:  [UIApplicationLaunchOptionsKey:  Any]?)  ->  Bool  {

    let  configuration  =  AIDefaultConfiguration()

    configuration.clientAccessToken  =  "YOUR_CLIENT_ACCESS_TOKEN"

    let  apiai  =  ApiAI.shared()

    apiai?.configuration  =  configuration

    return  true

}

將字符串”YOUR_CLIENT_ACCESS_TOKEN”替換你自己的機器人的client access token,如果你不知道在哪里可以找到,請移動到Dialogflow中的chatbot settings。 在”General”選項下,你應(yīng)該在”API keys欄位下找到client access token。

Dialogflow-api-key

現(xiàn)在,當(dāng)我們的應(yīng)用程式啟動時,它將使用client access token連接到Chip bot。

讓裝置開始說話

前往ViewController.swift,并且在import UIKit之下,import ApiAI和AVFoundation框架:

import  ApiAI

import  AVFoundation

我們需要導(dǎo)入AVFoundation框架,因為我們需要bot與用戶交談,該框架附帶了能夠從文本轉(zhuǎn)為合成語音的“AVSpeechSynthesizer”類別,為了讓裝置與我們的用戶交談,在ViewController類中插入以下幾行代碼:

let  speechSynthesizer  =  AVSpeechSynthesizer()

func  speechAndText(text:  String)  {

    let  speechUtterance  =  AVSpeechUtterance(string:  text)

    speechSynthesizer.speak(speechUtterance)

    UIView.animate(withDuration:  1.0,  delay:  0.0,  options:  .curveEaseInOut,  animations:  {

        self.chipResponse.text  =  text

    },  completion:  nil)

}

讓我告訴你上面的代碼做了哪些事。首先,我們定義一個常數(shù)speechSynthesizer,并初始化一個 AVSpeechSynthesizer的實例。AVSpeechSynthesizer是一個提供自文本轉(zhuǎn)換為語音的object,并允許存取控制正在進行的訪問,然后創(chuàng)建一個新的函數(shù)speechAndText(text: String),根據(jù)用戶輸入的內(nèi)容執(zhí)行更改。

在函數(shù)內(nèi)部,我們創(chuàng)建一個AVSpeechUtterance的實例,最簡單的說,它是一個將被宣讀的文本塊。然后,我們要求裝置讀出這段文字,同時,我們想向用戶展示機器人的response,這就是為什么我們將label的text設(shè)置為機器人的response。

我使用UIView.animate方法為label轉(zhuǎn)換為微妙的動畫,當(dāng)你正在開發(fā)自己的應(yīng)用程式,但不具備創(chuàng)建高品質(zhì)的動畫知識,則這種方法可以實現(xiàn)這一效果。

發(fā)送請求

我們只剩下最后一部分,當(dāng)用戶點擊按鈕時,應(yīng)發(fā)送request給我們的代理,讓我們看看我們該怎么做!在sendMessage操作方法中插入以下幾行代碼:

let  request  =  ApiAI.shared().textRequest()

if  let  text  =  self.messageField.text,  text  !=  ""  {

    request?.query  =  text

}  else  {

    return

}

這段code是相當(dāng)基本的,但是可能部分讀者不太理解這段代碼,還是讓我解釋一下。基本上,我們以用戶提供的query條件來準(zhǔn)備API.AI文本請求,從messageField中檢索文本并執(zhí)行基本驗證,確保文本字段不是空白,一旦我們得到了這段text,就將它丟給request的query屬性。

好的,文本request已經(jīng)準(zhǔn)備好了,下一步是發(fā)起請求并發(fā)送給機器人。當(dāng)然,我們需要處理API.AI代理回應(yīng)的任何內(nèi)容,有兩種可能性:successfailure,如果代理程序返回成功訊息,那么我們希望應(yīng)用程式說出回應(yīng)并將其顯示在螢?zāi)簧?,如果出現(xiàn)失敗訊息,那么應(yīng)用程式只是打印錯誤到控制臺,我們可以通過使用下面的代碼來實現(xiàn):

request?.setMappedCompletionBlockSuccess({  (request,  response)  in

    let  response  =  response as!  AIResponse

    if  let  textResponse  =  response.result.fulfillment.speech  {

        self.speechAndText(text:  textResponse)

    }

},  failure:  {  (request,  error)  in

    print(error!)

})

request執(zhí)行完成后,應(yīng)用程式需要做什么,你可以調(diào)用setMappedCompletionBlockSuccess方法并在閉包中指定動作,一旦請求完成,完成處理程序?qū)⒈徽{(diào)用,并將回應(yīng)作為參數(shù)傳遞,在閉包中,我們調(diào)用前面創(chuàng)建的speechAndText(text: )方法來說出并顯示回應(yīng)內(nèi)容,如果response顯示失敗,我們只需將其打印到logs即可。

剩下最后一件事,我們還沒有發(fā)起對API.AI的request,為此,我們調(diào)用enqueue函數(shù)并放入指定request,這可以通過使用下面代碼來完成:

ApiAI.shared().enqueue(request)

messageField.text  =  ""

我們將請求發(fā)送到API.AI并清除textfield中的文字,你的整個sendMessage方法應(yīng)該如下所示

@IBAction func  sendMessage(_  sender:  Any)  {

    let  request  =  ApiAI.shared().textRequest()

    if  let  text  =  self.messageField.text,  text  !=  ""  {

        request?.query  =  text

    }  else  {

        return

    }

    request?.setMappedCompletionBlockSuccess({  (request,  response)  in

        let  response  =  response as!  AIResponse

        if  let  textResponse  =  response.result.fulfillment.speech  {

            self.speechAndText(text:  textResponse)

        }

    },  failure:  {  (request,  error)  in

        print(error!)

    })

    ApiAI.shared().enqueue(request)

    messageField.text  =  ""

}

是時候了!現(xiàn)在運行應(yīng)用程式(在iPhone X上),一切都應(yīng)該按預(yù)期工作!

chatbot-demo-hotel-booking

下一步是什么

本教程包含很多的資訊,希望對讀者會是非常有益的,那么,接下來你應(yīng)該做什么?我會建議你繼續(xù)擴展這個機器人,甚至創(chuàng)建你自己的機器人,期待你分享如何創(chuàng)建自己的機器人,歡迎發(fā)表在下面的評論!

以供參考,你可以在Github下載完成的項目。

關(guān)于Dialogflow的更多資訊,你你可以參考他們的documentation。

勇敢大膽的嘗試吧!你可以在Dialogflow上創(chuàng)建自己的聊天機器人,并把它放在Google Assistant上。如果你想嘗試一下,請查看這個影片,可以打開Google Assistant并透過”Talk to Max the Programmer”來測試我用Dialogflow製作的聊天機器人!鼓勵大家繼續(xù)研究Dialogflow,因為你可以在Google Assistant,Alexa,Twitter,Cortana,F(xiàn)acebook Messenger,Telegram等平臺部署聊天機器人!

原文Building a Chatbot App for iOS with Dialogflow (API.AI) and Text-to-Speech

簡寶玉寫作群日更打卡第 29 天

?著作權(quán)歸作者所有,轉(zhuǎn)載或內(nèi)容合作請聯(lián)系作者
【社區(qū)內(nèi)容提示】社區(qū)部分內(nèi)容疑似由AI輔助生成,瀏覽時請結(jié)合常識與多方信息審慎甄別。
平臺聲明:文章內(nèi)容(如有圖片或視頻亦包括在內(nèi))由作者上傳并發(fā)布,文章內(nèi)容僅代表作者本人觀點,簡書系信息發(fā)布平臺,僅提供信息存儲服務(wù)。

相關(guān)閱讀更多精彩內(nèi)容

友情鏈接更多精彩內(nèi)容