忍者ブログ
MASTER →  ADMIN / NEW ENTRY / COMMENT
現代魔法(nearly equal 情報技術)を勉強中な人のメモ(チラシの裏)
/ 2024/11/22 (Fri) / 編集
×

[PR]上記の広告は3ヶ月以上新規記事投稿のないブログに表示されています。新しい記事を書く事で広告が消えます。

/ 2010/06/12 (Sat) / 編集
というわけで、お返事内容を考えるためのクラス作り。

bot(人口無能)には相手の発言をごにょごにょするマルコフ型や、過去ログを元に返事を考えるログ型などがあるけれど、マルコフ型だと自然な文章は作りづらいし、ログ型だとログがたまらないとダメダメなので今回は辞書型で行きます。
最終的には学習システムを実装して「自分で辞書を拡張する辞書型人口無能」を目指すつもり。

今回の実装では「文章のみから返事を考える」ことを目的としたいのでTwitterAPIは使いません。与えられる情報はあくまで「届いたメッセージ」と「送信者の名前」のみ!なのでTwitter以外のbotへも流用可能です。

実装したい事

  1. テンプレを使える事
  2. 例えば「user_nameさんこんにちは」という文章を登録しておくと「yosiloveさんこんにちは」と発言してくれる。
  3. コマンドが使えること
  4. 一定のコマンドを投げる事で、辞書に登録されていない返事も返せるといい。
  5. 言い換えに対応してること
  6. 「おはよう」と「おはー」と「Hi」と、、、等等を同じものとして扱える。
  7. 自分宛の発言と全員宛の発言を切り分けできること
  8. 自分に話しかけられた時に返事をするのと、相手が一人でしゃべってる時にあいづちを打つのでは文章の内容が違う方がいい。
  9. 独り言をしゃべること
  10. だれからも何も発言されなくても、自分から話題が振れるといい。時間帯別に違う発言が出来るとなおよし。

テンプレに対応する

まずはテンプレに対応する事、「%user-likeFood%が好き」とかすると「沖縄そばが好き」にしてくれるような関数を作ります。

データベースには「ユーザ名」「ステータス(likeFoodとか)」「内容(沖縄そば)」を入れておくようにする。なのでカラムは「name」「key」「value」と識別用の「id」を入れて4つ。 以下のようなレコード追加用関数も用意しとく、以降のテーブルにも同じようなのを用意しとく。 以下のようスクリプトを実行すると
require 'TalkClass'
talk = TalkClass.new
p talk.replace("test %my_likeFood% dayo",'testUser')
p talk.replace("test %user_name% dayo",'testUser')
p talk.replace("test %user_name% dayo",'othertUser')
データベース中で該当する者をさがしてきて置き換えてくれる。
"test 沖縄そば dayo"
"test テストなユーザ dayo"
"test othertUser dayo"

コマンド

お継ぎはコマンド。「<コマンド名>」という部分を置き換えてくれる関数。replaceとの違いは”データベースに登録しておけない情報”というところで、例えば現在の時刻(nowTime)などを置き換える。
scan関数大活躍w replaceと違ってデータベースを増やして対応する訳ではないので、新しい処理を追加したくなったらプログラムを書き換えないといけない。
require 'TalkClass'
talk = TalkClass.new
p talk.command("<NowTime>")
実行すると
"21:56:32"

返事を考える&言い換えの対応

まずはお返事テーブル(reply)を作り「こんにちわ」と言われたら「こんにちわ!」と返事するように作る、そして言い換えテーブル(trans)「こんちわ」も「こん」も「こんにちは」も、すべて「こんにちわ」と言われたものとして処理する、そうすればより多くの言葉に対応できる!

replyテーブルのカラムは「get」「say」「flag」の3つ、getと言われたらsayと返す、ただしflagを使って”自分宛のとき”と”全員宛のとき”で使うか使わないか選べるようにする。そうすることで、他の誰かに向かって「好きな食べ物は?」と聞いているのに自分が答えちゃうとかをなくします。

transテーブルは「key」と「value」を用意し、このvalueがreplyテーブルのgetと同じになるように作ってあります。
このsearch_choicesには句読点等で区切った文節が渡されます(後述)、返り値は返答の選択肢を入れた配列です。(sayには「|」区切りで複数の返答方法が入っています。)
そしてこの関数を使って返事を考えるのが次の関数、区切り文字に従って文章を文節にわけ、search_choicesに渡すのが主な仕事。さきほど紹介したreplaceとcommandでテンプレ対応とコマンド対応もしとく。
ここまででで以下のようなことができるよ。
require 'TalkClass'
talk = TalkClass.new
p talk.think_answer('testUser',"こんにちは!今何時?",'reply')
p talk.think_answer('testUser',"こんにちは!今何時?",'say')
実行すると以下のようになります。「今何時?」はお返事(reply)の時にしか使わないようにしてあるので話しかける(say)ときは無視されます。
"@testUser こんにちは!22:44:57だよ。"
"@testUser こんちわ!"

しかしここで問題が一つ、ツィートかダイレクトメッセージかはAPIで取得する時点でわかるけど自分宛のツィート(@myname)か全員宛のツィートかは読んでみないとわからない!
そこでこうゆう関数を用意します。ダイレクトメッセージ(DM)かツィート(TW)かは取得時にわかるはずなので引数で。
ちなみに引数を用意してあるのはテスト用で、別に引数なしでも動きます。
load 'config.rb',true
require 'TalkClass'

talk = TalkClass.new
p talk.think_tweet
p talk.think_tweet
今回は23時に実行したので以下のようなものがでてきました。
"誰か構ってよ、、、"
"夜ですね、わかります。"

拍手[0回]

PR
忍者ブログ [PR]