こちらの記事(Node.js から LUIS の API を利用する) では、自力で LUIS の REST API を呼び出すための URL を構築していました。
ここでは、botbuilder-ai
パッケージを使用して、もっと手軽に LUIS の機能を呼び出してみます。
botbuilder-ai
が提供している LuisRecognizer
などのクラスは、チャットボットの実装に使用する TurnContext
オブジェクトに依存した設計になっています。
そのため、単純なコンソールアプリケーションから botbuilder-ai
パッケージを使用することは難しく、チャットボットの実装でしか利用できません。LUIS のエンドポイント情報(接続情報)を確認しておく
LUIS API を使用するには、下記のような LUIS アプリの APP ID やエンドポイント情報が必要です。
- APP ID:
c39eb4df-fbcf-224f-b8b7-a0ee445d11b3
- エンドポイント:
https://japaneast.api.cognitive.microsoft.com
- エンドポイントキー(サブスクリプションキー):
c9162c5c0b5edff5270feb6145618acb
APP ID とエンドポイントキーは、LUIS ポータル から対象のアプリケーションを開き、下記のように確認できます。
- APP ID: MANAGEタブ → Application Information
- エンドポイント: MANAGEタブ → Keys and Endpoints → Endpoint カラムの URL の前半部分。
- エンドポイントキー: MANAGEタブ → Keys and Endpoints → Key 1 カラム
LUIS のエンドポイントキーは、Azure ポータル に作成した LUIS リソース の キー の項目に表示されるものと同じです。 念のため、同一のものが表示されているか確認しておくとよいでしょう。
Starter_Key
(管理者用キー)以外のリソースが表示されない場合は、Azure ポータルで作成した LUIS リソース(のキー)と、LUIS ポータルで作成した LUIS アプリの関連付けができていない可能性があります。
先に、LUIS ポータル上の Keys and Endpoints から関連付けを行ってください。botbuilder-ai パッケージのインストール
LuisRecognizer
クラスは、botbuilder-ai
という Node パッケージで提供されています。
botbuilder-ai
パッケージは、npm
コマンドで簡単にインストールすることができます。
$ npm install botbuilder-ai --save
上記のように --save
オプションを付けて実行することで、ついでに package.json
に依存情報を追記しておくことができます。
botbuilder-ai を使用する
LUIS サービスへの接続情報は、最終的には環境変数(Azure 上では App Service で設定できる)や .bot
ファイルで管理することになると思いますが、最初はハードコーディングして動作確認するのがよいでしょう。
まずは、botbuild-ai
モジュールの基本的な使い方を学ぶことにフォーカスしましょう。
ベースとする Bot クラス
ボット本体は、こちらで作成した Bot
クラス (bot.js
) をベースに作成することにします。
もともとのコードは下記のようなオウム返し実装になっており、ここに LUIS API の呼び出しを加えていきます。
const { ActivityTypes } = require('botbuilder');
class Bot {
async onTurn(turnContext) {
const type = turnContext.activity.type;
if (type === ActivityTypes.Message) {
const text = turnContext.activity.text;
await turnContext.sendActivity(`You said "${text}"`);
} else {
await turnContext.sendActivity(`[${type} event detected]`);
}
}
}
exports.Bot = Bot;
このクラスの onTurn
メソッドは、パラメータで TurnContext
オブジェクトを受け取るので、これを LuisRecognizer
クラスに渡すことで LUIS への問い合わせを行うことができます。
LuisRecognizer クラスをインスタンス化する
LUIS の API を利用するには、botbuilder-ai
パッケージに含まれている LuisRecognizer
クラスを使用します。
このクラスのインスタンスを作成するには、下記のような接続情報オブジェクトが必要です。
const luisEndpoint = {
applicationId: 'c39eb4df-fbcf-224f-b8b7-a0ee445d11b3',
endpoint: 'https://japaneast.api.cognitive.microsoft.com',
endpointKey: 'c9162c5c0b5edff5270feb6145618acb'
};
こちらの記事で作成した config.js
モジュールを使用すると、.bot
ファイルに記述した LUIS 接続情報を簡単に取得することができます。
const config = require('./config.js');
const luisEndpoint = config.loadLuisEndpoint('your-luis-app-name');
例えば、Bot
クラスのコンストラクタ内で、下記のように LuisRecognizer
インスタンスを生成すればよいでしょう。
const { ActivityTypes } = require('botbuilder');
const { LuisRecognizer } = require('botbuilder-ai');
class Bot {
/**
* Bot コンストラクタ。
* LUIS の接続情報を使って、LuisRecognizer オブジェクトを初期化します。
*/
constructor(config) {
const luisEndpoint = {
applicationId: 'c39eb4df-fbcf-224f-b8b7-a0ee445d11b3',
endpoint: 'https://japaneast.api.cognitive.microsoft.com',
endpointKey: 'c9162c5c0b5edff5270feb6145618acb'
};
const luisOptions = {};
this.luisRecognizer = new LuisRecognizer(luisEndpoint, luisOptions, true);
}
// ...
}
LuisRecognizer クラスの基本的な使い方
LuisRecognizer#recognize()
メソッドに TurnContext
オブジェクトを渡すと、LUIS による自然言語解析の結果 RecognizerResult を取得することができます。
RecognizerResult
オブジェクトの intents
プロパティを参照すると、LUIS によって認識されたユーザーの意図(インテント)の配列データを取得できます。
[
{ "intent": "SearchMeaning", "score": 0.8440653 },
{ "intent": "BookConference", "score": 0.1042322 },
...
]
一番スコアの高い(それらしい)トップインテントは、LuisRecognizer.topIntent()
ユーティリティ関数を使って取り出すことができます。
まずはトップインテントを取り出し、その意図に応じて各エンティティを取り出すとよいでしょう。
class Bot {
/**
* Every conversation turn calls this method.
* @param {TurnContext} turnContext Contains all the data needed for
* processing the conversation turn.
*/
async onTurn(turnContext) {
if (turnContext.activity.type === ActivityTypes.Message) {
// LUIS による認識結果を取得
const result = await this.luisRecognizer.recognize(turnContext);
const topIntent = LuisRecognizer.topIntent(result);
const topIntentName = topIntent.intent;
const topIntentScore = topIntent.score;
const entities = result.entities;
// どんなインテントだと認識したのか表示(デバッグ用)
await turnContext.sendActivity(`意図: ${JSON.stringify(topIntent)}`);
// インテントの種類に応じてエンティティを取り出す
let response = '';
switch (topIntentName) {
case 'SearchMeaning':
const words = entities['Word'];
if (words) {
response = `${words[0]} の意味は〇〇〇です。`;
} else {
response = '単語の意味を知りたいのですね。';
}
break;
case 'None':
response = '理解できませんでした。';
break;
}
await turnContext.sendActivity(response);
} else {
await turnContext.sendActivity(`[${turnContext.activity.type} event detected]`);
}
}
}
例えば、チャットクライアントから XYZの意味は何ですか?
と入力すると、このボットは下記のように応答します。
意図: {"intent": "SearchMeaning", "score": 0.8440653}
xyz の意味は〇〇〇です。
LUIS サービスが行ってくれるのは、上記のような意図の認識(例では SearchMeaning
)と、単語の抽出(例では xyz
)だけなので、ここから先の「単語の意味を検索する部分」は別の仕組みを使って実装する必要があります。
その仕組みが完成すれば、上記の○○○の部分に実際の意味を表示することができます。
ちなみに、LUIS は意図を認識できないと、デフォルトで None
インテントを返します。
例えば、チャットクライアントから いあ!いあ!くとぅるふ ふたぐん!
と入力すると、ボットは下記のような応答を返すことになります。
意図: {"intent": "None", "score": 0.489056647}
理解できませんでした。
(応用) デフォルトインテントを置き換える
LUIS はインテントを判別できなかった場合、デフォルトインテントとして { intent: "None", score: 0 }
を返します。
LuisRecognizer.topIntent()
メソッドで、RecognizerResult
オブジェクトから
トップインテントを取り出す時に、オプションパラメーターを指定すると、デフォルトのインテントを None
以外の任意のインテントに置き換えることができます。
const result = await this.luisRecognizer.recognize(turnContext);
const topIntent = LuisRecognizer.topIntent(result, 'Greet', 0.75);
関連記事
- LUIS (3) Node.js から LUIS の API を利用する
- チャットボット: LUIS や QnA Maker サービスへの接続情報を .bot ファイルから取得する
- チャットボット: MS Bot Framework の .bot ファイルで接続情報を管理する
- チャットボット: Azure ポータルで生成されるボットのテンプレートコードを解読&リファクタしてみる
- チャットボット (2-2) Web App Bot で生成されたボットのコードを編集する
- チャットボット (2-3) Azure の Web App Bot リソースにボットをデプロイする
- チャットボット (2-1) Azure でボットをホストするための Web App Bot リソースを作成する