🦙

llama.cppにおけるJSON Schemaパーサーの調査と仕様

に公開

llama.cppプロジェクトに実装されている、JSON Schemaを解析し、それに基づいてGBNF(GGML BNF)形式の文法を生成する機能についての調査結果をまとめます。

https://github.com/ggml-org/llama.cpp

1. 機能の概要

llama.cppは、JSON SchemaをGBNF文法に変換する機能を持ちます。これにより、大規模言語モデル(LLM)の出力を、指定されたJSON構造に厳密に準拠させることが可能になります。

この機能はcommon/json-schema-to-grammar.cppファイル内のjson_schema_to_grammar関数によって提供されています。

https://github.com/ggml-org/llama.cpp/blob/caf5681fcb47dfe9bafee94ef9aa8f669ac986c7/common/json-schema-to-grammar.cpp#L954

2. 主要な実装コンポーネントと処理の流れ

変換処理の中心はcommon/json-schema-to-grammar.cppに実装されているSchemaConverterクラスです。

https://github.com/ggml-org/llama.cpp/blob/caf5681fcb47dfe9bafee94ef9aa8f669ac986c7/common/json-schema-to-grammar.cpp#L726

  • エントリーポイント: json_schema_to_grammar関数が変換プロセスの入り口となり、nlohmann::ordered_json型のJSON Schemaオブジェクトを受け取ります。
  • 中心的なクラス: SchemaConverterクラスが実際の変換ロジックを担います。

2.1. 再帰的なスキーマ解釈 (visitメソッド)

JSON Schemaの解釈は、SchemaConverter::visit メソッドによって再帰的に行われます。

  1. visit メソッドは、JSON Schemaの断片(ノード)を受け取ります。
  2. if-else if構文を使い、$ref, oneOf, type, properties などのキーワードを優先順位に従って評価し、処理を分岐させます。
  3. オブジェクトのプロパティや配列の要素など、入れ子になったスキーマに対しては、visitメソッド自身を再度呼び出すことで再帰的に解釈を進めます。
  4. 再帰は、"type": "string" のようなプリミティブ型に到達した時点で停止し、あらかじめ定義された基本ルールが返されます。

2.2. 参照の解決 (resolve_refsメソッドと$defsの扱い)

スキーマ内の参照はresolve_refsメソッドによって解決されます。

  • $ref: "$ref" キーワードを見つけると、その参照先(内部または外部)のスキーマを解決します。
  • $defs: "$defs" キーワード自体を直接処理するロジックはありません。代わりに、"$ref": "#/$defs/my_definition" のようなJSONポインター形式の参照をresolve_refsメソッドが解釈することで、$defsセクションで定義されたスキーマが間接的にサポートされます。

3. サポートされるJSON Schemaキーワード

SchemaConverterがGBNF文法を生成する際に解釈するキーワードは以下の通りです。

schema_type (typeキー) 関連する子要素 (キーワード) 説明
(型を問わない) $ref 最優先。参照先のスキーマを解決する。
(型を問わない) oneOf, anyOf, allOf 複数のスキーマを組み合わせるための論理演算子。
(型を問わない) const 特定の定数値と完全に一致することを要求する。
(型を問わない) enum 値が列挙リスト内のものであることを要求する。
object properties, additionalProperties, required オブジェクトの構造(プロパティ、必須項目、拡張性)を定義する。
array items, prefixItems, minItems, maxItems 配列の要素のスキーマや個数を定義する。
string pattern, format, minLength, maxLength 文字列の正規表現、フォーマット、長さを定義する。
integer / number minimum, maximum, exclusiveMinimum, exclusiveMaximum 数値の範囲を定義する。

4. サポートされないJSON Schemaキーワード

JSON Schemaの仕様にはドキュメンテーションやメタデータのためのフィールドも含まれますが、これらはGBNFの構文定義に直接関係しないため、SchemaConverterでは無視されます

具体的には、以下のフィールドは文法生成のロジックで考慮されません。

  • title
  • description
  • default
  • examples

これらのフィールドは、あくまでスキーマの可読性や開発者向けの補助情報として扱われます。

関連記事

llama.cppで構造化出力がどのように処理されるかを調査しました。

https://zenn.dev/7shi/articles/fa36989a04c9ed

構造化出力の効率的な利用方法を探るため、複数のLLMを対象に5つの異なる指示形式を比較します。

https://zenn.dev/7shi/articles/20250704-structured-output

GitHubで編集を提案

Discussion