Prhub

#31975 Treat partial_json_parser AssertionError as incomplete JSON

原始 PR 作者 vedularaghu 合并时间 2026-07-22 23:25 文件变更 1 提交数 2 评论 4 代码增减 +9 / -0

执行摘要

修复 streaming 中 partial JSON 解析断言异常

Issue #31974 报告:在 streaming function/tool-call 解析中,_partial_json_loads()partial_json_parser.fix_fast() 对部分输入(如尾随非空白字符后跟可修复前缀)抛出 AssertionError,导致请求失败。期望行为是返回 JSONDecodeError 以便调用者按“未完成”路径处理。

建议合入此 PR。它是一个典型的小型防御性修复,虽简单但有效防止了特定输入导致的请求中断。阅读 _partial_json_loads 的异常处理结构可获得防御性编程启发。

讨论亮点

review 中无争议讨论。PR 作者直接描述了问题与修复方案,维护者 ispobock 触发了 CI 重新运行测试 test/registered/unit/function_call/test_function_call_parser.py,结果通过。

实现拆解

  1. 修改文件python/sglang/srt/function_call/utils.py
  2. 核心变更:在 _partial_json_loads 函数的 except 块中新增对 AssertionError 的捕获。
  3. 异常转换:将捕获到的 AssertionError 包装为 JSONDecodeError 并重新抛出,异常消息为“partial_json_parser assertion (treat as incomplete)”,保留原始异常链。
  4. 影响:仅涉及异常处理路径,不改变其他逻辑;现有调用者如 tool_call_parser 已处理 JSONDecodeError,因此能正确忽略不完整的 JSON 片段。
  5. 测试:无新增测试文件,但 PR 描述中提及手动复现验证。
文件 模块 状态 重要度
python/sglang/srt/function_call/utils.py 工具调用 modified 5.88

关键符号

_partial_json_loads

关键源码片段

python/sglang/srt/function_call/utils.py core-logic

核心文件。在 `_partial_json_loads` 函数中新增 `except AssertionError` 处理,将断言异常转换为 `JSONDecodeError`。

def _partial_json_loads(input_str: str, flags: Allow) -> Tuple[Any, int]:
    """..."""
    try:
        return (partial_json_parser.loads(input_str, flags), len(input_str))
    except (JSONDecodeError, IndexError) as e:
        msg = getattr(e, "msg", str(e))
        if "Extra data" in msg or "pop from empty list" in msg:
            start = WHITESPACE.match(input_str, 0).end()
            obj, end = JSONDecoder().raw_decode(input_str, start)
            return obj, end
        raise
    except AssertionError as e:
        # partial_json_parser.fix_fast() 对某些部分 / 模糊输入断言失败
        # (例如在一段本可修复的前缀后带有尾随非空白字符)
        # 而不是表示 "incomplete"。转换为 JSONDecodeError 以便
        # streaming 调用者将其视为未完成(等待更多 token)
        raise JSONDecodeError(
            "partial_json_parser assertion (treat as incomplete)", input_str, 0
        ) from e

评论区精华

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

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

风险与影响

低风险。变更仅添加了一个 except 子句,不会影响正常解析路径。可能的风险是如果 future 版本的 partial_json_parser 修正了断言行为,则此 catch 可能变为 dead code,但不会导致错误。

影响有限但重要:直接影响使用 streaming tool-call 功能的用户,修复后此类断言错误不再导致请求失败,提升了流式解析的鲁棒性。不影响非流式场景。

低风险

关联 Issue

#31974 [Bug] Streaming tool-call parsing can raise AssertionError from partial_json_parser

完整报告

参与讨论