串接 Dialogflow (3)
本篇教学会延伸“LINE BOT 串接 Dialogflow ( 搭配外部 Webhook )”文章,利用自己的 Webhook 服务器解析 Dialogflow 与 LINE 传递的消息,并将消息透过 Requests 的方式直接传送到 LINE,实作一个可以聊天,并可以查询雷达回波图的简单“气象聊天机器人”。
快速导览:
本篇文章所需知识
要实作本篇文章的范例,需要先参考下列文章,先建立自己的 LINE BOT 以及打开 Dialogflow 专案,并将 Dialogflow、LINE BOT 和自己的 Webhook 服务器进行连动。
如果已经有账号或专案,直接点击下方链接开始。
- Google Dialogflow:https://dialogflow.cloud.google.com/
- LINE Developers:https://developers.line.biz/zh-hant/
- LINE 官方账号管理页面:https://tw.linebiz.com/login/
建立 Dialogflow Intent
进入自己的 Dialogflow 专案 ( 参考“使用 Dialogflow 打造聊天机器人” ),建立一个名为 radar 的 Intent,在 Training Phrases 的区块输入一些与“雷达回波图”有关的词汇。
往下前往 Responses 区块,输入一个回应语句,因为待会会在 Webhook 服务器端直接透过 Request 发送消息,并不会使用到 Dialogflow 的回应,但因为串接需要有消息内容,所以只需要一句即可,输入后往下勾选 nable Webhook call for this intent。
回传雷达回波图 ( 本机环境 )
前往自己本机环境的 Webhook 服务器程序 ( 参考“Dialogflow 串接 Webhook” ),搭配“使用 Requests 传送消息”和“串接雷达回波图”文章范例,判断当收到的 intent 为 radar 时,使用 requests 函数库直接回传消息 ( 参考“安装 requests 模组” )。
由于 LINE Reply Token 只能使用一次,因此使用 request 回传消息后,就无法再透过 Dialogflow 传送消息,因此 return 回 Dialogflow 的消息就不包含 fulfillmentText。
from flask import Flask, request
import requests, json, time
app = Flask(__name__)
@app.route("/")
def home():
return "<h1>hello world</h1>"
@app.route('/webhook', methods=['POST'])
def webhook():
req = request.get_json()
print(req)
reText = req['queryResult']['fulfillmentText'] # 取得 Dialogflow 的回應文字
intent = req['queryResult']['intent']['displayName'] # 取得 intent 分類
replytoken = req['originalDetectIntentRequest']['payload']['data']['replyToken'] # 取得 LINE replyToken
token = '你的 LINE BOT Access Token'
# 雷達回波圖網址,後方加上時間戳記,避免緩存
img = f'https://cwbopendata.s3.ap-northeast-1.amazonaws.com/MSC/O-A0058-003.png?{time.time_ns()}'
# 如果收到的 intent 是 radar
if intent=='radar':
headers = {'Authorization':'Bearer ' + token,'Content-Type':'application/json'}
body = {
'replyToken':replytoken,
'messages':[{
'type': 'image',
'originalContentUrl': img,
'previewImageUrl': img
}]
}
# 使用 requests 方法回傳訊息到 LINE
result = requests.request('POST', 'https://api.line.me/v2/bot/message/reply',headers=headers,data=json.dumps(body).encode('utf-8'))
print(result.text)
# 完成後回傳訊息到 Dialogflow
return {
"source": "webhookdata"
}
# 如果收到的 intent 不是 radar
else:
# 使用 Dialogflow 產生的回應訊息
return {
"fulfillmentText": f'{reText} ( webhook )'
}
app.run()
完成后启动服务器,除了可以在 LINE 里与机器人聊天,也可以询问雷达回波图。
回传雷达回波图 ( Colab )
如果要使用 Colab 产生 Webhook,请先参考“Google Colab 使用 ngrok”文章,在 Colab 里安装 ngrok,接着执行下方的程序码 ( 和本机环境的差别只在于有多使用 flask_ngrok )
from flask import Flask, request
import requests, json, time
from flask_ngrok import run_with_ngrok
app = Flask(__name__)
@app.route("/")
def home():
return "<h1>hello world</h1>"
@app.route('/webhook', methods=['POST'])
def webhook():
req = request.get_json()
print(req)
reText = req['queryResult']['fulfillmentText'] # 取得 Dialogflow 的回應文字
intent = req['queryResult']['intent']['displayName'] # 取得 intent 分類
replytoken = req['originalDetectIntentRequest']['payload']['data']['replyToken'] # 取得 LINE replyToken
token = '你的 Access Token'
# 雷達回波圖網址,後方加上時間戳記,避免緩存
img = f'https://cwbopendata.s3.ap-northeast-1.amazonaws.com/MSC/O-A0058-003.png?{time.time_ns()}'
# 如果收到的 intent 是 radar
if intent=='radar':
headers = {'Authorization':'Bearer ' + token,'Content-Type':'application/json'}
body = {
'replyToken':replytoken,
'messages':[{
'type': 'image',
'originalContentUrl': img,
'previewImageUrl': img
}]
}
# 使用 requests 方法回傳訊息到 LINE
result = requests.request('POST', 'https://api.line.me/v2/bot/message/reply',headers=headers,data=json.dumps(body).encode('utf-8'))
print(result.text)
# 完成後回傳訊息到 Dialogflow
return {
"source": "webhookdata"
}
# 如果收到的 intent 不是 radar
else:
# 使用 Dialogflow 產生的回應訊息
return {
"fulfillmentText": f'{reText} ( webhook )'
}
run_with_ngrok(app) # 啟用 ngrok
app.run()
执行后,复制 ngrok 网址。
将网址贴回 Dialogflow 的 Fulfillment Webhook 网址里 ( 注意,要改成 https )
完成后就可以和 LINE 机器人聊天,询问雷达回波图。
回传雷达回波图 ( Cloud Functions )
透过 Google Cloud Functions 可以建立一个可以 24 小时运作的 Webhook 网址,在程序码编辑的 main.py 输入下方的程序码 ( 参考“使用 Google Cloud Functions” )。
import requests, json, time
def webhook(request):
try:
req = request.get_json()
reText = req['queryResult']['fulfillmentText']
intent = req['queryResult']['intent']['displayName']
replytoken = req['originalDetectIntentRequest']['payload']['data']['replyToken']
token = '你的 LINE BOT Access Token'
img = f'https://cwbopendata.s3.ap-northeast-1.amazonaws.com/MSC/O-A0058-003.png?{time.time_ns()}'
if intent=='radar':
headers = {'Authorization':'Bearer ' + token,'Content-Type':'application/json'}
body = {
'replyToken':replytoken,
'messages':[{
'type': 'image',
'originalContentUrl': img,
'previewImageUrl': img
}]
}
result = requests.request('POST', 'https://api.line.me/v2/bot/message/reply',headers=headers,data=json.dumps(body).encode('utf-8'))
print(result.text)
return {
"source": "webhookdata"
}
else:
return {
"fulfillmentText": f'{reText} ( webhook )'
}
except:
print(request.args)
因为 requests 为第三方函数库,所以需要在 requirements.txt 里添加 requests。
# Function dependencies, for example:
# package>=version
requests
完成后如果成功部署,会出现绿色打勾图示,复制触发条件的 Webhook 网址。
回到 Dialogflow 的 Fulfillment 页签,将网址贴到 Webhook 的 URL 字段。
完成并储存后,与 LINE BOT 聊天时,就会透过 Google Cloud Functions 进行逻辑判断,并回传雷达回波图。
微信扫码关注
抖音扫码关注