串接 Dialogflow (4)
因为 Dialogflow 只能处理“文字”,如果遇到“表情贴图”、“地图信息”等非文字消息,就会发生无法处理的状况,这篇教学将会介绍如何透过自建的 Webhook 服务器解析 LINE 消息后,再将文字交由 Dialogflow 处理,让串接 Dialogflow 的 LINE BOT 可以正确处理聊天消息。
快速导览:
本篇文章所需知识
要实作本篇文章的范例,需要先参考下列文章,先建立自己的 LINE BOT 以及打开 Dialogflow 专案,并于 Dialogflow 专案里预先建立好相关的 Intent。
在之前“LINE BOT 串接 Dialogflow”的相关文章里,都是使用 Dialogflow 产生的 Webhook 串接 LINE 机器人,由于这次要改成使用自建的服务器串接 Dialogflow,所以需要额外启用 Google Cloud 的安全性设定,请参考下方文章,进行相关设定:
如果已经有账号或专案,直接点击下方链接开始。
- Google Dialogflow:https://dialogflow.cloud.google.com/
- LINE Developers:https://developers.line.biz/zh-hant/
- LINE 官方账号管理页面:https://tw.linebiz.com/login/
服务器串接 Dialogflow 流程图
架设自己的 Python 服务器后,会透过 Webhook 网址与 LINE BOT 链接,透过 Dialogflow 的 API 和 Dialogflow 连接,可以参考下方的串接流程图,了解相关的流程:
接收表情贴图 ( 本机环境 )
参考“服务器串接 Dialogflow”和“建立并串接 Webhook”两篇文章范例,将 LINE BOT 的 Webhook 程序结合 Dialogflow API,在收到 LINE 消息时,解析消息的类型 type,如果 type 为 text 表示纯文字,就将消息内容提供给 Dialogflow 进行自然语言处理,如果不是纯文字,则直接回传“你传的不是文字呦”的消息 ( 要填入自己 LINE BOT 的 Access Token 以及 Channel Secret )。
注意,因 Google Dialogflow 函数库无法运行在 Python 3.7 的环境,所以如果遇到无法安装的情形,请先将 Python 升级为 3.9 以上版本,同理,因为 Colab 默认 Python 3.7,也就无法正确安装和执行 Google Dialogflow 函数库。
import os
import google.cloud.dialogflow_v2 as dialogflow
from flask import Flask, request
# 載入 json 標準函式庫,處理回傳的資料格式
import json
# 載入 LINE Message API 相關函式庫
from linebot import LineBotApi, WebhookHandler
from linebot.exceptions import InvalidSignatureError
from linebot.models import MessageEvent, TextMessage, TextSendMessage
os.environ["GOOGLE_APPLICATION_CREDENTIALS"] = 'dialogflow_key.json' # 金鑰 json
project_id = 'XXXX' # dialogflow project id
language = 'zh-TW' # 語系
session_id = 'oxxostudio' # 自訂 session id
# dialogflow 處理自然語言
def dialogflowFn(text):
session_client = dialogflow.SessionsClient()
session = session_client.session_path(project_id, session_id)
text_input = dialogflow.types.TextInput(text=text, language_code=language)
query_input = dialogflow.types.QueryInput(text=text_input)
print(query_input)
try:
response = session_client.detect_intent(session=session, query_input=query_input)
print("input:", response.query_result.query_text)
print("intent:", response.query_result.intent.display_name)
print("reply:", response.query_result.fulfillment_text)
return response.query_result.fulfillment_text
except:
return 'error'
app = Flask(__name__)
@app.route("/", methods=['POST'])
def linebot():
body = request.get_data(as_text=True) # 取得收到的訊息內容
try:
json_data = json.loads(body) # json 格式化訊息內容
access_token = 'Access Token'
secret = 'Channel Secret'
line_bot_api = LineBotApi(access_token) # 確認 token 是否正確
handler = WebhookHandler(secret) # 確認 secret 是否正確
signature = request.headers['X-Line-Signature'] # 加入回傳的 headers
handler.handle(body, signature) # 綁定訊息回傳的相關資訊
tk = json_data['events'][0]['replyToken'] # 取得回傳訊息的 Token
type = json_data['events'][0]['message']['type'] # 取得 LINe 收到的訊息類型
if type=='text':
msg = json_data['events'][0]['message']['text'] # 取得 LINE 收到的文字訊息
print(msg) # 印出內容
reply = dialogflowFn(msg) # dialogflow 處理後回傳文字
else:
reply = '你傳的不是文字呦~'
print(reply)
line_bot_api.reply_message(tk,TextSendMessage(reply))# 回傳訊息
except:
print(body) # 如果發生錯誤,印出收到的內容
return 'OK' # 驗證 Webhook 使用,不能省略
if __name__ == "__main__":
app.run()
完成后使用 ngrok ( 参考“本机环境使用 ngrok” ) 产生 Webhook,将网址填入 LINE Developer 里,完成后与 LINE 机器人聊天,机器人就可以识别表情贴图或文字,如果是文字,就会透过 Dialogflow 处理并回传结果。
接收表情贴图 ( Cloud Functions )
参考“串接 Dialogflow ( Cloud Functions )”文章,进入 Cloud Functions 专案后,加入 dialogflow 的 API 金钥 json,并在 requirements.txt 里新增下列三个第三方函数库。
google-cloud-dialogflow
line-bot-sdk
requests
最后输入下方的程序码,完成后点击下方的“部署”,就会将程序部署到 Cloud Functions 里 ( 要填入自己 LINE BOT 的 Access Token 以及 Channel Secret )。
import os
import google.cloud.dialogflow_v2 as dialogflow
import json
from linebot import LineBotApi, WebhookHandler
from linebot.exceptions import InvalidSignatureError
from linebot.models import MessageEvent, TextMessage, TextSendMessage
os.environ["GOOGLE_APPLICATION_CREDENTIALS"] = 'dialogflow_key.json' # 剛剛下載的金鑰 json
project_id = 'XXXXX' # dialogflow 的 project id
language = 'zh-TW' # 語系
session_id = 'oxxostudio' # 自訂義的 session id
def dialogflowFn(text):
session_client = dialogflow.SessionsClient() # 使用 Token 和 dialogflow 建立連線
session = session_client.session_path(project_id, session_id) # 連接對應專案
text_input = dialogflow.types.TextInput(text=text, language_code=language) # 設定語系
query_input = dialogflow.types.QueryInput(text=text_input) # 根據語系取得輸入內容
try:
response = session_client.detect_intent(session=session, query_input=query_input) # 連線 Dialogflow 取得回應資料
print("input:", response.query_result.query_text)
print("intent:", response.query_result.intent.display_name)
print("reply:", response.query_result.fulfillment_text)
return response.query_result.fulfillment_text # 回傳回應的文字
except:
return 'error'
def webhook(request):
body = request.get_data(as_text=True) # 取得收到的訊息內容
try:
json_data = json.loads(body) # json 格式化訊息內容
access_token = 'Access Token'
secret = 'Channel Secret'
line_bot_api = LineBotApi(access_token) # 確認 token 是否正確
handler = WebhookHandler(secret) # 確認 secret 是否正確
signature = request.headers['X-Line-Signature'] # 加入回傳的 headers
handler.handle(body, signature) # 綁定訊息回傳的相關資訊
tk = json_data['events'][0]['replyToken'] # 取得回傳訊息的 Token
type = json_data['events'][0]['message']['type'] # 取得 LINe 收到的訊息類型
if type=='text':
msg = json_data['events'][0]['message']['text'] # 取得 LINE 收到的文字訊息
print(msg) # 印出內容
reply = dialogflowFn(msg)
else:
reply = '你傳的不是文字呦~'
print(reply)
line_bot_api.reply_message(tk,TextSendMessage(reply)) # 回傳訊息
except:
print(body) # 如果發生錯誤,印出收到的內容
return 'OK' # 驗證 Webhook 使用,不能省略
完成后如果成功部署,会出现绿色打勾图示,复制触发条件的 Webhook 网址。
将 Webhook 网址填入 LINE Developer 里,完成后与 LINE 机器人聊天,机器人就可以识别表情贴图或文字,如果是文字,就会透过 Dialogflow 处理并回传结果。
微信扫码关注
抖音扫码关注