首页
/ llama.cpp PEG 解析器实战指南:流式解析模型输出、构建 AST 与生成 GBNF 文法

llama.cpp PEG 解析器实战指南:流式解析模型输出、构建 AST 与生成 GBNF 文法

2026-09-06 21:04:08作者:江焘钦

本文基于 llama.cpp 的官方开发文档 docs/development/parsing.md,系统讲解 common 库中的 PEG(Packrat/Earley 风格)解析器:如何用组合子(combinators)以 DSL 方式构建模型输出解析器,如何通过"标签节点"生成带语义的 AST,以及如何将同一套 PEG 定义转换为 GBNF 文法约束采样。读完本文,你将能够自行编写针对特定模型输出格式的解析器,并理解它与聊天模板、语法约束生成之间的协作关系。

一、定位:两套类型前缀与三大特性

llama.cpp 的 common 库内置了一个专为"解析模型输出"设计的 PEG 解析器。文档明确将其分为两类 API:

文档列出的三大核心特性,在源码中都能找到直接对应:

  1. 流式输入的部分解析(partial parsing)。解析结果类型 common_peg_parse_result_type 定义了三种状态:FAILSUCCESSNEED_MORE_INPUT(见 common/peg-parser.h 第 66-70 行)。当模型输出尚未到达终止符时,解析器不会报错,而是返回 NEED_MORE_INPUT 并保留已确认的 AST 节点——在 common/peg-parser.cpp 中可以看到大量 COMMON_PEG_PARSE_RESULT_NEED_MORE_INPUT 的返回点,分别覆盖字面量、重复、字符类等各组合子的"输入可能还没完"分支。每个 AST 节点还带有 is_partial 标志(common_peg_ast_node::is_partial),mapper 在提取数据时会跳过尚未闭合的部分节点(例如 common/chat-peg-parser.cppif (!node.is_partial) 的大量判断)。这正是逐 token 流式解析得以工作的基础。

  2. 内置 JSON 解析器。builder 直接提供 json()json_object()json_array()json_string()json_number()json_bool()json_null()json_string_content()json_member(key, p) 等组合子;此外源码中还有文档未展开的 Python 值解析器(python_value()python_dict() 等)以及 marker()quoted_string() 等工具(见 common/peg-parser.h 第 451-489 行)。

  3. 带语义标签的 AST 生成(tagged nodes)。通过 tag(tag, p) 组合子给子解析器打上语义标签,多个节点可共享同一标签;解析完成后用 mapper 按标签从 AST 中抽取结构化数据(如 reasoning_contentcontentarguments)。AST 由 common_peg_ast_arena 管理,节点包含 ruletagstart/endtextchildrenis_partial 字段,并提供 find_by_tag / find_by_rule 辅助检索。

二、完整示例:解析带 JSON 参数的工具调用

以下是文档给出的示例,演示如何解析"先输出正文、再输出 `

登录后查看全文
热门项目推荐
相关项目推荐