Chienomi

Inflaton Stella 〜チャットAIの理想への挑戦

開発

今回は弊社で展開するチャットボットAIサービス “Stella” に関するお話。

この記事はStellaの側から見た話ではなく、私の側から見た話になる。 つまり、Stellaユーザーに向けた記事ではなく、私をウォッチしている人に向けた記事である。

また、この記事中では各ソフトウェアを「AI」と読んだり呼ばなかったりする。 これについて私の立場を明らかにすれば、私は「AIとは自己更新するプログラムのことである」と定義しており、これに照らし合わせればStellaも、Erinaも、Surtrもあくまでただのプログラムであり、AIではない。 そして、今の世の中にAIと呼ぶに値するプログラムはない。

実際にはシンギュラリティを狙うSurtrは部分的に自己更新を行うが、何に対してどのように更新を行うかというのは規定されている。 例えばマニュピレーションモジュールをSurtr自身が生成することはあるが、SurtrのコアプログラムをSurtr自身が変更することはない。 このため、SurtrはAIと呼ぶに値しない。

Erinaに関してはそもそもSurtrにおいて自己更新の対象となっている機能を一切使わないため、Erinaには自己更新機能がない。 そしてプログラム的にも、プログラムを変更する機能は除去されている。

Stellaに至ってはもっと単純にプログラムである。

これらを「AI」と呼ぶのは、どちらかというと商業的側面が強い。 だから、Chienomi的には便宜上そう呼ぶことはあっても、「AIについて」語ろうというスタンスではない。

もちろん、ディープラーニングごとき1がAIだなどとは微塵も思っていない。

コンセプト立案

Stellaのコンセプトに関しては諸々述べているが、中心になっているのは

「シンプルに、実用的に」 (=Erinaとは逆)

である。

Erinaの場合、あれは研究の副産物であり、Surtrの一部である。 だから、Erinaの場合コミュニケーションボットとしては実用に供することはないという前提があり(そもそもその成果物をリリースすることは不可能なのだから)、その複雑さは実利とは全く関係のないところで不可欠なものである。

Erinaはシミュレータだから、過程の保証が出来なければ価値がないので、結果が同一であるということには意味がない。

また、Erinaの名前が「ELIZAの逆であり、ELIZAに直交する」ということを意味してつけられていることからもわかるように、「反ELIZA的」なAIデザインである。 ErinaはSurtrにない固有コンポーネントも持っていて、これはコミュニケーションに特化したものなわけだが、これはもう前提として「ELIZAは正しくない」という考えがある。

Stellaは全く逆に、「ELIZAは実用的だ」という観点から構築される「ELIZA的」なチャットボットである。

このようになる根本としては「人は基本的に人の話を聞いていない」ということにある。 私は記憶能力の構成上、かなり相手の発言を正確に聞いているのだが、大抵の人は「2つ前の言葉の反復」を求めてもまず言えない。

ここらへんは私の例によって悪魔的な私の実験によって確認されている。 これは単純な例なので手のうちを完全に明かしてしまうが、Erina最終調整の段階で多くの人と対話を試みるチャンスがあったわけで、ここで証明した。 手法としては、「メンタリズムに長ける」という情報を入れた上で、そこに関心を引いてから誘導的に会話を進め、メモを取り出して一切の説明なしに会話を継続する。そして「2つ前にメモを見ながら私はなんと言ったか?正確に言ってみて」と言うわけである。 実際にメモを読み上げただけなのだが、これが「メモを読み上げた」という印象に残る行為を伴っていても当たらない。 もちろん、この作業には「メモの読み上げが会話の文脈上自然な内容にする」という小技も入っているが。

そして、ある会話の流れで「実際の内容はとても変なことを言っているのだが、非常に高い確率で全く違う内容に理解する」という会話を展開するテクニックなんかも身につく。ちなみに、これによって相手が私の発言を全く違うように捉えさせると、実際に私が何を言ったかということを反復させると実際に言ったことからは「凄まじくかけ離れた」内容になる。

これはほんのいち要素にすぎないのだが、重要なのは「人の脳は解像度が低く、普通は収束する」ということである。

