2016年2月1日月曜日

Pepper に Watson を組み込み、コグニティブロボット化

SoftBank(Aldebaran)のPepperの頭脳にIBMのWatsonを導入させ知性を進化をさせる、という記事を見かけたがどのような仕組みで連携させているのだろうか。自前でも2つのサービスを繋げ、Pepperを高度なシナリオや会話ができるコグニティブロボットへと変身させてみる。


◆ 事前に用意するもの
(Choregraphe)
Pepperの実機を用意するのは難しいだろう。しかし、SDKであるChoregraphe(無料)があれば一部制約はあるがバーチャルロボットを画面内で動かしながら開発することができる。


(IBM Bluemix アカウント)
Watsonサービスを使うためにはBluemixでアカウントを取得する必要がある(30日間は無料である)。
複数のWatsonサービスがあるが、今回はその中で次の2つのサービスを利用する。

 - Natural Language Classifier(NLC)
機械学習とニューラルネットワークを使った分類器サービスである。

 - Dialog ※Conversation というサービスに変わっている
ChoregrapheのSDKで使えるALDialog/QiChatではない。Watsonサービス群の一つであるDialogである。
自然言語ソフトウェアエージェント構築のためのXMLを応用したマークアップ言語としてAIML(Artificial Intelligence Markup Language)が知られているが、そのIBM拡張だろう。
質問と回答の問答集をXMLファイルで作成するだけで対話形式のサービスを作成できる。
簡単なチャットボットのアプリケーションなら力技ですぐに作れるだろうか、と思ったがすぐに思い直した。

例えば、
表記揺れ: "引っ越し"、"ひっこし"、"引越"、"引越し"、
同義語:  "引っ越す"、"転居"
綴り誤り: "引き越し"、"引 越"
用言活用(動詞、形容詞など): "遊ぶ"、"遊んで"

さらに異字体や英数漢字が混ざった言葉はどうするか。
正規表現で対応するか?かなりハードルが高いことが想像つくと思う。
(参考までにこういった人工無脳チャットボットの作り方もある)

Dialogにはifなどの条件式を入れた処理フローを挿入できるようであるが、自分は言葉の揺らぎを吸収するデータベースとしての活用に期待が持てた。モデルとコントローラを分けるという意味でもよいだろう。

ただ、触ってみる限り手を叩いて喜ぶほど嬉しい効果はまだ見られないようだ。
しかし、どのbluemixサービスもそうだが、更新が非常に早いため、今後の期待は持てる。

正式なドキュメントがないため日本語文章のカバレッジ範囲の詳細は分からないが、期待する動作が未対応であっても、独自にカスタマイズできる要素を活用することでで意図した動きをさせることは可能そうである。
XML内に記載できるタグとして用意されているentity, conceptあたりを利用するのだろう。

entity
 複数の語を一つの変数で代替
 (例) サイズ: 小さい、中くらい、大きい

concept
 同義語の定義
 (例) 小さい、スモール、ちっちゃい



◆ 実現したいこと
ありとあらゆる、デジタル機器のサービスサポート受付支援ロボットを作成する。

「スマホの電源が入らない」
「マウスが動かない」
「WiFiがつながらない」

などの質問に対話形式で回答を導く。



◆ 設計概要

                        質問
                         ↓ 
                      +-----+
                      | NLC |
                      +-----+
                         ↓
+---------+  +---------+  +---------+  +---------+
| Dialog1 |  | Dialog2 |  | Dialog3 |  | Dialog4 |
+---------+  +---------+  +---------+  +---------+


質問を受けつけたのち、NLCで質問の意図を抽出し、
そのインテントを元に専用のDialogへ流す。

例えば、先の会話例文だと下の動きになる。

      質問文            NLC           Dialog
「電源が入らない」     ⇒ 電源   ⇒ 電源トラブル解決問答集
「マウスが動かない」   ⇒ マウス ⇒ マウストラブル解決問答集
「WiFiがつながらない」 ⇒ WiFi   ⇒ WiFiトラブル解決問答集


最初のポイントはNLCである。
種々の会話に対応するチャットシステムを構築することは難しい。
そこで、特定の会話に特化したDialogを細分化して作っておき、
どのDialogへ受け流すべきかをNLCに判断させるわけである。
この構成にしておくと頭脳のスケールも容易にできる。

そしてDialogだが、先の電源トラブル回答問答集であれば、このようになるだろう。
「電源が壊れたんだけれどどうすりゃいい?」
「それはパソコンですか、モバイル機器ですか」
「パソコンだけど」
「Windows機ですか、Macですか」


基本は以上だが、「バカ、アホ、マヌケ」のようないたずら会話が来ることを想定し、
これらを"悪口"として、NLCに学習させておくといいかもしれない。
悪口を言われたらそれにふさわしい返答をPepperがするときっと驚かれるだろう。


NLCからDialogまでの間にデータベースを挟ませてもいいだろうか。

                      +-----+
                      | NLC |
                      +-----+
                         ↓
                      +-----+
                      | DB  |
                      +-----+

NLCが返してくるインテントと結びつけるDialogをDBで管理するためである。
それ以外の用途として、すべての質問に対話形式で答える必要がない場合もあるだろうと考えたためである。
必ず対話形式に持っていかなくとも、あるインテントに対していきなり回答を出す、またはURL等を示し別サイトへ誘導する方が親切な場合がある。
Dialogへ流さすまでもない一言で終わる回答などを入れておくというわけである。



