Prhub

#47138 [Bugfix][Tool Parser] PoolsideV1: fix logprobs AttributeError on Responses API

原始 PR 作者 joerowell 合并时间 2026-07-01 03:14 文件变更 2 提交数 2 评论 0 代码增减 +37 / -2

执行摘要

修复 PoolsideV1 Responses API logprobs AttributeError

社区用户反馈(Hugging Face discussion)PoolsideV1 模型在 /v1/responses 端点上因 logprobs 属性缺失而崩溃,导致工具调用流式解析失败。PR body 明确指出 extract_tool_calls_streaming 直接读取 request.logprobs 导致 AttributeError。

该 PR 是典型的低风险 bugfix,代码改动清晰,测试覆盖完善,建议快速合并。可作为工具解析器请求类型兼容性处理的参考模式。

讨论亮点

无实质性 review 讨论。sfeng33 直接批准。claude[bot] 因 fork 仓库自动评论指出无法执行自动 review。

实现拆解

  1. 修复核心逻辑(vllm/tool_parsers/poolside_v1_tool_parser.py):在 extract_tool_calls_streaming 方法的第 446 行,将原直接判断 if request.logprobs: 替换为多分支条件:使用 getattr(request, "logprobs", None) 兼容 ChatCompletionRequest,再通过 isinstance(request, ResponsesRequest) and request.is_include_output_logprobs() 覆盖 ResponsesRequest。
  2. 新增测试辅助函数(tests/tool_parsers/test_poolside_v1_tool_parser.py)
    • 扩展 _build_responses_request 函数,新增可选参数 include,允许构造带 logprobs 选项的请求。
    • 新增 _stream_partial_start_token 辅助函数,封装流式解析起始 token 的调用逻辑,减少重复。
  3. 新增两个测试用例(tests/tool_parsers/test_poolside_v1_tool_parser.py)
    • test_streaming_responses_request_without_logprobs:验证无 logprobs 时返回 None。
    • test_streaming_responses_request_with_logprobs_emits_empty_delta:验证有 logprobs 时返回空 delta 消息,不崩溃。
文件 模块 状态 重要度
vllm/tool_parsers/poolside_v1_tool_parser.py 工具解析器 modified 6.04
tests/tool_parsers/test_poolside_v1_tool_parser.py 工具解析器 modified 6.55

关键符号

extract_tool_calls_streaming _stream_partial_start_token _build_responses_request

关键源码片段

vllm/tool_parsers/poolside_v1_tool_parser.py core-logic

核心修复文件,修改 extract_tool_calls_streaming 方法中 logprobs 判断逻辑,新增 ResponsesRequest 分支。

# vllm/tool_parsers/poolside_v1_tool_parser.py (head version, lines 444-453)
        tool_calls = list(pending_deltas.values())
        if content is None and len(tool_calls) == 0:
            # 修复:兼容两种请求类型的 logprobs 判断
            # ChatCompletionRequest 使用 getattr 安全读取,ResponsesRequest 调用专用方法
            wants_logprobs = getattr(request, "logprobs", None) or (
                isinstance(request, ResponsesRequest)
                and request.is_include_output_logprobs()
            )
            if wants_logprobs:
                return DeltaMessage(content="")
            return None
        return DeltaMessage(content=content, tool_calls=tool_calls)
tests/tool_parsers/test_poolside_v1_tool_parser.py test-coverage

新增两个流式 Responses 测试用例,覆盖带 / 不带 logprobs 的场景,防止回归。

# tests/tool_parsers/test_poolside_v1_tool_parser.py (head version, lines 80-248 excerpt)
def _build_responses_request(
    *, tool_choice: str | dict[str, Any], include: list[str] | None = None
) -> ResponsesRequest:
    return ResponsesRequest(
        model="poolside-test",
        input=[{"role": "user", "content": "write the file"}],
        tools=[_responses_write_file_tool()],
        tool_choice=tool_choice,
        stream=True,
        max_output_tokens=200,
        include=include, # 新增参数,用于传递 logprobs 选项
    )def _stream_partial_start_token(request: ResponsesRequest):
    """辅助函数:流式解析工具调用起始 token"""
    parser = _make_parser(request)
    delta = parser.tool_call_start_token[0]
    return parser.extract_tool_calls_streaming(
        previous_text="",
        current_text=delta,
        delta_text=delta,
        previous_token_ids=[],
        current_token_ids=[],
        delta_token_ids=[],
        request=request,
    )def test_streaming_responses_request_without_logprobs() -> None:
    """无 logprobs 时应返回 None"""
    request = _build_responses_request(tool_choice="auto")
    assert _stream_partial_start_token(request) is Nonedef test_streaming_responses_request_with_logprobs_emits_empty_delta() -> None:
    """有 logprobs 时应返回空 delta 消息,不崩溃"""
    request = _build_responses_request(
        tool_choice="auto", include=["message.output_text.logprobs"]
    )
    result = _stream_partial_start_token(request)
    assert result is not None
    assert result.content == ""

评论区精华

没有提炼出高价值讨论线程

当前评论区没有形成足够清晰的争议点或结论,后续有更多讨论时会体现在这里。

风险与影响

变更范围极小(源码修改 6 行,测试新增 32 行),风险低。但需注意:若未来新增请求类型未覆盖,类似 AttributeError 可能重现。建议后续关注工具解析器的请求类型扩展。

直接影响 PoolsideV1 工具解析器在 Responses API 流式场景下的稳定性。修复后,使用 /v1/responses 端点且开启 logprobs 的用户不再遭遇崩溃。对其他模型和 ChatCompletion API 无影响。

影响面小 低风险

关联 Issue

未识别关联 Issue

当前没有检测到明确关联的 Issue 链接,后续同步到相关引用后会出现在这里。

完整报告

参与讨论