人工無能 Reudy (ロイディ) 1.9

書いた人: Glass_saga (@Glass_saga)

Reudy1.9 とは

Reudy1.9 とは、東京工業大学 ロボット技術研究会の市川 宙 (Gimite) さんが中心となって作成した日本語人工無脳ロイディを、Ruby1.9 で動作するようにしたものです。Ruby1.8 では動作しません。

人工無能とは、人間の発言を理解したような「ふり」をするプログラムです。あくまでふりをするだけなので、知能は持ちません。その為、このようなプログラムは「人工無能」又は「人工無脳」と呼ばれます。

ロイディの仕組み

Gimite さんが RubyKaigi2006 で発表された時の資料 [PDF] を元に、ロイディの仕組みを簡単に説明します。 例として「Rails ってどうよ?」という入力があった場合について考えてみましょう。 ロイディは、人間の発言を受け取ると、ログからそれに類似した発言を探し、さらにその発言に返答している発言を探します。例えば、ログから「Ruby ってどうよ?」という類似した発言が見つかり、さらにその返答として「Ruby サイコー!」という発言が見つかる、といった具合です。

類似した発言に対する返答を見つけると、ロイディはそれを「ベース発言」として、この発言中の単語を入力された文章中の単語 (ここでは「Rails」) で置換して、「Rails サイコー!」と発言します。

人間同士のやりとりの一部を書き換えるだけなので、人間から見て自然な発言を作りやすいというメリットがあります。

その他、ロイディに関してはGimiteさんが執筆された『人工無能 ロイディ』 [PDF]『人工無能 ロイディ (2)』 [PDF]といった資料があります。

また、人工無脳一般については、Ruby を使って解説した書籍『恋するプログラム 〜Ruby でつくる人工無脳』などがあります。

Reudy1.9 を使ってみよう

さて、ここからは早速 Reudy1.9 を動かしてみましょう。

インストール

次のコマンドを実行して下さい。

 % git clone git@github.com:Glasssaga/Reudy19.git

Reudy19 というディレクトリができているはずです。

ファイル構成

Reudy19 以下には LICENCE や README の他に

  • stdio_reudy.rb (標準出入力用インターフェース)
  • irc_reudy.rb (IRC 用インターフェース)
  • twitter_reudy.rb (Twitter 用インターフェース)
  • lingr_reudy.rb (Lingr 用インターフェース)
  • public (デフォルトの設定が含まれるフォルダ)

があります。

使い方

Reudy1.9 は標準出入力、IRC、Twitter、Lingr に対応するインターフェースを持っています。ここでは、それぞれに関して使い方を説明します。

ひとまず話してみる

まずは Reudy1.9 と会話してみましょう。

% ruby stdio_reudy.rb public

で Reudy1.9 が起動します。指定するディレクトリは public でなくても構いません。

public 以下のファイルを別のディレクトリにコピーして、それを指定する事ができます。Reudy1.9 の人格(?)を決める設定ファイルやログファイルなどは全て public 以下に含まれているので、これをコピーしたディレクトリを作ると複数の人格を管理できます。

ターミナルでなにか話しかけてみて下さい。

ログロード終了
単語ロード終了
こんにちは。
caption : 1.1/"デフォルト発言率:0.88, 最近の発言者: [nil, nil, nil, nil, nil, nil, nil, nil, nil, \"test\"]"
[1, 5]
caption : "こんにちは。"/5
おはよう。

これは Reudy1.9 に「こんにちは。」と話しかけてみた例です。

デフォルトでは文字コードが UTF-8 になっていますので、実行する環境によっては調整が必要です。stdio_reudy.rb をいじってください。

初回の起動ではデフォルトで含まれている数個の発言と起動後に入力されたの発言をランダムに繰り返すだけですが、学習が進むにつれ文中の単語を適宜組み替えて話すようになります。

IRC ボットとして使う

ロイディは元々 IRC ボットとして開発されました。その為 IRC クライアントも自前のものが使われています。

準備

始めに Reudy19/public にある setting.yml を編集して接続したい IRC サーバのホスト名やポート、入りたいチャンネルなどを指定します。

デフォルトでは IRCnetの#reudy_test に ReudyTest という nick で join するよう設定されているので、適宜書き換えて下さい。

起動
% ruby irc_reudy.rb public

