Prhub

#26590 [BugFix] preserve cached token details in multi-tokenizer output

原始 PR 作者 cquil11 合并时间 2026-05-29 04:31 文件变更 2 提交数 1 评论 4 代码增减 +71 / -0

执行摘要

修复多 tokenizer 路径丢失缓存详情

修复多 tokenizer 场景下 cached_tokens_details 丢失问题,使 HiCache 逐级缓存指标(device/host/storage_)正确上报。PR body 描述了启动参数和 curl 验证步骤,并指出目前 metrics 仅输出 cache_source="total" 而丢失了预期分层。

值得精读:变更虽小,但展示了多 tokenizer 路径中字段转发的模式,是维护 metrics 一致性的关键修复。可关注同类字段是否还有遗漏。

讨论亮点

该 PR 讨论较少,仅有的评论为 bot 配额提醒和测试触发命令。评审人 hnyls2002 直接批准,无反对意见或设计争议。

实现拆解

  1. 源码修改:在 python/sglang/srt/managers/multi_tokenizer_mixin.py_handle_output_by_index 函数中,针对 BatchStrOutput 分支(第 231-248 行),在 cached_tokens 字段之后新增 cached_tokens_details 字段转发,使用现有的 _extract_field_by_index 工具函数按索引提取。
  2. 测试新增:新建 test/registered/unit/managers/test_multi_tokenizer_mixin.py 文件,导入 BatchStrOutput_handle_output_by_index。定义 _make_batch_str_output 辅助函数构造包含 cached_tokens_details 的批输出,编写 test_batch_str_output_preserves_cached_tokens_details 测试用例,验证索引为 1 的请求能正确获得 cached_tokens_details=[{"device":1,"host":3}]
  3. CI 注册:测试类通过 register_cpu_ci 注册为 CPU 单元测试,指定预估时长 5 秒,归入 base-a-test-cpu 套件。
文件 模块 状态 重要度
python/sglang/srt/managers/multi_tokenizer_mixin.py Token 化 modified 5.96
test/registered/unit/managers/test_multi_tokenizer_mixin.py 测试 added 6.8

关键符号

_handle_output_by_index

关键源码片段

python/sglang/srt/managers/multi_tokenizer_mixin.py core-logic

核心修复文件,在 BatchStrOutput 分支添加 cached_tokens_details 转发。

# 文件 : python/sglang/srt/managers/multi_tokenizer_mixin.py
# 函数 _handle_output_by_index 中 BatchStrOutput 分支 ( 第 231 行起 )
# 批量输出按索引 i 拆分为单个请求输出
elif isinstance(output, BatchStrOutput):
    new_output = BatchStrOutput(
        rids=[output.rids[i]],
        spec_verify_ct=_extract_field_by_index(output, "spec_verify_ct", i),
        # ... 其他字段省略 ...
        cached_tokens=_extract_field_by_index(output, "cached_tokens", i),
        # [ 修复 ] 新增 cached_tokens_details 转发,确保 HiCache metrics 能按来源划分
        cached_tokens_details=_extract_field_by_index(
            output, "cached_tokens_details", i
        ),
        input_token_logprobs_val=_extract_field_by_index(
            output, "input_token_logprobs_val", i, check_length=False
        ),
        # ... 后续字段省略 ...
    )
test/registered/unit/managers/test_multi_tokenizer_mixin.py test-coverage

新增回归测试,验证 BatchStrOutput 拆分后 cached_tokens_details 正确保留。

# 文件 : test/registered/unit/managers/test_multi_tokenizer_mixin.py
import unittest
from sglang.test.ci.ci_register import register_cpu_ci
from sglang.test.test_utils import maybe_stub_sgl_kernelmaybe_stub_sgl_kernel()from sglang.srt.managers.io_struct import BatchStrOutput
from sglang.srt.managers.multi_tokenizer_mixin import _handle_output_by_indexregister_cpu_ci(est_time=5, suite="base-a-test-cpu")# 构造包含 cached_tokens_details 的批输出,用于测试拆分后字段保留
def _make_batch_str_output() -> BatchStrOutput:
    return BatchStrOutput(
        rids=["rid-0", "rid-1"],
        # ... 其他字段,重点关注 cached_tokens_details
        cached_tokens=[3, 4],
        cached_tokens_details=[
            {"device": 3, "host": 0},
            {"device": 1, "host": 3},
        ],
        # ... 其余省略
    )class TestMultiTokenizerMixin(unittest.TestCase):
    def test_batch_str_output_preserves_cached_tokens_details(self):
        output = _make_batch_str_output()
        # 取索引 1 的请求,验证其 cached_tokens_details 正确
        single_output = _handle_output_by_index(output, 1)
        self.assertEqual(single_output.rids, ["rid-1"])
        self.assertEqual(single_output.cached_tokens, [4])
        self.assertEqual(
            single_output.cached_tokens_details,
            [{"device": 1, "host": 3}],
        )if __name__ == "__main__":
    unittest.main()

评论区精华

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

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

风险与影响

低风险。 变更仅添加 3 行转发逻辑(使用现有工具函数),不改变其他字段行为。新增测试覆盖拆分正确性。潜在风险:若 cached_tokens_details 在批输出中为 None(非多 tokenizer 场景),_extract_field_by_index 应能正确处理(视其实现而定),但现有测试未覆盖该 case;不过该字段通常由调度器填充,为空时可视为退化情况。

影响范围:中。 仅影响启用 HiCache、metrics 且 --tokenizer-worker-num >1 的用户。修复后这些用户的 metrics 能正确按缓存来源(device/host/storage)区分,提升可观测性精确性。对其他用户无影响。

低风险

关联 Issue

未识别关联 Issue

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

完整报告

参与讨论