クオリティの高い記事が続きましたが、ここらでどうぞ息抜きをしてください。
あんまり目新しいこともないのですが、
最初にこのテーマでエントリーしてしまったので、このまま書いていきたいと思います。
発端
12月16日。
去年のこの日、eeicに新しいおもちゃが生まれた。
こんなクソbotつくりやがって→ @dedede45450721
— じゃがよこ (@potato_eeic) 2014, 12月 17
デデデボっととは
某クソeeicツイッタラーD君(仮名)のツイートを真似るbotです。
以下「原作」と呼ぶことにします。
「いかに原作のアルゴリズムが単純か」を示すため、本botには次のような制限をかけています。
- 構文解析をしない
- あんまりめんどくさいことはしない
実装は全てGoogle Apps Script (GAS)デ行っています。
デデデボっとを作った動機
前々から原作のクソリプにはうんざりしていて、本当にbotみたいだと思っていました。
eeic2015botを作った関係で、もう一つくらいbotを作ろうと思っていたところでこのbotを思いつきました。
さすがに原作の製作者に許可なく作るのもどうかと思ったので本人に構想を話したところ、
意外とまんざらでも無さそうだったので、
クリスマスも近いし、皆さんがこれで少しでも寂しさを紛らわせたら、との思いから作ることにしました。
最初は本人が可哀想なので1週間くらいで止めようかと思いましたが、
意外とウケてしまったし、本人もやっぱりまんざらでも無さそうだったので、
なんだかんだで長生きしてしまいました。
デデデボっとの概要
デデデボっとは、次の機能を持ちます。
全て原作に備わっている機能です。
- クソリプ機能
- クソ画像リプ機能
- パクツイ機能
- TL上のアカウント名を連呼する機能
- 飯テロ機能
順に説明していきます。
クソリプ機能
飛んできたメンションに対して、クソリプを返します。
@o_nishy は?おい
— デデデボっと (@dedede45450721) 2014, 12月 17
クソ画像リプ機能
飛んできたメンションに対して画像リプを行います。
@dedede467099 pic.twitter.com/jbjLDeGhup
— デデデボっと (@dedede45450721) 2014, 12月 31
##パクツイ機能
TL上のツイートをパクツイします。
わかる。初エンドカードがごちうさ、強すぎる
— デデデボっと (@dedede45450721) 2015, 1月 5
アカ名連呼機能
TLにいるアカウントの名前を呼びます。
デデデはホモ
— デデデボっと (@dedede45450721) 2015, 1月 12
飯テロ機能
毎日決まった時刻に飯テロをします。
— デデデボっと (@dedede45450721) 2015, 1月 14
他にも**「自分以外の相手への『ありがとう』に対して『どういたしまして』と返す」や
「『おはよう』に対して『おやすみ』と返す」、「『〜致します』に対して『致すな』と返す」**など、
もう少し細かい機能はありますが、基本的にはこれだけです。
みんなの反応
@dedede45450721 自動リプの内容がまじで本人かと思った
— じゃがよこ (@potato_eeic) 2014, 12月 17
このクオリティの高さな RT @dedede45450721 かりばぁはね、ホモ。
— かりばぁ (@KRiver1) 2014, 12月 30
@dedede45450721 リプ送ろうとしてid見るまで気づかなかった…
— えるこはる (@spi_you_LK) 2015, 1月 24
「クオリティが高い」と評してくれている人も多く、
原作と同じ、いや原作を超えたと言っても過言ではないでしょう。
デデデボっとの中身
こうしてデデデボっとは多くの人から好意的に受け入れられました。
しかし中身は本当に単純です。
例えば、パクツイ機能は次のように実装されています。
if(!twflag && (
text.match(/よな$/) != null ||
text.match(/よな。$/) != null ||
text.match(/よな…$/) != null ||
text.match(/だな$/) != null ||
text.match(/だな。$/) != null ||
text.match(/だな…$/) != null ||
text.match(/では$/) != null ||
text.match(/すぎる$/) != null ||
text.match(/すぎる…$/) != null ||
text.match(/やん$/) != null ||
text.match(/よね$/) != null ||
text.match(/かよ$/) != null ||
text.match(/かよ。$/) != null ||
text.match(/かよ…$/) != null ||
text.match(/思った$/) != null ||
text.match(/んですよ$/) != null ||
text.match(/なあ$/) != null ||
text.match(/なぁ$/) != null ||
text.match(/.+すごい$/) != null
)) {
tweetMsg = "わかる。" + text;
twflag = true;
}
特定の語尾を持つツイートを見つけたら、「わかる。」を頭に付けてツイートするだけです。
語尾でフィルタリングしているのは、ある程度文章化されたツイートのみを取り出すためです。
10時頃に起床ツイートをすると「不可」と返ってくることがあります。
が、これもこんな感じです。@dedede45450721 botなのにやるじゃん
— えるこはる (@spi_you_LK) 2015, 1月 15
if( !twflag && (
text.match(/寝坊/) != null ||
text.match(/寝落ち/) != null ||
text.match(/度寝/) != null ||
text.match(/寝ぶっち/) != null ||
text.match(/おはようございます…/) != null
)) {
if(Math.random() < 0.4) {
tweetMsg = "@" + result.user.screen_name + " 不可";
options = "in_reply_to_status_id=" + result.id_str;
twflag = true;
}
}
いわゆる「絶起」の際には「おはようございます…」と三点リーダをつける人が多いので、
時間を見なくても、これを検出するだけでそれっぽくなります。
クソリプに至っては、14種類の中からランダムに選ぶだけです。
文脈は当然考慮しません。
if(result.entities.media != null || Math.random() < 0.4) {
tweetMsg = "@" + result.user.screen_name;
var min = (new Date()).getMinutes();
for(var j = 0; j < min % 10; j++) {
tweetMsg += " ";
}
tweetImg = getKusoPicReply();
} else {
tweetMsg = "@" + result.user.screen_name + " ";
tweetMsg += getKusoReply();
tweetImg = NO_IMG;
}
一応工夫した
あまりにシンプルな実装ですが、一応それっぽくなるように多少の工夫を行いました。
変化をつける・インタラクティブにする
常に定型文をツイートしているだけでは、当然飽きられます。
パクツイ機能など、TLに対してインタラクティブに変化するツイートをする必要があります。
またクソリプ機能では、「一度ツイートしたツイートが再度使われる確率を下げる」ような処理を行っています。先ほどのクソリプリストの2列目がそれです。この値は毎日リセットされるようになっています。
なお、3列目の数字は「どの言葉に相対的に重きを置くか」を数値で表しています。
「は?おい」と「ピュ」の頻度が他に比べて高くなるように設定されています。
確率的に動作を決める
先程からコードを読んでいると、Math.random
が多いことに気付くと思います。
上のような機能をただ愚直に実装しただけでは、ただTLを荒らしているだけです。
特定の語尾を呟くと必ず反応されるのでは、それが一種のNGワードとなり、ストレスとなってしまいますし、
反応されてもあまり特別な気持ちになりません。
そのため、特定のワードに常に反応するのではなく、
ある程度の確率でしか反応しないようにすることが大事でした。
数を打つ
デデデボっとは半年間しか稼働しませんでしたが、この間に5000ツイートをしています。
これは全くの個人的な意見ですが、
面白いツイートはかなり強く記憶に残りますが、
面白くないツイートというのは存在すら覚えていません。
数が多ければ、それだけツボに入るツイートも多くなります。
ネガティブ評価を恐れてツイートをしないよりも、多めにツイートをしてたまにツボに入れる程度のほうが、
結果として好印象になりそうです。
本人のトレンドの変化を読み取る
ここまで仕様を書いてきて、もし原作をフォローしている人であれば、「今とはだいぶ仕様が違う」と思うはずです。
(最近は残念ながら、「ピュ」のような見境のないクソリプは減ってしまいました。)
人には自分の中のトレンドがあり、これは意外と短いスパンで変化します。
原作のトレンドの変化を読み取り、頻繁に仕様変更を加えると、ギャップ無く受け入れてもらえるはずです。
それにしたって、これだけシンプルに再現できるのは、やはり「「流石」」と言わざるを得ないでしょう。
デデデボっとはチューリングテストに通るか?
結論から言えば通らないでしょう。
ここまで読んでも、実際に原作を知らない人にとっては、一体どうして騙されるのかが分からないと思います。
そして、恐らく原作も通らないでしょう。
Elizaのような一般的に通用するbotは難しいですが、
ある特定の人物を模すというようなコピーbotを作るなら、アイコンとアカウント名で十分にバイアスがかかってくれるため、比較的簡単です。
あとはチューリングテストに通らなさそうなアカウントを選べば良いというだけのことです。
さいごに
デデデボっとが成功したのは、偏に原作のクソツイートがあったからです。
クソアカウントをありがとう。
デデデボっと(2014-2015)
2015年5月24日、OAuth1.0のサポート打ち切りと同時に、メンテを放棄され永眠。
(享年6ヵ月)