Grammar制約(LLM Guided Decoding)(グラマーセイヤク ガイデッドデコーディング)
Grammar制約(Guided Decoding)とは、LLMのトークン生成時に文脈自由文法(CFG)・正規表現・GBNFなどの形式文法でデコーディングを制約し、出力が指定した構造に100%準拠することを保証する技術である。
Grammar制約(LLM Guided Decoding)とは
Grammar制約(Guided Decoding / Constrained Decoding)は、LLMがトークンを生成する際に、文法規則に基づいて次のトークンの候補を制限する技術である。通常のLLM推論では語彙全体(例: Llama 3の場合128,256トークン)から次トークンを確率的に選択するが、Grammar制約では文法的に許容されるトークンのみをサンプリング対象とする。これにより、JSONやXMLなどの構造化形式への100%準拠が数学的に保証される。クラウドAPI経由のJSON ModeやFunction Callingとは異なり、主にローカル推論エンジンで使用される技術である。
Grammar制約の仕組み
トークンマスキング方式
Grammar制約の基本原理は「トークンマスキング」である。
- 文法規則から現在の状態で許容されるトークン集合を計算
- 許容されないトークンの確率を
-inf(マスク)に設定 - マスク適用後の確率分布からサンプリング
この方式により、文法違反のトークンは絶対に生成されない。計算コストは文法の複雑度とボキャブラリサイズに依存するが、効率的な実装では推論速度への影響を5〜15%程度に抑えられる。
有限状態マシン(FSM)方式
正規表現制約の場合、正規表現をDFA(決定性有限オートマトン)に変換し、各状態で許容されるトークンを事前計算する。Outlinesライブラリがこの方式を採用しており、推論開始前にトークンごとのFSM遷移テーブルをインデックス化することで、実行時のオーバーヘッドを最小化する。
プッシュダウンオートマトン方式
CFG(文脈自由文法)制約の場合、プッシュダウンオートマトン(PDA)を使用する。JSONのようなネスト構造を持つ文法では、スタックベースの状態管理が必要であり、FSM方式では表現できない。llama.cppのGBNF実装がこの方式を採用している。
主要な実装ツール
| ツール | 制約形式 | 対応推論エンジン | 言語 | 特徴 |
|---|---|---|---|---|
| llama.cpp GBNF | GBNF (BNF拡張) | llama.cpp | C/C++ | JSON/SQL/正規表現/任意文法対応 |
| Outlines | 正規表現 / JSON Schema / CFG | vLLM, TGI, llama.cpp | Python | FSM方式で高速。JSON Schemaから自動変換 |
| vLLM Guided Decoding | 正規表現 / JSON Schema | vLLM | Python | Outlinesベース。guided_json/guided_regexパラメータ |
| SGLang | 正規表現 / JSON Schema | SGLang | Python | Compressed FSMで高速化。Outlinesの2〜5倍速 |
| XGrammar | EBNF / JSON Schema | MLC-LLM, vLLM | C++/Python | ByteレベルPDA。マルチGPU並列対応 |
| lm-format-enforcer | 正規表現 / JSON Schema | vLLM, TGI | Python | Character-level enforcement |
GBNF(GGML BNF)
llama.cppで使用されるBNF拡張文法記法。
- 基本構文:
root ::= "{" ws members ws "}"のようにBNFルールを定義 - 文字クラス:
[a-zA-Z0-9]などの正規表現的な文字クラスをサポート - 繰り返し:
*(0回以上)、+(1回以上)、?(0または1回) - JSON用定義済みGrammar:
llama.cpp/grammars/json.gbnfに標準的なJSONの文法定義が付属
Outlines
Python製のGuided Decodingライブラリ。正規表現・JSON Schema・CFGの3つの制約方式をサポート。
- 正規表現制約:
outlines.generate.regex(model, r"[0-9]{3}-[0-9]{4}-[0-9]{4}")のように正規表現パターンを直接指定 - JSON Schema制約:
outlines.generate.json(model, MyPydanticModel)でPydanticモデルからJSON Schema制約を自動生成 - CFG制約:
outlines.generate.cfg(model, grammar_string)でEBNF文法を指定 - インデックス事前計算: 初回実行時にFSM/PDAのトークンインデックスを構築し、キャッシュ。2回目以降の実行はオーバーヘッドが大幅に削減される
vLLM Guided Decoding
vLLMの組み込みGuided Decoding機能。OpenAI互換APIとして提供される。
- guided_json: JSON Schemaオブジェクトを指定。Outlinesバックエンドで制約を適用
- guided_regex: 正規表現パターンを指定
- guided_choice: 選択肢のリストを指定(enumに相当)
- guided_grammar: EBNF文法を指定
- パフォーマンス: Outlinesバックエンドでは10〜15%のスループット低下。XGrammarバックエンドでは5%以下に改善(vLLM 0.6+)
Grammar制約のユースケース
- 確実なJSON出力: ローカルLLM(Llama 4、Qwen 3、Gemma 4など)でJSON形式の出力を100%保証。クラウドAPIのJSON Modeに依存しない自律的な構造化出力
- SQL生成: SQLの文法をGBNFで定義し、構文的に正しいSQLクエリのみを生成。Text-to-SQLタスクの精度向上
- フォームデータ入力: メールアドレス・電話番号・郵便番号などの形式を正規表現で制約し、バリデーションコストを削減
- コード生成: プログラミング言語の文法をCFGで定義し、構文エラーのないコードを生成
- 構造化ログ出力: JSON Lines形式のログエントリをLLMに生成させる際、行ごとの形式を保証
パフォーマンス比較
| ツール | JSON生成速度 (tokens/s) | オーバーヘッド | メモリ増加 | 初回起動時間 |
|---|---|---|---|---|
| GBNF (llama.cpp) | 45-65 | 5-10% | 50-100MB | < 1秒 |
| Outlines (FSM) | 40-55 | 10-15% | 200-500MB | 5-30秒 |
| vLLM + Outlines | 80-120 | 10-15% | 300-600MB | 10-60秒 |
| SGLang (Compressed FSM) | 100-180 | 3-5% | 150-300MB | 5-15秒 |
| XGrammar | 90-160 | 3-8% | 100-200MB | 2-10秒 |
※ Llama 3 8B、A100 GPU、JSON出力タスクでの参考値
よくある質問(FAQ)
Q1: Grammar制約とJSON Modeの違いは何ですか? A: JSON Modeはクラウドプロバイダがモデルレベルで提供する機能で、APIパラメータで有効化する。Grammar制約はローカル推論エンジンが提供する機能で、任意の形式文法(JSON以外も含む)でトークン生成を制約する。Grammar制約は数学的に100%の形式準拠を保証するが、JSON Modeはプロバイダの実装に依存する。
Q2: Grammar制約で推論速度はどの程度低下しますか? A: 文法の複雑度と実装方式に依存する。単純なJSON文法で5〜15%、複雑なネスト構造を持つ文法で15〜25%のスループット低下が典型的。SGLangのCompressed FSMやXGrammarでは最適化により3〜8%程度に抑えられる。初回実行時のFSM/PDAインデックス構築に数秒〜数十秒かかる点にも注意が必要。
Q3: GBNFの文法定義を自分で書く必要がありますか?
A: JSON出力であればllama.cppに付属のjson.gbnfをそのまま使用できる。特定のJSON Schemaに準拠させたい場合はOutlinesやXGrammarを使えばJSON SchemaやPydanticモデルから自動変換される。SQLや独自フォーマットの場合はGBNF/EBNF文法を手書きする必要がある。
まとめ
- Grammar制約はトークン生成時に形式文法で出力を制約する技術で、100%の形式準拠を保証
- GBNF(llama.cpp)、Outlines、vLLM Guided Decoding、SGLang、XGrammarが主要ツール
- JSON・SQL・正規表現パターンなど多様な構造化出力に対応
- スループット低下は最新実装で3〜15%程度に抑制可能
- ローカルLLM活用時のJSON出力保証に特に有効