mistral.rs 正则约束解码实战用 Python SDK 让 LLM 只输出符合 regex 的文本【免费下载链接】mistral.rsFast, flexible LLM inference项目地址: https://gitcode.com/GitHub_Trending/mi/mistral.rs本文基于官方 Python SDK 示例regex讲解 mistral.rs 中基于正表达式的约束解码constrained decoding能力如何通过grammar_typeregex强制模型输出只包含指定字符集如[0-9A-Z ]的文本并深入源码剖析grammar参数在 PyO3 绑定层的解析流程、四种受支持的语法类型以及该机制在采样管线中的落地位置。读完后你将能够直接复制运行示例并理解从 Python 请求到 Rust 约束对象之间的完整调用链。示例主题把生成结果锁死在字符集合内mistral.rs 文档站中的 regex 示例页 指向的可运行源码位于 examples/python/regex.py。该示例的核心意图是向模型提出一个开放式问题Tell me a short joke.但通过正则约束把输出空间限制为「数字、大写字母与空格」组成的序列。这展示了结构化输出中粒度最细的一类约束——不要求 JSON不要求 Lark 文法而是直接对每个 token 的合法性做屏蔽masking使模型在解码过程中根本无法生成字符集之外的内容。完整可运行代码与参数解析以下是 examples/python/regex.py 的完整源码可直接保存运行from mistralrs import Runner, Which, ChatCompletionRequest runner Runner( whichWhich.Plain( model_idmicrosoft/Phi-3.5-mini-instruct, ), num_device_layers[500], ) res runner.send_chat_completion_request( ChatCompletionRequest( modeldefault, messages[{role: user, content: Tell me a short joke.}], max_tokens30, temperature0.1, grammar_typeregex, grammarr[0-9A-Z ], ) ) print(res.choices[0].message.content) print(res.usage)各参数的作用如下参数取值说明whichWhich.Plain(model_id...)microsoft/Phi-3.5-mini-instruct以纯文本Plain方式加载模型Which枚举还支持 GGUF、LoRA、多模态等其它加载形态本示例只用最普通的权重加载路径num_device_layers[500]指定加载到计算设备的层数。示例写成字符串列表500表示该值支持按设备维度传入如多卡时可按卡分配层数500层意味着全量放入设备Phi-3.5-mini 总层数小于该值modeldefault请求中的模型名占位符单模型 Runner 下使用default即可max_tokens30限制生成长度配合约束解码可快速验证只能输出白名单字符的行为temperature0.1低温采样在约束已限定字符集的前提下进一步稳定输出grammar_typeregex声明约束类型必须与grammar同时提供见下文源码校验逻辑grammarr[0-9A-Z ]正则表达式本身一个或多个「数字 / 大写字母 / 空格」注意grammar使用的是 Python 原始字符串r...避免反斜杠被解释本例中的模式[0-9A-Z ]要求至少一个字符因此模型不能输出空内容。源码剖析grammar参数如何变成约束对象在 PyO3 绑定层grammar与grammar_type是成对出现的可选字段。类型存根 mistralrs.pyi 中ChatCompletionRequestL171–L172与CompletionRequestL224–L225都声明了grammar: str | None None grammar_type: str | None None即聊天补全与原始补全两条 API 都支持正则约束。真正决定约束类型的入口是 mistralrs-pyo3/src/lib.rs 中的build_constraint函数它在每次发送请求时被调用chat/completion 等多个入口如 L1416、L1900、L2377、L2754 处fn build_constraint(grammar: Optionstr, grammar_type: Optionstr) - PyApiResultConstraint { if grammar_type.is_none() { if grammar.is_some() { return Err(PyApiErr::from( Grammar text is specified but not grammar type, )); } return Ok(Constraint::None); } let grammar grammar.ok_or_else(|| PyApiErr::from(Grammar type is specified but not grammar text))?; let constraint match grammar_type.unwrap() { regex Constraint::Regex(grammar.to_string()), lark Constraint::Lark(grammar.to_string()), json_schema { /* 先 serde_json 解析再 Constraint::JsonSchema */ } llguidance { /* 解析 llguidance 对象再 Constraint::Llguidance */ } _ return Err(PyApiErr::from( Grammar type is specified but is not regex, lark, json_schema, nor llguidance, )), }; Ok(constraint) }从中可以确认三条实现事实成对校验只给grammar不给grammar_type、或只给grammar_type不给grammar都会直接抛错错误信息分别为Grammar text is specified but not grammar type与Grammar type is specified but not grammar text。受支持的类型白名单regex、lark、json_schema、llguidance四种。regex分支把字符串原样包装成Constraint::Regexjson_schema与llguidance分支则要求grammar是合法 JSON解析失败会带原因返回错误。默认无约束两个字段都为None时返回Constraint::None行为退化为普通自由解码。约束在采样管线中的生效位置Constraint对象最终流入引擎的采样管线。从 mistralrs-core/src/pipeline/sampling.rs 的源码结构看约束解码与工具调用tool call共用同一套基于 llguidance 的流中激活语法规则机制L64 的activate_required_tool_call_grammar会通过maybe_force_required_grammar在序列到达指定长度时强制激活语法约束L233 起的注释明确说明Mid-stream grammar activation for tool calls当检测到工具调用前缀且尚无活动语法时构建格式专属的 grammar 并激活使后续 token 的 logits 被语法规则屏蔽工具调用的格式级语法构建块集中在 mistralrs-core/src/tools/grammar.rs例如build_json_format_grammar组合 Lark 外层文法与json_bodyJSON Schema 子语法。可以推断用户侧通过grammar_typeregex传入的正则约束与工具调用自动注入的 Lark/JSON Schema 约束在引擎侧走的是同一类每步解码前根据当前已生成内容过滤合法 token的机制。区别在于前者由请求显式携带、贯穿整个生成过程后者由模型格式解析器在中途按需激活与解除如 L1527–1529 在工具调用体完成后clear_active_grammar。同一机制下的其它约束示例examples/python 目录提供了与regex.py平行的另外三个约束示例可与本篇对照阅读lark.pygrammar_typelark用 Lark EBNF 文法描述结构如 JSON 对象文法表达能力强于正则json_schema.pygrammar_typejson_schema直接传入 JSON Schema适合强类型结构化输出llguidance.pygrammar_typellguidance传入 llguidance 的编译对象用于需要复用/离线编译语法的场景。选择建议依据 lib.rs 中的白名单只约束字符集/简单序列时正则最轻本例即此场景需要嵌套结构时优先json_schema需要自定义文法细节时用lark性能敏感或需要预编译语法的复杂场景考虑llguidance。运行前提与注意事项示例依赖 Hugging Face 上可用的microsoft/Phi-3.5-mini-instruct模型权重与分词器缓存首次运行会拉取模型文件num_device_layers[500]要求设备显存足以容纳全部层显存不足时可改小该值。约束解码会改变输出分布即使 prompt 要求讲个笑话模型也只能拼出[0-9A-Z ]允许的大写字母、数字与空格组合这是预期行为而非模型没听懂。若希望约束覆盖到流式返回ChatCompletionRequest的stream参数默认为False启用流式后每个增量 token 同样受同一约束对象控制。本文所有行为均以当前仓库代码为准四种grammar_type取值与成对校验逻辑见 mistralrs-pyo3/src/lib.rs#L905-L938字段默认值见 mistralrs-pyo3/mistralrs.pyi。【免费下载链接】mistral.rsFast, flexible LLM inference项目地址: https://gitcode.com/GitHub_Trending/mi/mistral.rs创作声明:本文部分内容由AI辅助生成(AIGC),仅供参考
