执行摘要
- 一句话:修复Responses API多轮对话中推理消息未正确丢弃
- 推荐动作:建议关注
render_for_completion的改动与新增测试,理解如何跨API共享逻辑并精确控制库默认行为。该PR是一个典型的bugfix + cleanup示例,展示了修复多路径不一致问题的策略。
功能与动机
Harmony prompts should drop reasoning from completed turns, but keep reasoning from the current in-progress turn so tool-calling can continue correctly. Responses API previously only relied on Harmony's default filter, which only drops analysis messages when the conversation ends with an assistant final message, leaving stale reasoning from all previous turns when the prompt ends mid-turn on a tool call or tool result. (PR body)
实现拆解
- 移动自动丢弃逻辑:从
parse_chat_inputs_to_harmony_messages中移除auto_drop_analysis_messages调用,改为在共享的render_for_completion函数中调用该函数,使两个API路径在渲染input tokens前都丢弃已完成轮次的analysis消息。
- 禁用Harmony库的默认丢弃:在
render_for_completion中向render_conversation_for_completion传递RenderConversationConfig(auto_drop_analysis=False),防止Harmony编码器重复丢弃。
- 简化Responses上下文构建:删除
_construct_input_messages_with_harmony中一个复杂的slice-delete-reappend循环(实际是no-op),避免混淆。
- 修复构造方法调用:在
responses/harmony.py中将Message.from_author_and_contents(不存在的方法)改为Message(author=..., content=...)。
- 更新测试:新增
test_completed_turns_drop_reasoning验证多轮推理正确丢弃;调整test_serving_chat.py中多轮测试期望,反映当前轮分析消息被保留。
关键文件:
tests/entrypoints/openai/parser/test_harmony_render_parity.py(模块 渲染测试;类别 test;类型 test-coverage;符号 test_completed_turns_drop_reasoning): 新增test_completed_turns_drop_reasoning测试用例,验证多轮对话中推理消息正确丢弃,是此修复的关键验证。
vllm/entrypoints/openai/responses/serving.py(模块 服务层;类别 source;类型 core-logic): 主要源码变更,删除无操作的消息循环,简化_construct_input_messages_with_harmony。
tests/entrypoints/openai/chat_completion/test_serving_chat.py(模块 聊天测试;类别 test;类型 test-coverage): 更新现有测试以反映行为变化:第二轮的输入消息现在应包含当前轮分析消息而非被丢弃。
vllm/entrypoints/openai/parser/harmony_utils.py(模块 解析器;类别 source;类型 core-logic;符号 render_for_completion, parse_chat_inputs_to_harmony_messages): 核心逻辑:将auto_drop_analysis_messages移到render_for_completion并禁用Harmony默认丢弃。
vllm/entrypoints/openai/responses/harmony.py(模块 服务层;类别 source;类型 bugfix;符号 _parse_harmony_format_message): 修复不存在的方法调用bug。
关键符号:auto_drop_analysis_messages, render_for_completion, _construct_input_messages_with_harmony, _parse_harmony_format_message, parse_chat_inputs_to_harmony_messages, test_completed_turns_drop_reasoning
关键源码片段
tests/entrypoints/openai/parser/test_harmony_render_parity.py
新增test_completed_turns_drop_reasoning测试用例,验证多轮对话中推理消息正确丢弃,是此修复的关键验证。
def test_completed_turns_drop_reasoning(self):
"""验证已完成轮次的推理被丢弃,而当前正在进行的推理保留。"""
first_reasoning = "FIRST_TURN_REASONING"
second_reasoning = "SECOND_TURN_REASONING"
# Chat Completions 路径
chat_msgs = self._build_chat_msgs(first_reasoning, second_reasoning)
chat_tokens = render_for_completion([_system()] + chat_msgs)
rendered = get_encoding().decode(chat_tokens)
# 第一轮推理应被丢弃,第二轮推理应保留
assert first_reasoning not in rendered
assert second_reasoning in rendered
# Responses 路径
resp_msgs = self._build_response_msgs(first_reasoning, second_reasoning)
resp_tokens = render_for_completion([_system()] + resp_msgs)
rendered_resp = get_encoding().decode(resp_tokens)
assert first_reasoning not in rendered_resp
assert second_reasoning in rendered_resp
vllm/entrypoints/openai/parser/harmony_utils.py
核心逻辑:将auto_drop_analysis_messages移到render_for_completion并禁用Harmony默认丢弃。
def render_for_completion(messages: list[Message]) -> list[int]:
# 先应用 vLLM 的自动丢弃逻辑(丢弃已完成轮次的分析消息,保留当前轮)
messages = auto_drop_analysis_messages(messages)
conversation = Conversation.from_messages(messages)
# 禁用 Harmony 编码器自带的自动丢弃,因为我们已经处理
token_ids = get_encoding().render_conversation_for_completion(
conversation,
Role.ASSISTANT,
config=RenderConversationConfig(auto_drop_analysis=False),
)
return token_ids
评论区精华
风险与影响
- 风险:自动丢弃逻辑移至
render_for_completion后,所有调用该函数的路径都会应用丢弃,可能影响其他未预期场景,但已有测试覆盖。禁用Harmony默认丢弃依赖 RenderConversationConfig 参数,若未来升级 openai-harmony 版本导致该参数行为变化,需重新验证。移除的循环虽注释为no-op,但考虑其编写时可能另有考虑,不过已有补充测试保障。重构仅针对GPT-OSS Harmony路径,其他模型不受影响。
- 影响:直接影响使用GPT-OSS模型和Responses API的用户,修复了多轮工具调用中推理消息残留导致模型行为异常的问题;Chat Completions路径行为不变;清理冗余代码降低了维护成本;统一推理丢弃策略使两条API路径行为一致。
- 风险标记:核心路径变更, 依赖库默认行为关闭, 测试覆盖新增
关联脉络
- PR #46030 [Refactor] Responses API parser state into conversation context: 同属Responses API重构与修复,改动相同的
responses/serving.py模块。
- PR #44105 [BugFix] Omit empty tool_calls from OpenAI chat responses: 同为前端工具调用相关bug修复,涉及聊天消息处理。
- PR #46441 fix gpt_oss pp>1 with ep: 同为GPT-OSS模型修复,属同一功能线。
参与讨论