Chienomi

ERINA the emotional AIのコンポーネントモデル

情報技術

論文前に公開するERINAの解説・紹介、第二段である。 今回はERINAがどのようなコンポーネント設計から成り立っているかを紹介する。

ERINAは他のAIと比べ、かなり複雑で大規模なプログラムとなっている。 多角的なエミュレーションのために処理は泥臭く複雑だ。 さらに、非常に長期に渡って開発されているために、開発言語がかなり多く、開発時期もバラバラのコンポーネントがごった煮のようになっている。 そもそもERINAの目標は果てしなく遠いものであり、その開発の事前予測は事実上不可能である。このようなプログラムは非常に高い可能性で混沌の中で終焉を迎える。

だが、実際はERINAはそのような失敗に至るプロダクトのような特徴を持ちながら、うまく調和がとれ、良い結果をもたらしている。 古いコンポーネントの改修は不可能に近いほど困難だが、新規開発や古いコンポーネントの置換えはそれほど難しくない。

これは全体を通じる設計の効果によるところが非常に大きい。 個々のコンポーネントは追加することも削除することもできるし、設計に基づく約束事さえ守れば全体の設計は個々のコンポーネントの設計には立ち入らない。 これはいわゆるカプセル化やダックタイピングに通じる考え方で疎結合しているのである。

このような設計には私はふたつの物事からインスピレーションを得た。 ひとつはUnixのツールボックスであり、もうひとつは生物的モデルである。 生物においてそれぞれの要素が適切に自分の役割だけをこなすことにより、結果的に全体が調和して生命を形成する。だが、例え一部の要素が機能しなかったとしてもそれが直ちに生命を損失することにはつながらない。ERINAのような予測も把握もできない、変化しつづけるものにはこのような設計が適しているように思えたのだ。

なお、ERINA/Surtrのコンポーネントの命名だが、北欧神話に関するものと脳神経に関するものを使っている。 だが、北欧神話の用語の使い方としてはやや間違っているし、脳神経に関する用語に関しては多分大いに間違っている。 論文を書く時に問題になりそうでちょっと困っているのだが、そういうふうに名前をつけてしまったてので大目に見ていただければと思う。

さらに内部的に使っている用語としては

  • ヴァルキリー = データを収集、分析、登録するワーカーのこと (実際はプログラム自体よりワーカーを指していうが、プログラム名称にも一応入っている)
  • エインヘリアル = 収集対象になっているデータのこと
  • ヴァルハラ = エインヘリアルを解析したデータベース(somaデータベース)のこと
  • アスガルド = データベースやERINAインスタンスなど、「こっち側」
  • ミッドガルド = ERINAがコミュニケーションを取る相手や、取得可能 or 未取得な情報などの「あっち側」

という扱いである。ゲームとかファンタジー小説とかが好きな人ならなんとなく伝わるかもしれないが、そうでないと全くわからないだろう。 これについては、「短い言葉で端的に概念を表すことができるようになったことは素晴らしいが、よく綴り間違えて痛い目を見る」という感じである。 脳神経に関する言葉を採用したのはその問題を解消するためだったが、結果「概念が若干似ているがために用法として間違っているように感じられるものになってしまい、口外するのが恥ずかしい」という別の問題を発生してしまった。

orbital design

orbital designは処理対象をキューとして生成し、複数のワーカーが順に処理を行っていく独自のモデルデザイン。

ワーカーは基本的にはジョブスケジューラによって生成される。 この起動時にキューも生成される。 このことから場合によっては生成されたワーカーがキューを消化する前に次のキューとワーカーが生成されることになるが、構わず複数サイクルが同時に回るようになっている。

つまり、処理対象はキューが生成されるときに確定されている。 この瞬間から状態が変更されたとしても影響を受けない。 これを実現する手っ取り早い方法は「スナップショットを取って、スナップショット上のデータを対象にする」である。

orbital designによりコンポーネント全体で連続的処理を行う構造になっている。 完成、あるいは完了という概念がなく、それぞれのコンポーネントが自身が担う処理を最新の状態にアップデートしつづける。