だから会話すること自体は緻密に書かなくてもなんとなくそれっぽく返せていれば会話は通じているように見える。 Erinaが「ごまかし方」にこだわっているのはそれが曖昧さをつなぐ「糊」になるからだ。

そして、人の行動パターン、言葉は想像よりもずっと種類が少ない。 いや、正確には全パターンを網羅しようとすると実際に膨大になるのだが、「例外的な小数を除外すると極めて少なくなる」という特性がある。

「自然言語の対話の7割は単純な正規表現マッチングでカバー可能である」というErinaの研究結果の副産物がここで生きてくる。

まして実用的、しかも企業におけるサポートの一環としてのチャットであればなおさら絞り込める。 「ちょっと気の利いたテーブルAI」でも十分実用的に扱えるのだ。

こうしたことを踏まえて実用的なチャットボットを定義する。 実際、私は世の中のサポートチャットボットが実用的だとは微塵も思えない。

じゃあ実用的なチャットボットってなんだろう? チャットボットを求めるときというのは基本的に「help needed」なのである。 このときの私の心理としては

  • 都合を問わない即時性。 営業時間まで待とうとも、営業時間に問い合わせようとも思わない
  • 人とは話したくない。電話は大嫌いだし、メールもそんなに好きではない。問い合わせフォームはメールよりも嫌だ。対人につなぐチャットボットとか最低すぎる
  • 対人チャットはそこまで嫌ではないが、なんらかのトラブルやミスを恐れることになるので精神的には嬉しくない
  • 期待値は割と低い。だいたいサポートなんて役に立たないものだから、解決する可能性は5割あれば上等だ
  • チャットボットは最も敷居が低い問い合わせである。最初に試みて、解決しなければ人手を煩わせることも考えるかもしれないし、諦めるかもしれない

である。じゃあ、help neededな状況でこういう心理に対して欲しいものはなんだろうか。 答えは簡単。FAQである。

でも、私はFAQってめっちゃ見る人なのだが、ほとんどの場合FAQって全く役に立たない。 まぁ、ナレッジサービスやフォーラムでも既存の質問がない問題にぶち当たってサポートを頼ることが大抵だし、自己解決力が高いとそうなってしまうのでFAQが役に立たないのは必然ではあるのだが、それにしても「これはあっていいだろう」と思うものがFAQにないことって本当に多い。 多分、実際の問い合わせをちゃんとFAQに反映していないのだ。

じゃあFAQが欲しいというのは机上の空論なのではないか、という話をすると、そんなことは全然ない。 Googleもまるで役に立たない今、私はhelp neededな状況を非常に高い確率で解決してくれるものを知っている。Archwikiだ。

つまり、wikiのような知識集合は問題を解決する。 ユーザーが本当に必要としているのは「ちゃんとドキュメントを作ること」と「検索エンジンを作ること」である。

だがしかし、現実にはこれは効果を発揮しない。なぜならば

  • 人はFAQを読まない
  • 人はドキュメントを読まない
  • 人はGoogle以外で検索しない

からだ。

まぁ、私の気持ちとしては「人ってそんなにチャットボット使うかなぁ…みんなあんまり使わない気がするしアクセスされないのでは」という気持ちはとってもたくさんあるのだけど、そこは弊社取締役の力説を信じることとする。

まぁ、仮に人はFAQは読まないがチャットボットは利用するのであれば、チャットボットにFAQの代わりをさせてあげればよろしい。 ちゃんとドキュメントを整備しているのであれば、検索エンジンの代わりをさせてあげればよろしい。

さぁ、「実用的」は定義できた。 Erinaは経緯的にも目的上も複雑にならざるをえなかったが、その意味でも実用に耐えず、プロダクトとしては話にならない。 「問題を解きほぐしてシンプルにすることでシンプルなソリューションを生み出す」ことが私の真骨頂。simplify, simplicityは私の生き方に反して私が力を行使する上で重要なキーワードだ(おかげでcomplex simplicityというパワーワードも誕生してしまった)。 ここまで明確かつシンプルな定義ができたのだから、今までの経験から必要なものをessentialに抜き出せば要素は少なくて済む。これをできるだけシンプルに組み上げよう、ということがコンセプトとして立てられた。

