本页面介绍了llama.cpp中的语法约束生成功能,该功能允许您将模型的输出限制为遵循特定格式,如JSON、XML或自定义结构化文本。有关通用采样参数和策略,请参阅Token Sampling。
语法约束生成使用户能够定义正式的语法,将模型的输出限制在特定的完整性子集中。这对于以下场景特别有用:
语法系统通过在生成过程的每一步过滤模型的令牌概率分布来工作,删除会导致无效语法结构的令牌。现代llama.cpp将语法约束与聊天模板和工具调用集成,以实现无缝的结构化输出生成。
来源
Llama.cpp 支持多种定义语法约束的格式
JSON Schema 是定义结构化输出约束的主要方法,尤其是在服务器环境和工具调用场景中。json_schema_to_grammar() 函数会自动将 JSON Schema 转换为 GBNF 语法。
此 Schema 会被自动转换为强制执行结构的 GBNF 语法。服务器通过聊天补全中的 json_schema 参数和 response_format 字段支持此功能。
来源
GBNF (Grammar BNF) 是一种类似 BNF 的上下文无关语法格式,但针对令牌级约束进行了优化。它定义了指定有效令牌序列的产生规则。
GBNF 基本语法
rulename ::= definition"literal"[a-z]+ 或 /regex/a | ba b*(零次或多次),+(一次或多次),?(可选)(a | b) cJSON 的 GBNF 语法示例
root ::= object
value ::= object | array | string | number | "true" | "false" | "null"
object ::= "{" ws (string ws ":" ws value (ws "," ws string ws ":" ws value)*)? ws "}"
array ::= "[" ws (value (ws "," ws value)*)? ws "]"
string ::= "\"" ([^"\\] | "\\" .)* "\""
number ::= ["-"]? ([0-9] | [1-9] [0-9]*) ("." [0-9]+)? ([eE] [+-]? [0-9]+)?
ws ::= [ \t\n\r]*
来源
聊天模板可以直接指定语法约束和触发器。这使得格式感知的对话流程成为可能,其中语法是根据对话上下文激活的。
来源
语法约束生成与llama.cpp中的多个系统集成
关键组成部分是
json_schema_to_grammar() 将 JSON Schema 转换为 GBNFcommon_grammar_trigger 定义激活模式来源
现代llama.cpp实现了复杂的语法触发系统,仅在需要时激活约束
| 触发类型 | 描述 | 用例示例 |
|---|---|---|
COMMON_GRAMMAR_TRIGGER_TYPE_WORD | 在特定单词令牌上激活 | 工具调用标记,如<tool_call> |
COMMON_GRAMMAR_TRIGGER_TYPE_PATTERN | 正则表达式匹配 | 函数名称模式 |
COMMON_GRAMMAR_TRIGGER_TYPE_PATTERN_FULL | 完全文本正则表达式匹配 | 复杂格式检测 |
COMMON_GRAMMAR_TRIGGER_TYPE_TOKEN | 特定令牌 ID | 保留的特殊令牌 |
系统维护一组preserved_tokens,这些令牌永远不会被语法约束过滤掉,确保重要的标记(如工具调用边界)可用。
来源
基本语法文件使用
JSON Schema 约束
带触发器的延迟语法
服务器提供了多个用于结构化生成的端点
语法约束在工具调用场景中自动应用
系统会自动生成语法约束,以确保工具调用参数与指定的 Schema 匹配。
来源
语法约束已深度集成到工具调用和聊天模板中,实现无缝的结构化输出。
当在聊天补全中指定工具时,系统会自动生成语法约束。
聊天模板可以指定语法触发器和约束。
语法触发器通过聊天模板系统进行配置。
| 参数 | 描述 | 示例 |
|---|---|---|
grammar_triggers | 触发器模式列表 | [{"type": "word", "value": "<tool_call>"}] |
preserved_tokens | 永远不会被语法过滤的令牌 | ["<tool_call>", "</tool_call>"] |
grammar_lazy | 启用延迟语法激活 | true |
测试套件验证了跨不同聊天模板的语法行为。
来源
对于高级用例,您可以编写自定义 GBNF 语法。
root规则开始。ws规则以实现灵活的间距。来源
语法约束生成会产生额外的计算开销,该开销因实现方法而异。
| 策略 | 性能影响 | 用例 |
|---|---|---|
| 延迟语法加载 | 触发前最小化 | 工具调用、条件格式化 |
| 保留的令牌 | 低开销 | 在应用语法时维护特殊令牌 |
| 语法触发器 | 激活前开销极低 | 具有偶尔结构化输出的大型上下文 |
| 简单语法 | 较低的解析开销 | 基本 JSON、简单格式 |
grammar_lazy 功能通过延迟语法激活显著提高了性能。
这在仅偶尔需要结构化输出的聊天场景中尤其有效。
语法解析会创建其他数据结构
对于长上下文长度,延迟加载通过在需要时避免语法结构分配来减少内存压力。
来源
语法约束生成与llama.cpp的其他功能无缝集成
语法约束应用于投机解码,以确保草稿令牌保持有效。
语法约束可与多模态模型(LLaVA)配合使用,以确保即使在处理图像时也能获得结构化的响应。
服务器的连续批处理系统为每个槽维护独立的语法状态。
语法与完整的聊天模板生态系统集成。
| 模板功能 | 语法集成 |
|---|---|
| 工具使用模板 | 函数调用的自动语法生成 |
| 推理格式 | 用于结构化思维模式的语法 |
| 多轮对话 | 上下文感知语法激活 |
| 自定义格式 | 模板定义的语法触发器 |
语法约束在所有llama.cpp后端之间一致工作
来源
如果您遇到语法问题:
llama-gbnf-validator 工具验证语法文件。对于更复杂的语法创建,请考虑使用专门的工具或库来从其他格式生成 GBNF。
来源