これはアジャイル開発やPCDAサイクル(これはちょっと違うか?)と似たような考え方でもある。

ERINAは実装面では決して良いものではないのだが、それでもなんとか動作しているのはこれを含めたデザイン面が大きい。 それぞれのプログラムが独立してサイクルを回せるようになっているため、技術レベルや実装言語などによらずシンプルな約束事だけでコンポーネントを作り、使っていくことができる。 ずっとむかしに作られたPerl製コンポーネントが今も動作するのはこれが理由で、ERINAの実装言語がやたらに多い理由でもある。

基本的にデータの受け渡しが必要なときは標準入出力経由のテキストであると決まっている。 最近新しく登場した部分はYAMLになっているが、XMLだった時期もあるし、もっと独自の形式だったときもある。 ただ、基本的にコンポーネント種別ごとには受け渡しフォーマットも統一されている。 実際には変更されることもあるのだが、そのような場合は一世代ごとに形式を変換するフィルタがあり、これを世代数分経由することで統一を図っているものもある。

orbital designとこの規約どちらが先かというのは難しいところだが、決めたのは標準入出力経由というのが最初で、 コンポーネントを連動させると大変というのはかなり初期からあった問題なのでほとんど最初から独立してそれぞれが自分のことに専念できるように書かれていた。 その発展として最近採用されたのがorbital designというわけであり、初期は繰り返し直列的に処理していくシェルスクリプトだった。 明確にorbital designというコンセプトを決めたのは2015年である。ただ、それらしきことはそれ以前からしていた。

orbital designのメリットを簡単にいうと、AとBというふたつのデータベースがあり、それぞれが解析によって得られた結果を書き込み、その解析はAのためにB、BのためにAが使われるとき、AとB両方のデータベースを連続的に同時に更新したとしても時間と共に精度が向上する、ということにある。 ERINAの場合は話はそこまで単純ではないが、相互に必要とされるデータベースの更新を並列かつ連続的に行うためのデザインとしいうことには変わりない。

orbital designは結構幅広くメリットがあり、例えば計算することそのものは独立しているため入出力の問題さえなんとかなれば非常にスケールしやすく、コア数やマシン数で稼ぎやすい。 特にERINAは通しで処理した場合データ量増加に対して処理量は指数的増加するようなモデルであるため、非同期かつ連続的に更新していけることは必須である。

このデザインは設計・採用するのが容易で、見通しがよくなり、実装も楽で、停止もしやすい、といったメリットがあるので結構有用なのではないかと考えている。

入力

Ninja Valkyrie

Ninja Valkyrieはデータの収集を担う。

プログラム的にはそれぞれのメディアに合わせたものが存在する。 その詳細は秘密であるが、 インターネット(特にウェブ)のみからデータを収集しているわけではない という点は強調しておこう。

基本的にはERINA(というかSurtr)にとっては情報のことをエインヘリアルとして扱うことになっている。 私は北欧神話にそこまで精通しているわけではないので、斥候を担う者にちゃんと名前があったりするのかもしれないが、それは知らないためNinja Valkyrieと名付けられている。 もちろん、斥候だからNinjaだ。

Ninja Valkyrieはあくまでデータをデータとして取ってくるところまでを担う。

Guardian Valkyrie

Guardian Valkyrieはデータのデータベースへの登録を担う。 大部分がファイルシステムベースのデータベースになっているため、Guardian Valkyrieの出番は非常に少ない。

最も大きいのは動画専用のフラグメントオブジェクトファイルシステム(Surtrコンポーネントの一部として専用に開発されているもの)に動画を切り刻んで登録することである。 この処理に関してはそれ以上解析する余地がないため、Knight Valkyrieによる処理が行われない。

ただし、この方法はあまりうまく言っているとはいえない。 動画の解析の難しさもさることながら、やはり本質的にデータが失われることが重大すぎる。 もちろん、この方法は「収集する動画データを動画として保持しておくだけのディスクスペースがない」ことに由来するのであり、あまり実用的な期待は持てない状態だ。

