contents
  • チャットボットを作る

    • 関連研究のレビュー

    • 人工知能技術

      • テキスト検索(1)

      • テキスト検索(2) - 形態素解析

      • テキスト検索(3) - TFIDF

      • 自動テキスト生成

        • マルコフ連鎖による文生成

    • ケーススタディ

      • 傾聴ボット(1)

      • 傾聴ボット(2)

      • 傾聴ボット(3)

      • 名付けボット(1)

      • 名付けボット(2)

      • 占いボット

      • 夢語りボット

      • 物語ボット

チャットボットを作る

チャットボットを作る

2022-08-20

Shinichi Kato
加藤真一 Ph. D.
チャットボット研究者

チャットボットは私達が普段使っている日本語や英語を利用してユーザとコミュニケーションするプログラムです。 実際に動いているチャットボットには様々な工夫が盛り込まれているのですが、まずはこれをできるだけ簡単にしてエッセンスの部分だけを取り出してみます(Fig.1)。

Fig. 1. チャットボットの基本的な構造
Fig. 1. チャットボットの基本的な構造

チャットボットにはユーザから様々なメッセージが入力文字列として与えられます。 メッセージはそれぞれ意味を持っており、例えば「おはよう」や「こんにちは」の意味は「挨拶」です。 この意味を解釈できて初めてチャットボットは対応ができるため、チャットボットはチャットボットなりに入力文字列を分類して解釈を試みます。 最先端の人工知能であっても日本語を人と同じレベルで理解することは到底できないので、チャットボットの解釈は精度が低く表面的なものになるという限界があります。 そして人間であれば意味には「挨拶」などの呼び名がつきますが、チャットボットの場合は代わりに数字の羅列などのデータとして表現し、それを内部コードと呼びます。 次に人の場合「挨拶」を受け取ったと理解したら時間や相手、今の気分、シチュエーションなどを考慮して返事を決めます。 この働きを心理学では「心理的過程」などと呼び、チャットボットでも工夫のしどころなのですが、最も単純には内部コードに対して常に決まった出力文字列を生成し、返事とします。

これを整理して、

  1. 入力文字列を何らかの内部コードに読み替えるエンコーダ
  2. 返答を決める内的処理
  3. その内部コードから出力文字列を作り出すデコーダ

という三つの要素に分解します。

エンコーダ

エンコーダは更に、入力文字列を分割する分割部と分割した文字列を何らかのベクトルに変換するベクトル化部に分けられます。 実際によく用いられるエンコーダのひとつに「辞書の中から似ている文を探し、その行番号を内部コードとする」という方法があります。 似ているかどうかを計算する方法は様々で、2000年代にはパターンマッチングがよく使われていました1。その後統計的機械学習が盛んになるとテキストのベクトル化が利用されるようになりました。 まず分割部ではテキストを形態素などにわけ、ベクトル化部では得られた形態素ごとに数を数えたものをベクトルとして表します。 ベクトル化した入力文字列と、同じくベクトル化した辞書の各行がそれぞれどれくらい近いかを0~100%で表します。 下に辞書の例が書かれています。その下にテキストフィールドがありますので、そこに辞書に似た文字列や似ていない文字列を入力してみてください。 右端に計算された類似度が表示されます。

行番号辞書類似度
計算対象の文字列:

内的処理

チャットボットがユーザの入力に答える一問一答形式の動作をするだけでは、生きている感はなかなか得られません。 例えば会話開始時や終了時の挨拶、ユーザから何かを聞いて記憶する、などの動作を盛り込むにはチャットボットが状態を持つ必要があります。 その一つの方法として有限オートマトンやプッシュダウン・オートマトンを用いましょう。 オートマトンでは入力文字列だけでなく、オートマトンの状態を変えるためにintent(意図)と呼ばれるコマンドのようなものを利用することにします。 簡単な例をFig. 2に示します。

Fig. 2 簡単な状態機械
Fig. 2 簡単な状態機械

このオートマトンは▶▶の記号からスタートします。 システムの準備ができた時チャットボットに対して「start」というコマンドを入力するとチャットボットの状態はstartになります。 このときにオートマトンが出力するintentに「挨拶」を設定することができます。start状態ではユーザの入力を受け取るとaccept()状態に進みます。 ユーザ入力はエンコーダによって中間コード化されており、ユーザ入力が辞書のどの行にどれくらい似ているのかというスコア情報が 含まれています。accept()でチャットボットは中間コードのスコアを調べ、しきい値よりもスコアが高ければ*、低ければnot_found状態に進みます。 *状態ではintentを*に、not_found状態ではintentをnot_foundにします。これらふたつの状態は再び入力待ちにもどり、accept()とループを形成します。 accept()でbyeを受け取ったら会話は終了します。システムの終了や別URLへの移動をしても良いでしょう。

このようにチャットボットをシステムとして動作させるための状態機械を組むと動作が整理され、ロバストかつ理解しやすくなります。

デコーダ

