llama.cpp 中的 LLGuidance 支持
LLGuidance 是一个用于大型语言模型(LLM)约束解码(也称为约束采样或结构化输出)的库。该库最初是作为 Guidance 库的后端开发的,也可以独立使用。
LLGuidance 支持 JSON Schema 和使用 Lark 语法变体编写的任意上下文无关语法(CFG)。它具有极高的性能和出色的 JSON Schema 覆盖率,但需要 Rust 编译器,这会增加 llama.cpp 构建过程的复杂性。
构建
要启用 LLGuidance 支持,请使用 LLAMA_LLGUIDANCE 选项构建 llama.cpp:
cmake -B build -DLLAMA_LLGUIDANCE=ON
make -C build -j
在 Windows 系统上,请使用 cmake --build build --config Release 替代 make。
此功能需要安装 Rust 编译器和 cargo 工具。
接口使用
启用 LLGuidance 后,无需新增命令行参数或修改 common_params。当语法规则以 %llguidance 开头时,系统会将其传递给 LLGuidance 处理,而不是使用当前的 llama.cpp 语法。此外,JSON Schema 请求(例如在 llama-cli 中使用 -j 参数)也会传递给 LLGuidance 处理。
对于现有的 GBNF 语法,您可以使用 gbnf_to_lark.py 脚本将其转换为 LLGuidance 的 Lark 格式。
性能表现
在 JSON Schema Bench 测试中,为拥有 128k 个令牌的 llama3 分词器计算"令牌掩码"(即允许的令牌集合)平均需要 50μs 的单核 CPU 时间。p99 时间为 0.5ms,p100 时间为 20ms。这些优异的性能表现得益于词法分析器/解析器的分离设计和多项优化措施。
JSON Schema 支持
LLGuidance 严格遵循 JSON Schema 规范。例如:
additionalProperties默认为true,这与当前的语法不同,不过您可以根据需要设置"additionalProperties": false- 允许任意空白字符
"properties": {}对象中的定义顺序会被保持,无论属性是否为必需(当前语法总是将必需属性排在前面)
不支持的 schema 会返回错误消息——不会静默忽略任何关键字。
为什么不重用 GBNF 格式?
GBNF 缺乏词法分析器的概念。
大多数编程语言(包括 JSON)使用两步处理过程:词法分析器(使用正则表达式构建)将字节流转换为词素(lexeme),然后由 CFG 解析器处理这些词素。这种方法更快,因为词法分析器的计算成本更低,而且词素数量比字节数量少约10倍。
LLM 令牌通常与词素对齐,因此解析器仅在不到 0.5% 的令牌中参与工作,其余工作由词法分析器处理。
但是,用户需要区分词素和 CFG 符号。在 Lark 中,词素名称使用大写,而 CFG 符号使用小写。gbnf_to_lark.py 脚本通常可以自动处理这种转换。更多详细信息请参阅 LLGuidance 语法文档。
错误处理
错误信息目前会打印到 stderr,生成过程会继续进行。未来可能会添加改进的错误处理机制。
注意: 在使用 LLGuidance 时,请确保已正确安装 Rust 编译环境,否则构建过程可能会失败。建议在构建前先验证 Rust 和 cargo 工具的可用性。