Knight Valkyrieと両立されている関係にあるGurdian Valkyrie最大の仕事はファイルインデックス(取得日時や更新日時の情報を持ったデータベース)の生成であり、これはKnight Valkyrieがキューを生成するために必要になる。

Guardian Valkyrieは基本的にはNinja Valkyrieから呼ばれる。 この中には現在の形式に合わないエインヘリアルを連れてくるNinja Valkyrieを現在のフォーマットに合わせる処理を含んでいる。 このためにGuardian Valkyrieの呼び出しコマンドはラッパーとなっており、呼び出し形式に合わせて別のGuardian Valkyrieに移譲する方式。 もし現在望まれる形でデータを保存するNinja Valkyrieから呼び出された場合はGuardian Valkyrieはなにもしない。

Knight Valkyrie

エインヘリアルたるデータをヴァルハラたるデータベースに登録するのがKnight Valkyrieである。

このデータベースに登録されるのはインテリジェンスが直接扱うことのできる細分化した情報の断片である(somaと呼んでいる)。 Guardian Valkyrieが取得したデータ全体をデータベースに登録するのに対し、Knight Valkyrieはデータの解釈や分解などを行う。

Knight Valkyrieもひとつのデータフォーマットに対して一種類だけしか存在しないわけではない。 特に会話文テキストを解釈するKnight Valkyrieに至っては30種類以上に及ぶプログラムが存在する (そしてそれはそれぞれ異なる言語で書かれていたりもする)。

ひとつのデータに対してそれぞれのvalkyrieがそれぞれの解釈によってデータを登録することはERINAのデザインにとって重要なものになっている。 これは特定の考え方や特定の視点、特に常識や前提にとらわれることなく発見を続けていくためには例え思い違いで役に立たないようなものであってもそれぞれのルールで解釈・解析することが必要なのだ。

Knight Valkyrieはさらに分解した情報を元に「盤面」を作るという処理も行う。 実際にsomaとして扱われるのはこちらのほうで、分解した内容は盤面に対してタグ付けしたような状態になる。 分解した内容は検索に使われるほか、次段のシナプス形成においても必要となる。

これがKnight Valkyrie単体で担っていることに違和感があるかもしれないが、実際はこのあたりを分けて話すのは難しい。 なぜならば、盤面を構成するのは「分解した要素の構成」だからであり、要素の集合は盤面のIDとして機能する。 おおよそこのデータベースはキーバリューストアのようになっているのだが、要素の集合はキーとしても値としても動作する。

そして盤面側は複数のデータベースがレイヤー状になっており、このほかに要素に基づく統計的データベースが複数存在する。

Knight Valkyrieの動作は最も実装が難しいもので、「思考とはなにか」「情報は何を持っているか」ということを決定づけることになる。

Connexon

Connexonは盤面(soma)に対して接続可能な盤面を登録する。 ちなみに、接続可能な盤面を表すキー名はsynapseになっている。

この処理自体は単純なものであり、入力過程にあるものでは唯一稼働している実装が1種類しかない。 ただし処理が単純だからといって実装が簡単なわけではない。Connexonが簡単なのは、「どのような要素に分解し、この要素はどのような意味を持ちうるか」という設計をKnight Valkyrieの時点で行う必要があるために、Connexonによって新規に設計する必要がないということに過ぎない。

また、処理は単純だが、接続可能なsomaを探索するために全somaをあたる必要があり、しかもsynapseが更新されると接続可能なsomaも更新されることになるため非常に長いループを回すタイプである。ERINAコンポーネントの中で最も長いCPU時間を求めるのがConnexonである。

そして処理量の関係上、現状Connexonは全てのsomaを巡回しない。Connexonのキュージェネレータが「Connexonが当該somaをいつ巡回したか」「somaがいつどれくらい探索されたか」という情報を元にキューを生成する。だからsynapseが長く更新されていないsoma、及び頻繁に参照されているsomaが優先順位高くキューに入ることになり、生成後一定時間経つとキューの状態に関係なくConnexonキューは終端を返す。

