perlで人工無脳 #0

ちょっと興味と必要があって、人工無脳に手を出してみることになりました。まあ、人工無脳なんて今更って気もしますが、とりあえずやってみたことはどんなにしょぼくても公開する、というポリシーですので、恋するプログラム―Rubyでつくる人工無脳を参考にしながら、perlで実装していく過程をここに載せていきたいと思います。

といっても、この本の流れに沿っていくわけではなく、俺の思いつきのままにやっていきますので、そこんとこよろしくです。

で、今回は人工無脳のパターン辞書を、何らかのデータから自動生成することを考えてみます。

パターン辞書というのは、人工無脳への問いかけの中に、「A」という言葉がある場合に、「B」という応答を返す、というパターンが記述された辞書です。これをひとつひとつ設定していくのではなく、自動的に生成するにはどうすればいいのか、という話ですね。

これは形態素解析を利用して、以下の様な処理を行います。

perlで実装してみるとこんな感じです。形態素解析にはMeCabを利用しています。(たまたまインストールされていたので。)

#!/usr/local/bin/perl

use MeCab;
use strict;
use Storable qw(lock_retrieve lock_store);

my $text_file = $ARGV[0];
open(IN, $text_file) or die $!;

my $pattern_dic_file = "pattern_dic";

my $pattern_dic = {};
eval { $pattern_dic = lock_retrieve($pattern_dic_file); };

my @arg = ($0);
my $m = new MeCab::Tagger(\@arg);
while(<IN>){
    my $n = $m->parseToNode($_);

    while ($n->hasNode () != 0) {
    my $s = $n->getSurface;
    my $f = $n->getFeature;

    if($f =~ /名詞/ and ($f =~ /一般/ or $f =~ /固有/ or $f =~ /サ変/ or $f =~ /形容動詞語幹/)){
        push(@{$pattern_dic->{$s}}, $_);
    }

    $n = $n->next ();
    }
}

lock_store($pattern_dic, $pattern_dic_file);

exit;

辞書を作っただけではおもしろくないので、実際に辞書データをもとに応答してくれる簡単な人工無脳ボットbot.pmを作ってみます。

package bot;

use base qw(CGI::Application);
use strict;
use Storable qw(lock_retrieve);

my $pattern_dic_file = 'pattern_dic';

sub setup {
    my $self = shift;
    $self->mode_param('rm');
    $self->start_mode('bot');
    $self->run_modes ( bot => 'bot');
    $self->param(
         pattern_dic => lock_retrieve($pattern_dic_file),
         );

    $self->header_props(
            -type => 'text/html',
            -charset => 'euc-jp',
            );
    $self->tmpl_path('/path/to/template');
    
}

sub bot {
    my $self = shift;
    my $pattern_dic = $self->param('pattern_dic');
    my $input = $self->query->param('input');
    my $output;
    foreach (keys %$pattern_dic){
    if($input =~ /$_/ig){
        my $num = $#{$pattern_dic->{$_}};
        $output = $pattern_dic->{$_}->[int(rand($num+1))];
        last;
    }
    }

    if(!$output){
    $output = "何それ?";
    }

    my $template = $self->load_tmpl('bot.html', die_on_bad_params => 0);
    $template->param(
             input => $input,
             output => $output,
             );
    return $template->output;
}

1;

こいつをCGIとして呼び出すコードbot.cgiです。

#!/usr/local/bin/perl

use bot;
use strict;

my $bot = bot->new;
$bot->run;

あと、HTMLファイルbot.htmlですね。

<form method="post" action="bot.cgi">
<input type="text" name="input" size="50" id="input" value="<!-- TMPL_VAR NAME=input -->">
<input type="submit" value="submit">
</form>

<!-- TMPL_VAR NAME=output -->

<script type="text/javascript">
document.getElementById('input').select();
</script>

試しに、「最近おもしろいゲームある?」と聞いてみたところ、「MGS3もおまけゲームが魅力的です。」という答えが返ってきました。どうやらこの人工無脳、メタルギアソリッド3のおまけゲームであるサルゲッチュが好きなようです。といっても、この様に会話になることはまだ稀で、もう一度同じ質問をしたところ、「セガとサミーがくっつくわ、ファルコムは韓国からゲーム買うようになっちまったわ」とか「今日横断歩道で プーさんの格好でスクーターに乗った人を見かけたけど、その人もバツゲームかなあ。」なんて返してきました。

こんな感じで、まだまだお馬鹿ではありますが、発言データさえ豊富にあれば、簡単なコードでも十分楽しいもんですね。本当は今回作った人工無脳ボット、実際に動いているものを公開したいのですが、なにしろ発言データをすごくプライベートなチャットから採っているものですから、勘弁して頂きたいと思います。

これをベースに、今後少しづつ改良していって、より自然な文章が作れるものを目指したいと思います。