デコーダでは状態機械から得られた中間コードをテキストに変換します。 中間コードにintentが指定されている場合はこれを優先してテキストを出力します。 上の例ではintent=startのときに挨拶、intent=not_foundのときに任意の相槌を出力します。 intentが指定されていない場合は「最も似ている行」に対応するテキストを出力します。

チャットボットのシステム

上で説明したチャットボットの中核となる部分だけではアプリとして成り立ちません。そこで一例としてこれを組み込んだチャットアプリを考えます。

チャットボットシステムの基本的な構成

チャットボットシステムを機能別に分解すると、UI(ユーザインタフェース)、チャットシステム会話エンジンのブロックに分けることができます(Fig. 2)。 通常のデータの流れでは、ユーザが発言するとその内容はUIを介してチャットシステムに渡され、会話ログに保存されるとともに会話エンジンにも渡されます。 会話エンジンにはエンコーダデコーダ内的処理が含まれ、エンコード用辞書、デコード用辞書を利用します。 内的処理ではエンコーダから得た内部コードだけでなく、時刻などユーザの発言以外の内部入力も利用して自発的に内部コードを生成する場合があります。 このチャットボットの返事はチャットシステムに渡り、会話ログに追記されるとともにUIに渡され、画面上に描画されます。

Fig. 2. チャットボットの基本的な構成
Fig. 2. チャットボットの基本的な構成

チャットシステムはユーザ認証、ユーザの名前やアバターの管理、ログの管理、チャットルームの管理などの機能を持ちます。 共通のログのようにサーバーでの一元管理が必要な場合は、バックエンドとして何らかのデータベースを利用することになります。

システム構成の例

さらに具体的なアプリケーションを考えてみましょう。 チャットシステムはweb上で複数の人が利用することが前提です。そのためフロントエンド+バックエンドという構成が必要です(Fig. 3)。

Fig. 3. 構成例
Fig. 3. 構成例

この構成のうち、2000年代あたりに主要だったのはFig. 3(a)のCGIです。 CGIではバックエンド側ですべての処理を行い、完成したhtmlをブラウザ側に送ります。ブラウザは基本的に表示するだけです。 この方法ではチャットのように一行づつ表示が増えるものであっても毎回全画面の書き換えをすることになり、今では効率はよくないとみなされています。 一方でプログラムの構造は比較的単純でpython,ruby,perl,Cなど様々な言語で対応できます。

2010年代以降はブラウザ側でも計算処理を行い、チャット中の通信を効率化したWebAppという構成が一般的になりました。 このうちチャットボットが常時稼働している必要がある場合は会話エンジンやチャットシステムをバックエンドに置いた構成にします(Fig.3(b))。 その場合はバックエンドとして常時稼働しているサーバーが必要になります。Amazon Web Services(AWS)やGoogle Cloud Platform(GCP)などのクラウドコンピューティングサービスが適しているでしょう。

ユーザがブラウザを開いている間だけチャットボットが稼働すればよい場合はブラウザ側にすべてのプログラムを置き、バックエンドにはログ機能とホスティングの機能のみを残す方法がとれます(Fig. 3(c))。 Firebaseは後者の構成に適しています。

「チャットボットを作る」

さて、ここまでで初歩的なチャットボットについてアプリケーションとしての構成を大まかに見てきました。 この先本章ではエンコーダーやデコーダーの詳細を始め、周辺技術やチャットボットならではの工夫について論じていこうと思います。 これらの中には機械学習の技術が応用されたものもあり、その意味では現代のチャットボットは人工知能の一種と呼んで良いのかもしれません。

チャットボット以外で機械学習を扱っていると、「思ったように性能が出ません。深層学習を試してみようと思うのですが!」と考える開発者をまま見かけます。 このようなアプローチは多くの場合うまく行きません。 よくある失敗の一つはどんなデータが必要なのか理解されておらず、とりあえず集めたデータでなんとかしようとするというものです。 開発者はみなさん自分が何をしたいのか分かっていると思っています。ところが、詳しく話を整理していくと実は目的が明確でないケースがほとんどです。 目的が不明確であれば、集めたデータもやはり要点を欠くものになるでしょう。テキストデータで例えて言うなら小説10作品からランダムにページを抜き取り、シャッフルして作った一冊の本のようなものです。 いくら性能の良い機械学習を持ってきたところでそこに意味のわかる物語を読み取ることはできません。

チャットボットでもそれは同じです。目的に沿ったデータとそれに適したプログラムの両方が重要です。 そこで本サイトでは「何を作るか」の部分を心をめぐる考察の章で探り、「どう作るか」を本章で検討します。

「マシン」はしょせん機械です。 計算とか判定という重荷を人間の肩からとりさることによって人間の進歩を早める役には立ちますよ。 しかし、人間の脳の仕事は相変わらず残っている。 つまり、分析すべき新しいデータを発見すること、検査する新しい概念を考え出すことだ。
Isac Asimov
「災厄のとき」 - われはロボット(1950)
Copyright(c) 1999-2022, 人工無脳は考える