で、Reudy1.9 が起動し IRC サーバへの接続を開始します。

しばらくすると指定しておいたチャンネルに join してくるはずなので、話かけてみましょう。

Lingr ボットとして使う

本家 Reudy も Lingr ボットとしての利用ができましたが、Lingr に大幅な仕様変更があった為、これに対応しています。

現在の Lingr では、何かイベントが発生すると登録しておいた URL に対して HTTP の post リクエストが発行されます。

Lingr 側の設定を済ませた後、

% ruby lingr_reudy.rb public -p 1234

とすると、ポート1234でWEBRickが起動します。

起動したら、bot を join させておいた Lingr のルームで発言してみて下さい。うまくいけば Reudy1.9 が応えてくれるはずです。

Twitter ボットとして使う

まずは Twitter の app としての登録が必要です。

https://dev.twitter.com/apps/new から登録して、key と secret を控えておきます。

エディタで twitter_reudy.rb を開き、3 行目にある定数 CONSUMER の :key と :secret に対応する value を控えておいた key と secret で書き換えます。

書き換えが終了したら、実際に動かしてみましょう。

% ruby twitter_reudy.rb public

で Reudy1.9 が twitter ボットとして起動し、タイムラインから学習して、適度に発言します。

Ruby1.9 への移植に必要だった事

Ruby1.9 で Reudy を動作させる為に必要だった点について書きます。

エンコーディング

Ruby1.9 では M17N に対応し、各エンコーディング間のコンバータが標準搭載されるようになりました。

本家 Reudy はエンコーディングの変換に Kconv を使用していましたが、Reudy1.9 ではString#encode を使っています。

String の扱い

Ruby1.8 では String はバイト列でしたが、1.9 での String はバイト列としてだけではなく、エンコーディングに沿って文字列としても扱えるようになりました。また、String#each の廃止や、String#[] がバイトの値ではなく文字を返すようになるなど、大きな変更がありました。従って、String がバイト列である事を前提として書かれたコードは修正する必要があります。

例えば、本家ロイディでは苦肉の策でしょうか、文字列を扱いたいが為に

str.split(//e)

として文字の配列を得ている箇所がいくつかあります。このような箇所は、split を使わず String を文字列として扱うように書き換えています。

その他の改善点

設定ファイルとログファイルを .txt から YAML へ

従来の設定ファイルとログファイルは .txt に独自の形式で保存していましたが、YAML を使うようにしました。独自形式での保存は、その形式を扱う為のコードをメンテナンスしなければなりませんが、YAML であればそういった面倒がありません。

単語の抽出に形態素解析エンジン MeCab を利用できるように

従来の単語抽出は、正規表現を組み合わせて

 # 単語として適切かどうか判定する
 # 主語っぽい語などの特例には適用しない
 # 不適だとnilを返す
 def wordFilter1(word)
   # 論外(^_^;
   return nil if !word
   # 一文字だけ
   return nil if word=~/^.$/e
   # 平仮名だけ
   return nil if word=~/^[ぁ-んー]+$/e
   # 非ひらがなの2文字以上の連続を含まない
   return nil if !(word=~/[^ぁ-んー][^ぁ-ん]/e)
   # 助詞っぽいものを含む
   return nil if word=~/[^ぁ-ん][のとな]$/e
   # 先頭以外に「が」「は」を含む
   return nil if word=~/^.+が/e
   return nil if word=~/^.+は/e

   return word
 end

このような職人技で実現されていました (実は同様のフィルタがもう一つあります)。しかしこれでは単語の抽出に失敗する事も少なくない為、オープンソースの形態素解析エンジンである MeCab を使って単語を抽出できるようにしました。MeCab とその Ruby バインディングをインストールする必要がありますが、従来と比較して正確な抽出が期待できます。-m 又は –mecab オプションを付加して Reudy1.9 を起動すると、MeCab の使用を試みます。

終わりに

この記事では Ruby1.9 で動作するものとしてはおそらく唯一の人工無能である Reudy1.9 について解説しました。 人工無能はとうにブームを過ぎてしまった感がありますが、競争相手のいない今がチャンスですから、これを機に好みの人工無能を作ってみてはいかがでしょうか。

著者について

Glass_saga (@Glass_saga) 大学生です。最近は IRC ばかりしていて、Kanzashi という IRC proxy を書き始めました。