経緯
markovifyを用いて自分のツイートから文章を自動生成してツイートするbotを作った。
ツイートするだけじゃ物足りないのでリプライを送る機能を追加しようとした。
リプライを送る際、送り先のツイートから単語を抜き出してその単語を起点として文章を自動生成しようとした。
ここでエラーが発生した。
内容
発生箇所のコードは以下の通り
model = markovify.Text(text, well_formed=False, state_size=3)
sentence = model.make_sentence_with_start(beginning='テスト')
エラーの内容は以下の通り
KeyError: ('___BEGIN__', '___BEGIN__', 'テスト')
これは、テスト
という単語を起点としてマルコフ連鎖を行い文章を自動生成する処理。
make_sentence_with_start
関数の引数beginning
が起点となる文字を表している。
markovify
、KeyError
というキーワードで検索するとwell_formed=False
にするといい、という記事が多数ヒットするが、上記にある通り、それはすでにやっている。
ではなぜエラーが発生するのか。
スタックトレースを見てみるとエラーの発生している箇所は、markovifyライブラリの以下のところ。
choices, weights = zip(*self.model[state].items())
どうやらself.model
の中に該当するKeyがないのが問題らしいです。
この中には学習したテキストが格納されるのですが、ここで疑問に思ったのが「学習したテキストに完全一致しないと文章を自動生成できないの?」ということ。
そこでmake_sentence_with_start
の中を見ていると、ありました。
引数にstrict
というものがあり、以下のようにコメントが書かれていました。
If strict == True, then markovify will draw its initial inspiration
only from sentences that start with the specified word/phrase.
If strict == False, then markovify will draw its initial inspiration
from any sentence containing the specified word/phrase.
英語なのでよくわからないですが、strict
という名前なので厳密にみるかどうかを表しているようです。
先ほどの「キーが学習内容に完全一致しないとエラー」という話に通じる気がします。
この引数はデフォルトでTrue
になっているので、ここをFalse
にするとKeryErrorが発生しなくなりました!
model = markovify.Text(text, well_formed=False, state_size=3)
sentence = model.make_sentence_with_start(beginning='テスト', strict=False)
まとめ
markovifyのmake_sentence_with_start
で単語を起点に文章を自動生成する際、その単語から始まる学習データがないとエラーなる。
その際には引数にstrict=False
を指定すると解決する。
参考資料