ささきしき

チラシ

言語野と戯れる

Mastodon を始めとする各種 Fediverse's SNS の中で、 :don: (末代とも)、mikutter、 およびその近辺でたむろしている零細・個人サーバ勢をここではひっくるめて雑にオタク共と呼ぶが、そのオタク共のなかで最近にわかに流行っているのが個人 bot である。 ある人物の発言(toot)を教師データにとって、任意の手法を用いて*1生成された文章を bot アカウントに発言させることで、予期されない面白い文章が生まれたりしたりしなかったりするのをなんとなく楽しんだりしている。

さて、そんな bot ブーム(?)であるが、おそらく、多分きっと、もしかすると、オタク共のなかで最初に bot の運用を始めたのは私ではないかと思っている。 これは勝手にそう思っているだけなので何の信憑性もないが、時にはそういう思い込みも必要だろうということで、第一人者(笑)として筆を取った次第である。

現在オタク共の bot で多く採用されている(と思われる)プログラムの源流は https://github.com/naaaaaaaaaaaf/mastodon-markov-bot である。 何を隠そうこれを書いたのが私——という訳ではなく、私は私で別なプログラムを用立てて使っている。 というのは、そもそも私が何のために bot を立ち上げたのか、という話になってくるので、そんな思い出話をしつつ、私が書いたコードを雑に紹介しつつ、今後 my new bot するオタク共のために雑に知見を残したり残さなかったりしようと思う。

経緯

はるか昔*2オタクたちのお喋りツールとして隆盛を誇った Twitter というサービスに、「メカらこ」という bot がいた。 この bot は、らこ@laco0416 氏*3 によってメンテナンスされていたが、前述ようなお喋り機能の他に、ユニークな機能を複数搭載しており、Twitter のオタクから大変愛されていた(思い出補正++)。 なかでも人気だったのが(?)「bbop」であり、メカらこに規定のメンションを飛ばすと「ビビッドレッド・オペレーション」をランダムに捩った文章を返してくれる機能だ*4

メカらこ自体は Twitter の度重なる仕様変更の煽りを受け稼働を停止してしまって久しいが、往年の賑やかな TL は今でも昨日のことのように云々。 なんて思い出話を数年前にどこかでしたら、らこ氏が当時の bbop コマンドのプログラムを公開してくれたのであった。

ということで、これをなんとか現代に蘇生させようと思い立って造られたのがメカそーたであり、お喋り機能はメカらこリスペクトにあたって追加された副産物なのであった。

メカそーたの諸機能

メカそーたの実装は GitLab で公開している。

gitlab.com

全編に渡って TypeScript で書いた。これは手癖の問題である。 ライブラリの方が充実していれば Deno でホストすることも検討していたが、今回は安定をとって Node.js とした。 公開当初は自宅に置いた RaspberryPi 4B に載せていたが、自宅のインターネット環境に不安があったため、こちらも安定のため GCE に転居した。

主な機能は以下の通りである。

  • 喋る
    • 定期的に喋る
    • 雑にメンションを飛ばすと喋り返す
    • どちらもメカらこリスペクト
  • bbop
  • smap
    • メカらこリスペクト
    • SMAPのメンバー5名の苗字*5をランダムに切り貼りして返す
  • ping
    • 独自機能(のはず)
    • pong とだけ返す
  • btml
    • 独自機能
    • オタク共の間で何故か流行っているブチミリというテンプレート構文を返す。ランダムに他人を巻き込む
  • 勤怠管理
    • 独自機能
    • 規定の文言をメンションすると時間を記録してくれる。今一番ホットに開発している

特に書くこともないのだが、本稿ではとりあえず「喋る」と「勤怠管理」について、経験を交えてもう少し細々と書こうと思う。

喋る

