Watson AssistantからIBM Cloud functionsを使う時の考慮点
初めに
本記事は、開発相談会#4 : IBM CloudFunction/Laravelでのディスカッション内容です。
サンプルアプリケーションについて
こちらで作成した、LaravelとWatson Assistantを連携したアプリケーションを使って検証をしています。
ソースコードはGithubで公開しています。
Watson AssistantからIBM Cloud Functionsを使うには…
使うだけであれば簡単です。
[公式のドキュメント](https://cloud.ibm.com/docs/assistant?topic=assistant-dialog-webhooksの力を借りることで、かなり簡単にWatson AssistantからIBM Cloud Functionsを使うことが出来るようになりました。
実際に使ってみると…
ただ、実際にユーザーアプリケーションからWatson Assistantを呼び出すにあたって、疑問ポイントがありました。
IBM Cloud Functionsのキーを持たせる場所
IBM Cloud Functionsを呼び出す際には、credentials
というパラメータで、user
とpassword
を渡す必要があります。
下記の様に実際に呼び出すNodeでAPIキーを設定して呼び出すこともできますが、公式ドキュメントにも記載がある通り、コンテキストの一部として資格情報を渡すのが正解のようです。
資格情報を保護するために、資格情報は Watson Assistant ワークスペースに保管しないでください。
代わりに、コンテキストの一部としてクライアント・アプリケーションから渡してください。
メッセージ・コンテキストの $private セクション内にコンテキスト変数をネストすると、
この情報が Watson ログに保管されることを防止できます (例: `$private.my_credentials`)。
(contextをNodeで直接設定する方法)←本番でこれはNG
{
"context": {
"private": {
"my_credentials": {
"user": "xxxxxxxx-xxxx-xxxx-xxxx-xxxxxxxxxxxx",
"password": "xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx"
}
}
},
"output": {
"generic": [
{
"values": [
{
"text": "どこの天気を知りたいですか?"
}
],
"response_type": "text",
"selection_policy": "sequential"
}
]
}
}
IBM Cloud Functionsを呼び出すNodeの書き方
{
"output": {
"generic": [
{
"values": [
{
"text": ""
}
],
"response_type": "text",
"selection_policy": "sequential"
}
]
},
"actions": [
{
"name": "/enomotuProject_testSpace/getWeather",
"type": "server",
"parameters": {
"location": "$repeat"
},
"credentials": "$private.my_credentials",
"result_variable": "context.weather"
}
]
}
PHPから呼び出すときのSample
<?php
namespace App\Services;
use GuzzleHttp\Client;
class CallWatsonAssistant{
/**
* Watson Assistantを呼び出すモジュール
*
* @param string $spokenWord ユーザーが入力した文字列
* @param array $context watson assistantのcontextデータ
* @return json Watson AssistantをCallした結果
*/
public function call(string $spokenWord,array $context)
{
$context["private"] = ["my_credentials" =>
[
//ここは環境変数から取得
"user" => config('watson.icf_user'),
"password" => config('watson.icf_password')
]
];
$requestData = json_encode(['input'=>['text'=>$spokenWord],'context'=>$context]);
$headers = ['Content-Type' => 'application/json','Content-Length' => strlen($requestData)];
$curlOpts = [
CURLOPT_USERPWD => config('watson.user_name').':'.config('watson.password'),
CURLOPT_POSTFIELDS => $requestData
];
$path = config('watson.workspace_id') . '/message?version=2018-07-10';
$guzzleClient = new Client(['base_uri'=>'https://gateway-fra.watsonplatform.net/assistant/api/v1/workspaces/']);
return $guzzleClient->request('POST',$path,['headers'=> $headers,'curl'=>$curlOpts])->getBody()->getContents();
}
}
ただ、このままですとREST APIのレスポンスにIBM Cloud Functions
のcontextにAPIキーが埋め込まれてしまう(下図参照)のでWebアプリから使う時には何らかの工夫が必要だと思います。
私は下記の様にprivate
contextをクリアするNodeを持たせて、全てのNodeの最後はここにJump to
するようにしています。
ただ、必ずJumptoを仕込む手間が面倒なのと、このJump to
を忘れた時にAPIキーが外に出る恐れがあるので、より良い方法を模索中です
エラーハンドリングはどうするか?
何も判定していない状態では、ありえない住所を入力した場合に下記のようになってしまします。
ただ、実際のWebアプリケーションに返る値は正常値で、上記の例ですと「ほげほげの天気は」で文章が止まったままとなってしましまいます。
理想は「入力された地域が見つかりません」となることだと思いますが、このエラーハンドリングも掘り下げて考える必要があります。
CASE1 資格情報などが誤っており呼び出しに失敗する。
この場合は、公式ドキュメントにある通り、context
にcloud_functions_call_error
が設定されます。
この時にはエラー内容をNodeに返してしまっても良いかもしれません。
CASE2 呼び出し自体には成功したがICF側でエラーとなった場合
様々な原因が考えられますが、可能な限りでIBM Cloud Function側でエラーの原因やメッセージなどをセットして返せると良いのでは、と思います。
というのも、ICF側で502等のステータスとなった場合には、returnしたcontextにはerror
という値のみが入ってくることになる為です。
ここも気を付ける点になりそうです。
おまけと宣伝
上記とは無関係ですが、勉強会の当日にはIBM様や@tokidaさんからIBM Cloud Functionに関する興味深い話を聞くことが出来ました。
箇条書きではありますが、IBM Cloud Functionsについて下記のメリットについて細かく聞くことが出来ました。
- 応答時間はCloud Foundryとほぼ同じ応答時間です!
- IBM Cloud FunctionsのSLAは99.95%です!
- dockerを使えばどのような言語でもサービスでも実装OK
- 必ずしもマイクロサービス的な使い方をする必要はない…が、1つのFunctionは60sまでしか動かないので注意。
- 最初からLog Analysysサービスと統合されているのですぐにログ管理ができる!
- 今のシステムの隙間を埋めるような使い方が可能。
Apache Open Whiskはログ管理機能がない(IBM Cloud Functionsの優位性はここにある)
IBM Cloudを使ってみたい(もしくは実際に使った)けど、どう使ったらよいか分からない!という方は、是非、相談会に遊びに来てください。
次回の開催情報はこちらです。
Author And Source
この問題について(Watson AssistantからIBM Cloud functionsを使う時の考慮点), 我々は、より多くの情報をここで見つけました https://qiita.com/motuo/items/37fff359d0587e5a446b著者帰属:元の著者の情報は、元の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 .