最近久々にWatson Assistantを触っていたら、見た目がだいぶ変わっていました。そして、よく見るとなんとwebhookが使えるようになっていたんです。ん?webhook?今まで結構Assistantを触ってきましたけどそんな機能聞いたことありませんでした。というわけで、今回はWatson AssistantのWebhook機能を触ってみたのでその覚書きです。
Watson Assistantのwebhookとは?
Watson Assistantでの会話フローを作る際に外部アプリケーションとやり取りを行うときの手段の一つとしてこのwebhookを使うようです。webhookを設定したフローを使用することでそれがトリガーになって予め設定したパラメータを外部アプリケーションにPOSTするようになるそうです。これによってAssistantの機能が更に拡張されるということです。他のWatson APIを呼び出すやり方もありますし、自分で作成したFunctionを呼び出す方法もありです。
とりあえず作ってみた
早速Watson Assistantのフローにwebhookを組み込んでみたいと思います。今回は世界各国の都市名を指定したら、その都市の天気を返すシンプルなボットを作ってみます。天気を聞き出す部分は以前紹介したIBM Cloud Fucntionsを使って実装します。
APIの用意
今回は天気を呼び出すために、Open Weather Mapを使います。こちらから会員登録します。登録するとホーム画面にAPI keys
タブがあるので、クリックしてAPIキーを取得します。このAPIは英語のAPIなので日本語で来る都市名を英語に変換する必要があります。そこで、今度はIBM CloudのLanguage Translatorを使って翻訳をしたいと思います。IBM Cloudのダッシュボード画面の「リソースの作成」から「Language Translator」を選択してリソースを作成します。作成出来たら、「Manage」タブをクリックしそこに書かれているAPIキーをコピーします。二つのAPIキーをメモ出来たら、Functionsでアクションを作成していきます。
アクションの作成
続いてIBM Cloud Functionsでアクションを作成していきます。こちらを参考にして、初期設定を完了させましょう。その後、Code
タブをクリックして、はじめから書かれていたコードを消して、以下のコードに書き換えてください。
#
#
# main() will be run when you invoke this action
#
# @param Cloud Functions actions accept a single parameter, which must be a JSON object.
#
# @return The output of this action, which must be a JSON object.
#
#
import sys
import json
import requests
from watson_developer_cloud import LanguageTranslatorV3
def main(dict):
translator_key = dict["TRANSLATOR_API_KEY"]
language_translator = LanguageTranslatorV3(
version='2018-05-01',
iam_apikey=translator_key,
url="https://gateway.watsonplatform.net/language-translator/api"
)
# Assistantから受け取った都市名を変数に格納、テストをするときはサンプルの値を格納
try:
text = dict["call_city"]
except KeyError:
text = dict["CITY"]
# APIでリクエストする用に翻訳
model = "ja-en"
translation = language_translator.translate(
text=text,
model_id=model).get_result()
# OpenWeatherMapを使う
city_name = translation["translations"][0]["translation"]
weather_key = dict["WEATHER_API_KEY"]
api = "http://api.openweathermap.org/data/2.5/weather?units=metric&q={city}&APPID={key}"
url = api.format(city = city_name, key = weather_key)
print(url)
response = requests.get(url)
data = response.json()
print(data["weather"][0]["main"])
# 更に日本語で返答するために翻訳
text = data["weather"][0]["main"]
model = "en-ja"
translation = language_translator.translate(
text=text,
model_id=model).get_result()
return { 'condition': translation["translations"][0]["translation"] }
以前説明しましたが、このコードの中にあるdict
はアクションに定義しているParameters
のことを指します。APIキーなどはParametersに定義しておくと安全なコードになってこのまま他の人にシェアしても安全です。また、LanguageTranslatorはIBM Cloud Functionsに予めWatson SDKをセットアップされているのでそのまま使います。
パラメータを設定
それでは、前述の通りまだAPIキーをParametersに定義していないので、必要なパラメータの設定を行ってきます。アクションの画面からParameters
タブをクリックして、必要な値を定義していきます。Parametersに定義する変数は下記の表にまとめています。Parametersの中のParameter Valueは必ずダブルクオテーションで囲むようにしてください。
Parameter Name | Parameter Value |
---|---|
TRANSLATOR_API_KEY | "YOUR_OPEN_WEATHER_API_KEY" |
WEATHER_API_KEY | "YOUR_LANGUAGE_TRANSLATOR_API_KEY" |
CITY | "動作確認用にPOSTする都市名を日本語で" |
動作確認
それでは、作成したアクションが正しく動作するかを確認するために、もう一度Codeタブに戻って画面右上のInvoke
ボタンをクリックして動作確認します。ぎこちない訳だと思いますが、CITY
で設定した都市の天気が出力されたら正常に動いています
URLの生成
Functionsでの作業の最後はwebhook URLを使えるようにするための準備をします。Endpoints
タブをクリックして、Enable as Web Action
にチェックを入れてセーブしてください。すると、Webアクションを呼び出すことのできるURLが生成されるので、これをコピーします。
Watson Assistantの設定
Assistantに接続するためのアクションが出来たので、今度はボットの本体を作ります。今回は都市名を認識したらアクションを動作するノードを実行するだけなので、エンティティに都市名を並べるだけです。Language Translatorと同様にWatson Assistantのリソースを作成して、Skillsタブ(画面右上にある吹き出しマークではない方のアイコン)をクリックして、Create skill
で新たにスキルを作成します。以下の画面が出てきたら、Dialog skillを選択して、Nextボタンをクリックします。
Skillの設定をします。Nameは何でもOKですが、Languageは日本語で設定します。設定が終わったら、Create dialog skill
をクリックして完了させます。
Skillの編集画面が出たら、Entity
タブを開き、My entities
から都市名のエンティティを作成します。このあとフローを作成する際にエンティティ名はcity
として進めます。
webhookを使うための準備
今度はWatson Assistantとwebhookの接続設定をします。Options
タブを選択して、Webhooksを開きます。そのURLの欄に先程生成したWebhookのURLを記入します。URLを記入する際には、URLの最後に.json
を入れるようにしてください。拡張子を指定することで、Web アクションの機能を利用して、希望する応答のコンテンツ・タイプを指定できます。Web Actionで設定しているので、Headersには特に値を設定する必要はありません。
フローの作成
いよいよフローを作成していきます。とは言っても全体のフローは下の通りにあまり複雑なものではありません。この中の「天気を教えて」ノードが新たに追加するノードになります。Add node
をクリックして設定をしていきます。
設定画面を開くとまだwebhookが有効になっていないので、webhookの実行を選択出来ません、そこで設定画面の右上のCustomize
をクリックして、WebhookをONにします。終わったら、Apply
をクリックします。
これでwebhookを使える状態なので、ノードで実行するアクションを設定します。city
が入力されたら実行するので、ParametersのKEYにはcall_city
と入力し、Valueには入力されたテキストを変数に格納したいので、<? input.text ?>
とタグを埋め込むことで変数に格納します。下のReturn variable
にはwebhookの実行結果を格納する変数名を定義します。この場合はwebhook_result_1
です。
更に下にスクロールすることで、結果に対してどんな返答をするのかを設定します。今回の場合は、webhook_result_1
が取得出来たら、その結果を返答します。今回作成したアクションの返り値は{ 'condition': translation["translations"][0]["translation"] }
となっているのでこのconditionを取り出すために、返答では$webhook_result_1.condition
としています。この時、引用する変数と文字列の間は必ず半角スペースで開けてください。
#完成
これで完成です。あとはAssistantのTry it
をクリックして、テストチャットで都市名を入力してみてください、ちゃんと指定された都市の天気が返答されたら成功です。