はじめに
第4回目の本稿は、「docomo Developer support」で公開されているAPIのなかで、「雑談対話API」をつかって、コンピュータと自然な会話を行うためのAndroidアプリ作ります(本稿は、2015年2月24日時点の最新情報に基づいております)。
対象読者
- JavaとEclipseを用いたAndroidアプリの開発で、基本的な知識がある方
- SNSで友達と楽しく会話したいが、筆者のように友達がいない方
雑談対話APIとは?
NTTドコモが提供する雑談対話APIは、ユーザの会話を受け、その入力に対して自然な会話となる返事を提供するAPIです。このAPIを使うと、ユーザのどんな発話に対しても必ず返事を返しますので、コンピュータ相手にたわいもない雑談をすることができます。
雑談対話APIは次の機能を持っています。
対話履歴機能
ユーザとシステムの対話での話題と文脈を認識したうえで、大規模発話データをもとに返答をするので、ユーザの幅広い発言に柔軟に対応できます。
ユーザープロフィール認識機能
ユーザのニックネーム/性別/誕生日などのプロフィール情報に基づいた会話をするため、より人間との対話に近い自然なやりとりができます。
パーソナライズ機能
ContextIDと呼ばれる任意のキーを使って、コンピュータとの会話の流れを記憶し、個人の嗜好に基づいた対話を行うことができます。また、docomo IDと連携することで、ユーザごとの会話の内容をサーバ上に保存し、後日会話を行ったときもスムーズな内容になるよう学習します。このdocomo IDは、NTTドコモと回線契約のないユーザも無料で取得できます。
キャラクタ設定機能
次の3タイプのキャラクタ(デフォルト/関西弁/赤ちゃん)から対話を楽しみたい相手を選ぶことができます。
しりとり機能
ユーザとコンピュータのあいだでしりとりができます。単語の末尾から次の単語を選び返事をするので、しりとりゲームを行うことができます。しりとりではコンピュータが負けることもあります。語尾に「ん」がついたら負けを判定する機能もあります。
SDKの説明とAPI Keyの取得
雑談対話APIのSDKは、公式ページからダウンロードできます。
提供されているファイル(執筆時点では、Dialogue_API_Android_SDK_v2.0.0.zip)には、ライブラリ本体に、サンプルアプリ、利用ガイドなどが含まれています。利用ガイド(雑談対話SDK for Android利用ガイド_v2.0.0.pdf)には、SDKの使い方が詳しく載っていますので、参考にしてください。SDKで提供されるライブラリファイルは、次のとおりです。
ファイル名 | ライブラリ概要 |
---|---|
docomo-common-android-sdk-1.0.2.jar | SDK共通ライブラリ |
docomo-dialogue-android-sdk-2.0.0.jar | 雑談対話ライブラリ |
jackson-annotations-2.2.3.jar | Jacksonライブラリ |
jackson-core-2.2.3.jar | Jacksonライブラリ |
jackson-databind-2.2.3.jar | Jacksonライブラリ |
雑談対話APIでは、ユーザからのリクエストおよびコンピュータからのレスポンスをJSONで返します。そのため、JSONデータを扱うためのオープンソースライブラリである、Jacksonライブラリが含まれています。Androidアプリで、雑談対話APIを利用するときはAndoridプロジェクトのlibsフォルダ内にこの5つのjarファイルをコピーしてください。SDKにはサンプルコードも同梱されています。
雑談対話APIの実行に必要な、API Keyの取得手順については、連載初回の記事を参照してください。
雑談対話APIを使ったコンピュータとのチャットアプリ(1)
この雑談対話APIを使って、ユーザとコンピュータで雑談するアプリを作成します。まず、Eclipseを起動し、新規でAndroidプロジェクトを作成します。プロジェクト名は「BotChat」とし、エントリポイントとなるアクティビティをMainActivity.java、レイアウトファイルをactivity_main.xmlとして作成します。
画面の作成(ListViewとカスタムレイアウト作成)
最初にアプリケーションのUIを作成します。ユーザとコンピュータでの会話を交互に表示するため、ListViewコントロールを使います。ListViewコントロールは、複数のアイテムを1つにまとめてリスト形式で表示することができるビューです。
まず、プロジェクトで作成したactivity_main.xmlのレイアウトに対話内容を表示するためのListViewコントロールと、対話内容を送信するためのEditTextコントロールとButtonコントロールを配置します。
ListViewコントロールは、あらかじめいくつかのレイアウトが用意されていますが、今回は、ユーザとコンピュータの会話を異なるレイアウトで表示したいので、カスタムレイアウトを作成します。
まず、ユーザの会話を表示するためのレイアウトをcomment_list_right.xmlとして作成し、LinearLayoutコントロール内にTextViewコントロールとImageViewコントロールを水平方向に配置します。
同様に、画像とテキストビューを水平配置した、コンピュータからの返答を表示するためのレイアウトをcomment_list_left.xmlとして作成します。コードの詳細については、Androidプロジェクトのres/layout配下のサンプルを確認してください。
会話データの保持クラス作成
次に、カスタムレイアウト内で表示するデータを保持するためクラスであるCommentItem.javaを作成します。CommentItem.javaでは、コメントのテキストデータを保持するString型のフィールドと、表示する画像のリソースIDを保持するint型フィールドと表示するレイアウトのリソースIDを保持するint型フィールドをもたせます。これを他クラスから利用するため、各フィールドのアクセサメソッドを実装します。
Adapterクラスの作成
これで、画面(XMLレイアウト)の作成とデータ保持クラス(CommentItem.java)ができましたので、これらの橋渡しをするためのAdapterクラスを作成します。画面とデータの橋渡しを行うことをデータバインディングと言います。Adapterクラスを使うことで、データソースである雑談対話APIからの返答データと画面のデザインを分離することができます。
Androidでは次のようなAdapterがいくつか用意されています。
名前 | 説明 |
---|---|
ArrayAdapter | 配列やListを表示 |
SimpleAdapter | XMLファイルで定義された複数のビューを表示 |
CursorAdapter | データベースでアクセスするデータを表示 |
BaseAdapter | ArrayAdapter/SimpleAdapter/CursorAdapterの基底クラス |
Adapterは、ListViewコントロールだけでなく、AdapterViewから派生したViewで使えます。今回は、ユーザとコンピュータの会話を異なるレイアウトで交互に表示させたいので、ArrayAdapterを継承した独自のAdapterクラス(CommentAdapter.java)作成します。
public class CommentAdapter extends ArrayAdapter<CommentItem> { ~中略~ @Override public View getView(int pos, View convertView, ViewGroup parent) { CommentItem item = (CommentItem) getItem(pos); ViewHolder holder; // 1. Viewの再利用 if ( convertView == null || convertView.getId() != item.getLayoutType()) { convertView = inflater .inflate(item.getLayoutType(), parent, false); holder = new ViewHolder(convertView); convertView.setTag(holder); } else { // すでにViewがあればそれを使いまわす holder = (ViewHolder) convertView.getTag(); } // ビューにアイコンとコメントをセットする holder.icon.setImageResource(item.getImgtype()); holder.text.setText(item.getText()); return convertView; } // 2.ビューを保持するためのメンバークラス private static class ViewHolder { TextView text; ImageView icon; private ViewHolder(View view) { this.text = (TextView) view.findViewById(R.id.comment); this.icon = (ImageView) view.findViewById(R.id.image); } } }
getViewメソッドは、新しいデータが表示されるタイミングで呼び出されます。ListViewではスクロールして、画面外から新しいデータが表示されるタイミングです。1の箇所でパフォーマンスの観点からgetViewメソッド内でViewを再利用しています。
雑談対話APIのリクエスト
レイアウトおよびデータを保持/更新するクラスが作成できたので、次は、雑談対話APIの呼び出しを行います。
雑談対話APIでは、対話に必要な情報をリクエストパラメータとしてセットしてAPIを呼出し、サーバからのレスポンスに含まれる返答を取得することで雑談対話を行います。
流れは次のようになります。
リクエストパラメータは、DialogueRequestParamクラスを作成し、setUttメソッドの引数に、ユーザから入力された会話をセットし、API呼出しのリクエストを行います。
また、コンピュータと継続して雑談を行うためには、雑談対話APIのリクエストボディに、contextIDを設定します。このcontextIDとは、サーバのレスポンスに含まれる任意の値を、次回の会話のリクエストに設定することで、対話の流れや文脈をAPIエンジンが判断し、より自然な会話になるようにレスポンスを返します。
また、ユーザのプロフィール属性を設定することで、対話をよりユーザの好みに近づけることができます。設定できる主な属性は以下のとおりです。
内容 | 項目 | データ型 | 説明 |
---|---|---|---|
ニックネーム | nickname | string | ユーザのニックネーム |
性別 | sex | string | ユーザの性別を設定(男/女) |
血液型 | bloodtype | string | ユーザの血液型を設定(A/B/AB/O) |
年齢 | age | int | ユーザの年齢を設定 |
星座 | constellations | string | ユーザの星座を設定 |
場所 | place | string | ユーザの地域情報を設定(公式サイトの場所リスト参照) |
モード | mode | string | 対話のモード(対話:dialog/しりとり:srtr) |
キャラクタID | character | int | キャラクタを設定(なし: デフォルト/20: 関西弁/30: 赤ちゃん) |
このほかにも、誕生日やニックネームの読み方などのプロフィール属性も指定できます。詳細な仕様については、公式サイトや仕様書(PDF)を確認してください。
今回のチャットサンプルアプリではPreferenceActivityクラスを使って設定画面から登録しています。PreferenceActivityクラスの詳細については、本記事の内容からはそれますのでサンプルコードを参照してください。
雑談対話APIの呼び出しを行います。画面のコメント送信ボタンをクリックしたときの処理を次のように実装します。
public void onClick(View v) { // 1. 雑談対話パラメータ生成 DialogueRequestParam param = new DialogueRequestParam() { { // 設定値をリクエストパラメータに設定 sp = PreferenceManager .getDefaultSharedPreferences(getApplicationContext()); setUtt(editText.getText().toString()); ~中略~ setContext(contextId); } }; // 2. ユーザの発言を画面のListViewにセット String comment = editText.getText().toString(); CommentItem peopleData = new CommentItem(comment, R.drawable.people, R.layout.comment_list_right); list.add(peopleData); // 3. 雑談対話のタスク生成/実行 AlertDialog.Builder dlg = new AlertDialog.Builder( MainActivity.this); task = new DialogueAsyncTask(dlg); task.execute(param); }
簡単にコードの説明をします。
1. 雑談対話パラメータ生成
リクエストパラメータは、DialogueRequestParamクラスを作成し値をセットします。雑談対話APIで必須項目となるのが、会話内容です。setUttメソッドの引数に、ユーザから入力された会話をセットし、API呼出しのリクエストを行います。このutt属性は必須項目です。その他の項目は任意項目ですが、ContextIDをセットしないと会話が続きません。
2.ユーザの発言を画面のListViewにセット
ユーザの会話の入力値をListViewに表示します。
3. 雑談対話のタスク生成/実行
DialogueAsyncTaskクラスを生成し、雑談対話APIを実行します。executeメソッドに、1で生成したリクエストパラメータを引数として渡します。
雑談対話APIを使ったコンピュータとのチャットアプリ(2)
docomo IDと連携したパーソナライズ機能
ContextIDを使ってユーザとコンピュータ間でより自然な対話になるよう文脈を解析しながらやりとりができますが、このContextIDはアプリケーションを終了すると、サーバ上から削除されてしまいます。雑談対話APIでは、会話の内容をdocomo IDと紐づけてサーバ上に蓄積し、後日改めて対話を行ったときも、前回の会話内容を分析し、より最適な会話を続けるパーソナライズ機能が提供されています。
docomo IDを使ったパーソナライズを行うには、OAuth認証を行って、アクセストークンを取得します。取得したアクセストークンを、雑談対話APIのリクエストパラメータにセットすることで、docomo IDに紐づいた対話内容がサーバ上に蓄積されます。OAuth認証を行うためのSDKは以下のサイトから取得します。
ダウンロードしたファイルに含まれるdocomo-oauth-android-sdk-1.1.1.jarをAndoridプロジェクトのlibsフォルダ内にコピーしてください。
また、このSDKを利用するため、docomo Developer supportのマイページから必要なキー情報を取得します。
取得した情報を、次のとおり認証を行うOAuthActivity.javaにセットします。
/** OAuth 認証用 client id */ private static final String CLIENT_ID = "xxxxx"; /** OAuth 認証用 client secret */ private static final String SECRET_ID = "xxxxx"; /** OAuth 認証用 scope */ private static final String SCOPE = "dialogue"; /** OAuth 認証用 コールバックURL */ private static final String REDIRECT_URI = "xxxxx";
今回のチャットアプリのサンプルでは、取得したアクセストークンをPreferencesに保存しています。OAuthActivityクラスの詳細については、本記事の内容からは逸れますのでサンプルコードおよびSDK付属のドキュメントを参照してください。
雑談対話APIのレスポンス
DialogueAsyncTaskクラスは、雑談対話APIのレスポンスを受け取ります。docomo ID認証によるパーソナライズ機能を使うためには、APIのリクエストに取得したアクセストークンを、リクエストパラメータとともに送信します。パーソナライズ機能を使わない時はAPIの呼び出しはリクエストパラメータのみを送ります。
// 雑談対話要求処理クラスにリクエストデータを渡し、レスポンスデータを取得する Dialogue search = new Dialogue(); // パーソナライズ機能を利用するときは、リクエストにアクセストークンを送る boolean oauthFlg = sp.getBoolean("personalize", false); if ( oauthFlg ) { String accessToken = sp.getString("accessToken", ""); resultData = search.request(reqParam, accessToken); } else { resultData = search.request(reqParam); }
雑談対話APIを呼び出すと、以下のような項目がレスポンスとして返ります。このレスポンスから雑談対話の返答(utt)を取得し、画面のListViewコントロールにデータを表示します。
内容 | 項目 | データ型 | 説明 |
---|---|---|---|
システムの返答 | utt | string | 雑談返答 |
音声合成用読み出力 | yomi | string | 音声合成用出力 |
モード | mode | string | 対話のモード |
対話番号 | da | int | ユーザとシステムの対話に対してサーバが付与した番号 |
コンテキストID | context | string | 自動的にシステムより出力されるID |
これで、チャットサンプルアプリの作成がひととおり終わりました。
動作確認
雑談対話APIのサーバとネットワーク通信を行う必要があるので、最後にAndroidManifest.xmlに以下のパーミッションを設定します。
<uses-permission android:name="android.permission.INTERNET" /> <uses-permission android:name="android.permission.ACCESS_NETWORK_STATE" />
サンプルアプリを実行すると、対話画面が表示されます。筆者が試したところ、対話内容は、会話の文脈をもとに返答されることが多いですが、時々、ニックネームで呼ばれたり、登録した場所の天気やイベント情報などが返答されたりすることもあります。
おわりに
今回は、雑談対話APIのご紹介と、雑談対話APIを使ったチャットアプリを作りました。コンピュータとの対話を行うには、機械学習や形態素解析などの自然言語処理など、しきいの高い技術を勉強する必要がありますが、docomo APIを使うと短時間で手軽にアプリケーションに組み込むことができることがお分かりいただけたでしょうか。
「docomo Developer support」では、本連載で紹介した他にもさまざまに有用なAPIを提供しています。本稿で興味を持った人は、ぜひ、他のAPIも触れてみると良いでしょう。