2026-09-15
重构结构化输出与投机解码的约束起点契约
值得精读,且建议按「契约 → 消费方 → 测试」的顺序读:先看 `vllm/v1/structured_output/__init__.py` 的 `_get_constraint_start()`,它是整个 PR 唯一的语义来源;再看 `scheduler.py` 三个调用点确认新契约的用法;最后看 `test_structured_output_manager.py` 的 `FlowCase` / `_run_real_flow()` 理解验证方式。重点关注四个设计决策:(1) 用 `len + 1` 哨兵而非 `None` 表达「本窗口无约束」,三个消费点的 `>=` / `>` / `<=` 各有语义,不要「顺手统一」;(2) 降序扫描把语义从「第一次边界」改成「最后一次边界」,这对交错思考模型更合理但改变了行为;(3) 断言降级为日志是刻意的(避免 engine core 被打挂),代价是失败请求要等 accept 阶段兜底;(4) 「reasoning parser 必须无状态」目前只是文档契约,落地前不建议在生产上把 stateful parser 与投机解码 + 结构化输出组合使用。
headless 模式提前导入 reasoning parser 插件,修复启动 KeyError
值得花 5 分钟精读,属于“改动小、信息密度高”的启动顺序修复。重点看三处:①`run_headless()` 中插件导入必须早于 `create_engine_config()` 的时序原因(配置期 `ReasoningConfig.initialize_token_ids()` 解析 `--reasoning-parser`);②测试用 `_StopAfterEngineConfig` 异常 + `MagicMock.side_effect` 做“进入配置构造前必须已导入”的断言写法,是低成本验证启动顺序的可复用模式;③QwertyJack 提出的 CI 目录覆盖未落实,说明这条回归保护实际可能悬空——建议后续把该类测试迁入 `tests/entrypoints/launchers/` 或扩展 entrypoints-unit-tests 作业,同时考虑是否有其他 headless/DP 入口需要同样的插件预导入。
reasoning 结束判定统一由语法派生,删除多模型 override
值得精读,尤其推荐 parser / structured-output 方向的 owner 逐段读 `ParserEngine.is_reasoning_end` 的新实现与两条新测试。三个最值得关注的设计决策:一是把「无标记尾部」语义显式提为 config 字段而不是继续散落在模型分支里;二是用「从初始状态出发的 `THINK_START` 迁移是否进入 REASONING」来区分惰性 `<think>` 与真正打开 reasoning,这一条同时支撑了 thinking off 的行为修正;三是用 `turn_boundary_tokens` 而非更长的手写分支来限定回合。阅读时请一并记住作者自曝的三处未解决项(`extract_content_ids` 分歧、未声明边界的 latch、gemma4 惰性 `<|tool_response>`),若后续要动这些模型的 `continue_final_message` 或多轮工具调用,应优先补上边界声明与针对性用例。
DSv4.1 工具调用启用 XGrammar schema 约束并保留旧版回退
值得精读,但重点不在代码量。源码只有 13 行,真正的价值是三点设计模式:用 `getattr(module, name, None)` 做跨版本能力探测以规避 ImportError、把 grammar 构造委托给上游 builtin 时显式覆盖 `reasoning="disabled"` 以维持 serving 的推理边界契约、以及用 `skipif(hasattr(...))` + `monkeypatch` 双写测试同时锁定新路径与回退路径。建议读者额外关注:(1) 后续 XGrammar bump PR 是否把 ≥ 0.2.7 落到依赖与镜像;(2) 是否补一条带真实权重的 tool-calling eval,验证 strict 约束不会引发重采样或误截断;(3) 回退分支的删除时机与对应测试清理。
xgrammar 后端放行简单 patternProperties/propertyNames,并守卫会静默错编译的组合
值得精读,尤其是 `vllm/v1/structured_output/backend_xgrammar.py` 中守卫逻辑的分支条件,和 `tests/v1/structured_output/test_utils.py` 的测试范式升级(`grammar_accepts` + 独立 fixture)。建议重点追问四件事:一是布尔形式的 `propertyNames` / `additionalProperties` 是否也应纳入守卫;二是运行环境的 xgrammar 版本下限是否已在镜像或依赖中锁定到 0.2.1;三是 `patternProperties` 与 `properties` 共存时的拒绝是否应配合更友好的错误提示(当前用户只能看到 VLLMValidationError);四是上游 #749/#826 修复后由谁负责回访放宽守卫。若线上开启了结构化输出,建议用真实的 MCP schema 集合回归一遍,而不是只依赖单测。
修复 Gemma4 解析器静默丢弃裸 tool_call
值得精读。该 PR 展示了 FSM 解析器应对模型非规范输出的一种最小干预模式:单个终端 + 单条转移即可修复整类静默丢失问题,且依赖 lexer 最长匹配优先级保证零回归。建议关注两点:一是 `TOOL_PREAMBLE -> TOOL_NAME` 转移与 #53657 逃逸舱口的协同设计,二是测试对"畸形+规范混合序列"的覆盖方式,这种场景最容易暴露 FSM 状态泄漏。