Prhub

#31810 runtime_context: add resolved-config namespace bags and accessors

原始 PR 作者 ch-wan 合并时间 2026-07-22 16:16 文件变更 2 提交数 1 评论 5 代码增减 +334 / -17

执行摘要

配置命名空间 bag 与访问器,分层只读

PR body 指出这是 stacked series 的一部分,旨在引入结构化 RuntimeContext 配置 API,将解析后配置通过域命名空间暴露,让 ServerArgs 成为只读记录,业务代码从 namespace bag 读取配置,实现关注点分离与显式依赖。

建议精读此 PR 以理解 namespace bag 设计模式,特别是碰撞检测和 fail closed 机制。但合并前必须解决 Codex 提出的 P1/P2 问题,否则后续依赖此 API 的功能可能隐藏细微的不一致缺陷。测试覆盖质量高,可作参考。

讨论亮点

ChatGPT Codex 自动审查提出 4 个未解决问题:

  • 配置 bags 与 ServerArgs 覆盖不同步(P1):生产路径如 Scheduler.set_internal_state() 通过 override() 修改 ServerArgs 后,config bags 未更新,导致 get_spec()/get_memory() 返回过时值。
  • 缺少永久配置覆盖 API(P2):文档声称 get_context().override(source, ...) 为永久写入器,但该方法未实现,仅存在测试域的 scoped override。
  • 还原 server args 时 config bags 不清除(P2):override_server_args 作用域结束后,_server_args 被清除但 _config_bags 残留,违反 fail closed 合约。
  • 部分初始化 ServerArgs 导致投影崩溃(P1):测试发布 object.new(ServerArgs) 时实例缺少属性,导致 getattr 抛出错误,阻止测试收集。

实现拆解

  1. 定义 _ConfigBag 类(python/sglang/srt/runtime_context.py):私有容器,通过 getattr 返回不可变叶子值,setattr 禁止裸赋值(仅允许内部 _set 与 scoped override)。支持嵌套子 bag(如 exec.moe)。
  2. publish 时快照到 bags:在 RuntimeContext.set_server_args 末尾调用 _publish_config_bags,遍历 ServerArgs 所有 dataclass 字段的 NS 元数据,递归构建与字段路径匹配的 _ConfigBag 树,读走叶子值。
  3. 暴露 11 个模块级访问器:get_device()/get_model()/get_exec()/get_schedule()/get_memory()/get_spec()/get_lora()/get_mm()/get_disagg()/get_serving()/get_observability(),每个返回对应根 bag。publish 前调用抛 ValueError。
  4. 碰撞检测:构建 bag 树时检测“叶子与子分组同名”冲突(如 exec.moe.topk 既是叶子又是分组),抛出 ValueError。
  5. 配套测试(test/registered/unit/test_runtime_context_config_bags.py):含 _DeepFake 验证深层嵌套构建正确性,_CollisionFake 验证碰撞检测; TestConfigBags 集成测试覆盖 fail closed、值一致性、只读、scoped override、未知叶子报错、reset 后 fail closed。
文件 模块 状态 重要度
python/sglang/srt/runtime_context.py 配置层 modified 8.8
test/registered/unit/test_runtime_context_config_bags.py 测试 added 7.54

关键符号

_ConfigBag.__init__ _ConfigBag.__getattr__ _ConfigBag.__setattr__ _ConfigBag._set _ConfigBag.__contains__ _ConfigBag.override _build_config_bags get_exec get_memory get_schedule get_model get_device get_spec get_lora get_mm get_disagg get_serving get_observability RuntimeContext.set_server_args RuntimeContext.reset_context

关键源码片段

test/registered/unit/test_runtime_context_config_bags.py test-coverage

新测试文件,覆盖 fail closed、值一致性、只读、override 恢复、深层嵌套和碰撞检测,验证 bags 正确性。

# test_runtime_context_config_bags.py (partial)@dataclasses.dataclass
class _DeepFake:
    # NS metadata defines paths like "exec.moe.eplb"
    a: A[int, NS("exec.moe.eplb")] = 1
    b: A[int, NS("exec.moe.eplb.tuning")] = 2@dataclasses.dataclass
class _CollisionFake:
    # 'topk' is both a leaf on exec.moe and a subgroup of exec.moe -> collision
    topk: A[int, NS("exec.moe")] = 8
    x: A[int, NS("exec.moe.topk")] = 1
​
​
class TestConfigBagTree(CustomTestCase):
    def test_deep_nesting(self):
        bags = rc._build_config_bags(_DeepFake())
        self.assertEqual(bags["exec"].moe.eplb.a, 1)
        self.assertEqual(bags["exec"].moe.eplb.tuning.b, 2)
​
    def test_leaf_subgroup_collision_raises(self):
        with self.assertRaises(ValueError):
            rc._build_config_bags(_CollisionFake())

评论区精华

配置 bags 与 ServerArgs 覆盖不同步 正确性

ChatGPT Codex 指出在 Scheduler.set_internal_state() 等路径中通过 ServerArgs.override() 修改运行时配置后,config bags 仍保持启动值,导致 get_spec()/get_memory() 返回过时值,违反文档承诺的“单一真相源”。

结论:PR 合并前未修复;后续需确保 bags 同步或直接废弃 bags 作为替代源。 · unresolved

缺少永久配置覆盖 API 设计

文档声称 get_context().override(source, ...) 为永久写入器,但此方法未实现,只存在测试域的 scoped override,导致生产代码无法通过 bags 写入配置。

结论:PR 合并前未添加;后续需实现或修改文档。 · unresolved

还原 server args 后 config bags 未清除 正确性

Codex 指出在 override_server_args 作用域结束后,_server_args 被清除但 _config_bags 残留,导致 get_exec() 仍可访问且暴露已删除的配置,违反 fail closed 合约。

结论:PR 合并前未修复;后续需在 restore 时清空 bags。 · unresolved

部分初始化 ServerArgs 导致投影崩溃 正确性

Codex 指出当测试发布 object.__new__(ServerArgs) 时,实例缺少 NS 字段对应属性,导致 _build_config_bags 中的 getattr 抛出 AttributeError,阻止测试收集。

结论:PR 合并前未处理;需在投影前增加对部分初始化实例的防护。 · unresolved

风险与影响

核心风险在于 Codex 指出的同步缺失:

  • 生产代码通过 ServerArgs.override() 修改运行时配置(如 speculative 阈值)后,config bags 仍保持启动值,导致 get_spec()/get_memory() 返回不一致结果。这是设计层面的未决缺陷。
  • reset_context() 后未清除 _config_bags,可能导致后续测试间状态污染。
  • 缺少永久覆盖 API 意味着当前 bags 无法在生产中写入,只能通过仍未迁移的 get_server_args() 获取最新值。
  • 部分初始化实例崩溃影响测试套件的健壮性。

此 PR 是配置系统重构的中间层,影响所有通过 namespace bag 读取配置的代码路径。当前 impact 有限(下游调用尚未迁移),但在未来系列 PR(如 #31812)中会成为配置读取的唯一入口。用户无感知,开发者需要理解 bags 的只读语义和 override 机制。团队需关注上述未解决问题的修复。

核心数据不一致风险(bags vs ServerArgs) 缺少生产覆盖 API reset 时 bags 残留 部分初始化实例崩溃 未解决的 P1 问题

关联 Issue

未识别关联 Issue

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

完整报告

参与讨论