なお、私は解剖学・生物学の知識もそんなにないので、名前に対するツッコミはお控えいただきたい。 ただし、新しいネーミングのご提案はいつでも大歓迎である。

Neuron

NeuronはKnight Valkyrie及びConnexonとは別のフローでエインヘリアルを接待する。

これは主に語彙や知識に関する情報収集と接続を行うものであり、一般的なビッグデータ処理に近いものになっている。 Neuronによって処理されるデータは盤面を作られることはないのだが、そもそもKnight Valkyrieがこのデータベースを使う。

Neuronが作るデータベースは解析だけでなく生成側でも必要となる。

対話

Erina receptor

Erina receptorは入力された情報から盤面の探索を行うものである。

Erina receptorはまずKnight Valkyrieを使って受け取った要素を解析する。 そして、「与えられた要素」と「コンテキスト上キープしている要素」から得られる要素を、Erina context finderによって絞り込み、これによって残る要素を元にコンテキスト上のcurrent盤面のsynapseを探索する。

Erina receptorは探索されたsomaのIDとスコアを返す。 なお、somaは「発言」ではなく「状況における言動の要素」の盤面であるため、「無視する」といった行動もありえる。

Erina context finder

状況を推測するための調整用フィルタであり、アルゴリズムやデータベースを含めた完全手入力である。

これは、「前回の会話からこのメディアでこれくらいの時間が空いたら前回のコンテキストとの関連性を下げる」というような処理を行う。

これが調整用であるのは、そもそもKnight Valkyrie側に「応答時間の変動」のような要素を理解する処理が入っているからだ。 だから学習的にしきれない部分をフォローするためにあり、基本的にはこのプロセスのみが担っているものはないはずである。

だが、とても重要で、このフィルタがないといまいち自然な応答にならない。 「その話今する!?」みたいな不自然な感じが残ってしまうのだ。

Erina emotion engine (effector)

Erina emotion engineはかなり複雑な処理をするため複数コンポーネントに分かれているが、それらは直列に処理するためここでまとめて紹介する。 なお、Erina emotion engineはERINA固有のものであり、Surtrにはない。ERINAが単独で存在する意味は元はSurtr emotion engineと呼ばれていたこのコンポーネント群にある。

Erina emotion engineはneuronデータベースをかなり細かく読み込む。 これはキャラクターづくりにも関係している。

単純にErina receptorの結果から「それらしい振舞い」を導き出すことはできる。 だが、実際にはErinaは常に最善手を指すわけではない。 もし常にreceptorが最も高いスコアをつけたものを選ぶと「振舞いに全くゆらぎがない」「人物に一貫性がない」といった問題が出る。 これは非常に重要なポイントで、このような特徴に対しては人間はかなり敏感に反応し、不自然さを感じてしまう。

そのため、Erina emotion engineはまず「キャラクター性」というものを持つ。 これを実現するためにErinaインスタンスは自身に特化したキャラクターデータベースを使用する。 ERINAにとっての「学習」はこのキャラクターデータベースの更新にあると言っていい。

Erina emotion engineはまずキャラクターデータベースに基づいてreceptorが返したスコアを書き換える。 この機能のためにreceptorは複雑なスコアのつけ方をしている。

この処理にはコンテキストも使われる。 生活状態や感情状態という要素があり、これはシミュレーターのように計算・動作する。この部分はおおよそ(硬派な)シミュレーションゲームのような処理である。 このコンテキスト処理が「ゆらぎ」を担う。この処理のときに行動条件も出す。これは「返信をわざと遅らせる」といった処理のために使われる。

コンテキストの生成・更新もErina emotion engineの機能の一部であり、この情報はインスタンスデータベースに書く。

