Watson AssistantとDb2 on Cloudの連携でいろいろと手間取ったので、ログとして実施した手順を記載しておきます。SlackとWatson Assistantの連携は、Watson Assistantの手順に従えば簡単に連携できるようになっています。
###どんな感じの処理なのか?
Slackに入力した値をWatson Assistantで受けて、IBM FunctionsからSQLでDb2 on Cloudの情報を持ってきます。そしてWatson Assistantで回答した内容を再度Db2 on Cloudに書き込むという内容です。
###参考文献
↓Watson AssistantとDb2を外部連係する
https://qiita.com/schiyoda/items/89064693d6353fdc69e1
###前提
- IBM CloudでDb2 on Cloud, Functions, Watson Assistant, ワークスペース(Cloud Foundryベース)を作成する手順は省略
- Slackの対象ワークスペースに管理者権限を持っていること
- IBM Cloudのアカウント(ライトアカウント)を持っていること
- Watson assistantのSkillは作成してあること
- Db2 on Cloudのデータベースとテーブルは作成してあること
Db2 on CloudのTable構成
Db2 on Cloudのデータを取り込んでWatson Assistantに回答し、またその戻り値をDb2 on Cloudに保存するためのテーブルを用意する。
今回は、以下の構成でDb2 on CloudのTableを構成する
Watson Assistantに回答するテーブル
- DB名:MPX09999
- Table名:TABLE01
- Column:name , VARCHAR(255)
- Column:content , VARCHAR(255)
- Column:Link , VARCHAR(255)
- Column:remark , VARCHAR(255)
Watson Assistantにログを保存するテーブル
- DB名:MPX09999
- Table名:LOG
- Column: result1, VARCHAR(255)
- Column: result2, VARCHAR(255)
- Column: result3, VARCHAR(255)
- Column: result4, VARCHAR(255)
- Column: KEYWORD_INPUT, VARCHAR(255)
- Column: KEYWORD_INTENTS, VARCHAR(255)
- Column: KEYWORD_ENTITIES, VARCHAR(255)
- Watson AssistantのCreate assistantを押す
- Nameに任意の名前を入れて、Create assistantを押す
- Add dialog skillを押す
- Slack連携させる対象Skillを押す
- SkillsにDialogが追加されたことを確認する
- Add Integrationを押す
- Slackを押す(知らないうちに連携できるアプリが増えてた。。。今度試してみよう)
(以下、Watson Assisatntに記載されている手順通りに実施すればいいのですが、一応記載しておきます) - Slack API( https://api.slack.com/apps )にアクセスする
- Create New Appを押す
- App Nameに任意の名前を入れて、Development Slack Workspaceに追加するワークスペースを選択して、Create Appを押す
- SlackのBasic InformationのVerification TokenをWatson AssistantのVerification Tokenにコピーする
↓Slackの画面
↓Watsonの画面
- Basic informationでBotsを押す
- Add a Bot Userを押す
- Add a Bot User → Save Changesを押す
→ - OAuth & Permissionsをクリックし、Install App to Workspaceを押す
- SlackワークスペースとBotsの連携確認画面が出るので、Installを押す
- SlackのOAuth Access TokenとBot User OAuth Access TokenをWatson Assistantにコピーする
↓Slackの画面
↓Watsonの画面
- Create request URLを押す
↓URL作成後
- SlackのEvent SubscriptionsをOnにして、Request URLにWatson Assistantで取得したURLを入力する。正常に登録されると、Verifiedという文字が表示される
↓正常にURLが認証される
- Add Bot User Eventでmessage.imを選択する
↓message.imが正常に追加されている
- Watson AssistantのSave Changesを押す
- 正常に登録されると下記画面のようにSlackが追加される
- Slackにアプリを登録して、文字を入力するとWatson Assistantからレスポンスが戻ってくるようになる
Db2 on CloudとFunctionsとWatson Assistantの連携
Cloud Foundryの名前空間およびスペースを利用していますので、ご注意ください。(IAMの名前空間ではない)
- IBM CloudのFunctionsにアクセスして、作成の開始を押す
- アクションの作成を押す
- アクション名に任意の名前を入れて、ランタイムにPython3を選択して作成を押す
- Watson AssistantからFunctionsに連携されてDB2 on CloudにSQL Queryを実行するPythonスクリプト
Watson Assistantのname引数から文字を読み込んできて、それのSelect文の結果をリターンで戻している。
import sys
import ibm_db
def main(dict):
rows = []
conn = ibm_db.connect("DATABASE=BLUDB;HOSTNAME=dashdb-txn-sbox-yp-dal09-04.services.dal.bluemix.net;PORT=50000;PROTOCOL=TCPIP;UID=xxx99999;PWD=xxxxxxxxxxxxxxxxxxx;","","")
sql = 'SELECT "name", "content", "Link", "remark" FROM MPX09999.TABLE01 WHERE upper("name") like upper({})'.format(dict["name"])
stmt = ibm_db.exec_immediate(conn, sql)
row = ibm_db.fetch_tuple(stmt)
while (row):
rows.append(row)
row = ibm_db.fetch_tuple(stmt)
return { 'result': rows }
- DB名:MPX09999
- Table名:TABLE01
- Watson Assistantからの引数:"name"
Db2資格情報となる以下の太文字の箇所は、Db2画面のサービス資格情報のdsn設定からコピーする。
conn = ibm_db.connect("DATABASE=BLUDB;HOSTNAME=dashdb-txn-sbox-yp-dal09-04.services.dal.bluemix.net;PORT=50000;PROTOCOL=TCPIP;UID=xxx99999;PWD=xxxxxxxxxxxxxxxxxxx;","","")
Watson Assistantの設定
Watson Assistantのインスタンスは「Watson AssistantとSlack連携」で作成済
- Dialogを開く。
- Welcomeのようこその中に、Functionsの認証情報をセットする。(Dialogの中は下記画像のように作成していますが、あまり詳しくなくテスト用で作成しているため、適宜修正して使用してください)
{
"context": {
"icf_cred": {
"user": "3fbf5059-f5d0-4a17-baee-79cf0a2a20d5",
"password": "ogp2LnjgCmCAeqjg8IV0CnGi6A1NbHY556ZU53p1x0OAn4UPGvZ8eX0bjfGH8H66"
}
},
"output": {
"generic": [
{
"values": [
{
"text": "検索キーワードを入力してください。"
}
],
"response_type": "text",
"selection_policy": "multiline"
}
]
}
}
Functionsの認証情報として設定しているicf_credのuserとpasswordは、Functionsの名前空間の設定からコピーしてくる。
2. 子ノード(ここでは@Keyword or #Keyword_intent)のJSONを以下のように設定する。
{
"output": {
"generic": []
},
"actions": [
{
"name": "/HogeHoge-039485_hogehogespace/hogehoge-application",
"type": "cloud_function",
"parameters": {
"name": "'%@Keyword.literal%'"
},
"credentials": "$icf_cred",
"result_variable": "context.my_result"
},
{
"name": "/HogeHoge-039485_hogehogespace/hogehoge-application",
"type": "cloud_function",
"parameters": {
"result1": "'<? $my_result.result[0][0] ?>'",
"result2": "'<? $my_result.result[0][1] ?>'",
"result3": "'<? $my_result.result[0][2] ?>'",
"result4": "'<? $my_result.result[0][3] ?>'",
"keyword_input": "'<? input.text ?>'",
"keyword_intents": "'<? intents ?>'",
"keyword_entities": "'<? @Keyword.literal ?> '"
},
"credentials": "$icf_cred",
"result_variable": "context.log_result"
}
]
}
- "name": [Cloud Foundry組織]_[Cloud Foundryスペース]/[Functions名]とする
- "type": cloud_functions固定
- "parameters"の"name": Functionsのname引数へ渡す値。@Keyword.literalはエンティティの値を渡す設定としている。%で囲んでいるのはSQLのQueryで曖昧検索を行うため。'で囲んでいるのは、FunctionsのSQL文で文字列として認識されるようにするため。要は、@Keywordエンティティの文字を曖昧検索するようにしている。
- "credentials": Welcomeで設定したFunctionsの認証情報
- "result1": FunctionsのSQLのSelect文で戻ってくる最初の列。ここではname。$my_result.result[0][0]は、"result_variable": "context.my_result"のmy_resultから持ってきている。以下、result2以降も同様。
- "result2": FunctionsのSQLのSelect文で戻ってくる二番目の列。ここではcontent
- "result3": FunctionsのSQLのSelect文で戻ってくる三番目の列。ここではLink
- "result4": FunctionsのSQLのSelect文で戻ってくる四番目の列。ここではremark
- "keyword_input": Watson Assistantに入力した値。 input.text ?>。'は、FunctionsのSQL文で使用するため追記。
- "keyword_intents": 検索にヒットしたインテント。 intents ?>。'は、FunctionsのSQL文で使用するため追記。
- "keyword_entities": 検索にヒットしたエンティティ。 @Keyword.literal ?>。'は、FunctionsのSQL文で使用するため追記。
{
"output": {
"generic": [
{
"values": [
{
"text": "<? $my_result.result[0][0] ?>"
},
{
"text": "<? $my_result.result[0][1] ?>"
},
{
"text": "<? $my_result.result[0][2] ?>"
},
{
"text": "<? $my_result.result[0][3] ?>"
}
],
"response_type": "text",
"selection_policy": "multiline"
}
]
}
}
- "text": $my_result.result[0][0] ?> Slackへの戻り値の1番目
- "text": $my_result.result[0][1] ?> Slackへの戻り値の2番目
- "text": $my_result.result[0][2] ?> Slackへの戻り値の3番目
- "text": $my_result.result[0][3] ?> Slackへの戻り値の4番目
import sys
import ibm_db
def main(dict):
conn = ibm_db.connect("DATABASE=BLUDB;HOSTNAME=dashdb-txn-sbox-yp-dal09-04.services.dal.bluemix.net;PORT=50000;PROTOCOL=TCPIP;UID=xxx99999;PWD=xxxxxxxxxxxxxxxxxxx;","","")
sql = 'INSERT INTO MPX09999.LOG(keyword_input,keyword_intents,keyword_entities,result1,result2,result3,result4) VALUES ({0},{1},{2},{3},{4},{5},{6})'.format(dict["keyword_input"],dict["keyword_intents"],dict["keyword_entities"],dict["result1"],dict["result2"],dict["result3"],dict["result4"])
stmt = ibm_db.exec_immediate(conn, sql)
return {'message': "keyword_intents"}
##所感
- Watson Assistantは詳しくないのでDialogのロジックとか変なのですいません。回答する内容によって微妙にエラーが出ます。
- たぶんこんな感じでレスが戻ってくるのですが、プログラムの組み方が悪いのか、それともFunctionsのレスポンスが悪いのか、ある程度の時間をおいてSlackから文字列を入力すると、Db2のデータのレスポンスが無くなります。ただ、すぐに2回目を入力するときちんとDb2データのレスポンスがありました。プログラミングが得意ではないので、Functionsの中身を工夫すればいい感じになるのかなー。。