背景は複雑だが、プログラムとしての設計、挙動、ルールはシンプルに、ユーザーにとって理解しやすく、ユーザーの作業も単純に。 これでコンセプトは確立された。

ここで鬱陶しくも自己アピールをしておくのであれば、この節に書かれていることは熟考と検証の末に導き出したような内容になっているが、実際にはこの節の内容を考えるのに10秒とかかっていない。 確かに中学生、高校生のときと比べると頭の回転は桁違いに遅くなり、それによって人を恐れおののかせるようなものではなくなったとはいえ、研究によって積み重ねたものは血肉となっており、この程度の内容であれば10秒もあれば検討は終わる。

諸君、これが研鑽というものなのだよ!

もちろん、私が研鑽の至らない分野ではこうして瞬殺ボッコボコにされるのである。

if文AI

さて、if文AIという言葉を耳にしたことはあるだろうか。

この言葉、実は割と古く使われていたのだが、フィーチャーされるようになったのはAIブーム以降である。 「AI=ディープラーニング」の図式が出来てから、技術的に安易な「ひたすらifで条件式とのマッチングを行って挙動を決定する」という手法(あるいは具体的にその手法ではなくともそのような単純な手法)を用いたAIに対する揶揄として使われるようになった。

この揶揄は、「ディープラーニングこそが正義でありAI、ディープラーニングにあらずんばAIにあらず」という安直な思想に基づいている。 だからそれ自体は割と取るに足らないことではある。

しかし考え見て欲しい。 「条件が明らかである」=「問題が明示的である」という状況下では条件を判定し、それに対して最も適切な挙動を明記したプログラムを動かす以上に適切なことがあるだろうか? 世の中割と「それプログラムで解けるじゃない」ということをディープラーニング使いたがる状況がある。

だが、問題が明確なのであればそれを解くプログラムを書くのがプログラマではなかろうか。 それは競技プログラミングと同じようなものであり、問題が定義されているのであればその解を 書かなければならならい のである。

プログラムというのは本懐を遂げるのであれば次のいずれかだと考えられる

  1. 明確な問題を解く
  2. 特定の用途に供する
  3. 不明な用途に対して明確な意図を以て機能を提供する

1は競技プログラミングなどでよくあるもの、2はアプリケーションプログラムのこと、3は例えばgrepやsedやlessなんかのことだ。

そして、問題が明らかなのであり、それを解くことを意図するならばそれを解くプログラムより優れたものなど存在しない。

AIが必要とされるのは問題が明らかでなく流動的であり、導出条件も不明であることから「なんとなく」解くという妥協を行う場合である。 AIが普通のプログラムより優れた解を出すと思っているのなら、さすがにそれは無知にすぎる。 普通のプログラムが解けない曖昧な問題に対し完璧でなくてもいいから答えを出すのがAIである。

そして、「問題と導出条件が不明」であればプログラム自体が動的でなければならず、その機能を正しく果たすにはそのプログラム自身が動的でならない、と私は考えるのだ。

さて、もしも条件を事前に用意できるのであればif文AI、というか問題を解くプログラムは最も正しいということを述べたわけだが、ここからはSurtrとErinaの挙動に触れていこう。

Surtrの場合「自分が取るべきアクションをプログラムとして生成する」という手法を取っている。 これは、私の当時の技術力不足を補い、できるだけ単純化するためにとられた手法である。

一般的にプログラムはその挙動の過程で問題は収束していく。 ところが、不明な問題に対するプログラムを書くと、どうしてもその処理中に問題は拡散する。 だから、「実行ステップ数を事前に予測する方法がない」という非常に特殊なプログラムになる。

単純に再帰すれば良い、とも考えられるのだが、問題が不明なので処理を決定する段階で深さ優先探索ができない。 だから各ステップごとに次のステップで実行するコードをキューイングしていくというような感じになるのだが、これがうまくできなかった。どうしてもGOTO文を使う以外の手法が思いつかなかったのだ。 もちろん、今であれば関数オブジェクトを配列にpushしていくみたいな方法を考えるだろう。

ただ、その処理自体が実に様々な言語で書かれた様々なプログラムに分散しているので、外部に出さないことにはあまりメリットがない。 だから、挙動としては無限ループの中でステップ処理を行い、次のステップをプログラムとして出力する。このプログラムは最終的な段階ではZshスクリプト、またはRuby DSLスクリプトである。 そして、これを実行し、実行結果を次のステップに反映させる。

