AI・機械学習
上級
Grammar-Constrained Decoding(グラマー コンストレインド デコーディング)
LLMのトークンサンプリング時にBNF/EBNF等の形式文法を使い、文法的に無効なトークンのlogitを-∞にマスクして構造化テキストのみを生成する推論技術。
0 回閲覧
0 いいね
2026/6/6 更新
関連タグ
構造化出力
LLM推論
形式文法
BNF
トークンマスキング
Grammar-Constrained Decodingとは
LLMのデコード(推論)ステップで形式文法(BNF/EBNF等)を使い、文法違反トークンのlogit(確率スコア)を-∞に設定してサンプリングから排除する技術。これにより「必ずJSONになる」「必ずSQLになる」出力が確実に得られる。
動作原理
生成ステップ t での処理:
1. 現在のパース状態 S_t から「次に来うるトークン集合」T_valid を計算
2. 語彙 V 全体のlogit l を LLM から取得
3. V \ T_valid に含まれるトークンの logit を -∞ にマスク
4. マスク後のlogitでソフトマックス→サンプリング→次トークン決定
5. パース状態を S_{t+1} に更新、繰り返し
文法記述フォーマット
| フォーマット | 使用ツール | 特徴 |
|---|---|---|
| GBNF | llama.cpp | llama.cpp独自拡張BNF、JSON/SQL/コード対応 |
| EBNF | Outlines, lm-format-enforcer | 標準的、Python正規表現とも統合 |
| JSON Schema | Outlines, XGrammar, OpenAI | JSONに特化、自動変換対応 |
| 正規表現 | Outlines, guidance | 単純パターン向け |
GBNFの例(llama.cpp)
# JSONオブジェクト(name: string, age: number)
root ::= "{" ws "\"name\":" ws string "," ws "\"age\":" ws number "}"
string ::= "\"" [^""]* "\""
number ::= [0-9]+
ws ::= [ \t\n]*
JSON Schemaからの自動変換
Outlines・XGrammarはJSON Schemaを受け取り内部的に文法へ自動変換する:
from outlines import models, generate
model = models.transformers("mistralai/Mistral-7B-v0.1")
schema = {
"type": "object",
"properties": {
"name": {"type": "string"},
"score": {"type": "number", "minimum": 0, "maximum": 100}
},
"required": ["name", "score"]
}
generator = generate.json(model, schema)
result = generator("製品名とスコアをJSONで返して")
# 常に {"name": "...", "score": XX.X} 形式を返す
パフォーマンスへの影響
| 実装 | オーバーヘッド | 方式 |
|---|---|---|
| 素朴なマスキング | 10〜50% | ステップごとに全文法再評価 |
| XGrammar | <1% | コンパイル済みオートマトン + GPU並列 |
| Outlines(FSM) | 1〜5% | 有限状態機械をキャッシュ |
| llama.cpp GBNF | 2〜10% | Wasm統合、単スレッド最適化 |
よくある質問(FAQ)
Q1: Grammar-Constrained DecodingはLLMの品質を落とす? A: 文法的には正しいが意味的に最適でないトークンを選ぶ場合はある。ただし実用上の品質低下はほぼ報告されていない。
Q2: ストリーミング出力との相性は? A: 問題なし。各トークン生成時にリアルタイムでマスクを適用するためストリーミングと完全互換。
Q3: どのLLMでも使える? A: 理論上は任意のLLMに適用可能。llama.cppベースモデルとHugging Face Transformersモデルで広くサポートされている。