先出の mastodon-markov-bot (以後 Python 版)との機能的な大きな差は、メンションに対応している点と、教師データに用いるデータ数とその参照方法である。 Python 版は、教師データとする特定ユーザに対して API からアクセスして、直近のツーツを幾ばくか抽出している。 それに対しメカそーたは、教師データとするユーザ(つまり私)の Twitter アカウントと Mastodon アカウントの全投稿のべ 13万件*6すべてを利用している。 それもこれもデータエクスポート機能さまさまである。投稿内容を納めた json ファイルが全部で 19MB くらいあってウケる。

また、日本語文を分かち書き*7するための形態素解析に、mecab-ipadic-neologd を用いている。 mecab のオプション辞書という位置付けで、ウェブ上のトピックから抽出された語句で辞書を更新しているので、新語に明るかったりするらしい。 個人の呟きなどは新語スラングなんでもござれであるからして、なるべくナウい辞書を採用しておくのが良い解析を生むのではないかと思う。 加えて、自分が普段使う独特な言い回しなどがあれば、ユーザ辞書として自分で語句登録しておくとなお良い。 フレンドのスクリーンネームだとか、 mastodon で使える絵文字のコマンド文だったりとかは、独自の固有名詞であることが多いので、積極的に登録しておくといい。

注意すべき点としては、URL およびハッシュタグの取り扱いがある。 昨今の SNS では、「http://example.com/~~~ 」「#○○」と書くとその部分がリンクになる機能が標準的に搭載されていることが多い。 ご多分漏れず Fediverse SNS でも搭載されている機能だが、これは bot の文章出力と相性が悪い。 というのも、基本的なマルコフ連鎖を用いた文章生成ライブラリは分かち書きで出力されるものが多く、それを標準的な日本語文にするために空白を詰める処理を挟むことが一般的である。 そうすると、URL やハッシュタグを区切るための空白も一緒くたに詰めてしまうことになり、結果としてhttps://example.com/←このツイートめっちゃウケるwwwwといった具合になったり*8、「#大正こそこそ噂になってるんだけど何かやらかしたのアイツ?」のように後続の文章を巻き込んだ URL やタグが生成されてしまったりする*9

Python 版はこれを完全に黙認しているが、メカそーたは教師データ作成の前に元データから URL とハッシュタグを削除することで対応している。 現状では生成された後の文章だけを見て URL やハッシュタグとそうでない文の境界を判別することは難しく、妙なリンクやタグを発生させて二次影響を心配するくらいなら最初から無い方が管理が楽という消極的解決策である。 教師データを作成する前に元データをスクレイピングして URL とハッシュタグだけ予めユーザ辞書に書き込んでおくとかするといいのかしらん。いつかやるかも。

同様に、空白を詰める都合で文章が壊れがちなものとして、英文がある。 英文はそもそも分かち書きを前提としているので、日本語文用の空白詰めをそのまま適用してしまうと「Thisisapen」*10のようになって見た目によろしくない。 メカそーたでは分かち書きされた要素がラテン文字かどうかを判別して空白を足し直す処理を追加している。 まあまあの精度。

そのほか、気をつけるとそれっぽい文章になる設定として、文章の長さがある。 文章生成 bot 界で使われるようなマルコフ連鎖ライブラリには、出力文章の文字数制限ができるものが多い。 このときに、長くても100字くらいで制限しておくと、比較的支離滅裂な文章が発生しづらい傾向がある(肌感覚)。 というよりは、200字制限くらいで生成すると、1文内で文意が二転三転することが増える。 おそらく1文70字くらいが文意を乱さずに接続できる限界であり、それ以上文章を伸ばそうとすると変になる、ということだと思う。 論文や作文を書くなどする上でも1文の長さはそれくらいにと教わったように思うので、それくらいがいいんだと思う(適当)。

