跳到主要內容

[簡易教學] 使用Google DialogFlow十分鐘內建立聊天機器人



How to create Google DialogFlow chatbot in10 minutes

前言


隨著Machine Learning的技術越來越成熟, 越來越多的雲端大廠也開始提供自家的AI solution給大眾使用, 如  Google DialogFlow, MS Luis, FB Wit, Amazon Alexa...

DialogFlow 是Google 提供的自然語言處理服務, 能夠將文字轉換成電腦看得懂的結構性資料, 再傳遞給後端介接的Web Service處理, 現在的聊天機器人大多都是使用這種架構

DialogFlow response 的簡單範例,
{

  "queryResult": {

    "queryText": "find some hotel in taipei",

    "parameters": {

      "geo-city": "Taipei"

    },

    "intent": {

      "displayName": "FindHotel"

    },

    "intentDetectionConfidence": 1,

    "languageCode": "en"

  }

}
intentName 就是使用者意圖, chatbot 可以根據意圖去執行對應的商用邏輯
parameter 則是語句當中的關鍵字, chatbot可以用這些關鍵字當成查詢資料庫的條件, 最後再將答案反饋給使用者 

Integration

作為輸入的來源, DialogFlow 目前支援自家的Google Assistant, 還有其他頻道像是 Line, Skype, Facebook ..., 也就是說使用DialogFlow開發的機器人, 不一定只能用在Google Assistant上, 還可以串到Skype, 臉書,,,等等


以下教學, 如何快速建立一個聊天機器人


Agent

首先, 建立一個訂飯店機器人 HotelBot Agent


Intent


開發chatbot時最有可能會遇到問題是, 同一個意思的說話方式可能百百種,

find a hotel for me in Taipei
search a hotel in Taipei
i'm looking for a hotel in Taipei

我們不可能在後端寫一大堆很複雜的Regular Expression 去解析這些句子,  所以我們需要NLP引擎將相似句子對應到同一個類上(也就是意圖)然後再處理

建立一個FindHotel的意圖


將相關的對話都映射到這個意圖上



DialogFlow 背後的NLP引擎, 會將我們剛剛定義的相關語句訓練出一個模型, 當未來有類似的句子時, 就會分析出FindHotel的意圖出來

建立action

透過這個action, 當使用者沒有特別表明目的地的時候呢, action就會被執行起來反問使用者 where are you looking for



建立回復的句子, 回答使用者的問題



基本上, 做到這一步, 機器人已經算是成型了,

可以透過右方的功能進行簡單的測試







Webhook


實務上, 我們開發的機器人不可能完全依賴於DialogFlow上定義的Respone來滿足使用者的需求, 有些商務邏輯必須要在後端動態地處理, 列如處理訂單, 查詢飯店房間等等...

Webhook就是一個能夠讓我們後端程式跟DialogFlow介接的橋樑

基本上需要是一個HTTPS 的REST API


var express = require('express');
var bodyParser = require('body-parser'); //parse POST request for text/json/query string

var app = express();
app.use(
    bodyParser.urlencoded({
        extended: true
    })
)

app.use(
    bodyParser.json()
)

app.get("/",function(req,res){
    res.send({ message: 'welcome' }); 
})

app.post("/webhook", function(req,res){
    console.log(JSON.stringify(req.body, null, 2))
    var intent = req.body.queryResult.intent.displayName;
    var entityCity =  req.body.queryResult.parameters["geo-city"];

    if(intent === 'FindHotel')
    {
        return res.json({
            fulfillmentText: `I found some hotel in ${entityCity}`
        });
    }
    else
    {
        return res.json({
            fulfillmentText: `sorry i am not sure`
        });
    }
})

app.listen(process.env.PORT || 1337, function(){
    console.log('server start ...');
})

部屬

接下來教大家如何將Node Application部屬在Azure App Service上

Step 1. 建立資源群組

az group create --name NodeResourceGroup --location "West US"
Step 2. 建立Service plan

az appservice plan create --name NodeAppPlan --resource-group NodeResourceGroup --sku F1
Step 3. 建立web 應用程式
az webapp create --resource-group NodeResourceGroup --plan nodeappplan --name DialogFlowHotelBot --runtime "NODE|6.9"
Step 4. 建立Deployment credential
az webapp deployment user set --user-name andylai --password 12345
Step 5. 設定部屬方式
az webapp deployment source config-local-git --name DialogFlowHotelBot --resource-group NodeResourceGroup
指令成功後會得到Repository Url
{
 "url": "https://erggw1234@dialog1234azure.net/DialogFlowHotelBot.git"
}

Step 6.
git remote add azure https://erggw1234@dialog1234azure.net/DialogFlowHotelBot.git
Step 7.
git add -A
git commit 
git push azure master

設定Webhook

回到DialogFlow的頁面, 在我們左手邊可以找到Fullfillment