Erinaにも同様の機能は使われているが、Erinaの場合なるべく関数オブジェクトの配列(というかRuby的に言うと大部分はメソッドオブジェクトの配列)で処理するように変更されている。

この挙動は「可能な限り生成を遅延した上で、プログラム自身によって書かれたif文AIを実行する」みたいなものである。 かなり際どい技法だが、Surtrの中でもこれは応用が効くものだと思っている。

Stellaはこれをもっともっと単純化したものであり、言ってみれば「if文AIを書くためのフレームワーク」である。

「なぁんだ」と思うかもしれないが、我々が肝に銘じておかなくてはならないことがひとつある。 それは、「顧客が望んでいるのは技術的に高度であったり、技術的トレンドを用いて作られたプログラムではなく、問題を適切に解決するプログラムである」ということだ。

確かにStellaはプログラム自体は至って単純だ。 なんといっても、本体コンポーネントのみに関していえば、0.0.1ではわずか170行に収まり、0.0.16にあっても428行に過ぎない。2

しかし、私はそもそもプログラムの記述で勝負するタイプではない。 数学的素養がなく、アルゴリズムも得意とは言えない。もちろん、それなりに経験は積み、ある程度の記述力はあるが、突出して優れているとはいい難い。 私の勝負どころは発想と問題の整理であり、「設計」を至上とするタイプなのである。

「Stellaをif文AIを生成するフレームワークにする」という判断自体が、その技倆の一部なのである。 そして、そのフレームワークで提供される機能の選択によって「実用的なif文AIを構築する」ことへと誘導するのである。

巧みな設計で勝負するステラ

プログラミングに関する素養がなくても、また私の固有能力であるコミュニケーションフローコントロールを持っていなくても実用的に書けるようにする、というのもひとつではあるのだが、実際にはステラはこのような設計になっているために単純なif文AIよりもはるかに複雑なつくりが可能である。

その挙動を決定する「ロジックファイル」はYAML形式になっている。 一応は直接に記述することを想定してはいるものの、その階層的複雑さを考えれば何らかの手段で生成するほうが望ましい。

YAMLという汎用性のある形式を取っているために「お好きなプログラミング言語でお好きなジェネレーターとDSLを書いてお作りになれます」なのだ。

実際、純正でStella DSLというRuby DSLが提供されているが、別にそれを使わなければならないというわけではない。

そして、プログラムによってロジックファイルが生成できる、ということは「if文AIを動的に生成できる」ということにほかならない。 基本的には「事前に静的に生成される必要がある」と説明してはいるが、現実にはそのような制約が存在しているわけではなく、インスタンス全体共通にはなってしまうものの、任意のタイミングで適用可能である。 インスタンスの制約はあくまでサービス上のおはなしなので、純粋にStellaの能力を語るのであれば、会話中の動的な変更だって可能だ。

そう、つまり「任意のタイミングでif文AIを動的に構築可能」なのであり、これは「次の挙動をプログラムで生成する」というSurtrと同じものである。

ここで言っているのは潜在能力の話であり、実際には「現実性」という形でもっと制約されている。 だが、これは「制約しないことが正しい」わけではない。だってStellaは実用的なチャットボットであり、これを構築するのは非エンジニアである。「チュートリアルに従って自然に書けば実用的に動作する」のが望ましいのであり、過剰に複雑で高度な機能を解放することは誰も幸せにしない。

それはさておき、if文AIというのは単純で幼稚という揶揄に使われる言葉となっているが、「任意かつ動的にif文AIを構築する」というのは言うほど単純ではない。 概要として、実作業としてのシンプルさに反して「それが正しい」と判断しているモデル自体は極めて高度である。 その可能性のほとんどは使わない前提になっているが、使うこと自体は任意であり、発想力と技術力のある者にはその選択肢は常に開放されている。

さらにいえば、StellaはコンテキスチュアルなAIである。 これは私が世のEQ AIに対して抱いている強烈な不満であり、「文脈を一切考慮しない」のはEQ AIとして決して許されざることだと思っている。 だからこそErinaは文脈処理に対して極めて複雑なプログラムが組まれている。

