読者です 読者をやめる 読者になる 読者になる

null部の部誌

プログラミングの話とか色々。

2016年度文化祭展示作品「文豪チャット」公開

今年度も文化祭の作品として、さくらミケ氏と合作でプログラムを作成しました。UIはA.js(仮名)氏が作ってくれました。

どんなプログラムかざっくり言うと、
「文豪風に喋る会話プログラム」
です。会話の相手は夏目漱石太宰治など、また文豪以外にも猫とかエヴァとかあります。

Vectorにて配布中! 是非お楽しみくださいませ。
文豪チャットの詳細情報 : Vector ソフトを探す!

操作説明は以下のさくらミケ氏のブログにあるので、私のブログにおいては割愛させていただきます。
2017年文化祭展示作品 文豪チャット|猫もあきれるプログラミング日記

ソースコードはこちらから。
GitHub - sakurakitten/Bungo-chat: 文豪チャット( http://www.vector.co.jp/soft/winnt/amuse/se515415.html )のソースなどです. 必要なデータファイルはこちら(https://github.com/sakurakitten/Bungo-chat-data )

バグ報告はこの記事のコメント欄でもGitHubのIssueでも何でも良いですが、詳しい状況が分からないと対応できないことがあるので、「落ちた。クソアプリ。」とコメントしたまま放置とかだと改善に繋がらないため、作者から返信が来ていないかたまにチェックしていただけるとありがたいです。(その点ではGitHubのIssueが一番ですね)
既知の不具合については、GitHub以外で報告されたものも気付き次第Issueを立てておくので、バグ報告する前に同じバグ報告がされていないかチェックしていただけると助かります。

さて、この記事では、会話の応答文の生成に用いられている手法などについて書いていきます。なお、分担して制作したプログラムのうち、さくらミケ氏担当の部分については、この記事では割愛させていただきます。

目次

コンセプト

目指したもの
りんな

目指してないもの
iOS - Siri - Apple

両方とも人間の発話に応答するプログラムですが、私にとってのりんなとSiriの違いを的確に表す画像がこちらです。

要するに、今回のプログラムでは、「道案内」や「Webで検索しました」などの便利機能はなしで、単に会話の相手を務めることを目指しています。

最初は「コミュ障カメレオン」というオリジナルキャラクターの会話AIを作るみたいな流れだったんですが、日本語の文章を大量に入手する手段として青空文庫を紹介したのがきっかけで、文豪の会話AIを作ることになりました。

各種制約

「文化祭作品」としての制約

  • インターネット環境なし
  • Visual C++ 2008
  • Windows XP/Vista/7 で動作
  • あんまり自由に色々インストールできない雰囲気

自ら設定した制約

  • 異なる文豪のAIが同じように会話すると面白くない
  • その文豪「らしさ」が失われないようにすべき
  • 文豪の著書以外の文章はなるべく使用しない

制作当時、学校のパソコンに入っているIDEVC++ 2008だったことで、あれがないこれがないとグチグチ言っていたのですが、どうやらstd::tr1というところに色々入っているらしい、というのを最近知りました(かなしい)。
後半の制約は「文豪の会話AI」というコンセプトを選択した結果生じたものですが、特に「文豪の著書以外の文章はなるべく使用しない」が最も厳しい制約だったように思います。

会話文生成プログラム

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

文生成の手法としてマルコフ連鎖というものが有名らしい、ということで実装してみました。

この手法では、ある単語についてその次に来うる単語のリストを作成しておき、文生成の時には、ある単語に対して次に来うる単語を適当に選び、さらにその単語に対して次に来うる単語を…、ということを繰り返して文を生成します。

たとえば、「きのこの山は好き。だけどたけのこの里はそこまで好きじゃない。」*1という文章に対して、前後の単語のつながりを表にすると、

きのこ
山, 里
好き, そこまで
好き 。, じゃ
だけど
だけど たけのこ
たけのこ
じゃ ない
ない

ここから単語を適当に辿って新たな文を作ります。たとえば、「たけのこ」から始めると、

「たけのこ」→「の」→「山」→「は」→「好き」→「。」

なんてのが作れます。元の文章にはない文ができました。

この例では一つ前の単語から次の単語を決めていますが、実際のプログラムでは、一つ前の単語と二つ前の単語が一致する単語のリストから単語を選んでいます。

さて、これをどう会話に組み込むかについて、最初は相手の発言に含まれる単語の一つを文を生成するようにしたのですが、全然会話になりませんでした。ボツにすることも考えたのですが、それももったいないので、相手が寡黙な時に自分から話を始めるために、これを用いて適当な文を生成しています。今思うと、「相手の発言に含まれる単語の一つを含む文」という条件は会話には緩すぎるので、相手の会話に含まれる単語やその関連語の出現確率を上げるとかするともっと良くなるかもしれないです。

この手法による文生成は、文法的には不自然でない文を作りやすいですが、文が長くなるにつれて前後で内容のつながりがなくなり、意味的にはさっぱりわからない文ができることが多いです。短い文が出るまで繰り返すみたいなことをやると改善するかもしれません。また、地の文を基にして文を生成しているため、会話として不自然になりがちなので、会話文のみを基にするのが良い気がします。

返答リストから乱択

何かの参考になるかなと自分のLINEのトーク履歴を眺めていたところ、9割くらい「へえ」「そう」「はあ」「ほー」「なるほど」「はい」のような当たり障りのない相槌*2で会話していることに気がつきました。LINEみたいな短文でのやりとりでは、相槌は結構役に立つ気がしたので、これを取り入れてみようと思いました。

ただ、確率で「へえ」とか「なるほど」とか言うという作りでは、「文豪らしい会話を!」とかいう制約に引っかかるので、著書から相槌を抽出して、それを使うようにしています。その抽出方法とは、

手動

手動です手動。文章から「」『』で囲まれた文を取り出して、その中から相槌に使えそうなものを人手で集めました。感動詞のみからなる文を抽出するとか、短い/単語数が少ない文を抽出するとかで自動化もできたかもしれませんし、学習的なことをさせても良かったのですが、そんなことを考えるよりも手動でやった方が早い気がしました。こういう人がいるから神エクセルが無くならないのでしょう。

ただこれが結構上手く行くんですよね。当たり障りのない返事ばかりなので。

ついでに、質問に対し適当に答えるものも作りました。たとえば「誰」が含まれる発言に対し、「妻がその人の名をいいましたか」(夏目漱石)といったような応答が用意されています。また、質問をはぐらかす、「今日は駄目です」(夏目漱石)のような応答もあります。特に「いつ」については、答えの中の日時にあたる部分を適当な日時に置き換えることでちょっとバラエティを出す、という小細工が仕組まれています。

ちなみにこれは黒歴史なんですが、公開当時は「君の名は。」という映画が流行していた*3もので、「君の名は。」と質問すると「名前はまだ無い。」(夏目漱石)とか「如何にも自分は隴西の李徴である」(中島敦)とか答えるようになっています。「名前はなんですか」みたいな尋ね方でも同様に返答できます。

この手法は、作業さえ頑張ればそこそこのクオリティになるので、割とおすすめです。作業さえ。

まとめ

会話プログラムを作るのはとっても楽しいです。今後も開発を続ける気満々です。時間があればTwitter botにしてみるとか、新たな手法を追加するとかやってみたいと思っています。ソースも公開されているので、いじってみたい方は是非フォークして遊んでください!(再利用しやすいコードかというと……うーん………)

*1:この文章に戦争を起こす意図はありません。似た構造の2文が欲しかっただけです。もっと中立な例文募集中

*2:当たり障りのないとは書いていますが、自分の中では話題に対する興味とか話の流れとかで厳格に使い分けています

*3:でも名前を答える機能自体については「君の名は。」の前から考えていたんですよ!!証拠のメール(4月29日付)もありますっ!!!(必死)