ついに今日、パターン辞書でしゃべる人工無能を完成した。
パターン辞書なので、会話から自動的に学ぶタイプの人工無能では無く、手動でパターンを覚えさせていくタイプ。
しかしながら、プログラムがこちらの話しかけに応じて返事をしたときは本当に、おおおおーーーーー!!っといった感じで本当にうれしかった。
ちなみに、手動で覚えさせるのが必ずしもレベルの低い方法ともいえない。
自動学習をする無能が支離滅裂なことばっかしゃべるのに比べると、こちらの方がある程度会話の内容をコントロールできるからだ。
ちなみに、このブログの右上にある「ひこまた」も手動型ですね。
自分は40万語も覚えさせる気はないですが。
それではソースです。
↑私の座右の書というか、それ以上の本、つまりバイブルである。(故)秋山智俊氏の著、恋するプログラムRubyでつくる人工無脳を見ながら、「うわぁ~~!また、エラーだぁ!!」などと、日がなDOS窓とや、ふりかけのカスが挟まった“Z”キーと格闘しながら、なんとかたどり着いた記念すべきプログラム。
実は、何が難しいのかというと、自分のパソコンの不具合なのか、インストール時にエラーがあったのか、Rubyのバージョンが自分のVISTAに対応していないのか、requireメソッドが働かない。
なので、全てのクラスを一つのファイルに納めている。
これが、あれこれとエラーを起こすもとになっていて、悩みの種だった。
では。ソースです。
#! ruby -Ks
class Dictionary
def initialize
@random = [] # (1)
open('random3.txt') do |f|
f.each do |line|
line.chomp!
next if line.empty?
@random.push(line)
end
end
@pattern = [] # (2)
open('pattern.txt') do |f|
f.each do |line|
pattern, phrases = line.chomp.split("\t") # (3)
next if pattern.nil? or phrases.nil?
@pattern.push({'pattern'=>pattern, 'phrases'=>phrases})
end
end
end
attr_reader :random, :pattern # (4)
end
class Responder
def initialize(name, dictionary) # (1)
@name = name
@dictionary = dictionary
end
def response(input)
return ''
end
attr_reader :name # (2)
end
class WhatResponder < Responder
def response(input)
return "#{input}ってなに?"
end
end
class RandomResponder < Responder # (3)
def response(input)
return select_random(@dictionary.random)
end
end
class PatternResponder < Responder # (4)
def response(input)
@dictionary.pattern.each do |ptn_item|
if m = input.match(ptn_item['pattern'])
resp = select_random(ptn_item['phrases'].split('|')) # (5)
return resp.gsub(/%match%/, m.to_s) # (6)
end
end
return select_random(@dictionary.random)
end
end
class Unmo
def initialize(name)
@name = name
@dictionary = Dictionary.new # (1)
@resp_what = WhatResponder.new('What', @dictionary)
@resp_random = RandomResponder.new('Random', @dictionary)
@resp_pattern = PatternResponder.new('Pattern', @dictionary)
@responder = @resp_pattern
end
def dialogue(input)
case rand(100) # (2)
when 0..59
@responder = @resp_pattern
when 60..89
@responder = @resp_random
else
@responder = @resp_what
end
return @responder.response(input)
end
def responder_name
return @responder.name
end
attr_reader :name # (3)
end
def select_random(ary)
return ary[rand(ary.size)]
end
def prompt(unmo)
return unmo.name + ':' + unmo.responder_name + '> '
end
puts('Unmo System prototype : proto')
proto = Unmo.new('proto')
while true
print('> ')
input = gets
input.chomp!
break if input == ''
response = proto.dialogue(input)
puts(prompt(proto) + response)
end
同じフォルダ内に、patternファイルとrandom3ファイルを作成。
どちらも拡張子は.rb
パターンファイルにはパターンで反応する言葉を書きます。
例えば。
こんにちは おっす
おはよう おは
こんばんは ばんわ
などです。左の列が私たちが無能に話しかけることば、右側が無能の反応。
空欄で区切ります。ちなみにこの空欄はTABボタンで入力してください。
それと反応パターンごとに改行することも。
それからランダム3ファイルには、
あーーあ、ねむい、
疲れた。
何か話してよ。
何かいいことあった?
などと、無能がランダムに話すことを入力します。
これも反応ごとに改行。
Rubyをインストールしたパソコンでルビーコンソールを開始して、DOSプロンプト上で動かします。
例によって、DOSプロンプトが得意な人にはなんてことないが・・・、cd (カレントディレクトリ)で無能ファイルのあるディレクトリまで移動する。
それから、ruby sample.rb.txtを押せば動き出す。
「ドス窓で日本語が打てません。」
「はいはい、altキー押しながら半角/全角ボタンね。」
天国の秋山智俊先生、ありがとうございます。
おかげで、思ったよりも早く良い人工無能が作れそうです。
あ、自分唯物論者なのに天国とか言ってしもた。