括弧に気を遣うのも、よりそれっぽい文章になる一助である。 …と一口に言っても実際はやたら難しいのでメカそーたでも現状無視している項目だが、これはなかなかやりがいがあるように思われる。 数多くの文章のつぎはぎで作られた生成文には、「」や()の対応がとれていない箇所が生まれることがある。 その場合どう処理をするのか。 ただ削除するだけでいいのか、それっぽい箇所に対応する括弧を追加するのか。 入れ子になっている場合はどうするか。 《「「」》と片方が足りない場合はどちらを優先して対応させるか。 考えることは多くあり、この処理ひとつで構文解析ライブラリができるのではと疑っている。 効果的な解決法を思いついた人がいたら教えてください。

その他メカそーた特有の問題としては、選定したマルコフ連鎖文章生成ライブラリがどうもバグっているのか、文章生成に偏りがあるように見受けられている。 最近は自作するかなぁ〜と思っている。 あと教師データの大きさの都合なのか常駐してるときのメモリ使用量が気になるんだよな。この辺なにかしらダイエットを検討してもいいかもしれない。

今話題の GPT-3 とかブン回してみてぇよなぁ〜〜

勤怠管理

個人的な話だが、最近は知人に雇われて時給雇用でITエンジニアとして働いている。 そのため、何時間働いたのかを計測する必要があるのだが、世に存在する勤怠管理アプリ、タイムカードアプリでは、基本的な要求が満たせないことがわかった。

一般的な労働というものは、毎日必ず同じ時間に働き始め、毎日同じ時間休み、残業することはあれど基本的には毎日同じ時間に終業する。 ところが私はゴミクズなので、適当な時間に作業を始め、適当な時間休み、適当な時間働いている。 そもそも働かない日もある。一日で複数回労働することもある(案件別などの理由により)。 そうなってくると、開始終了時刻を決め打ちする必要のあるアプリは候補から外れ、また1日に複数回出退勤できないと困る。 結局そんな都合の良いアプリはなく、じゃあアプリまるっと作るか〜〜だりィ〜〜とぼやいていた折に、mastodon に出退勤報告をしているオタクの話を聞き、UI を SNS に委譲することで工数をサボる方法を思いついたのだった。

具体的には、予め定めた文章をメカそーたに送ると、メカそーた側で時刻を保持して DB に保存させている。 また、メカそーたへの送信部分を iOS のショートカットアプリを用いて API を叩く仕様にすることで、わざわざ文字を打つ手間なく行えるようにしている(これもオタク諸氏の手法を参考とした)。

f:id:sota_n:20201212030325j:plain
ショートカットの入力画面

現在はコマンドも「勤怠管理」の上、私のアカウントからのコマンドしか受領しない設定となっているが、いずれ一般に時間管理コマンドとして開放したい。

そのほかのコマンド

こっちが主目的で立ち上げた bot だけど、移植しただけなので説明することはないんですよね。 ぜひ Fediverse にお立ち寄りの際は遊んでください。

まとめ

んなもんねぇ〜〜〜〜〜

あっ仕事探してます。人手が欲しい案件あったらご連絡ください。


この記事は「mstdn.maud.io Advent Calendar 2020」またの名を「A:don:vent Calendar」12日目の担当でした。 記事冒頭で言及した「オタク共」が各々好き勝手にやいのやいの書いてるだけなので、カレンダーの方向性みたいなものは無いに等しいと思います。 ためになるオタクからマジでしょうもないオタクまで取り揃えられておりますので、お暇な折がありましたら読んでみてください。

adventar.org

本文おわり

*1:ほとんどがマルコフ連鎖を使っていると思う。

*2:オタクは過剰修飾をしがち

*3:このアカウントは凍結されている。Twitter君のせいです。あーあ。

*4:当時同作がオタクうちで流行ってたんだと思うけど細かい背景は忘れました。

*5:当時。ここに注釈必要になるかもなんて当時は全く想像してなかったなぁ…(オタク)

*6:ただしここからリツイートなどが除かれるので実際はもう少し減る

*7:「私 は 日本人 です」のように、単語で区切る記法

*8:これはわざとそれっぽく書いた

*9:これは「#大正こそこそ噂話」の一部が他の文章と接続してしまった例

*10:これはもちろん This is a pen である。