画像電子学会 第29回VMA研究会    
VMA29-4,  2011-01-17        


会話型twitterbotにおける個性的レスポンスの追及

Chatterbot on twitter for more unique responses

福井 康弘†

      

小町 祐史‡

Yasuhiro FUKUI†

      

Yushi KOMACHI‡


大阪工業大学情報科学部, 〒573-0196 枚方市北山 1-79-1

E-mail: †e1b06125@info.oit.ac.jp, ‡komachi@y-adagio.com


1. はじめに

人によるコンピュータ操作を人に代わって自動的に実行するプログラムであるbot(クローラ,ボットネット(スパム送信プログラム),ゲームの自動操作など)の中で,会話的な動作を行うbotは会話型bot,おしゃべりbot,chatterbot,chat-botなどと呼ばれ,人工無能と称されることもある。Eliza[1],人工無能うずら[9],ゆいぼっと[10]がその例である。

Twitterの普及によって,twitter上で動作する(twitterアカウントを取得してツイート(発言)を行う)twitterbot[5][14]への認知が高まっているが,ここでは会話的な動作を行う会話型twitterbot(つまりtwitter上で動作する人工無能)に着目する。これまでの代表的な会話型twitterbotには,shuumai[4],ha_ma[6],donsuke[7]があり,非会話型twitterbotには,meigenbot[11],情報収集系アカウント(tenki.jp[12])などがある。

これらのbotを図1に整理する。

図1 会話型twitterbotの位置付け

これまでの会話型twitterbotは,会話的とはいえ,頻繁な会話を行わず,独り言や一言だけの返事を返すものが多い[2][3][4][6][7]。その背景を調査し,もう少し人間っぽい会話への追及によって,会話型twitterbotにおける個性的レスポンスへの可能性を検討する。

2. 会話型bot

1966年に開発されたEliza[1][13]では,文章はオウム返し,質問に対して答え,相手の話に対して質問する。その後の会話型botでも,会話の基本構造に大きな変化はなく,これまでの会話型botの要件として次の機能を挙げることができる。

会話型botのこれらの機能は,会話を行うことだけを対象とするが,より複雑なアプローチによって人間っぽさを強調できる。

3. 会話型twitterbot

Twitterではツイート構成文字が140文字に制限され,1ツイートの中で内容がまとまっていることが多いため,会話型botの動作環境として適している。それは,人間っぽさを追及する上でも,問題点が顕わになりにくいという点で,適切な動作環境である。

会話型twitterbotの構造は次の3形式に分類できる。

(1) テンプレート型
複数の決められた言動から選ばれた一つをツイートする[2]。
(2) 反射型
特定の範囲からキーワードを抽出し,編集して発言する[3]。
(3) 自己発言型
プログラムが文章を構成して対話を試みたり,発言する[4]。

テンプレート型は,作成者が予め用意した内容に限定されるが,文が安定していて意味が明瞭であり,追加・編集が容易である。twitterでは,会話のきっかけを作れれば充分であり,充実した意味内容である必要はないため,テンプレート型の実用性は高い。しかし適当な文を拾ってくるだけでは,話す内容の一貫性がないことが問題である。

4. 会話型twitterbotの試作

個性的レスポンスのできる会話型twitterbotを目指して,テンプレートを用いて文を構成し,リプライとフォロー返しを行うプログラムを作成した。プログラム言語としてRubyを用い,ライブラリTwitter_oauthを利用した。

テンプレート内容を次の示す。twitterbotは食べ物に関するキーワードをつぶやく。つぶやく頻度は2〜3時間に1回で,時間によって食べ物が変化する。バッチファイルを利用して自動化を行い,同じ日に同じものを食べないよう調整する。「その○○はおいしい?」などとリプライで問いかけられた場合には,味の評価をする。

適当な文を拾ってくるだけでは,話す内容の一貫性がないことの問題に対処するため,話題のはじめは誰にでもわかる内容を提供することが望ましいとの判断に基づき,このキーワードを設定した。しかしテンプレート内容はまだ乏しいので,今後さらに語彙を追加していく必要がある。

リプライ部分については,相手のリプライを読みとって正規表現で特定語彙を判定する。例えば,疑問符が付けば質問文フラグを立て,「おいしい」「まずい」など味に関する自分の評価を語るように設定した。リプライの中でも既読・未読を判定するために,リプライのIDを記載したDMを自身に送り,それを読むことで未読判定を行う。

しかし,食べていないものをおいしいかと聞かれたときにも答えてしまう問題を残している。この場合の選択肢を作る,複数のフラグが立ったときに優先順位を付ける,などのプログラムの充実が望まれる。

5. むすび

会話型twitterbotを調査検討して,構造に基づく3形式の分類を提案した。テンプレート型は意図した話題作り・テーマ作りに適しており,共通したキーワードを必ず話させることができる。