キャラクター性による再評価と出力の編成は近いものがある。 キャラクター性を評価した段階で意味的にはこのような振舞いをする、ということがわかっている。 「どのような心理状態か」「どのような行動か」ということは新たに定義しなくても要素の組み合わせで確定できる。 なにを発言するかという点で主旨はなにか、というのはsoma側にある。そのため「応答すべき内容が表現段階で意味的に間違う」ということはまずない。

その状況における意味的な言葉というのはKnight Valkyrieが集めている。 これは主には同じ要素構成になる言葉(綺麗な文章であるならば「文」)の共通要素を抜き出す方式である。

そしてneuronデータベースには発言の編成がある。 そもそもKnight ValkyrieもNeuronも共に「誰が誰に対して発言したか」という情報を取り扱うため、模倣するのは比較的簡単。 特定の組み合わせから見た一連の発言だけでは非常に表現に乏しくなってしまうため、なるべく類似の発言傾向をまとめるようになっている。

例え意味や心理を完全に模倣できていなくても、ある一定の傾向を持つ発言を元に、意味的にどのような発言をすればいいかということを外さないように組み上げるため「ちゃんと意味が通っていて会話が成り立つ」感覚が補助される。 実のところそもそもERINAは人間の身勝手な補完と錯覚を突くように作られているため、発言を精査すると意外とあやふやである。

別の角度から見ると、他が分析・理解・解明を追求しているのに対し、この出力部分だけ結果が出ることを重視した全く異なるアプローチになっている。 そうなっている理由は、「この部分だけがERINA固有のコンポーネントだから」である。データベースの利用方法として検索や検証といった機能はSurtr側にあり、ERINAは基本的にコミュニケーションの様態を模倣する方向であり、Surtrのコンポーネントとはアプローチが異なる。 現在の試行の範囲では理解など忠実な再現において自然なコミュニケーションを実現することはかなり遠そうだが、ERINAがそれを目指すことはない。 なぜならばERINAの意図、そして命名理由からも外れてしまうものであり、もしそれを目指すとしたらERINAとは別のAIとして開発することになるだろう。

アルゴリズムに踏み込んだ話はおいておくとして(なんとなく筆がそっちに走ってしまったが)、Erina emotion engineの手順としては

  1. キャラクターとコンテキストをロード
  2. コンテキストの解析と更新
  3. receptorの応答の受け取り
  4. キャラクターに基づいて結果を編集
  5. 応答に使用するsomaを決定
  6. somaとキャラクターに基づいてneuronデータベースを検索し応答語句を編成
  7. コンテキストを更新
  8. 結果を出力

となる。

コンテキストの更新をreceptorの応答を受け取るより前にも行っているのは、receptorが探索にコンテキストを使うため。

Erina controller

receptor, emotion engine, media frontendとのやりとりを仲介するコンポーネント。 一応、これがERINAのインスタンスプロセスになる。

なんのデータベースをロードするかはこのcontroller起動時点で決定する。 というよりも、インスタンス生成時に決定する必要があり、変更は難しい。変更してしまうと初期化されてしまう。

コンポーネントとのやりとり以外ではコンテキストデータベースとキャラクターデータベースの初期化処理を受け持っている。

Erina media frontend

入出力処理用レイヤー。

単に読み書きするための抽象化をしているのではなく、文字数、送信ペースなどの「自然なやりとりのスタイル」を定義するデータベースでもある。 ちなみに、これも学習ではなく手入力。

emotion engineが語句編成のときに使うものはこのレイヤーの種類分あるわけではなく、メディアタイプはごく少ない種類だけで、あとはちょっとした調整パラメータがあるだけ。 調整パラメータは「連続送信」「顔文字」「絵文字」「Unicode」「句読点」などなど。

例えば連続送信型とした場合、改行したりするよりも複数の発言に分けるようになり、文の構成が簡素になる。 あまり推敲していないような文章になりやすく、端的でかつ文単独では意味が伝わらないような発言を選択する。 連続送信型でない場合は、発言主旨を一度の発言にすべて含めるようになる。