LoginSignup
1
3

More than 3 years have passed since last update.

小ネタ: Watson SDK V4(Node.js)では、もっと楽にコールバック(やPromise)を意識せずAPIを呼び出せるようになりました

Last updated at Posted at 2019-06-13

要は(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紹介のブログ記事 :newspaper: 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構文と組み合わせると、こんな感じで直感的なコードが書けます。

assistantの例
async function hoge(parm) {
    ...
    let response = await assistant.message(assistant_params); // SDKはPromiseを返す
    [直下に続けてresponseの処理を書ける]
    ...
}    

:point_up: aync/awaitについては@soarflatさんの記事:newspaper: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"
  }
]

以上です。


  1. 今回はWatsonAssistantのV2のAPIを使うようにしたので、Sessionの扱いの部分が前より長くなってますが、そこは本題と関係ないのでお忘れください。:-) 

1
3
0

Register as a new user and use Qiita more conveniently

  1. You get articles that match your needs
  2. You can efficiently read back useful information
  3. You can use dark theme
What you can do with signing up
1
3