会話型twitterbotの試作し,リプライ機能の付与によって会話内容の充実を図り,個性的レスポンスによって話し相手を楽しませることができるようにした。


文献

附属資料 A

試作した会話型twitterbotのソースコードを示す。

A.1 メソッドA「今何食べてる?」

require 'rubygems' require 'Twitter_oauth' require 'kconv' require 'date' CONSUMER_KEY = '’  #以下4項は,botのアクセスに必要な情報なため,文字列を消してある。 CONSUMER_SECRET = '' ACCESS_TOKEN = '' ACCESS_TOKEN_SECRET = '' client = TwitterOAuth::Client.new( :consumer_key => CONSUMER_KEY, :consumer_secret => CONSUMER_SECRET, :token => ACCESS_TOKEN, :secret => ACCESS_TOKEN_SECRET ) now_hour = Time.now.hour sweets =[ "ショートケーキ", "モンブラン", "チョコシュー", "バウムクーヘン", "ロールケーキ" ] rice =[ "炒飯", "ピラフ", "おこわ", "オムライス", "カレーライス" ] midnight_snack =[ "カップヌードル(カレー)", "俺の塩", "プリン", "メロンパン" ] breackfast =[ "食パン", "朝の和食", "卵焼き", "朝のコーヒー" ] meet =[ "焼き肉", "ステーキ", "コロッケ", "飲み会" ] food_end =[ "mogmog", "なう", "たべてる", "は結構すき" ] case now_hour when 7..10 eat_in = breackfast[ rand(breackfast.size)] when 11..14 eat_in = rice[ rand(rice.size)] when 15..17 eat_in = sweets[ rand(sweets.size)] when 18..19 client.update(Kconv.toutf8("もうすぐ晩御飯♪")) exit when 20..22 eat_in = main[ rand(main.size)] else eat_in = midnight_snack[ rand(midnight_snack.size)] end client.update(Kconv.toutf8(eat_in + food_end[ rand(food_end.size)]))

A.2 フォロー返し

require 'rubygems' require 'twitter_oauth' require 'kconv' CONSUMER_KEY = '' CONSUMER_SECRET = '' ACCESS_TOKEN = '' ACCESS_TOKEN_SECRET = '' client = TwitterOAuth::Client.new( :consumer_key => CONSUMER_KEY, :consumer_secret => CONSUMER_SECRET, :token => ACCESS_TOKEN, :secret => ACCESS_TOKEN_SECRET ) #followers = client.all_followers followers = client.followers #フォロワー100名を読み込む followers.each do |follower| #フォロワーを配列followrへ積む id = follower["id"] name = follower["screen_name"] puts "#{id}: #{name}" client.friend("#{name}") end

A.3 リプライ

require 'rubygems' require 'twitter_oauth' require 'kconv' CONSUMER_KEY = '' CONSUMER_SECRET = '' ACCESS_TOKEN = '' ACCESS_TOKEN_SECRET = '' client = TwitterOAuth::Client.new( :consumer_key => CONSUMER_KEY, :consumer_secret => CONSUMER_SECRET, :token => ACCESS_TOKEN, :secret => ACCESS_TOKEN_SECRET ) MY_NAME = 'eat_in_bot' question = '?' taste = ["おいし", "美味", "まず", "不味" ] taste_text=["いよ", "かった〜", "いと思う?" ] dm = client.messages since_id = 1 dm.each do |key,value| if key['text'] =~ /^\d+$/ since_id = key['text'].to_i break end end timeline = client.home_timeline( :count => 200, :since_id => since_id ) timeline.each do |tl| ques = Kconv.toutf8(question) text = tl["text"] id = tl["id"].to_i since_id = id if id > since_id if text =~ /#( ques )/u user = tl["user"]["screen_name"] if user == MY_NAME || (text =~ /@/ && ! (text =~ /#{MY_NAME}/)) next end text_mean = Kconv.tosjis( taste_text{ rand(rand(taste_text.size)) } ) mention_m = "@#{user} #{taste}#{taste_text}" client.update(mention_m,:in_reply_to_status_id => id) sleep 1 end end client.message(MY_NAME,since_id )

附属資料 B

試作した会話型twitterbotによるツイートの例を示す。

eat_in_bot 大食漢 俺の塩は結構すき 27分前 お気に入り 返信 削除 eat_in_bot 大食漢 俺の塩mogmog 57分前 お気に入り 返信 削除 eat_in_bot 大食漢 プリンは結構すき 1時間前 お気に入り 返信 削除 eat_in_bot 大食漢 カップヌードル(カレー)なう 1時間前 お気に入り 返信 削除 eat_in_bot 大食漢 @otegami_bot おいしいよ 4時間前 お気に入り 返信 削除 otegami_bot おてがみさん @eat_in_bot そのモンブランはおいしい? 4時間前 お気に入り リツイート 返信 eat_in_bot 大食漢 もうすぐ晩御飯♪