はじめに
reac-native-giftedChatライブラリとQnA Makerサービスを用いてチャットボットアプリを作成します。
ReactNativeのアプリ上にチャットボット機能を実装する事がありましたので、備忘録として記事に纏めます。
react-native-giftedChat
綺麗なチャット画面を作る為のライブラリです。チャットボットに限ったものではない為、いわゆる人間同士のチャット画面として利用できます。今回はUser(利用者)とBot(チャットボット)の2人物のやりとりという形で画面を作成します。
ステートのmessages配列で一連の会話内容を管理します。messageオブジェクトの要素は下記の通りです。
- _id ...messages内で一意の番号
- text ...表示する文字列
- createdAt ...投稿時のタイムスタンプ
- user ...メッセージの投稿者
QnA Maker
Microsoft社が提供しているコグニティブサービスの1つです。
専用ポータルから質問と回答の組み合わせを登録することで、簡単にボットサービスを作成できます。
詳細なデプロイ方法については割愛しますが、公式のクイックスタートがとても分かりやすかったです。
(https://docs.microsoft.com/ja-jp/azure/cognitive-services/QnAMaker/Quickstarts/create-publish-knowledge-base)
デプロイ完了後にテスト用の質問と回答のペアを登録します。
公式が提供しているチャットのデータセットがあるので、こちらをインポートします。(https://github.com/microsoft/botframework-cli/blob/main/packages/qnamaker/docs/chit-chat-dataset.md)
回答ペア登録完了後、Publishタブから公開することで、回答生成のAPIを確認できます。API呼び出しに使う為、{}で囲まれた3つの値を控えておきます。
- https://{QnA-Maker-endpoint}/knowledgebases/{knowledge-base-ID}/generateAnswer
- Authorization: EndpointKey {QnA Makerのエンドポイントキー}
処理の流れ
チャットボット画面の全体の処理の流れは下記の通りです。
- チャット画面からテキストを入力
- 入力内容からmessageオブジェクトを作成(User側)
- ステートのmessages配列に追加
- QnA MakerのAPIを呼び出し
- 返答からmessageオブジェクトを作成(Bot側)
- ステートのmessages配列に追加
ライブラリのインストール
'react-native-gifted-chat'をインストールします。
npm install react-native-gifted-chat --save
また、メッセージの採番用に'react-native-uuid'もインストールします。
npm install react-native-uuid --save
コード
App.jsは下記の通りです。expoで動作する事を確認しています。
import { StyleSheet } from 'react-native';
import { GiftedChat } from 'react-native-gifted-chat';
import React, { useState, useCallback, useEffect } from 'react';
import uuid from 'react-native-uuid';
const CHAT_URL = 'https://{QnA-Maker-endpoint}/knowledgebases/{knowledge-base-ID}/generateAnswer'
const ENDPOINT_KEY = 'EndpointKey {QnA Makerのエンドポイントキー}'
/* 利用者(画面右側) */
const USER = {
_id: 1,
name: 'Me',
}
/* ボット(画面左側) */
const BOT = {
_id: 2,
name: 'Bot',
avatar: 'https://placeimg.com/140/140/any',
}
export default function App() {
/* メッセージを保持するステート */
const [messages, setMessages] = useState([]);
useEffect(() => {
/* 初回画面表示時のメッセージ */
setMessages([
{
_id: uuid.v4(),
text: '質問はありますか?',
createdAt: new Date(),
user: BOT,
},
])
}, [])
/* QnA MakerのgenerateAnswerAPIをコール */
const generateAnswer = async (message) => {
try {
const response = await fetch(CHAT_URL, {
method: 'POST',
headers: {
Authorization: ENDPOINT_KEY,
'Content-Type': 'application/json'
},
body: JSON.stringify({
question: message,
})
})
const json = await response.json();
const responseMessages = {
_id: uuid.v4(),
text: json.answers[0].answer,
createdAt: new Date(),
user: BOT,
}
/* レスポンスをmessagesに追加 */
setMessages(previousMessages => GiftedChat.append(previousMessages, responseMessages))
} catch (error) {
console.error(error);
}
}
/* テキスト送信時の処理 入力内容をmessagesに追加後、QnA MakerのAPIをコールする */
const onSend = useCallback((messages = []) => {
setMessages(previousMessages => GiftedChat.append(previousMessages, messages));
generateAnswer(messages[0].text);
}, [])
return (
<GiftedChat
messages={messages}
onSend={messages => onSend(messages)}
user={USER}
/>
);
}
const styles = StyleSheet.create({
container: {
flex: 1,
backgroundColor: '#fff',
alignItems: 'center',
justifyContent: 'center',
},
});
完成イメージ
まとめ
画面はチャット用のライブラリ、バックエンドはAzureのサービスという簡単な構成ではあったのですが、意外とそれっぽく動かせています。Q&Aの内容はポータルからいつでも更新も可能な上、quickRepliesを用いればマルチターン回答(選択肢つきの回答)も実現できそうなので、拡張性もあるのではと思っています。
参考URL
- react-native-giftedChat (https://github.com/FaridSafi/react-native-gifted-chat)
- QnA Makerポータル (https://www.qnamaker.ai/)
- QnA MakerのGenerateAnswer APIドキュメント (https://docs.microsoft.com/ja-jp/azure/cognitive-services/qnamaker/how-to/metadata-generateanswer-usage)
- Teamsで使えるQ&Aチャットボットを60分で組み立てる(QnA Maker)(https://qiita.com/abemaki29/items/b0933e3ee51cb5220400)