尧图网站设计 尧图网站设计YAOTU DESIGN
ARTICLE DETAIL

资讯详情

深耕网站设计与一线实操的经验洞察。

mistral.rs 中使用 Lark 语法约束生成:从 lark_llg 示例到 llguidance 底层实现

mistral.rs 中使用 Lark 语法约束生成:从 lark_llg 示例到 llguidance 底层实现 mistral.rs 中使用 Lark 语法约束生成从 lark_llg 示例到 llguidance 底层实现【免费下载链接】mistral.rsFast, flexible LLM inference项目地址: https://gitcode.com/GitHub_Trending/mi/mistral.rs本文围绕 mistral.rs 仓库中的可运行 Python SDK 示例 examples/python/lark_llg.py 及其自动生成的文档 docs/src/content/docs/examples/python/lark-llg.md系统讲解如何在 mistral.rs 中通过grammar_typelark为 LLM 解码过程施加语法约束并下沉到Constraint枚举、llguidance 集成与SequenceRecognizer的源码链路。读完本文你将掌握 Lark 语法与内联 JSON Schema 的写法、ChatCompletion 请求的参数组合方式以及该能力在推理引擎中的完整执行路径可直接复用到自己的结构化输出场景中。一、示例概览一份可运行的 grammar-constrained 生成脚本lark_llg.py是 mistral.rs 众多 Python SDK 示例之一其 Markdown 文档由 docs/scripts/render_examples.py 从源码自动渲染生成文档头部标注了generated by docs/scripts/render_examples.py; edit the source example instead。该示例的核心意图非常明确用 Lark 文法强制模型先输出一段自由推理Reasoning再输出一个受 JSON Schema 约束的 JSON 对象。完整脚本如下与文档内容一致from mistralrs import Runner, Which, ChatCompletionRequest runner Runner( whichWhich.Plain( model_idmicrosoft/Phi-3.5-mini-instruct, ), num_device_layers[500], ) # see llguidance syntax docs for details on grammar syntax top_lark r start: Reasoning: /./ \nJSON: answer answer: %json { type: object, properties: { answer: {type: string, enum: [Yes, No]} }, required: [answer], additionalProperties: false } res runner.send_chat_completion_request( ChatCompletionRequest( modeldefault, messages[ { role: user, content: If all dogs are mammals, and all mammals are animals, are dogs animals?, } ], max_tokens100, temperature0.1, grammar_typelark, grammartop_lark, ) ) print(res.choices[0].message.content) print(res.usage)脚本的构成可以拆成四块Runner 构建通过Which.Plain声明加载一个纯文本指令模型microsoft/Phi-3.5-mini-instruct并通过num_device_layers[500]指定层放置策略Lark 语法定义top_lark是一个 raw stringr...内部混合了字面量 token、正则 token 与内联 JSON Schema请求发送ChatCompletionRequest中同时携带grammar_typelark与grammartop_lark结果输出打印生成文本res.choices[0].message.content与 token 用量统计res.usage。二、逐段拆解Runner 与模型加载配置2.1 Which.Plain 与 model_idWhich是 mistral.rs Python SDK 中描述“加载哪种模型、如何加载”的枚举入口。Which.Plain表示直接加载 Hugging Face 上的普通非 LoRA、非 GGUF 量化模型model_idmicrosoft/Phi-3.5-mini-instruct指定仓库 ID。示例选用小尺寸指令模型目的就是让脚本在普通机器上也能快速跑通从而聚焦“语法约束”这一主题本身。2.2 num_device_layers 的作用num_device_layers[500]用于控制层到设备的映射列表中的每个元素对应一个设备值为该设备上放置的层数。这里的500远大于模型实际层数实际效果等价于“把所有层都放到默认设备上”。需要多 GPU 或 CPU/GPU 混排时可以改为类似[25, 25]前半部分层放设备 0、后半部分放设备 1这样的写法。三、Lark 语法详解混合正则与内联 JSON Schema示例中的top_lark是 llguidance 所支持的 Lark 文法Lark 是一种流行于 Python 生态的解析器生成器文法llguidance 复用了其语法表示用于约束 token 级解码。逐行解读如下start: Reasoning: /./ \nJSON: answer answer: %json { type: object, properties: { answer: {type: string, enum: [Yes, No]} }, required: [answer], additionalProperties: false }片段含义start:顶层规则解码必须从该规则开始匹配Reasoning: 字符串字面量 token模型输出中必须原样出现/./正则表达式 token.匹配任意字符表示一或多个即“任意长度的自由文本”此处即模型自由推理部分\nJSON: 换行与固定前缀JSON:的字面量约束answer引用下面的子规则%json { ... }内联 JSON Schema在文法内部直接嵌入一段标准 JSON Schemallguidance 会将其编译为对应的生成约束%json内联块中使用的 Schema 字段含义type: object要求输出是一个 JSON 对象properties.answer声明对象包含answer字段类型为字符串enum: [Yes, No]该字段只允许取Yes或No两个值required: [answer]对象必须包含answer键additionalProperties: false不允许出现 Schema 之外的额外键。也就是说这份文法把模型的输出空间“锁死”为Reasoning: 任意文本\nJSON: {answer: Yes 或 No}。对上面的逻辑题一个合法输出形如Reasoning: Yes, by the transitive property, dogs are animals. JSON: {answer: Yes}由于grammar参数是一个 Python raw string文法是按字面字节传给引擎的\n会被解释为换行符本身而不是反斜杠加n这一点对约束“换行后再输出 JSON”至关重要。四、请求参数grammar_type 与 grammar 的配对规则4.1 ChatCompletionRequest 中的相关参数ChatCompletionRequest在 mistralrs-pyo3/src/requests.rs 中定义grammarOptionString与grammar_typeOptionString是其中的可选字段在类型声明文件 mistralrs-pyo3/mistralrs.pyi第 172、225 行附近中也可见其默认值为None。CompletionRequest补全接口同样支持这两个参数。4.2 底层校验逻辑build_constraint两个参数最终汇聚到 mistralrs-pyo3/src/lib.rs 的build_constraint函数其行为可以归纳为一张规则表grammar_typegrammar结果未提供未提供Constraint::None无约束未提供已提供报错Grammar text is specified but not grammar type已提供未提供报错Grammar type is specified but not grammar textregex正则表达式文本Constraint::RegexlarkLark 文法文本Constraint::Larkjson_schemaJSON Schema 文本会被serde_json解析解析失败报错Constraint::JsonSchemallguidancellguidance JSON 对象文本如{grammars: [...]}Constraint::Llguidance其他值—报错提示只支持regex、lark、json_schema、llguidance因此grammar_type与grammar必须成对出现只给其一都会直接抛错。这也是本示例中同时传grammar_typelark与grammartop_lark的原因。4.3 核心数据结构Constraint 枚举构造出的Constraint定义在 mistralrs-core/src/request.rs是贯穿推理引擎的核心类型pub type LlguidanceGrammar llguidance::api::TopLevelGrammar; pub enum Constraint { Regex(String), Lark(String), JsonSchema(serde_json::Value), Llguidance(LlguidanceGrammar), None, }可以看到Python 层的四种grammar_type与 Rust 层的四个约束变体一一对应lark分支保存的正是我们传入的 Lark 文法字符串后续由 llguidance 编译为可执行的解析器。五、源码级原理Lark 约束在推理引擎中的完整执行路径grammar-constrained decoding 的实质是每一步解码时用文法解析器计算当前 token 序列下“合法”的下一 token 集合并在采样阶段把不满足约束的 token 屏蔽掉。mistral.rs 中这条链路由四个环节构成。5.1 构建 llguidance 运行环境build_llg_factorymistralrs-core/src/pipeline/llg.rs 的build_llg_factory(tokenizer)负责从 Hugging Face Tokenizer 构造llguidance::ParserFactory提取 ByteLevel decoder若 tokenizer 的 decoder 是单层Sequence且内部为ByteLevel则只保留这一层在消费 tokenizer 之前收集特殊 tokenspecial tokens信息并对TokTrie中缺失SPECIAL_TOKEN_MARKER前缀的特殊 token 做修正源码注释指出 Tekken 系 tokenizer 会把特殊 token 先加进 BPE 基础词表容易导致前缀标记丢失将toktrie_hf_tokenizers::ByteTokenizer与TokTrie组装成 token 环境最终ParserFactory::new_simple(env)。不同 pipeline 在构建时都会调用它并把结果存入 pipeline 元数据中的llg_factory: OptionArcllguidance::ParserFactory见 mistralrs-core/src/pipeline/mod.rs例如普通文本 pipeline mistralrs-core/src/pipeline/normal.rs、GGUF pipeline mistralrs-core/src/pipeline/gguf.rs、GGML pipeline 以及多模态 pipeline 均有此调用。相反embedding、diffusion、speech 等 pipeline 的llg_factory为None意味着这些模型不支持语法约束。5.2 文法到 TopLevelGrammarllg_grammar_from_constraint同一文件中的llg_grammar_from_constraint把Constraint翻译成 llguidance 的统一文法表示TopLevelGrammarConstraint::Regex→TopLevelGrammar::from_regexConstraint::Lark→TopLevelGrammar::from_lark本例走的就是这条路径Constraint::JsonSchema→TopLevelGrammar::from_json_schemaConstraint::Llguidance→ 直接使用已解析的TopLevelGrammar。也就是说无论用户用 regex、Lark、JSON Schema 还是 llguidance 原生对象声明约束最终都会统一为同一种 llguidance 文法只是入口不同。5.3 生成解析器并注册识别器build_sequence_recognizer在 mistralrs-core/src/engine/mod.rs 的build_sequence_recognizer中调用llg_grammar_from_constraint得到OptionTopLevelGrammarConstraint::None返回None若文法存在则要求llg_factory必须存在否则报错No token environment (llg_factory) found.通过constraint_from_llg_grammar创建llguidance::Matcher内部调用factory.create_parser(grm)包装为SequenceRecognizer::Llguidance。SequenceRecognizer定义于 mistralrs-core/src/sequence.rs作为Sequence结构体的recognizer字段同文件第 823 行随序列生命周期保存。采样阶段见 mistralrs-core/src/pipeline/sampling.rs 附近对metadata.llg_factory的使用据此对每一步 logits 施加约束。此外投机解码speculative decoding路径中 verifier 与 driver 也会克隆llg_factory以保证候选 token 校验与目标模型约束一致。六、延伸用法命名 JSON Schema 引用与服务器端等价能力6.1 对比示例llguidance.py 的命名 Schema仓库中的另一个示例 examples/python/llguidance.py 展示了同一需求的另一种写法——把 Lark 文法与 JSON Schema分开定义再用myobj在文法中引用top_lark r start: Reasoning: /./ \nJSON: myobj answer_schema { type: object, properties: {answer: {type: string, enum: [Yes, No]}}, required: [answer], additionalProperties: False, } grammars [ {lark_grammar: top_lark}, {name: myobj, json_schema: answer_schema}, ] res runner.send_chat_completion_request( ChatCompletionRequest( modeldefault, messages[...], max_tokens30, temperature0.1, grammar_typellguidance, grammardumps({grammars: grammars}), ) )两种方式对比维度lark_llg.py本文示例llguidance.pygrammar_typelarkllguidanceSchema 位置%json内联在文法中独立的 JSON Schema经myobj命名引用适用场景单一约束、文法自包含多个命名 Schema 复用、文法与 Schema 分离管理可见grammar_typelark适合自包含的短文法而复杂项目多个可复用 Schema更适合走llguidance的{grammars: [...]}结构。6.2 服务器端OpenAI 兼容 API 的 Grammar 枚举同样的能力在服务器端亦有映射。mistralrs-server-core/src/openai.rs 定义了带 serde tag 的Grammar枚举四种变体与 Python 端一一对应regex、json_schema、llguidance、lark。Responses API 中还可以通过format字段声明自定义 grammar 工具例如该文件第 2338 行的文档示例使用{type: grammar, syntax: lark, definition: start: x}来描述一个 Lark 语法的结构化输出工具。也就是说本文讲解的 Lark 约束能力不仅限于 Python SDKmistralrs-server的 HTTP 接口同样支持便于在服务化部署中复用同一套文法。七、运行与验证7.1 安装与执行在 Python 3.10 环境中安装 mistralrs 后直接运行即可首次运行会自动下载microsoft/Phi-3.5-mini-instruct权重与 tokenizerpip install mistralrs python examples/python/lark_llg.py若本机 GPU 显存有限num_device_layers[500]的组合能保证模型完整落到单一设备上CPU 环境下 mistralrs 同样可以运行只是速度较慢。7.2 预期输出res.choices[0].message.content应严格符合文法形态Reasoning: 模型自由推理的若干字符 JSON: {answer: Yes}其中answer只能是Yes或No由enum约束保证print(res.usage)会输出本次请求的 token 用量统计提示、补全与总 token 数。7.3 常见踩坑点参数必须成对grammar_type与grammar缺一不可否则build_constraint直接抛错\n是换行Lark 文法请使用 raw string确保\nJSON: 被解析为真实的换行约束文法要能“收尾”start规则必须完整覆盖输出包括结束符号否则解码可能无法自然终止或与 EOS 冲突模型需支持embedding、diffusion、speech 类 pipeline 的llg_factory为None对这些模型传入语法约束会得到 “No token environment (llg_factory) found.” 之类的错误温度与 max_tokens 建议结构化输出场景建议使用较低temperature示例用 0.1并给足max_tokens以兼顾确定性与完整性。八、小结lark_llg示例展示了 mistral.rs 中 grammar-constrained decoding 的一个典型形态用grammar_typelark 一份混合字面量、正则与内联 JSON Schema 的 Lark 文法让模型在“自由推理 结构化 JSON”的组合约束下生成。从实现上看grammar/grammar_type经 mistralrs-pyo3/src/lib.rs 的build_constraint转为Constraint::Lark再经 mistralrs-core/src/pipeline/llg.rs 的 llguidance 集成编译为TopLevelGrammar与Matcher最终以SequenceRecognizer::Llguidance的形式在采样阶段逐 token 生效——这条链路同时服务于 Python SDK、补全接口、OpenAI 兼容服务器端与投机解码路径是 mistral.rs 结构化输出能力的统一底座。【免费下载链接】mistral.rsFast, flexible LLM inference项目地址: https://gitcode.com/GitHub_Trending/mi/mistral.rs创作声明:本文部分内容由AI辅助生成(AIGC),仅供参考
返回列表