DialogflowのfulfillmentをAzureで実装する
はじめに
AzureFunctionsって料金どれくらいかかるんでしょうか......(恐怖)
すごーく簡単にできるように頑張ります!
AzureFunction 側の設定・作成
Azure FunctionsでPython3とpipを使う - Qiita
が参考になりますので,こちらを見てPython3が使えるようにします.
import platform
print("Python '{0}'".format(platform.python_version()))
[Info] Python '3.6.1'
と出れば準備は完了です.
上部の 関数のURLの取得
からURLをコピーしておきます.
Dialogflow の設定
Fulfillment
左側のタブ Fulfillment
を選択,Webhookを有効にします.
URL
に先ほどコピーしたAzureのURLをペーストし, DOMAINS
を
Enable webhook for all domains
に変更し,SAVEします.
intent
Azure側で処理したいintentの設定から, Enable webhook call for this intent
をオン
これで準備は完了です.プログラムを書いていきます.
Dialogflow -> AzureFunctions
以下のjsonに色々入っているのでいじって情報を得ます.
{
"responseId": "ea3d77e8-ae27-41a4-9e1d-174bd461b68c",
"session": "projects/your-agents-project-id/agent/sessions/88d13aa8-2999-4f71-b233-39cbf3a824a0",
"queryResult": {
"queryText": "user's original query to your agent",
"parameters": {
"param": "param value"
},
"allRequiredParamsPresent": true,
"fulfillmentText": "Text defined in Dialogflow's console for the intent that was matched",
"fulfillmentMessages": [
{
"text": {
"text": [
"Text defined in Dialogflow's console for the intent that was matched"
]
}
}
],
"outputContexts": [
{
"name": "projects/your-agents-project-id/agent/sessions/88d13aa8-2999-4f71-b233-39cbf3a824a0/contexts/generic",
"lifespanCount": 5,
"parameters": {
"param": "param value"
}
}
],
"intent": {
"name": "projects/your-agents-project-id/agent/intents/29bcd7f8-f717-4261-a8fd-2d3e451b8af8",
"displayName": "Matched Intent Name"
},
"intentDetectionConfidence": 1,
"diagnosticInfo": {},
"languageCode": "en"
},
"originalDetectIntentRequest": {}
}
AzureFunctions -> Dialogflow
以下のようにレスポンスを作成し,Dialogflowに返却します.
最低限 fulfillmentText
があればGoogle homeくんが喋ってくれます.
{
"fulfillmentText": "This is a text response",
"fulfillmentMessages": [
{
"card": {
"title": "card title",
"subtitle": "card text",
"imageUri": "https://assistant.google.com/static/images/molecule/Molecule-Formation-stop.png",
"buttons": [
{
"text": "button text",
"postback": "https://assistant.google.com/"
}
]
}
}
],
"source": "example.com",
"payload": {
"google": {
"expectUserResponse": true,
"richResponse": {
"items": [
{
"simpleResponse": {
"textToSpeech": "this is a simple response"
}
}
]
}
},
"facebook": {
"text": "Hello, Facebook!"
},
"slack": {
"text": "This is a text response for Slack."
}
},
"outputContexts": [
{
"name": "projects/${PROJECT_ID}/agent/sessions/${SESSION_ID}/contexts/context name",
"lifespanCount": 5,
"parameters": {
"param": "param value"
}
}
],
"followupEventInput": {
"name": "event name",
"languageCode": "en-US",
"parameters": {
"param": "param value"
}
}
}
intent別に処理を実装する.
Request -> queryResult.intent.displayName にDialogflowが判定したインテント名が格納されているので,これを見て処理を分けていきます.
intent_name = Result["queryResult"]["intent"]["displayName"]
if intent_name == "インテント名":
処理
else:
エラー処理など
サンプル
Recommend
が来た時に現在放送中のラジオからランダムに返却して喋らせるやつ
# -*- coding: utf-8 -*-
import io
import os
import json
import random
import requests
import xml.etree.ElementTree as ET
from html.parser import HTMLParser
# 番組情報[info]がhtmlタグ付きなので削除に使用するクラス
class MyHtmlStripper(HTMLParser):
def __init__(self, s):
super().__init__()
self.sio = io.StringIO()
self.feed(s)
def handle_starttag(self, tag, attrs):
pass
def handle_endtag(self, tag):
pass
def handle_data(self, data):
self.sio.write(data)
@property
def value(self):
return self.sio.getvalue()
# インテントで処理を分ける
def intent_check(Result):
intent_name = Result["intent"]["displayName"]
if intent_name == "Recommend":
return intent_Recommend(Result)
else:
return Build_Response('NO')
# intent[Recommend]の時
def intent_Recommend(Result):
bangumi = Create_RadioData(None)
output = 'ただいま,' + bangumi['station'] + 'で,' + bangumi['title'] + 'が放送中です.'
return Build_Response(output)
# ETそのままのStationを受け取って,使いやすい辞書型に変換する
def Build_bangumiData(bangumi):
station = bangumi.findtext('name')
prog = bangumi[1][1]
title = prog.findtext('title')
info = MyHtmlStripper(prog.findtext('info')).value
return dict(station=station, title=title, info=info)
# APIアクセスとStation選択をする
def Create_RadioData(TEXT=None):
url_radiko = "http://radiko.jp/v3/program/now/JP13.xml"
res = requests.get(url_radiko)
res.encoding = res.apparent_encoding
root = ET.fromstring(res.text)
stations = root[2]
count = -1
for child in stations:
if not TEXT is None:
if TEXT == child.get('id'):
return Build_bangumiData(child)
count += 1
return Build_bangumiData(stations[random.randint(0, count)])
# レスポンス作成
def Build_Response(output):
tmp = {
'fulfillmentText': output
}
return tmp
# webhookの受信と送信.ここが一番長かった(マジ)
data = json.loads(open(os.environ['req'], encoding='utf-8').read())
returnData = intent_check(data["queryResult"])
response = codecs.open(os.environ['res'], 'w')
json.dump(returnData, response)
response.close()
おわり
Python3の日本語関連で詰まりすぎたので,次書く記事はそれにします......
参考文献
ありがとうございます.
Author And Source
この問題について(DialogflowのfulfillmentをAzureで実装する), 我々は、より多くの情報をここで見つけました https://qiita.com/taittide/items/4b649765419d006b58c9著者帰属:元の著者の情報は、元のURLに含まれています。著作権は原作者に属する。
Content is automatically searched and collected through network algorithms . If there is a violation . Please contact us . We will adjust (correct author information ,or delete content ) as soon as possible .