動的に文脈を判定してしまうとさすがにとてもユーザーに制御できるものではなくなってしまうので、Stellaではユーザーが明示的に使う形にしている。 これもロジック自体を動的生成する構造を選択すれば動的に判定できるのだけど、そこに言及するとサービスとしてのStellaからはかけ離れてしまうのでおいておこう。

コンテキスチュアルであるという特徴は他に類をみないので、「if文AIが動的に生成される」という要素を「実際にはしないほうが普通だから」という理由で除外したとして、じゃあ「ただのif文AIじゃないか、稚拙なもので特に強みはない」みたいな話になるかというと、「コンテキスト機能があるからね。コンテキストを踏まえたフローコントロールを行うif文AIを書くのは全く単純じゃないと思うよ」という返しができる。 「ロジックファイル」という中間レイヤーを介することでプログラムとして書くと非常に煩雑になるフローがいともたやすく構築できてしまう。

それがフレームワークというものだろう?

ここまで話せばわかるかと思うが、実のところStellaはErinaとは全く異なる手法、設計、構造になっているにも関わらず、潜在的にはessential Erinaである。 途方もなく複雑で膨大で動的なErinaから「実用的な意味で本当に必要なもの」だけを残した不自由を強制することで全く違う性格のプログラムにしている。 StellaをベースにしてErinaのようなプログラムを構成することも可能であり、Stellaサービスとしてもその余地は残されている。そして、StellaベースのErinaを作れば、現在のErinaよりも設計が改善する可能性すらある。

だが、それはあくまでプログラム的な話である。 StellaはInflatonのサービスだから、これらはあくまでプログラムとして、技術として、裏側を覗いた話であり、利用者に対して主張することではない。 なのだが、そうしたバックグラウンドがなければStellaは生まれないのである。 こういうものは膨大な知識と蓄積の上澄みなのだ。

ステラの可能性の範疇

前述のようにStellaの理想的な用法はFAQ、あるいはwikiへの導線である。 だからStella自身を複雑化することは全く推奨されていない。

だが、どこまでできるのかという話をするとまるで変わってくる。 なんといってもStellaは外部連携が可能であり、入力時に割り込んでStellaをバックエンドとして使用できる、挙動は動的に生成できる、実行中に別のサーバーに対するhookを使ってコールバックを実装可能であるということから実質なんでもできるし、 ディープラーニングとも排他的ではない!!!

このあたりは「かける労力次第」であり、どのような規模のロジックを書くか、どのような規模のシステムと連携するかによっていかようにもという話となる。 だから構築規模・コストとも青天井であり、基本的に多くを望むべきではない。

それでも、労力さえかければ可能性は無限大だ。

それが行使される計画がある。Stella Flagship Chatである。 これはStellaを使ってEQ AIを作ろうという計画だ。

労力もコストも本当に膨大だし、私の手があいている限りで行われることになるから、まだpendingになっているが、 Erinaのような完璧なレベルではなくてもそれなりに会話が楽しめるレベルにはなるはずだ。

そして、それが可能だというのは、「大部分は集約可能である」という経験に基づいている。 自由文脈では発端を推測できないため本当に自然に会話できるようにするのは現実的には不可能に近いが、少しずつ形になっていくだろう。 どこまでがんばれるか不安はあるが、うまくいかないとすればそれはStellaの限界ではなく、私の労力上の限界である。 (そしてそれは、決して低い可能性ではない)

それは私のプログラムだから

一般的に言えばイージーなプログラムを書く私だが、私としては制作するプログラムには著しいプライドがある。

例えば誰かの悪意によって行使されるプログラムを書かない。 誰かを侵害することを目的としたプログラムを書かない。

そんな強いプライドから、「汎用性のあるプログラムはあくまで道具である」というものまで。

そう、私が書くプログラムは、単一の問題を解決するためのものを除けば汎用性を前提としている。 プログラム自体がどのように使うか、なんのために使うか、どのような利点があるかということを 規定しない

商業的にはそれは嫌がられるんだなぁ…というのは感じるのだけど、そしてそれは社長として正しいことではないのかもしれないけれど、 それでもそれはプログラムに課すべきことではないと思うのだ。

