プロンプト デザインの芸術: プロンプト境界とトークン ヒーリング
これ ( Marco Tulio Ribeiroと共同執筆) は、プロンプト デザインの技術に関するシリーズのパート 2 (パート 1 はこちら)でありguidance
、.
この投稿では、言語モデルで使用される貪欲なトークン化方法が、プロンプトに微妙で強力なバイアスを導入し、不可解な世代につながる方法について説明します。
言語モデルは生のテキストではなく、単語のように一緒に出現することが多いテキストのチャンクであるトークンでトレーニングされます。これは、言語モデルがプロンプトを含むテキストを「見る」方法に影響します (プロンプトは単なるトークンのセットであるため)。GPT スタイルのモデルは、貪欲な方法ですべての入力バイトをトークン ID にマップするバイト ペア エンコーディング(BPE) などのトークン化方法を利用します。これはトレーニングには問題ありませんが、次の例に示すように、推論中に微妙な問題が発生する可能性があります。
プロンプト境界問題の例
HTTP URL 文字列を生成しようとしている次の例を考えてみましょう。
import guidance
# we use StableLM as an example, but these issues impact all models to varying degrees
guidance.llm = guidance.llms.Transformers("stabilityai/stablelm-base-alpha-3b", device=0)
# we turn token healing off so that guidance acts like a normal prompting library
program = guidance('The link is <a href="http:{{gen max_tokens=10 token_healing=False}}')
program()
Notebook output.
guidance('The link is <a href="http{{gen max_tokens=10 token_healing=False}}')()
print_tokens(guidance.llm.encode('The link is <a href="http:'))
print_tokens(guidance.llm.encode('The link is <a href="http://www.google.com/search?q'))
トレーニング中の URL はトークン 1358 ( ) でエンコードされていますが、プロンプトによって://
LLM は代わりにトークン27
( ) を認識します。:
://
実際、モデルは、トークン27
( :
) を見ると、次に来るものが のような「長いトークン」を使用してコロンと一緒にエンコードされた可能性が非常に低いことを意味することをかなり確信できます。モデルのトレーニング データでは、これらの文字://
はコロンと一緒にエンコードされています (後で説明する例外は、トレーニング中のサブワードの正則化です)。トークンを見るということは、そのトークンの埋め込みを見ることと、次に来るものは貪欲なトークナイザーによって圧縮されていないことの両方を意味するという事実は忘れがちですが、プロンプト境界では重要です。
モデルのボキャブラリ内のすべてのトークンの文字列表現を検索して、コロンで始まるトークンを確認しましょう。
print_tokens(guidance.llm.prefix_matches(":"))
print_tokens(guidance.llm.prefix_matches("http"))
# Accidentally adding a space, will lead to weird generation
guidance('I read a book about {{gen max_tokens=5 token_healing=False temperature=0}}')()
# No space, works as expected
guidance('I read a book about{{gen max_tokens=5 token_healing=False temperature=0}}')()
guidance('An example ["like this"] and another example [{{gen max_tokens=10 token_healing=False}}')()
print_tokens(guidance.llm.prefix_matches(" ["))
「トークンヒーリング」で意図しないバイアスを修正
これらの意図しないバイアスを回避するにはどうすればよいでしょうか? 1 つのオプションは、より長いトークンに拡張できないトークン (たとえば、チャットベースのモデルの役割タグ) でプロンプトを常に終了することですが、これは深刻な制限です。
代わりに、guidance
「トークン ヒーリング」と呼ばれる機能があり、プロンプトが終了する前に生成プロセスを 1 トークン分自動的にバックアップし、生成された最初のトークンがプロンプトの最後のトークンと一致するプレフィックスを持つように制限します。この URL の例では、これは を削除し:
、最初のトークンの生成に:
プレフィックスを強制することを意味します。トークン ヒーリングにより、ユーザーはトークンの境界を気にすることなく、プロンプトを好きなように表現できます。
たとえば、トークン ヒーリングをオンにして上記の URL の例をいくつか再実行してみましょう (Transformer モデルではデフォルトでオンになっているため、 を削除しますtoken_healing=False
)。
# With token healing we generate valid URLs,
# even when the prompt ends with a colon:
guidance('The link is <a href="http:{{gen max_tokens=10}}')()
# With token healing, we will sometimes generate https URLs,
# even when the prompt ends with "http":
program = guidance('''The link is <a href="http{{gen 'completions' max_tokens=10 n=10 temperature=1}}''')
program()["completions"]
# Accidentally adding a space will not impact generation
program = guidance('''I read a book about {{gen max_tokens=5 temperature=0}}''')
program()
# This will generate the same text as above
program = guidance('''I read a book about{{gen max_tokens=6 temperature=0}}''')
program()
guidance('An example ["like this"] and another example [{{gen max_tokens=10}}')()
言語モデルのトレーニング方法に精通している場合は、サブワードの正則化がこれらすべてにどのように適合するのか疑問に思うかもしれません。サブワード正則化は、モデルの堅牢性を高めるために、トレーニング中に最適ではないトークン化をランダムに導入する手法です。これは、モデルが常に最適な貪欲なトークン化を行うとは限らないことを意味します。サブワードの正則化は、トークンの境界に対してモデルをより堅牢にするのに役立ちますが、標準の貪欲なトークン化に対するモデルのバイアスを完全に取り除くわけではありません。これは、モデルのトレーニング中のサブワードの正則化の量に応じて、多かれ少なかれトークン境界のバイアスが発生する可能性がありますが、すべてのモデルには依然としてこのバイアスがあることを意味します。また、上に示したように、モデルの出力に強力で予想外の影響を与える可能性があります。
結論
プロンプトを作成するときは、貪欲なトークン化が、言語モデルがプロンプトを解釈する方法に大きな影響を与える可能性があることに注意してください。特に、プロンプトが長いトークンに拡張できるトークンで終了する場合はそうです。この見逃されやすいバイアスの原因は、驚くべき、意図しない方法で結果に影響を与える可能性があります。
これに対処するには、拡張不可能なトークンでプロンプトを終了するか、guidance
の「トークン ヒーリング」機能のようなものを使用して、トークン境界のアーティファクトを気にせずにプロンプトを好きなように表現できるようにします。
この記事の結果を自分で再現するには、ノートブックバージョンを確認してください。