選擇啟動Webhook
Url 的欄位內填入我們web api的位址


(記得在右下方點擊Save保存以上的設定)

有了webhook之後, 我們需要回到剛剛建立的FindHotel Intent的頁面, 選擇Enable webhook call for this intent


大功告成~





留言

  1. 抱歉 請問大大
    在這段「將Node Application部屬在Azure App Service上」的段落裡面 那些指令要在哪邊輸入啊?

    回覆刪除
    回覆
    1. 你可以在azure portal上敲指令,或是在本機端安裝az cli 請參考 https://andy51002000.blogspot.com/2018/04/azure-nodejs.html

      刪除
  2. 你好,我在找一个research assistant帮我用google dialogflow做一个chatbot。请你有兴趣吗?请邮件详谈。谢谢!

    回覆刪除
  3. 你好,请问机器人可以植入到网站,facebook,wechat吗

    回覆刪除

張貼留言

這個網誌中的熱門文章

[解決方法] docker: permission denied

前言 當我們執行docker 指令時若出現以下錯誤訊息 docker: Got permission denied while trying to connect to the Docker daemon socket at unix:///var/run/docker.sock: Post http://%2Fvar%2Frun%2Fdocker.sock/v1.26/containers/create: dial unix /var/run/docker.sock: connect: permission denied. See 'docker run --help'. 表示目前的使用者身分沒有權限去存取docker engine, 因為docker的服務基本上都是以root的身分在執行的, 所以在指令前加sudo就能成功執行指令 但每次實行docker指令(就連docker ps)都還要加sudo實在有點麻煩, 正確的解法是 我們可以把目前使用者加到docker群組裡面, 當docker service 起來時, 會以這個群組的成員來初始化相關服務 sudo groupadd docker sudo usermod -aG docker $USER 需要退出重新登錄後才會生效 Workaround 因為問題是出在權限不足, 如果以上方法都不管用的話, 可以手動修改權限來解決這個問題 sudo chmod 777 /var/run/docker.sock https://docs.docker.com/install/linux/linux-postinstall/

[C#] Visual Studio, 如何在10分鐘內快速更改命名專案名稱

前言: 由於工作需要, 而且懶得再重寫類似的專案, 所以常常將之前寫的專案複製一份加料後, 再重新命名編譯 假設今天我有一個專案HolyUWP, 我想把它重新命名成 BestUWP 時該怎麼做? 以下是幾個簡單的的步驟 使用Visual Studio 2017 備份原來專案 更改Solution名稱 更改Assembly name, Default namespce 更改每支程式碼的Namespace 更改專案資料夾名稱 備份原來專案 由於怕改壞掉, 所以在改之前先備份 更改Solution名稱 更改sln的名稱, 這邊我改成BestUWP.sln 使用Visual Studio打開你的.sln, 右鍵點擊Solution後選擇Rename, 這邊我把它重新命名成BestUWP(跟檔案名稱一致) 必要的話可以順便修改Porject名稱 更改Assembly name, Default namespce 進入 Project > OOXX Properties    修改Assembly Name, Default namesapce 更改每支程式碼的Namespace 基本上隨便挑一支有用到預設Namesapce(HolyUWP)的程式碼來改就好了 重新命名後點擊Apply,  這個動作做完後所有用到舊Namespace的程式碼都會被改成新的 更改專案資料夾名稱 以上動作做完後, 基本上就可以把專案編譯出來測看看了~

[解決方法] mac 作業系統上無法使用 docker

  錯誤訊息 Cannot connect to the Docker daemon at unix:///var/run/docker.sock. Is the docker daemon running? 原因 因為 docker 的設計是走 client-server 的架構,  如果少裝了 server 的部分就會出現以上的錯誤訊息 解決方法 因為 docker daemon 需要使用 linux kernel 上的某些功能, 所以若想要在 mac 的 OS X 上使用 docker 必須額外起一台 linux VM 給 docker daemon 用  Step 1. 安裝 virtual box $ brew install virtualbox --cask   Step 2. 安裝 docker machine $ brew install docker-machine --cask   Step 3. 設定 使用 docker-machine 建立 VM 跑容器 $docker-machine create --driver virtualbox default $docker-machine restart   輸出環境變數 $docker-machine env default 如果執行以上的指令出現錯誤訊息 Error checking TLS connection: ...  可以執行以下指令重新產生憑證 $docker-machine regenerate-certs 最後套用環境變數, 讓 docker 知道要怎麼去跟這台 VM 溝通  $eval $(docker-machine env default)   測試 若做完以上的步驟沒噴錯誤訊息的話, 可以跑個 hello-world 看看 docker daemon 有沒有起來 $docker run hello-world Unable to find image 'hello-world:latest' locally latest: Pulling from library/hello-world 0e03bdcc26d7: Pull complete Digest: sha256:95ddb6c31407e84e91a986b004aee40975cb0