サービスとしては見せ方を工夫すれば良い。実際、プログラムの汎用性に対して意図に反してもっと明確なイメージをもたれているものなんでいくらでもあるのだ。 だから、私としてはInflatonとして販売のためにStellaをどのように形容しようが、何を特色としようが、何をウリにしようが、間違っていない限り構わないし、それはソフトウェアプロモーションにおいては私の責任だが、それを販売の形にするのは私の仕事ではない。 だから、プログラム自体は中庸中立であり、私はそれを様々な切り口から解説するのである。

おわりに

Stella関係の話は公式ドキュメントとかでも結構色々書いてはいるのだけど、当然ながらInflatonのお客様はChienomiの読者みたいにエッジな人たちではないし、私としてもよそゆきのお話だからめちゃくちゃ気を遣うから書きたいことが全然書けなかったりする。 その意味で、今回こうして書いてようやっとスッキリしたという感じである。

Stellaはコード上の魅力は非常に乏しい――いや、ちゃんと言うならば割と私の今までの経験を色々活かしていて、動的メソッド呼び出しをしていて非常にシンプルにかけていたりとか、どの時点で正当性を保証し除染するかとか、メタプログラミングしていたりとか割と一般的でないテクニックが駆使されていてそれはそれで面白いかもしれないが、別にそれが必須なわけでもなく、力技で実装もできるものだから、その意味で「どうやっているのかわからないことをやっている」とか「高度なアルゴリズムを駆使している」みたいな要素はない。

だが特にそのデザインは他の誰も持っていない知識や背景からきている。 派手な魅力やアピールではなく実直に。 私が仕事としてプログラムを書くようになってから心がけていることを形にしたものだし、Plutoがかなり不本意なプログラムになってしまったことを考えると、これは私の、誰にも言わなかった日々を含めての集大成だとも言える。 これほど人より知悉している分野もないし、ちょっとやそっとの研鑽でこれを越えるプログラムを設計することはできないだろう。

だから、本当にこのプログラムに「ステラ」の名を、つまり原初宇宙の名を関するInflatonとしてその果てである「星」の名を冠してよかったと思う。 アイディアとしては「デネブ」などの女神星の名を関する案もあった。だが、そうしていたら今ほど輝きを感じることはできなかっただろう。

当記事で書いたようなStellaの魅力やよさは、直接にはユーザーが感じることはない。 ユーザーが感じるのはその結果の部分だけであり、そしてそこだけを見れば流行りのディープラーニングAIなどと比べればしょぼくて、みすぼらしくて、とてもとても見劣りする古くて単純な技術のソフトウェアでしかないのだ。

だが、私は確信できる。 使ってもらえばわかるはずだ。 100%でなくても、このソフトウェアは解決すべき問題を、着実に解決する方法を提供する。 そして、その積み重ねは100%へと近づくことを意味する。 それはきっと必要とするものであり、私が、私達が追い求めるべきは見栄えや華やかさではなく、正しく必要とするものなのである。

そして、このことに関しては――人心と人動、コミュニケーション様態に関すること、ましてその中で最も多くのデータを占めるチャットに関することであれば――世界中、誰にも負けないという自負がある。一番最初には、私が5歳のときに抱いた疑問から始まり、ずっと考えていて、今に至るまで積み重ねてきた。

ディープラーニングの信奉者よ、さぁ、勝負しようか。 よりよいエクスペリエンスを提供するチャットAIはどちらか。

私には、自信がある。


  1. 勘違いしてほしくないのだが、ディープラーニングを見下すつもりはない。私は限定的で使いどころが難しくコストの高い技術だと思っている。技術的には高度なのは認めているし、その高度さが適切さを妨げているとも思っている。ブロックチェーンと似たような話だとも思うが、あっちは技術的にもっと趣深くてテクノロジー好きの好物だと感じる。私もそうだし。↩︎

  2. 「過ぎない」とか言っているが、428行というとずいぶん拡張されたし、本体だけで428行、ステラコンポーネント全体だと1120行あるので個人活動では到底書かない規模に到達している。ちなみに、ドキュメントも含めるとユーティリティ分は除いて4831行ある。↩︎