1章
基礎知識等のため、いったん割愛。今後詰まったら読み返して記載する。
全32パターンをこれから学ぶ。
2章:コンテンツスタイルの制御
基盤モデルによって生成されるコンテンツのスタイルを制御することについて。
モデルのレスポンスは確率的なので、アプリケーションでレスポンスのスタイルを制御する必要がある。
- パターン1:ロジットマスキング
- パターン2:グラマー
パターン1:ロジットマスキング
一連の規則に準拠したテキストの生成をモデルに強制する。
- ロジット(Logit)
- ディープラーニングや統計学において、「確率(0〜1)に変換される前の、モデルが計算した生の出力値(スコア)」のこと
- テンソル(Tensor)
- 機械学習やディープラーニングにおいて、データを管理・計算するための「多次元配列(Multi-dimensional Array)」というデータ構造のこと
問題
LLMを用いてテキスト生成を行う際に、特定のスタイル規則に従うように生成させたい(ブランド戦略、正確性、スタイルなど)
アンチパターン
コンテンツの生成後、関連ルールによる評価を行い、却下・再生成する方法。
これは試行錯誤がほぼ必須となり、収束しない可能性も。
解決方法
基盤モデルは継続するシーケンスの候補からサンプリングしてテキストを生成する(ビームサーチ)
このサンプリング段階で生成を横取りするイメージ。
ロジットマスキングの機能
- 完全なコンテンツが生成されるまで待たずに、各中間地点で候補となる継続テキストのセットを取得
- 規則を満たさない継続テキスト候補の確率を0にする
- 規則を満たす継続テキストが1つでもあれば生成を続行
- 規則を満たす継続テキストがなくなったり、行き止まりであることがわかったら一段後退し、生成をやり直す
- 最大試行回数を超えた場合は、規則を満たすコンテンツを生成できないことをユーザーに伝える
サンプルコード
以下に、処理の流れ、内部機構のポイント、およびデータフローを記述。
1. 処理の流れ(データフローと状態遷移)
本実装における処理は、トークナイザによるID変換から始まり、LLMの推論、ロジットの変形、そしてサンプリングへと至る一連のパイプラインで構成される
フェーズ1: 入力テキストのエンコード
- Input: ユーザーが入力した文字列(プロンプト)
- 処理: トークナイザにより、文字列が語彙辞書(Vocabulary)に対応するトークンIDのシーケンス(テンソル)に変換
-
Output: トークンID配列(形状:
[1, sequence_length])
フェーズ2: モデル推論による生ロジットの出力
- Input: トークンID配列
- 処理: トークンID配列がLLMの層を順伝播(Forward Pass)します。モデルの最終線形層(LM Head)によって、次のトークン予測のための未正規化の対数確率(ロジット)が計算される
-
Output: 生のロジットテンソル(形状:
[1, vocabulary_size])
フェーズ3: ロジットマスクの適用
- Input: 生のロジットテンソル、および許可(または禁止)するトークンIDのリスト
- 処理:
- 語彙数(
vocabulary_size)と同じサイズのマスク用テンソルを初期化 - 生成を許可したいトークンIDのインデックスに対しては変更を加えず、排除したいトークンIDのインデックスに対して、負の無限大(通常は
-float('inf')または-1e9などの極端に小さな負の値)を代入 - 生のロジットテンソルとマスク用テンソルを加算(または要素ごとの要素置換)
-
Output: マスク処理済みのロジットテンソル(形状:
[1, vocabulary_size])
フェーズ4: Softmax計算とサンプリング
- Input: マスク処理済みのロジットテンソル
- 処理:
- ロジットテンソルに対してSoftmax関数を適用し、確率分布に変換。この際、
-infが代入されたインデックスの確率は数学的に $0$($e^{-\inf} = 0$)となる - 確率が $0$ になったトークンはサンプリング候補から完全に排除され、残った候補の確率の総和が $1$ になるよう再正規化
- 変形された確率分布に基づき、次のトークンIDがサンプリング
-
Output: 決定された次のトークンID(形状:
[1, 1])
2. 実装の主要なポイント
Notebookにおける技術的な要点
負の無限大(-inf)による確率の抹殺
ロジットに直接 0 を乗算するのではなく、-inf を加算するアプローチをとります。Softmax関数の定義は以下の通りです。
$$P(x_i) = \frac{e^{z_i}}{\sum_{j} e^{z_j}}$$
特定のインデックス $i$ のロジット $z_i$ を $-\inf$ に設定することで、$e^{-\inf} = 0$ となり、分子が $0$ になるため、そのトークンが選択される確率を厳密に $0$ に制御できる
Hugging Face LogitsProcessor の利用
Notebook内では、Hugging Faceの transformers ライブラリが提供する LogitsProcessor クラスを継承してカスタムマスクを実装している
__call__ メソッド内で現在の入力ID(input_ids)と生ロジット(scores)を受け取り、インプレースまたは新規テンソルとしてマスク済みロジットを返す構造になっており、これにより、model.generate() のループ処理内部にインターセプトする形でロジット制御が埋め込まれる
例
当初のプロンプト
# システムプロンプト
あなたは栄養サプリメントのマーケティング担当者である。
顧客を引きつける製品説明と、検索エンジン最適化と
広告ガイドラインに正確に収まるバランスを取れ
# ユーザープロンプト
プロテインドリンクの製品説明を書け
掲載が禁止される可能性のある単語が生成内容に含まれることで、ビジネス上のリスクを孕む内容の出力される可能性がある
これに対し、ロジットマスキングにより、望ましい特徴を持つシーケンスを採用し続けることでルールを満足するアウトプットを得る
考察
- 禁止された選択肢を除外する検閲を実現する場合に有用
- 代替手段
- プロンプトエンジニアリングでの回避
- ほかパターンの適用