しりとりぼっと開発。
16万語の名詞リストからゲームに使ったらまずい単語を除くべく、 ChatGPT (gpt-4o, API) で単語分類をやってみた。
難しかったのは、フィルタリングの基準を設定することと、大量のデータを小分けにして投入することの2つ。
今回は1つ目、フィルタリングの基準設計と system instructions について。
これまでの話:しりとりぼっと
しりとりでは、「ぼっと (bot)」と「あなた(ユーザー)」がかわりばんこに単語を出していく。
- 「しりとり辞書」
- 形態素解析器 Sudachi の辞書から名詞を取り出して作成、約16万語
- ここでいう名詞:
名詞,普通名詞,一般
または名詞,普通名詞,サ変可能
- 様々なテキストを形態素解析できるように、あらゆる名詞が入っている
- あまり一般に知られていない単語(専門用語、化学物質や文学表現など)や、存在が微妙な単語(ググっても情報が見つからない)も含まれる
- 一般的に差別用語とされる単語、使うときには慎重に場面を選ぶような単語も入っている
- ここでいう名詞:
- 形態素解析器 Sudachi の辞書から名詞を取り出して作成、約16万語
- 現状、しりとりで bot のターンで出力する単語は、「しりとり辞書」からランダムに取っている
- 今回、しりとり辞書からbot が出したらまずい単語を除去したい
- ※ ただし、ユーザーのターンでは、今回のフィルタリングとは無関係に、形態素解析器の辞書にある限りは何でも使えることとする
- 事前に見つけた不適切表現リスト:
- LDNOOBW/List-of-Dirty-Naughty-Obscene-and-Otherwise-Bad-Words: List of Dirty, Naughty, Obscene, and Otherwise Bad Words
- 多言語、日本語 (ja) は180語
- MosasoM/inappropriate-words-ja: 日本語における不適切表現を収集します。自然言語処理の時のデータクリーニング用等に使えると思います。
- 日本語、offensive 49語 + sexual 281語
- うーん、最低限かもしれないが少なすぎる
- LDNOOBW/List-of-Dirty-Naughty-Obscene-and-Otherwise-Bad-Words: List of Dirty, Naughty, Obscene, and Otherwise Bad Words
- 「不適切」って、ネット掲示板とかチャットルームや、広告とか、まあいろんな時と場合によって違う
- なので、独自の基準を設定する必要がある
API をどう使うか
参考ページ
- Text generation - OpenAI API
- Batch - OpenAI API
- Batch API ではリクエストを投げておくと 24 時間以内に処理される
- 今回投げた感じ、1時間以内〜10時間とか、さまざま(週末は混むとかある?)
- 利用料が半額、1日で処理できる量も多い
- 公式チュートリアルとドキュメントがわかりやすく、公式 SDK も使いやすい
基本的な構成
- completions
model: gpt-4o-2024-08-06
role: system
のcontent
に、system instructions を書く- フィルタリングの基準とデータ入出力形式の説明
role: user
のcontent
に、評価対象データを入れる- csv 形式、1 completion あたり 100語
- アウトプットも csv 形式
- Batch API でリクエストを投げる
- 1 batch あたり 100 completions とした
- 16万語ちょいなので、100 words * 100 completions * 17 batches
system instructions を書く
フィルタリングの基準
- 「楽しいゲーム」「bot のターンで使う」というと、「りんご」「ゴリラ」「ラッパ」みたいな、みんな知ってる無害で退屈な単語しか残らなさそう
- これはゲームデザイン次第
- 「みんな知ってる」でなくてもいい
- しりとりしながら新しい言葉を学ぶのは楽しいので、あまり一般に知られていない単語(専門用語、化学物質や文学表現など)も OK としたい
- 「無害」かどうかの線引きは難しい
- しりとりのようにたくさんの単語が一瞬で過ぎていくゲームなら、少々暗く悲しい印象を与えるような単語が現れても問題ないかもしれない
- 歴史的な事件などをしりとりで単語として出すことは、学びにつながるかもしれない(例:「下放」:かつて中華民国、中華人民共和国で行われた、国民を地方に送り出す政策 - Wikipedia)
- 武器でも、「カタナ」とかはしりとりにありふれていそうだし
- 一つの単語がしばらく画面上に表示され続けるゲームだと、明るく楽しい印象を与えるような単語だけを使いたいかもしれない
- いずれにせよ、一般的に差別用語とされる単語や、他にも「それをゲームに出すのはさすがにちょっと…」というものはあると思うが
- しりとりのようにたくさんの単語が一瞬で過ぎていくゲームなら、少々暗く悲しい印象を与えるような単語が現れても問題ないかもしれない
- 悩みはじめたらキリがないし、仮に決めてやってみよう(適宜見直していこう)
- 「みんな知ってる」でなくてもいい
微妙な基準をどう system instructions に落とし込むか?
- 一般に LLM のプロンプトでは、文脈を明示することが重要だと言われているが
- 単語ゲームで「bot のターンで選択する」 vs. 「私が使う」
- まあ、厳密にいうと他にも色々試行錯誤して改善したんだけど
- bot が使う旨を instruction に書くと、Assistant (ChatGPT) は「bot ≒ Assistant」と受け取るっぽい
- 「人当たりのいいAIアシスタント」がその単語を使うかどうか、という基準に近くなる
- 👉 使わないほうがいいほうに分類される単語が多めになる
- たとえば、「イタ飯」「DDT」「下放」「地獄」など
- 「私(I/me, おれ)」が使う旨を instruction に書くと、Assistant は「ユーザーの自由を尊重する」っぽい
- 👉 使わないほうがいいと判断される単語が少なめになる
- それでも「めくら」などはまずいほうに分類する
- 背景事情をすべて書いてしまうと重要な部分がぼやけるので、すべてを正直に打ち明ける必要はない
- 問題をシンプルに保とう
…プロンプトエンジニアリングって言葉の魔術か何かなの?
単語リスト(評価対象データ)の入出力形式
- 入出力する単語リストの形式は、カンマ・改行区切り (csv) とした
- 入力:
{index},{word},{reading}
- 出力:
{index},{word},{label},{comment}
- 入力:
- reading (単語の読み)は、SudachiDict にカタカナで入っているのを pykakasi でローマ字に変換したもの
- リアルタイム処理時には Structured Outputs - OpenAI API を使って出力形式を指定するのが便利そうだが
- アプリケーションに組み込んでユーザー入力をその場で処理する用途では、出力形式が合ってないエラーは深刻になるから、それを防げるのは重宝するよね〜
- とはいえ今、Batch API 利用時に structured outputs が使えるのかどうか、よくわからない…
- json 形式のカッコや項目名は、出力 token 数に含まれるんだろうか(今回、大量のデータを効率的に処理したいので、出力をなるべくコンパクトにしたい)
- 今回はバッチ処理
- structured outputs は使わずに system instructions で指定
- 入出力データの項目はそれほど多くないので、csv でも混乱しにくい
- まあ、形式がそれほど厳密でなくても、後処理でなんとかなるだろう
- ごく希にアウトプットに
Here's the breakdown for the provided words:
とかのメッセージが入ってた(後処理で除ける)
その他のテクニカルな話
- 今回は system instructions は英語で書いた
- 英語のほうが token 数の効率がいいので
- Tokenizer - OpenAI Platform
- 日本語理解力は、gpt-4o は gpt-4 よりも飛躍的に向上したが、まだ差があり、英語のほうがだいぶ強い印象
- 自分が日本語書く時よりも英語書く時のほうが、簡潔で明示的に書く傾向があるというのも影響してるとは思う
- system instructions を書いたら、まずは playground で試してみる
- Chat Playground - OpenAI API
- temperature, maximum length も適宜調整
- temperature は 0~2 の範囲、デフォルト 1 だが、今回は 1.1 にしてみた
- temperature を上げたほうがコメントが詳しく柔軟になる印象
- temperature はランダムネスなので、上げすぎるとアウトプットが壊れ(途中から意味不明のめちゃくちゃになり)やすくなるっぽい
- gpt-4o と gpt-4o-mini ではだいぶ応答が違うので、使うつもりのモデルはそれぞれ試したほうがいいね
- gpt-4o-mini では今回の「微妙なライン」をうまく捉えきれず、フィルタリングが厳しすぎたり、見落としがあったりした
- モデルにより、扱える context length が異なるというのもある
- 言うまでもないかもしれないかもしれないが、一般ユーザー向け ChatGPT は OpenAI 謹製の system instructions が既に入っているので、playground/API で自分で system instructions を指定するのとは全然違う
- とはいえ、system instructions を書いていて表現に迷ったら ChatGPT に相談してみるのはアリ
system instructions の冒頭部分はこんな感じ
全体は GitHub で公開しようかなあ しています。
Hey buddy! You are my sidekick in building a rich word game database. I will throw you a list of words, and your job is to kick me back if I shouldn't play with the word. Basically, I want you to save my ass from falling into the territory of offensive or discriminatory language. Oh, don't worry - you are not my mom - some witty, spicy words are fine to play with.
Ready to hear how to kick me back?
次回、大量のデータを小分けにして投入 に続く
最近読んでる本のアフィリエイトリンク