要は(TL;DR;)
- 2019/3月にWatson SDKが新しくなりました(V4)
- 新しいWatson SDKのnode-js版ではSDK APIの呼び出し時にデフォルトでPromiseを返してくれるようになりました。よって、ご自身のコードでPromiseを扱う必要がなくなりました。
- 具体的にはasync/awaitの枠組みでWatson SDKのAPIを呼び出せば、簡単に逐次的な処理を書けます
はじめに
こんにちわ!石田です。2018/11月に「小ネタ - Watson API / Node.jsでコールバック(やPromise)を意識せずAPIを逐次実行するコードを書く方法」という記事でpromisifyを使って逐次的なコードを書く方法をご紹介したのですが、Watson SDKが新しくなり更に楽に書けるようになりました。
新SDK紹介のブログ記事 IBM Watson SDK Major Releases March 2019によると
The major new feature is support for Promises — every call returns a Promise if no callback is passed in. If your code had to wrap the call in a Promise, you don’t need to anymore! The call returns a Promise by default.
翻訳
主要な新機能としてPromiseがサポートされました。(SDKは)コールバック関数を省略してAPIを呼び出(Call)せば、毎回Promiseを返してくれます。従来、皆さんがプログラムのコードをPrimiseで包み込むように書いていたのなら、もうその必要はありません!APIの呼び出し(Call)はデフォルトでPromiseを返してくれます。
ということです。
よって、以下のようにjavascriptのasync/await構文と組み合わせると、こんな感じで直感的なコードが書けます。
async function hoge(parm) {
...
let response = await assistant.message(assistant_params); // SDKはPromiseを返す
[直下に続けてresponseの処理を書ける]
...
}
aync/awaitについては@soarflatさんの記事 「async/await 入門(JavaScript)」が参考になります。
AssistantとDiscoveryの併用の例
以前の記事では「Assistantに問いかけて確信度が基準値を下回ったらDiscoveryに改めて問いかける」シナリオの簡単なサンプルをお示ししましたが、下記が新しいSDKを使った場合の例です。さらに簡単に1なっているのがお分かりいただけるかと思います。
新SDKでの例
'use strict';
/*
Watson Assistant & Watson Discoveryをpromisifyを使って逐次実行
*/
/* ibmcloud上のnode.jsで実行するならここをコメントアウト
const express = require('express');
const app = express();
const port = process.env.PORT || 8080;
app.get('/', (req, res) => res.send('Hello World!'));
app.listen(port, () => console.log('Example app listening on port %d', port));
*/
// コンスタント
const MIN_CONFIDENCE = 0.6; // 求める確信度。これを下回ったらDiscoveryに聞きなおす
const ASSISTANT_ID = "3462b323-5254-4b1e-895c-XXXXXXXXXXXX";
const DISCOVERY_ENVIRONMENT_ID = "957c7650-c919-435a-XXXXXXXXXXXXXXXXXX";
const DISCOVERY_COLLECTION_ID = "a1d33db4-c6f1-4ee1-XXXXXXXXXXXXXXX";
// Watson Assistant V2
// 別の記事に書きましたが最新のWatson SDKでは認証情報(Credentials)を
// ファイル(ibm-credentials.env)に外出しできますので、その前提で
const AssistantV2 = require('ibm-watson/assistant/v2');
const assistant = new AssistantV2({
version: '2019-02-28',
});
let assistant_params ={
assistant_id: ASSISTANT_ID,
session_id: null,
input: {
'message_type': 'text',
'text': null
}
}
// Watson Discovery
const DiscoveryV1 = require('ibm-watson/discovery/v1');
const discovery = new DiscoveryV1({
version: '2019-03-25'
});
let discovery_params = {
environment_id: DISCOVERY_ENVIRONMENT_ID,
collection_id: DISCOVERY_COLLECTION_ID,
passages: true,
passages_count: 1,
natural_language_query: null
};
/*
Assiatant V2 Session作成
*/
async function createSession(assistantID) {
return await assistant.createSession({
assistant_id: assistantID
});
}
async function chat(session,text) {
console.log('--------------------------------------------------------------------------')
console.log("chat:session[" + JSON.stringify(session) +"] 発話内容:[" + text +"]");
assistant_params.session_id = session["session_id"];
assistant_params.input.text = text;
let response = await assistant.message(assistant_params);
// Assistantの回答の確信度が所定の基準を下回ったらDiscoveryにて再度検索
if (response.output.intents.length > 0){
console.log('Assistantの回答確信度:' + response.output.intents[0].confidence )
if (response.output.intents[0].confidence < MIN_CONFIDENCE ){
console.log('--> Assistantの回答確信度が低いのでDiscoveryを呼び出します')
discovery_params.natural_language_query = text;
response = await discovery.query(discovery_params);
console.log('Discoveryからの回答:',
JSON.stringify(response.passages, null, 2));
} else {
// Assistantの回答確信度が所定の基準以上ならAssistantの回答を提示
console.log('Assistantからの応答:',
JSON.stringify(response.output.generic[0].text, null, 2));
}
}
}
// 発話を順番に逐次的に呼び出す
async function dialog(){
// Watson Assistan V2 = まずSessionを作る
let session = await createSession(ASSISTANT_ID);
// 以降の発話ではセッションを持ちまわる
let res = await chat(session, "");
res = await chat(session, "こんにちわ");
res = await chat(session, "Excelでページレイアウトビューを表示する方法を教えてください");
}
dialog();
実行ログ
--------------------------------------------------------------------------
chat:session[{"session_id":"649ebc10-40cf-4b4b-b547-eb834eefca31"}] 発話内容:[]
--------------------------------------------------------------------------
chat:session[{"session_id":"649ebc10-40cf-4b4b-b547-eb834eefca31"}] 発話内容:[こんにちわ]
Assistantの回答確信度:1
Assistantからの応答: "いらっしゃいませ。ご相談内容をお聞かせくださいますか?"
--------------------------------------------------------------------------
chat:session[{"session_id":"649ebc10-40cf-4b4b-b547-eb834eefca31"}] 発話内容:[Excelでページレイアウトビューを表示する方法を教えて
ください]
Assistantの回答確信度:0.3350169897079468
--> Assistantの回答確信度が低いのでDiscoveryを呼び出します
Discoveryからの回答: [
{
"document_id": "842b0690418b3d6d4c43203d2a511166",
"passage_score": 38.83379280996439,
"passage_text": "</p>\n\n<p><img alt=\"\" src=\"http://pc-support.com/qasearch/1007/doc/answer/image/mso2007/e162-1.gif\"/><br/>\nページレイアウトビューを表示するには、[表示]タブにある[ブックの表示]グループの[ページレイアウトビュー]ボタンをクリックし
ます。</p>\n<div class=\"ca\"></div>\n\n</td>\n</tr>\n</tbody></table>\n </div></div><div class=\"qanda-block-more\">\n <div c
lass=\"qanda",
"start_offset": 4699,
"end_offset": 4995,
"field": "html"
}
]
以上です。
-
今回はWatsonAssistantのV2のAPIを使うようにしたので、Sessionの扱いの部分が前より長くなってますが、そこは本題と関係ないのでお忘れください。:-) ↩