ボットにCognitive Servicesを組み込んでみる:特集:Cognitive Servicesを探る(3/4 ページ)
マイクロソフトが提供するCognitive Servicesがどんなものかを、Text Analytics APIを使いながら見てみよう。
Text Analytics APIをボットに組み込んでみる
ここではMicrosoft Bot Frameworkを利用して、ボットを作成し、そこに上で見た言語判定APIに加えてキーフレーズ抽出APIを組み込んでみよう。ボット作成の基本については「Microsoft Bot Frameworkでボットを作成してみよう」を参照されたい。
言語判定を行う
まずは言語判定までを行うコードを示す。
const builder = require('botbuilder');
const restify = require('restify');
const fetch = require('node-fetch');
const requrl = 'https://westus.api.cognitive.microsoft.com/text/analytics/v2.0/';
const key = '<取得したキー>';
var bot = new builder.BotConnectorBot({
appId: 'MyAppId', appSecret: 'MyAppSecret' });
function makeReqData(text, lang) {
return {
documents: [
{
id: '1',
text: text,
language: lang
}
]
}
}
function callTextAnalytics(type, data) {
var reqbody = JSON.stringify(data);
return fetch(requrl + type,
{
method: 'POST',
body: reqbody,
headers: { 'Ocp-Apim-Subscription-Key': key }
}
);
}
bot.add('/', function (session) {
const text = session.message.text;
var data = makeReqData(text);
var lang;
callTextAnalytics('languages', data)
.then(function(res) {
if (res.status != 200) {
return Promise.reject('error occured in detecting language');
}
return res.json();
})
.then(function(json) {
lang = json.documents[0].detectedLanguages[0].name;
session.send('I guess your language: **' + lang + '**.');
})
.catch(function(reason) { session.send(reason); });
});
var server = restify.createServer();
server.post('/api/messages', bot.verifyBotFramework(), bot.listen());
server.listen(process.env.port || 3978, function () {
console.log('%s listening to %s', server.name, server.url);
});
詳細は割愛するが、このボットではボット作成に必要となるbotbuilderパッケージとrestifyパッケージに加えて、node-fetchパッケージを使用している。node-fetchパッケージはXMLHttpRequestをラップしてPromiseオブジェクトを返送するようにしたものだ。
makeReqData関数とcallTextAnalytics関数はそれぞれJSON形式のデータを作成するヘルパー関数と、上で述べたnode-fetchパッケージのfetch関数呼び出しをさらにラップする関数だ(makeReqData関数をよく見ると分かるが、言語判定APIでは不要なlanguageプロパティを設定している。これはキーフレーズ抽出で必要になるプロパティだが、言語判定API呼び出しでこれを指定しても今回は動作に問題がなかったことから手抜きをしている)。
callTextAnalytics関数では、第1パラメーターに受け取ったタイプ(上のコードでは「languages」)を、requrl変数が示すリクエストURLのベース部分に追加した上で、第2パラメーターのJSONデータを文字列化したものを使用して、node-fetchパッケージのfetch関数の呼び出し結果を返送している。このようにすることで、この後で追加するキーフレーズ抽出処理では「callTextAnalytics('keyPhrases', data)」のようにして、異なるAPIを呼び出せるようにしている(言語判定とキーフレーズ抽出の2つのAPIのリクエストURLは末尾が「languages」か「keyPhrases」かが違うだけ)。
function callTextAnalytics(type, data) {
var reqbody = JSON.stringify(data);
return fetch(requrl + type,
{
method: 'POST',
body: reqbody,
headers: { 'Ocp-Apim-Subscription-Key': key }
}
);
}
node-fetchパッケージのfetch関数自体は第1パラメーターにリクエストURLを、第2パラメーターにオプションを受け取る。この場合はPOSTメソッドであることと、makeReqData関数で作成した解析対象データ(を文字列化したもの)、上で取得したAPI呼び出しに必要なキーを指定している。この関数はPromiseオブジェクトを返すので、この後は以下のような形式で処理をチェーンできる。
callTextAnalytics('languages', data)
.then(function(res) {
if (res.status != 200) {
return Promise.reject('error occured in detecting language');
}
return res.json();
})
.then(function(json) {
lang = json.documents[0].detectedLanguages[0].name;
session.send('I guess your language: **' + lang + '**.');
})
.catch(function(reason) { session.send(reason); });
言語判定API呼び出しの結果は最初のthenメソッド呼び出しで、無名関数のresパラメーターに引き渡される。エラーの場合にはPromise.rejectメソッドを呼び出して処理を中断する(これは最後のcatchメソッドで捕捉される)。成功した場合は、レスポンスをパースして得たJSONデータを次のthenメソッドへ引き渡す。先ほど、Webブラウザから確認したように、このオブジェクトのdocuments配列に言語判定の結果が含まれている。そこで、この配列の先頭要素のdetectedLanguagesプロパティ(の先頭要素)から言語名を取得して、それをボットの出力としている。
Bot Framework Emulatorでの実行結果は次のようになる。余談だが、ボットのメッセージはMarkdownをある程度受け入れてくれるので、ここでは「**言語**」として、使用している言語の名前が強調表示されるようにしている。
Copyright© Digital Advantage Corp. All Rights Reserved.