◆ Watson事前準備
(NLC学習セットの用意)
想定される問と、そこから抽出したいインテントをペアにした学習させるためのcsvファイルを作る。

"スマホの電源が入らない","電源"
"マウスが動かない","マウス"
"WiFiがつながらない","WiFi"
~snip~

トレーニングデータの各テキストは1024文字以下である必要がある。
全レコードは5件以上、15000件以下である必要がある。

NLCを使った別アプリを作成したことがあるのでこちらも参考になるだろう。


(Dialogの作成)
~XMLファイルの用意~
公式サイトにある、pizzaのサンプル用xmlと同じように作れば良い。
また、APIリファレンスはこちら。
https://watson-api-explorer.mybluemix.net/apis/dialog-v1
http://www.ibm.com/smarterplanet/us/en/ibmwatson/developercloud/dialog/api/v1/


~環境変数の設定~
$はプロンプトである。
$ url="https://gateway.watsonplatform.net/dialog/api"
$ username=“*****"
$ password=“*****“
$ file=“power.xml"
$ name=“power"


~ファイルのアップロード~
$ curl -k -u ${username}:${password} \
-X POST \
--form file=@${file} \
--form name=${name} \
"${url}/v1/dialogs"

レスポンスとしてdialog_idが返ってくる。
$ dialog_id=“*****"

~アップロードしたdialogと対応言語の確認~
以下のRESTでもdialog_idが確認できる。
またこのレスポンスとしてに対応している言語パックの情報も返ってくる。
$ curl -k -u ${username}:${password} \
-X GET \
"${url}/v1/dialogs"


以下はChoregrapheのPythonボックスで操作する。
操作手順としてcurlで書いているだけである。
~会話の開始~
$ input=""
$ curl -v \
-X POST \
-d "input=${input}" \
-u ${username}:${password} \
"${url}/v1/dialogs/${dialog_id}/conversation"

レスポンスとして会話の最初の応答(電源が入らないのはどちらの機器ですか、~など)と、client_id、conversation_idが返ってくる。

$ client_id=“*****"
$ conversation_id=“*****"

~会話の継続~
$ input=“パソコンです"
$ curl -v \
-X POST \
-u ${username}:${password} \
-d "conversation_id=${conversation_id}" \
-d "client_id=${client_id}" \
--data-urlencode "input=${input}" \
"${url}/v1/dialogs/${dialog_id}/conversation“

この処理を繰り返し会話をしていけばよい。
セッションの保持期間の明示的な記載はなかった。



◆ プログラム書く前の準備
(pythonモジュールの導入)
・requests
Watsonサービスは全てRESTで操作できる。
ChoregrapheではPythonを利用する。PythonでREST操作するにはrequestsモジュールが便利だろう。

$ sudo easy_install pip
$ sudo pip install requests

$ mkdir -p /Users/my_user/Desktop/pepper/watson/lib
$ cp -r /Library/Python/2.7/site-packages/requests
$ cp -r /Library/Python/2.7/site-packages/requests ./lib/


・sqlite3
先に少し書いたように、DBを挟むならsqliteに限らず準備しておく。
$ mkdir db
$ sqlite3 db/watson.sqlite3
$ create table maps(id integer primary key, key text, value text);
.table
.exit



◆ コード例
Choregraphe上のwatsonを利用したボックス部分だけを載せる。
特定の会話がきたらタブレットの表示を変える、など面白くなく要素はたくさんあるだろう。そこは各自工夫してほしい。

(NLC on Choregraphe)


(Dialog on Choregraphe)



◆ 改善点
よりAI的にするために手を入れる箇所は山ほどあるだろう。
思いついたものをいつか加えるための備忘録として残しておく。

(別技術との連携)
・Word to Vector
  単語の類似性の判断に使われる技術である。これはまさにNLCがやっていそうなことであるが、独自にカスタマイズする場合は一歩下がったレイヤーで触る必要があるだろう。

・Learning to Rank
  回答候補のランキング付けに使えそうである。
  Watsonサービスに、Retrieve&Rankというサービスがあるのでそれを使うと便利かもしれない。

・TF-IDF(Term Frequency Inverse Document Frequency)
  用語頻度と逆文献頻度を導入したい場合にこのアルゴリズムを使うといいだろう。


(フィードバック機能)
間違った応対を繰り返したくはない。
そこで、求められる解と違った場合は、そのQ&Aをバックエンドで記録し、学習データの修正に役立てる必要あるだろう。

満足させられなかった回答をどう拾うかだが、例えば、会話の最後にそれを素直に”はい"、"いいえ”で聞くのが確実だろうか。


(突然の例外)
突然怒り出す人もいるだろう。
「ロボットと会話したくねぇ。さっさと人を出せ」
そんな中でのんきに会話を続けるべきではないだろう。
そこで感情分析も並行して実施し、"怒り"のインテントがつけば、
「お待ちください、代わります」と引き下がるような例外処理を加えるのもいいだろう。


(ドローンとの連携)
これは単純に面白そうなため自分がやりたいだけである。
Pepperが手を挙げるとドローンが現れて、周りをクルクルSPのように巡回し始める。
ジョジョのアニメで言うところのスタンドみたいなものか。
「あいつを攻撃せよ」
と言えばドローンが目の前の誰かめがけて一斉に攻撃を開始する。


ソフトバンクのペッパーが面白い動きを見せたらまた追随してみる。