Skip to content

feat(loader): integrate bounded rank-local FastSafeTensors copyout - #1354

Open
ABNER-1 wants to merge 10 commits into
alibaba:mainfrom
ABNER-1:shuxing/dsv4-sleep-level2-fastsafetensors
Open

feat(loader): integrate bounded rank-local FastSafeTensors copyout#1354
ABNER-1 wants to merge 10 commits into
alibaba:mainfrom
ABNER-1:shuxing/dsv4-sleep-level2-fastsafetensors

Conversation

@ABNER-1

@ABNER-1 ABNER-1 commented Aug 30, 2026

Copy link
Copy Markdown
Collaborator

Why

RTP should use the config-driven FastSafeTensors AutoLoader as the single bulk-loading entry point while avoiding post-broadcast materialization for tensors that the local rank cannot consume.

What changed

  • Replace the duplicate per-expert loader path with config-driven AutoLoader integration.
  • Build the rank-local raw checkpoint key closure from direct tensor keys and stacked-MoE raw keys.
  • Apply filtering only to post-broadcast copyout and yield; planning, reads, source packing and collective order remain global.
  • Use bounded per-expert stacked-MoE delivery by default, with RTP_FASTSAFETENSORS_STACKED_MOE_MODE=full-stacked as an explicit comparison mode.
  • Extend loader and database tests and document the supported configuration variables.

Review boundary

  • Rebased on main commit b7a5437.
  • External commits: d1e0fe1 and 42c68d0.
  • FlashInfer packaging and runtime changes are explicitly excluded.
  • Internal wheel URLs and hashes are explicitly excluded from the open-source diff and are maintained in internal CR 29629265.
  • Rank-local selection must not affect I/O planning or collective participation.

Validation

  • git diff --check passed after rebase.
  • Final external diff adds no FlashInfer lines or internal Alibaba URLs.
  • Paired internal functional-test runs use this exact external head; remaining PPU PD reuse cache-store timeouts reproduce on main-internal itself and are tracked as a baseline blocker, not claimed as this PR passing.

@LLLLKKKK LLLLKKKK left a comment

Copy link
Copy Markdown
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

AI Code Review - PR #1354

Status: BLOCKING

Summary: P0/0 · P1/3 · P2/11 · P3/5

Reviewed: commit dcbd9388ab1d · 2026-08-30 23:30 UTC+8

Blocking Issues

P1

  • AutoLoader 硬依赖缺版本闸门,cuda12_9 pin 未同步且无能力探测与回退 @ rtp_llm/utils/database.py:316
    • 建议:二者择一并明确表态:(1)在本 PR 内把 cuda12_9 及其它仍在 0.1.19 的平台 requirements/lock 升到提供 AutoLoader + local_copyout_filter 的版本,并在 fastsafetensors_weights_iterator 入口保留一次性能力断言(inspect.signature 校验形参),不匹配时 fail-fast 并给出「所需最低版本 + 当前版本」;(2)若要保留运维回滚路径,把 AUTO 选路的 has_module 换成能力探测(仓内已有 module_util.resolve_symbol),失败时 warning 并回落 LoadMethod.SCRATCH。同时统一策略:_fastsafetensors_transient_budget_bytes 对旧 wheel 做优雅降级、导入侧却硬失败,两处自相矛盾;并在 docs/backend/server_arguments.md 补最低版本、生效平台、失败现象(ImportError: cannot import name 'AutoLoader')与 --load_method scratch 回退指引,替代被删闸门原先承担的可读提示职责。
  • 删除逐 expert 广播后 stacked MoE 多 rank 峰值显存回退且无实测 @ rtp_llm/utils/database.py:363
    • 建议:给出同一 stacked MoE checkpoint 在 tp>1 / ep>1 下改动前后的 torch.cuda.max_memory_allocated 对比,并在 PR 描述中写明可接受的峰值上升幅度,便于回滚判断。若确认峰值上升:优先推动上游 AutoLoader 支持按 dim0 切片产出或分块 copyout,在传输前完成切分;短期至少把「一个完整 stacked 张量常驻 + 一份 clone」计入 _fastsafetensors_transient_budget_bytes,避免预检通过而加载期 OOM。另外 database.py:363 对所有 expert 都 clone,而 loader.py:472-474 随即丢弃非本 rank 的 key,ep>1 下建议让适配层只 clone get_selected_experts 命中的 expert(把 stacked_key_config 的 value 扩展为携带本 rank expert 集合)。若结论是依赖上游 bounded batch buffer 抵消该回退,请在 database.py:358-362 注释与配置文档中写明这一前提及所需配置。
  • cuda13_arm wheel 分发的 flashinfer 变体与实际链接的变体不一致 @ rtp_llm/libs/BUILD:78
    • 建议:让打包侧与链接侧使用同一平台判据。根 BUILD:44-47 的注释表明 using_cuda13_arm 本意就是启用 flashinfer_cpp_cu13,若确认如此,请先在 flashinfer_deps() 增加 using_cuda13_arm 分支;否则从本 select() 去掉 //:using_cuda13_arm,或为 ARM 单独声明并分发 @flashinfer_cpp 变体的 .so(注意 .bazelrc:159-164 的注释声明 x86 的 define 与 ARM 路径解绑,两处意图目前不一致,需先统一)。建议把「哪个平台用哪个 flashinfer 仓库」抽成 arch_config 中的单一常量,供 flashinfer_deps() 与本 BUILD 共同消费。并补一条 cuda13_arm 产物校验:确认 wheel 构建通过、libth_transformer.so 的 DT_NEEDED 全部能在 wheel 内解析且来自同一变体;同时确认 flashinfer_cu13.BUILD:12-15 硬编码 sm_90/sm_90asm90_cuda_copts 在 SM100 ARM 工具链上可编译。

Non-blocking Suggestions

P2

  • 平台无关宏无条件引用 CUDA-13 专用仓库,非 cuda13 平台通配构建会被动拉取 @ arch_config/arch_select.bzl:28
    • 建议:让声明侧与消费侧的平台条件对齐,任选其一:给这批拷贝目标加 tags = ["manual"](可在 copy_so 增加可选参数传入),使通配模式不再选中;或改用 rtp_llm/libs/BUILD 已有的 copy_files + select 模式(参考 copy_hf3fs_libscopy_acclep_libsbazel/defs.bzl 的实现对空 srcs 返回空 depset,天然支持「非目标平台不产出」);或让 genrule 的 srcsselect() 在非 cuda13 下取空。核心是不让平台专用概念泄漏进平台无关宏。并在 CI 对 rocm/cpu 至少跑一次覆盖 //rtp_llm/libs 的分析,确认非 cuda13 平台不会被动拉取 CUDA13 依赖。
  • 11 个 flashinfer 目标名三处手抄,无单一来源且漏发不可检测 @ arch_config/arch_select.bzl:16
    • 建议:把清单收敛为 arch_config 显式导出的单一来源(例如常量 CUDA13_FLASHINFER_SO_TARGETS),copy_all_so() 遍历它、rtp_llm/libs/BUILD load 后以 [":lib%s_so" % t for t in ...] 派生——这样任何 override 实现缺失该符号都会在 load 期显式失败,而不是等 cuda13 select 命中才暴露;并在 PR 描述中标注是否需要配套变更其它 @arch_config 实现。同时补一条轻量打包校验(wheel 内 rtp_llm/libs/libflashinfer_*.so 数量与清单长度一致,或 libth_transformer.so 的 DT_NEEDED 全部可解析),把「漏发一个库」从运行期故障前移到构建期失败。
  • transient 显存预算无下界,异常分支未覆盖且未纳入 OSError @ rtp_llm/model_loader/loader.py:359
    • 建议:对库返回值取下限并计入 RTP 侧已知瞬时量,例如 transient_mem = max(upstream_estimate, k * max_file_size) + 单个 stacked tensor 大小 + inline 量化余量,避免阈值退化为恒真。把 except 收口为 except Exception(或至少纳入 OSError)并在注释说明捕获范围的取舍,去掉冗余的 ModuleNotFoundError。补三条用例:注入不含 load_config 的 fake 模块、load_config() 抛异常(用 assertLogs 校验 warning 且返回 3 * max_file_size)、estimated_peak_device_bytes=0 的下界行为。
  • load_config() 早于 NOGDS 环境归一化被调用,预检预算与实际配置不一致 @ rtp_llm/model_loader/loader.py:356
    • 建议:把 FASTSAFETENSORS_NOGDSFASTSAFETENSORS_CONFIG_JSON 的归一化提前到任何 load_config() 调用之前(例如在加载入口一次性初始化),保证预检与实际构造读到同一份配置;或让 _fastsafetensors_transient_budget_bytes 显式接受最终生效的配置对象,消除对调用顺序的隐式依赖。同时确认上游 load_config() 是否做进程级缓存并在注释中记录结论。
  • copyout 谓词跨 rank 不对称,EP>1 语义边界未确认且无多卡覆盖 @ rtp_llm/model_loader/loader.py:467
    • 建议:先确认并在 loader.py:467 调用处注释中写明上游对 rank 间不一致 local_copyout_filter 的语义边界(是否仅作用于本 rank 的 copy-out、不参与集合通信调度),并引用上游文档与版本;若语义要求对称,改为传入各 rank key 的并集。补一条 ep_size > 1 的多进程单测或 smoke,验证非本 rank expert 被过滤后权重仍完整、无 hang——这是本次唯一真正改变多卡加载行为的分支,却完全没有多卡覆盖。
  • fallback 慢路径零覆盖且线上不可观测,_fallback_count 自增后从未使用 @ rtp_llm/model_loader/loader.py:523
    • 建议:补一条负向用例:让 fake database 只产出部分 key、令 is_collection_complete() 返回 False,断言确实走到 DatabaseTensorSource 且权重最终仍正确落位。生产侧把 _fallback_count 与回退权重名汇总为一条 warning 或指标(例如「N/M 个权重回退到 database 路径」),使该退化在线上可观测;若不打算使用该计数,请直接删除这个死变量。
  • 新增 loader 侧用例把生产边界整体 mock,关键联动无覆盖 @ rtp_llm/model_loader/test/test_stacked_moe_weight.py:315
    • 建议:用真实 MoeAtomicWeight / TensorCollector 构造最小 weight tree,让 _build_stacked_key_config 与 filter 在同一用例内联动,断言 _build_fastsafetensors_local_copyout_keys 的结果是下游实际消费 key 的超集、并断言最终写入 model_weights 的张量值;补一条 stacked_key_config 为空时 copyout 集合等于 tensor_to_weight_map 键集的用例。把 _build_fastsafetensors_local_copyout_keys 保留为纯函数测试,选路类测试下移到集成/smoke 层以减少对私有方法的 mock。
  • per-expert 拆分用例以纯 Python fake 替代张量,未校验切分语义与边界 @ rtp_llm/utils/test/ckpt_database_test.py:119
    • 建议:改用真实 torch 张量(如 torch.arange(6).reshape(3, 2))断言每个专家切片的数值、dtype 与 data_ptr 不同于原张量,真正验证「按专家切分 + 拷贝解耦」;补 1-2 个边界用例(template 无 {expert_id}shape[0]==1)。另建议新增一条不打桩、直接 import 真实 fastsafetensors 校验 AutoLoader 构造签名与 load_config() 字段的用例(可按依赖存在性 skip),使上游 API 漂移在 CI 而非部署期暴露——当前 FakeAutoLoader.__init__(test:143)由测试自行固化了上游签名契约。
  • 文档把生效前提写成显式 LOAD_METHOD,遗漏默认 auto 同样走 AutoLoader @ docs/backend/server_arguments.md:208
    • 建议:将前提改为「当最终选定 fastsafetensors 加载方式时(显式 LOAD_METHOD=fastsafetensors,或默认 auto 自动选中)」,并简述 auto 的选中条件(safetensors 权重、非 CPU 加载、张量名唯一、显存充足且已安装 fastsafetensors)或链接到 --load_method 表格行,使读者明确默认部署也在该配置面覆盖范围内。
  • 未记录 RTP 侧加载调优默认值移交上游这一运维可见行为变化 @ docs/backend/server_arguments.md:206
    • 建议:在小节中补一段:RTP 不再覆盖 fastsafetensors 的 buffer / shm / ordering 参数,相关默认值由所装版本决定;若原先依赖较大 buffer 行为,给出通过 FASTSAFETENSORS_CONFIG_JSON 显式配置 bbuf_size_kb 等价项的示例。按本页既有先例在 docs/release/breaking-changes.md 登记该加载后端切换与默认值移交。另建议把 FASTSAFETENSORS_CONFIG_JSONFASTSAFETENSORS_CONFIGFASTSAFETENSORS_NOGDS 各补一行进 ## Load Config 表格(Description 指向本小节),与本页「环境变量挂在表格行内」(201-204 行)的既有约定保持一致,便于按表格检索或结构化解析。
  • NOGDS 兼容开关的优先级结论未验证,且覆写不可逆污染进程级 env @ docs/backend/server_arguments.md:223
    • 建议:三者任选:(1)补一条同时设置 FASTSAFETENSORS_CONFIG 文件路径与 FASTSAFETENSORS_NOGDS=1 的用例,实测并锁定优先级;(2)把绝对化表述改为限定表述,注明该优先级由上游实现与版本决定、RTP 并不读取 FASTSAFETENSORS_CONFIG;(3)在覆写 FASTSAFETENSORS_CONFIG_JSON 的同时一并清除 FASTSAFETENSORS_CONFIG,使结论自洽而不依赖外部实现细节。同时在文档中说明该覆写是进程级、持续生效且会丢弃用户原有 inline JSON,并考虑改为仅在构造期临时生效(如 try/finally 恢复原值),避免不可逆污染进程状态。

P3

  • use_tqdm_on_load 成为死参数,加载进度可观测性静默丢失 @ rtp_llm/utils/database.py:312
    • 建议:若上游 AutoLoader 支持进度显示则透传该参数;否则从 fastsafetensors_weights_iterator 签名与 loader.py 调用点一并移除,或在注释中说明该职责已由上游配置接管。同时确认 loader.py:496-503 每 5000 个 tensor 的周期性日志足以替代原进度条,必要时下调打印间隔或补充剩余量信息。
  • budget helper docstring 字段名与实现不符,日志风格与参考值表述易误读 @ rtp_llm/model_loader/loader.py:352
    • 建议:docstring 中的 max_batch_bytes 改为实际读取的 estimated_peak_device_bytes;日志中明确 max_file_mem 仅为参考值(或与 transient_mem 合并表述);新增日志统一为文件内既有 f-string 风格。
  • 测试文件 Covers 清单与新增用例归类未同步 @ rtp_llm/model_loader/test/test_stacked_moe_weight.py:3
    • 建议:更新文件头 Covers: 列表,并把两个新用例移到独立测试类(例如 TestLocalCopyoutKeys),使测试类边界与被测方法对应,便于后续按方法定位失败用例。另建议把这批无 GPU 依赖的纯 CPU 用例拆到不带 H20 tag 的 py_test 目标,使其能在 cuda13 / ARM / ROCm lane 也执行——这恰是本 PR 两个 P1 最需要覆盖的平台。
  • select 并列分支未复用仓库既有 config_setting_group 约定 @ rtp_llm/libs/BUILD:76
    • 建议:在根 BUILD 增加 selects.config_setting_group(name = "using_cuda13", match_any = [":using_cuda13_x86", ":using_cuda13_arm"]),本文件改为单分支,后续新增 CUDA13 平台也不必逐个 select() 补分支。注意该归并须与上文 ARM flashinfer 变体问题一并确认——只有两平台确实使用同一变体时才可归并。
  • CUDA13 打包变更与本 PR 主题无关,缺少动机说明与构建证据 @ arch_config/arch_select.bzl:15
    • 建议:将 CUDA-13 FlashInfer 打包拆成独立提交或 PR;若保留在本 PR,请在 description 中补充动机(cuda13 运行期缺少 libflashinfer_*.so 的现象与复现方式),并附上 cuda13 / cuda13_arm 两个配置下 wheel 目标构建通过、wheel 内 .so 清单符合预期的证据。同时在循环上方补一行注释说明为何只有 cuda13 需要在本文件复制(例如 cuda12 由 override 版 arch_config 或镜像打包补齐),避免后续读者误以为 cuda12 wheel 也缺库;若 cuda12 确实同样缺失,应按前述建议做成随配置 select 的统一路径。

Checklist Findings (21 fail / 48 total)

General Principles Checklist

  • [6.1] Architecture — 依赖方向:无循环依赖/跨层惊喜 → issue 平台无关宏无条件引用 CUDA-13 专用仓库,非 cuda13 平台通配构建会被动拉取
    copy_all_so()rtp_llm/libs/BUILD:6 被无 select 包裹地调用,因此 11 个 genrule 在 cpu/arm/rocm/cuda12/cuda12_9/ppu 等所有配置下都存在;srcs 硬编码 @flashinfer_cpp_cu13,而 copy_so(bazel/defs.bzl:1-10)的 tags 只有 no-remote、无 manual。此前该宏只引用平台无关的 @rtp_llm//:...。一旦出现包级通配(//rtp_llm/libs/...//...bazel query)就会分析这些目标,触发该仓库 git clone + 15 个补丁并按 sm_90/sm_90a copts 编译,还引入 def_cu13.bzl:4-14@local_config_cuda//cuda:cudart,在 ROCm/CPU 上不可用。同文件 flashinfer_deps() 用 select 分流,本变更偏离该约定。
  • [6.1] Architecture — 兼容性:外部 HTTP/RPC API、持久数据、配置、环境迁移安全 → issue NOGDS 兼容开关的优先级结论未验证,且覆写不可逆污染进程级 env
    223-224 行断言该开关「therefore takes priority over other fastsafetensors configuration」,但 database.py:337-344 只覆写 FASTSAFETENSORS_CONFIG_JSON,从不读取也不触碰 FASTSAFETENSORS_CONFIG 文件路径;该绝对化结论完全依赖 209-210 行「inline JSON 优先于文件」这一上游行为,仓内无代码或测试可佐证,新增用例 ckpt_database_test.py:94-106 更在 setUp 中同时清空两个变量、恰好回避了文档承诺的组合。此外覆写直接写进 os.environ 且从不恢复(test:258-268 断言用户原值 {"loader":"fuse-shm"} 被静默替换),同进程后续 ViT / draft / EPLB 加载亦持续受影响,文档未提示该持久性。
  • [6.1] Architecture — 分层边界:新概念在正确层级,不泄漏内部 → issue 平台无关宏无条件引用 CUDA-13 专用仓库,非 cuda13 平台通配构建会被动拉取
    copy_all_so()rtp_llm/libs/BUILD:6 被无 select 包裹地调用,因此 11 个 genrule 在 cpu/arm/rocm/cuda12/cuda12_9/ppu 等所有配置下都存在;srcs 硬编码 @flashinfer_cpp_cu13,而 copy_so(bazel/defs.bzl:1-10)的 tags 只有 no-remote、无 manual。此前该宏只引用平台无关的 @rtp_llm//:...。一旦出现包级通配(//rtp_llm/libs/...//...bazel query)就会分析这些目标,触发该仓库 git clone + 15 个补丁并按 sm_90/sm_90a copts 编译,还引入 def_cu13.bzl:4-14@local_config_cuda//cuda:cudart,在 ROCm/CPU 上不可用。同文件 flashinfer_deps() 用 select 分流,本变更偏离该约定。
  • [6.1] Architecture — 可观测性:日志/指标/超时可操作、非噪声 → issue budget helper docstring 字段名与实现不符,日志风格与参考值表述易误读
    docstring(loader.py:352)写 when max_batch_bytes is unset,实现读的却是 estimated_peak_device_bytes(:359),max_batch_bytes 在代码中并不存在,维护者会去上游找错字段。max_file_mem(:334)改动后仅用于日志(:341),易被误读为仍参与判定。新增日志(:445-449)用 %-占位风格,与同函数内其余 f-string 不一致。
  • [6.1] Architecture — 回滚路径:风险行为存在运维回滚手段 → issue 未记录 RTP 侧加载调优默认值移交上游这一运维可见行为变化
    旧实现固定传 bbuf_size_kb=1024*1024*2use_shm=not use_nogdsnogds=use_nogds;新实现只传 pg / files / device / local_copyout_filter(database.py:345-350),buffer 大小、batching、读取粒度、tensor ordering 全部改由所装 wheel 的默认值决定。这是加载耗时与峰值内存的可观察变化,而新小节只写「怎么配」,未说明「默认行为已改变」,也未给出恢复旧读放大行为的等价 JSON。同页第 9 行已有「运维可见默认值变更需在 ../release/breaking-changes.md 说明」的先例。
  • [6.1] Architecture — 状态不变量:创建/更新/失败/重试/回滚路径有效 → issue NOGDS 兼容开关的优先级结论未验证,且覆写不可逆污染进程级 env
    223-224 行断言该开关「therefore takes priority over other fastsafetensors configuration」,但 database.py:337-344 只覆写 FASTSAFETENSORS_CONFIG_JSON,从不读取也不触碰 FASTSAFETENSORS_CONFIG 文件路径;该绝对化结论完全依赖 209-210 行「inline JSON 优先于文件」这一上游行为,仓内无代码或测试可佐证,新增用例 ckpt_database_test.py:94-106 更在 setUp 中同时清空两个变量、恰好回避了文档承诺的组合。此外覆写直接写进 os.environ 且从不恢复(test:258-268 断言用户原值 {"loader":"fuse-shm"} 被静默替换),同进程后续 ViT / draft / EPLB 加载亦持续受影响,文档未提示该持久性。
  • [6.1] Architecture — 错误语义:fail-fast/retry/fallback/silent 行为显式 → issue copyout 谓词跨 rank 不对称,EP>1 语义边界未确认且无多卡覆盖
    required_checkpoint_keys 来自 tensor_to_weight_map(loader.py:578-627),其 MoE 部分经 MoeAtomicWeight.get_tensor_names(ffn_weight.py:706-720)→ LoadConfig.get_selected_experts(load_config.py:89-98)按 ep_rank 切片,故 ep_size>1 时非 stacked 的 per-expert key 集合随 rank 不同(stacked 原始 key 对称)。该非对称谓词被无条件传入以进程组为基础的 AutoLoader,而 torch_patch.py:33-38 明确记载 AutoLoader 在多 rank 加载时通过 pg.broadcast 搬运权重,即内部确有跨 rank 集合通信。若上游把 copyout 判定与集合调度绑定,可能出现广播缺参与方而 hang。新增用例全部为单 rank + fake loader,无任何 ep_size>1 覆盖。
  • [6.1] Quality — Commit 原子、message 与行为匹配 → issue CUDA13 打包变更与本 PR 主题无关,缺少动机说明与构建证据
    本 PR 其余 8 个文件全部围绕 model_loader / utils 的 fastsafetensors 改造(loader.pyper_expert_parallel_loader.pydatabase.pytorch_patch.py 及对应测试、server_arguments.md),本文件新增的 CUDA-13 FlashInfer wheel 打包与该主题无逻辑关联,混在同一提交中会削弱 CI 二分定位能力,改动动机在代码中亦无任何注释说明。另外仅 cuda13 补齐 flashinfer 动态库,而 flashinfer.BUILD:133-143 为 cuda12 系列产出同名同构目标、whl_package_libs 默认分支仍为空,代码中没有任何线索解释该差异。
  • [6.1] Quality — Mega-PR 已拆分为独立变更 → issue CUDA13 打包变更与本 PR 主题无关,缺少动机说明与构建证据
    本 PR 其余 8 个文件全部围绕 model_loader / utils 的 fastsafetensors 改造(loader.pyper_expert_parallel_loader.pydatabase.pytorch_patch.py 及对应测试、server_arguments.md),本文件新增的 CUDA-13 FlashInfer wheel 打包与该主题无逻辑关联,混在同一提交中会削弱 CI 二分定位能力,改动动机在代码中亦无任何注释说明。另外仅 cuda13 补齐 flashinfer 动态库,而 flashinfer.BUILD:133-143 为 cuda12 系列产出同名同构目标、whl_package_libs 默认分支仍为空,代码中没有任何线索解释该差异。
  • [6.1] Quality — PR description 说明动机与设计 → issue CUDA13 打包变更与本 PR 主题无关,缺少动机说明与构建证据
    本 PR 其余 8 个文件全部围绕 model_loader / utils 的 fastsafetensors 改造(loader.pyper_expert_parallel_loader.pydatabase.pytorch_patch.py 及对应测试、server_arguments.md),本文件新增的 CUDA-13 FlashInfer wheel 打包与该主题无逻辑关联,混在同一提交中会削弱 CI 二分定位能力,改动动机在代码中亦无任何注释说明。另外仅 cuda13 补齐 flashinfer 动态库,而 flashinfer.BUILD:133-143 为 cuda12 系列产出同名同构目标、whl_package_libs 默认分支仍为空,代码中没有任何线索解释该差异。
  • [6.1] Quality — 逻辑变更未混入无关格式化 → issue 测试文件 Covers 清单与新增用例归类未同步
    文件头 Covers:(test:3-7)仍只列出 StackSplitTensorSourceMoeAtomicWeight._build_split_configModelLoader._build_stacked_key_config 三项,未包含新增覆盖的 _build_fastsafetensors_local_copyout_keys_fastsafetensors_transient_budget_bytes。同时 302 / 315 行两个新用例被放进 236 行的 TestBuildStackedKeyConfig,而该类 docstring 明确写着 Tests for ModelLoader._build_stacked_key_config,实际测的却是另外两个方法以及 _load_from_fastsafetensor 的整体流程。
  • [6.1] Software Engineering — DRY:重复非平凡逻辑被抽取或显式复用 → issue select 并列分支未复用仓库既有 config_setting_group 约定
    新增 select()//:using_cuda13_x86//:using_cuda13_arm 写了两个内容完全相同的分支。根 BUILD:116-124 已建立相反约定并写明理由:「Selects whose cuda13_x86 behavior is identical to cuda12_9_x86 use this group so we don't have to add a parallel branch to every select()」,即优先用 selects.config_setting_group 归并等价平台,而不是在每个 select() 里并列分支。
  • [6.1] Software Engineering — KISS/YAGNI:无投机性抽象 → issue use_tqdm_on_load 成为死参数,加载进度可观测性静默丢失
    旧实现把 use_tqdm_on_load 透传给 ParallelLoader(use_tqdm_on_load=...);新实现 AutoLoader(pg, hf_weights_files, device=device, local_copyout_filter=...)(database.py:345-350)不再使用该参数,但 fastsafetensors_weights_iterator 签名(:312)、内层 iterator(device, use_tqdm_on_load)(:318、:371)与调用方 loader.py:463-465(位置传参 True)都仍保留它。结果是参数保留却无任何作用,权重加载进度条静默消失,长时间加载缺少进展反馈,也给后续维护者留下误导性接口。
  • [6.1] Software Engineering — OCP:本地扩展点优先于修改中心逻辑 → issue 平台无关宏无条件引用 CUDA-13 专用仓库,非 cuda13 平台通配构建会被动拉取
    copy_all_so()rtp_llm/libs/BUILD:6 被无 select 包裹地调用,因此 11 个 genrule 在 cpu/arm/rocm/cuda12/cuda12_9/ppu 等所有配置下都存在;srcs 硬编码 @flashinfer_cpp_cu13,而 copy_so(bazel/defs.bzl:1-10)的 tags 只有 no-remote、无 manual。此前该宏只引用平台无关的 @rtp_llm//:...。一旦出现包级通配(//rtp_llm/libs/...//...bazel query)就会分析这些目标,触发该仓库 git clone + 15 个补丁并按 sm_90/sm_90a copts 编译,还引入 def_cu13.bzl:4-14@local_config_cuda//cuda:cudart,在 ROCm/CPU 上不可用。同文件 flashinfer_deps() 用 select 分流,本变更偏离该约定。
  • [6.1] Software Engineering — SRP:模块/类职责单一 → issue 测试文件 Covers 清单与新增用例归类未同步
    文件头 Covers:(test:3-7)仍只列出 StackSplitTensorSourceMoeAtomicWeight._build_split_configModelLoader._build_stacked_key_config 三项,未包含新增覆盖的 _build_fastsafetensors_local_copyout_keys_fastsafetensors_transient_budget_bytes。同时 302 / 315 行两个新用例被放进 236 行的 TestBuildStackedKeyConfig,而该类 docstring 明确写着 Tests for ModelLoader._build_stacked_key_config,实际测的却是另外两个方法以及 _load_from_fastsafetensor 的整体流程。
  • [6.1] Tests — 分布式/跨平台变更有对应覆盖 → issue copyout 谓词跨 rank 不对称,EP>1 语义边界未确认且无多卡覆盖
    required_checkpoint_keys 来自 tensor_to_weight_map(loader.py:578-627),其 MoE 部分经 MoeAtomicWeight.get_tensor_names(ffn_weight.py:706-720)→ LoadConfig.get_selected_experts(load_config.py:89-98)按 ep_rank 切片,故 ep_size>1 时非 stacked 的 per-expert key 集合随 rank 不同(stacked 原始 key 对称)。该非对称谓词被无条件传入以进程组为基础的 AutoLoader,而 torch_patch.py:33-38 明确记载 AutoLoader 在多 rank 加载时通过 pg.broadcast 搬运权重,即内部确有跨 rank 集合通信。若上游把 copyout 判定与集合调度绑定,可能出现广播缺参与方而 hang。新增用例全部为单 rank + fake loader,无任何 ep_size>1 覆盖。
  • [6.1] Tests — 新逻辑有聚焦单测 + 相关集成/smoke 测试 → issue NOGDS 兼容开关的优先级结论未验证,且覆写不可逆污染进程级 env
    223-224 行断言该开关「therefore takes priority over other fastsafetensors configuration」,但 database.py:337-344 只覆写 FASTSAFETENSORS_CONFIG_JSON,从不读取也不触碰 FASTSAFETENSORS_CONFIG 文件路径;该绝对化结论完全依赖 209-210 行「inline JSON 优先于文件」这一上游行为,仓内无代码或测试可佐证,新增用例 ckpt_database_test.py:94-106 更在 setUp 中同时清空两个变量、恰好回避了文档承诺的组合。此外覆写直接写进 os.environ 且从不恢复(test:258-268 断言用户原值 {"loader":"fuse-shm"} 被静默替换),同进程后续 ViT / draft / EPLB 加载亦持续受影响,文档未提示该持久性。
  • [6.1] Tests — 边界 case 覆盖(空、单元素、最大值) → issue per-expert 拆分用例以纯 Python fake 替代张量,未校验切分语义与边界
    test_stacked_experts_are_cloned_and_renamedFakeStackedTensor.shape = (3, 2)clone() 返回 object()(test:136-141),只验证键名改写顺序与 clone 调用次数。文件已 import torch,却没有任何一处断言 tensor[expert_id] 取到的数据、dtype、shape 与原 stacked 张量对应,也未验证 clone 结果与原 batch buffer 解耦——而 database.py:358-362 的注释明确指出 clone 的目的正是「loader 迭代进入下一批后可能释放当前 batch buffer」。同时缺少边界用例:template 缺少 {expert_id} 占位符导致 format 静默不生效、shape[0] == 1shape[0] 与预期专家数不一致。

RTP-LLM Checklist

  • [I] 代码质量 — 删除或重命名内部 file、registry entry、model name、metric enum、op binding、plugin symbol 时,必须全仓搜索消费者,并提供替代实现、迁移说明或 smoke 覆盖;只有暴露到 HTTP/RPC/config/persisted format 时才按外部兼容性处理 → issue 删除逐 expert 广播后 stacked MoE 多 rank 峰值显存回退且无实测
    被删类 docstring 写明其唯一价值:Peak GPU memory during broadcast drops from the full stacked tensor size to a single expert slicepg.size()>1 时非源 rank 只分配单 expert 空张量再逐个 pg.broadcast。新实现把 device 交给 AutoLoader(database.py:345-350),iterate_weights() 产出设备上完整 [num_experts, ...] 后才 tensor[expert_id].clone()(:363-367),且 tensor 在内层循环全程存活。loader.py:398 有意让 stacked 原始 key 在每个 rank 通过过滤;torch_patch.py:33-38 亦记载 AutoLoader 多 rank 加载时用 pg.broadcast 搬运权重。qwen3_next_weight.py:600 与 `qwen3_vl_m
  • [I] 代码质量 — 同一功能用统一工具函数 → issue select 并列分支未复用仓库既有 config_setting_group 约定
    新增 select()//:using_cuda13_x86//:using_cuda13_arm 写了两个内容完全相同的分支。根 BUILD:116-124 已建立相反约定并写明理由:「Selects whose cuda13_x86 behavior is identical to cuda12_9_x86 use this group so we don't have to add a parallel branch to every select()」,即优先用 selects.config_setting_group 归并等价平台,而不是在每个 select() 里并列分支。

Python Static-First Checklist

  • [P.G] 测试规范 — mock/fake/stub 不得替代本次声称覆盖的生产边界 → issue per-expert 拆分用例以纯 Python fake 替代张量,未校验切分语义与边界
    test_stacked_experts_are_cloned_and_renamedFakeStackedTensor.shape = (3, 2)clone() 返回 object()(test:136-141),只验证键名改写顺序与 clone 调用次数。文件已 import torch,却没有任何一处断言 tensor[expert_id] 取到的数据、dtype、shape 与原 stacked 张量对应,也未验证 clone 结果与原 batch buffer 解耦——而 database.py:358-362 的注释明确指出 clone 的目的正是「loader 迭代进入下一批后可能释放当前 batch buffer」。同时缺少边界用例:template 缺少 {expert_id} 占位符导致 format 静默不生效、shape[0] == 1shape[0] 与预期专家数不一致。

Strengths

  • 上游耦合面显著收窄:不再依赖 fb._get_rank_lidxfb.rank_loadersfb.instantiatedfb.auto_mem_deletefactory.free_dev_ptrs 等一整批 fastsafetensors 内部字段,后续升级 wheel 的破裂面大幅缩小。
  • _build_fastsafetensors_local_copyout_keys(loader.py:386-398)正确处理「过滤早于 per-expert 展开生效」的时序:stacked 条目按原始 ckpt key 保留,展开留在 database 适配层,docstring 写清了这一非显然约束并配有直测用例。
  • frozenset.__contains__ 作谓词,判定 O(1)、集合不可变,不会把可变状态泄漏给第三方 loader;对 dense 与非 stacked per-expert 权重是实质性的设备内存与带宽收益。
  • 被删闸门以 startswith("0.1.19") 判定,意味着 cuda13 所装的 0.1.20+ali 下 stacked MoE 原本必然抛 RuntimeError,本 PR 实际修掉了该平台的加载阻塞。
  • 删除收尾干净:全仓已无被删符号引用,torch_patch.py:29-39 的 UE8M0 broadcast 注释同步改写为 AutoLoader,未留指向已删类的悬空描述。
  • 显存预检保留 legacy 3 * max_file_size 兜底,并在同一条日志中打印 transient_memenough,AUTO 选路原因可定位。
  • 文档主动披露 FASTSAFETENSORS_NOGDS=1 覆写 FASTSAFETENSORS_CONFIG_JSON 这一反直觉行为,与 database.py:337-344 实现逐字一致,未粉饰副作用,代码侧还配了 warning。
  • ckpt_database_test.py:91-117sys.modules["fastsafetensors"] 与三个 FASTSAFETENSORS_* env 做了「原本存在/原本不存在」的区分式保存恢复;在生产逻辑会改写进程级 env 的前提下,这是必要的隔离防护。
  • rtp_llm/libs/BUILD:76-80select() 把新增 .so 限定在 cuda13,cuda12/cuda12_9/ROCm 的 wheel 内容不变,回滚面小。

Comment thread rtp_llm/utils/database.py Outdated
Comment thread rtp_llm/utils/database.py Outdated
# key per expert. Clone each slice because the loader can
# release the current batch buffer after iteration moves
# on to the next batch.
for expert_id in range(tensor.shape[0]):

Copy link
Copy Markdown
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

[P1] 删除逐 expert 广播后 stacked MoE 多 rank 峰值显存回退且无实测

被删类 docstring 写明其唯一价值:Peak GPU memory during broadcast drops from the full stacked tensor size to a single expert slicepg.size()>1 时非源 rank 只分配单 expert 空张量再逐个 pg.broadcast。新实现把 device 交给 AutoLoader(database.py:345-350),iterate_weights() 产出设备上完整 [num_experts, ...] 后才 tensor[expert_id].clone()(:363-367),且 tensor 在内层循环全程存活。loader.py:398 有意让 stacked 原始 key 在每个 rank 通过过滤;torch_patch.py:33-38 亦记载 AutoLoader 多 rank 加载时用 pg.broadcast 搬运权重。qwen3_next_weight.py:600 与 `qwen3_v...

建议: 给出同一 stacked MoE checkpoint 在 tp>1 / ep>1 下改动前后的 torch.cuda.max_memory_allocated 对比,并在 PR 描述中写明可接受的峰值上升幅度,便于回滚判断。若确认峰值上升:优先推动上游 AutoLoader 支持按 dim0 切片产出或分块 copyout,在传输前完成切分;短期至少把「一个完整 stacked 张量常驻 + 一份 clone」计入 _fastsafetensors_transient_budget_bytes,避免预检通过而加载期 OOM。另外 database.py:363 对所有 expert 都 clone,而 loader.py:472-474 随即丢弃非本 rank 的 key,ep>1 下建议让适配层只 clone get_selected_experts 命中的 expert(把 stacked_key_config 的 value 扩展为携带本 rank expert 集合)。若结论是依赖上游 bounded batch buffer 抵消该回退,请在 database.py:358-362 注释与配置文档中写明这一前提及所需配置。

Checklist: [I] 删除或重命名内部 file、registry entry、model name、metric enum、op binding、plugin symbol 时,必须全仓搜索消费者,并提供替代实现、迁移说明或 smoke 覆盖;只有暴露到 HTTP/RPC/config/persisted format 时才按外部兼容性处理

@ABNER-1 ABNER-1 Aug 30, 2026

Copy link
Copy Markdown
Collaborator Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Addressed in aa88afea4 with matching FastSafeTensors wrapper commit e6e39437.

The production default is now the bounded-memory per-expert path: the source rank clones one dim-0 expert slice, every rank executes the same slice broadcast sequence, and rank-local filtering is applied only after each collective. Non-source ranks no longer materialize the full stacked tensor. A cross-rank hash over raw key/template/shape fails before collectives if the split plans differ.

The previous full-stacked behavior is intentionally retained for controlled speed/memory comparison via RTP_FASTSAFETENSORS_STACKED_MOE_MODE=full-stacked; it is not the default. Ordinary non-stacked tensors remain on the existing bucket/rank-local path.

Exact wheel CI 278696 / 67401633 (revision e6e39437...) completed 16/16 jobs successfully; CUDA 12.9 x86 installed-wheel tests report 293 passed / 11 skipped. CPU coverage includes value/storage lifetime, interleaved ordering, expanded-key filtering, and capability forwarding. The new two-rank NCCL case exists but was skipped by CI workers without two visible GPUs. The previous DeepSeek test Pods were already recycled, so real multi-rank NCCL and per-expert vs full-stacked peak-memory/performance PK remain explicit pending gates and are not being inferred from CI success.

Comment thread rtp_llm/libs/BUILD Outdated
],
] + select({
"//:using_cuda13_x86": cuda13_flashinfer_shared_libs,
"//:using_cuda13_arm": cuda13_flashinfer_shared_libs,

Copy link
Copy Markdown
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

[P1] cuda13_arm wheel 分发的 flashinfer 变体与实际链接的变体不一致

whl_package_libs(BUILD:76-80)把 //:using_cuda13_x86//:using_cuda13_arm 都指向 cuda13_flashinfer_shared_libs,其 .socopy_all_so()(arch_select.bzl:15-28)从 @flashinfer_cpp_cu13 拷出;但 flashinfer_deps()(:164-171)只把 x86 路由到该仓库,ARM 落 //conditions:default@flashinfer_cpp。两仓同 commit,cu13 多 0011-0015 五个补丁(含两个 kernel-visibility,deps/git.bzl:93-108),sub_lib 输出同名 libflashinfer_*.so 且被 flashinfer 以 srcs 引用(flashinfer_cu13.BUILD:199-214)→ 产生 DT_NEEDED;配合根 BUILD:194$ORIGIN,A...

建议: 让打包侧与链接侧使用同一平台判据。根 BUILD:44-47 的注释表明 using_cuda13_arm 本意就是启用 flashinfer_cpp_cu13,若确认如此,请先在 flashinfer_deps() 增加 using_cuda13_arm 分支;否则从本 select() 去掉 //:using_cuda13_arm,或为 ARM 单独声明并分发 @flashinfer_cpp 变体的 .so(注意 .bazelrc:159-164 的注释声明 x86 的 define 与 ARM 路径解绑,两处意图目前不一致,需先统一)。建议把「哪个平台用哪个 flashinfer 仓库」抽成 arch_config 中的单一常量,供 flashinfer_deps() 与本 BUILD 共同消费。并补一条 cuda13_arm 产物校验:确认 wheel 构建通过、libth_transformer.so 的 DT_NEEDED 全部能在 wheel 内解析且来自同一变体;同时确认 flashinfer_cu13.BUILD:12-15 硬编码 sm_90/sm_90asm90_cuda_copts 在 SM100 ARM 工具链上可编译。

Copy link
Copy Markdown
Collaborator Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

已在 05413c2 修复:flashinfer_deps() 现在对 using_cuda13_armusing_cuda13_x86 都选择 @flashinfer_cpp_cu13//:flashinfer,与 whl_package_libs 通过 cuda13_flashinfer_shared_libs 打包 cu13 变体的行为一致。内源对应选择原本已经正确,本次只修改外源一处。已通过 git diff --check、pre-commit,并用静态断言核对 ARM/x86 的 link/package 映射一致。当前本机没有 CUDA13 ARM 开发容器,因此未把真实 ARM Bazel/wheel 链接验证冒充为已通过;该项继续由 PR CI 验证。

@LLLLKKKK LLLLKKKK left a comment

Copy link
Copy Markdown
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

AI Code Review - PR #1354 (non-blocking suggestions)

16 条 P2/P3 建议,不阻塞合并。阻塞判定与完整摘要见上一条 review。

Comment thread arch_config/arch_select.bzl Outdated
Comment thread arch_config/arch_select.bzl Outdated
from fastsafetensors import load_config

config = load_config()
estimate = getattr(config, "estimated_peak_device_bytes", None)

Copy link
Copy Markdown
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

[P2] transient 显存预算无下界,异常分支未覆盖且未纳入 OSError

loader.py:360 在 estimate 非 None 时原样返回(包括 0),而 loader.py:338enough = (free_mem - model_mem) > transient_mem 准入:库返回 0 时判定退化为 free_mem > model_mem,原 3 * max_file_size 的安全余量被完全抹掉。该估算也只覆盖库自身 batch buffer,不含 database.py:363-367 的逐 expert clone、完整 stacked 张量本体与 inline FP8 临时 buffer。loader.py:361 的 except 元组含冗余的 ModuleNotFoundErrorImportError 子类)却不含 OSError,而本 PR 文档新增的 FASTSAFETENSORS_CONFIG=<file> 在文件缺失/损坏时 load_config() 很可能抛 OSError,会穿透兜底崩掉整个加载。`TestFastsafetensorsTran...

建议: 对库返回值取下限并计入 RTP 侧已知瞬时量,例如 transient_mem = max(upstream_estimate, k * max_file_size) + 单个 stacked tensor 大小 + inline 量化余量,避免阈值退化为恒真。把 except 收口为 except Exception(或至少纳入 OSError)并在注释说明捕获范围的取舍,去掉冗余的 ModuleNotFoundError。补三条用例:注入不含 load_config 的 fake 模块、load_config() 抛异常(用 assertLogs 校验 warning 且返回 3 * max_file_size)、estimated_peak_device_bytes=0 的下界行为。

"""
legacy_budget = 3 * max_file_size
try:
from fastsafetensors import load_config

Copy link
Copy Markdown
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

[P2] load_config() 早于 NOGDS 环境归一化被调用,预检预算与实际配置不一致

AUTO 预检链路(loader.py:266 → :335 → :356-358)调用 load_config() 读取预算,而 FASTSAFETENSORS_NOGDS=1 → FASTSAFETENSORS_CONFIG_JSON 的兼容覆写发生在之后的 database.py:337-344。预检读到的是覆写前配置,与实际构造 AutoLoader 时生效的 base/nogds 配置不一致;若上游 load_config() 做进程级缓存,database.py 的覆写还可能对同进程后续加载(ViT / draft / EPLB)完全失效。两种 copier 的 peak 若不同,AUTO 可能基于错误预算选中 fastsafetensors 而在加载期 OOM,或过度保守退回 scratch。该不一致只在 AUTO 出现,显式 LOAD_METHOD=fastsafetensors 不走预检,行为不统一。

建议:FASTSAFETENSORS_NOGDSFASTSAFETENSORS_CONFIG_JSON 的归一化提前到任何 load_config() 调用之前(例如在加载入口一次性初始化),保证预检与实际构造读到同一份配置;或让 _fastsafetensors_transient_budget_bytes 显式接受最终生效的配置对象,消除对调用顺序的隐式依赖。同时确认上游 load_config() 是否做进程级缓存并在注释中记录结论。

device,
True,
stacked_key_config=stacked_key_config,
local_copyout_filter=required_checkpoint_keys.__contains__,

Copy link
Copy Markdown
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

[P2] copyout 谓词跨 rank 不对称,EP>1 语义边界未确认且无多卡覆盖

required_checkpoint_keys 来自 tensor_to_weight_map(loader.py:578-627),其 MoE 部分经 MoeAtomicWeight.get_tensor_names(ffn_weight.py:706-720)→ LoadConfig.get_selected_experts(load_config.py:89-98)按 ep_rank 切片,故 ep_size>1 时非 stacked 的 per-expert key 集合随 rank 不同(stacked 原始 key 对称)。该非对称谓词被无条件传入以进程组为基础的 AutoLoader,而 torch_patch.py:33-38 明确记载 AutoLoader 在多 rank 加载时通过 pg.broadcast 搬运权重,即内部确有跨 rank 集合通信。若上游把 copyout 判定与集合调度绑定,可能出现广播缺参与方而 hang。新增用例全部为单 rank + fake loader,无任何 ep_size>1 覆盖。

建议: 先确认并在 loader.py:467 调用处注释中写明上游对 rank 间不一致 local_copyout_filter 的语义边界(是否仅作用于本 rank 的 copy-out、不参与集合通信调度),并引用上游文档与版本;若语义要求对称,改为传入各 rank key 的并集。补一条 ep_size > 1 的多进程单测或 smoke,验证非本 rank expert 被过滤后权重仍完整、无 hang——这是本次唯一真正改变多卡加载行为的分支,却完全没有多卡覆盖。

Checklist: [6.1] 错误语义:fail-fast/retry/fallback/silent 行为显式;[6.1] 分布式/跨平台变更有对应覆盖

Comment thread rtp_llm/utils/database.py Outdated
Comment thread rtp_llm/model_loader/loader.py Outdated
Comment thread rtp_llm/model_loader/test/test_stacked_moe_weight.py
Comment thread rtp_llm/libs/BUILD Outdated
Comment thread arch_config/arch_select.bzl Outdated

@LLLLKKKK LLLLKKKK left a comment

Copy link
Copy Markdown
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

AI Code Review - PR #1354

Status: BLOCKING

Summary: P0/0 · P1/2 · P2/20 · P3/7

Reviewed: commit aa88afea4811 · 2026-08-31 01:26 UTC+8

Blocking Issues

P1

  • cuda13_arm wheel 分发的 flashinfer 变体与实际链接的变体不一致 @ rtp_llm/libs/BUILD:78
    • 建议:先明确 cuda13_arm 的 flashinfer 归属再统一两侧条件:若 ARM 也应使用 cu13 变体,请在 flashinfer_deps()using_cuda13_arm 分支使链接与打包同源(ARM 在 CUDA 13 下能否用不带 cub 兼容补丁的默认变体本身也需验证);若不应使用,则把 whl_package_libsusing_cuda13_arm 分支改指默认仓库产物或移除。建议同时为每个共享库建 native.alias + select(),让链接与打包共用同一路由,避免再次漂移,并在 PR 描述中附一次 cuda13_arm wheel 的构建与加载验证。
  • cuda12_9 公开依赖集引入内网制品库直链,破坏公网可构建性 @ deps/requirements_torch_gpu_cuda12_9.txt:5
    • 建议:按该文件既有约定,把这两个 wheel 转存到其余依赖所用的公开对象存储后再改 pin,并优先发布去掉 .dev 的正式版本;若必须保留内网来源,请在 cu129 的 requirements/lock 中显式声明该 index 与 trusted-host,在文件注释与 PR 描述中标注该配置不再支持公网构建、给出回退到旧公开 wheel 的方式,并说明制品保留策略(三平台 lock 同时依赖同一批快照,被回收将一起失效)。

Non-blocking Suggestions

P2

  • copyout 谓词跨 rank 不对称,EP>1 下与集合通信语义冲突且零覆盖 @ rtp_llm/model_loader/loader.py:465
    • 建议:三项任一即可解除阻塞:一是补 ep_size=2 的 fake-pg 用例或 stacked-MoE smoke 目标,断言各 rank 广播次数一致、权重逐元素相同且不挂起;二是在代码注释与 PR 描述中固化 wheel 契约——local_copyout_filter 仅作用于 rank 本地 copy-out、不参与任何集合通信的成组决策,并附一次 EP>1 实际加载记录;三是改为下传跨 rank 求并集后的 rank 无关 key 集合,EP 选择仍由 loader.py:497tensor_to_weight_map 过滤完成,从源头消除分歧。
  • 删除唯一版本闸门后无能力探测,旧 wheel 环境由可降级变为硬失败 @ rtp_llm/model_loader/loader.py:267
    • 建议:把 AUTO 判定顺序调整为先 has_module(即可消除噪声告警),并把存在性判断收紧为能力判断(探测 AutoLoader 属性,或用 inspect.signature 校验 dim0_split_templates / local_copyout_filter),探测失败降级 SCRATCH 并 warning;若坚持 fail-fast,则在导入处给出带最低版本号与升级指引的错误信息以替代被删的版本护栏,并把两个定制 kwarg 用同一套 except TypeError 转译覆盖。同时在文档补一行最低 wheel 能力要求与旧环境处置方式(升级镜像或显式 --load_method scratch)。
  • estimated_peak_device_bytes 缺正值下界,异常上报会使显存闸门失效 @ rtp_llm/model_loader/loader.py:359
    • 建议:要求正整数才采用,例如 if not isinstance(estimate, int) or estimate <= 0: return legacy_budget,或加下界 max(estimate, max_file_size),回退时打日志说明原因;并在 TestFastsafetensorsTransientBudget 补 0 与负值两个参数化用例,锁定"异常上报不得绕过门禁"。
  • load_config() 早于 NOGDS 环境归一化被调用,预检预算与实际配置不一致 @ rtp_llm/model_loader/loader.py:356
    • 建议:把 NOGDS→FASTSAFETENSORS_CONFIG_JSON 的映射抽成幂等的配置准备函数(如 apply_fastsafetensors_env_overrides())在两处复用,在读取 load_config() 之前先调用,保证选路与加载看到同一份配置;或至少把当前 FASTSAFETENSORS_CONFIG_JSON 摘要打进预检日志便于事后核对。
  • full-stacked 模式的额外显存峰值未纳入准入预算 @ rtp_llm/utils/database.py:387
    • 建议:在 full-stacked 模式下按最大 stacked tensor 尺寸放大 transient 预算(或至少乘一个模式相关系数),使准入检查与实际交付方式一致;若暂不改代码,请在文档中明确该模式仅建议在显存充裕的对比实验中使用,并给出配套动作(改用 --load_method scratch 对照或预留更大运行时显存)。
  • 模式环境变量为空串时抛异常导致加载硬失败 @ rtp_llm/model_loader/loader.py:410
    • 建议:令空值等价于未设置,例如 mode = (os.environ.get("RTP_FASTSAFETENSORS_STACKED_MOE_MODE") or "").strip() or "per-expert",仅对非空且不在白名单内的取值 fail-fast;并补空串与仅含空白两个边界用例。
  • 新开关绕过 LoadConfig 配置面,取值集合三处重复且不入启动配置快照 @ rtp_llm/model_loader/loader.py:413
    • 建议:按既有约定把开关落到 LoadConfig(字段 + to_string() + --flag,env 名保持不变以兼容脚本),并定义 class StackedMoeMode(str, Enum)LoadMethod 并列,由配置层单点完成 env→枚举解析与校验,loader.py / database.py 只消费已校验值;同时按表格行把该开关与 FASTSAFETENSORS_NOGDS 登记进文档 Load Config 表,并注明非法取值在权重加载阶段以 ValueError 直接失败、取值大小写敏感。
  • 平台无关宏无条件引用 CUDA-13 专用仓库,非 cuda13 平台通配构建会被动拉取 @ arch_config/arch_select.bzl:28
    • 建议:把目标定义与消费端一起按配置收敛:两个 flashinfer 仓库的 sub_lib 目标同名、输出文件名一致,可先为每个共享库建 native.aliasactualselect() 在 cuda13 下指向 @flashinfer_cpp_cu13//:<t>、默认指向 @flashinfer_cpp//:<t>,再对 alias 调用 copy_sowhl_package_libs 引用的目标名无需改动);或把该循环下沉为独立 macro / 加显式开关,仅由 cuda13 配置调用。该方案同时消除上文 ARM 打包与链接不同源的问题。
  • 11 个 flashinfer 目标名多处手抄,无单一来源且漏发不可检测 @ arch_config/arch_select.bzl:16
    • 建议:在 arch_config/arch_select.bzl 导出唯一清单常量(如 CUDA13_FLASHINFER_SO_TARGETS),copy_all_so()rtp_llm/libs/BUILD 都从该常量派生(BUILD 侧用列表推导);或把这些目标声明直接下沉到 rtp_llm/libs/BUILD。合并前确认内部 @arch_config 已同步导出同名常量,并补一条最小 cuda13 校验(构建后断言 11 个 .so 均落入 wheel,或加一步从构建产物导入引擎的冒烟),使清单不一致在 CI 而非部署时暴露。
  • 同一 fastsafetensors x86 wheel 跨 torch 2.8 与 2.11 复用,与注释声明矛盾 @ deps/requirements_lock_torch_gpu_cuda12_9.txt:768
    • 建议:确认该 wheel 是否含 torch ABI 绑定的原生扩展:若含,为 cu129 与 cu130 分别出包并分别 pin;若确实与 torch ABI 无关(原生部分都在 fast_safetensors 中),把注释改为"仅 fast_safetensors 按 torch 版本重建,fastsafetensors 为 torch 无关、仅区分 CPU 架构的构建,cu129/cu130 共用同一制品",并删掉重复注释,避免后续维护者按"每个 torch 版本必须重编"的错误前提操作。
  • copyout filter 用例未隔离模式环境变量,文档给出的场景会直接使其失败 @ rtp_llm/model_loader/test/test_stacked_moe_weight.py:315
    • 建议:给该用例加 patch.dict("os.environ", {...}, clear=False) 并显式注入 "per-expert"(或 pop 该变量、直接桩掉 _fastsafetensors_stacked_moe_mode);把"未设置时默认 per-expert"的契约拆成独立用例单独固定,不要压在这个宽口径用例里。
  • 缺少对 clone 语义的断言,去掉 clone 后测试仍会通过 @ rtp_llm/utils/test/ckpt_database_test.py:273
    • 建议:在该用例中保留源张量引用并断言切片与源不共享存储(例如比较 untyped_storage().data_ptr() 不同),使 .clone() 被移除时必然测试失败。
  • per-expert 拆分用例由 fake 自行完成拆分,用例名与实际覆盖不符 @ rtp_llm/utils/test/ckpt_database_test.py:119
    • 建议:将用例改名为如实描述覆盖范围(例如 test_dim0_split_templates_are_forwarded_and_prewired_keys_pass_through);另补一个用例让 fake 吐出原始 stacked 键与真实张量,断言 per-expert 模式下生产不会二次拆分,把"恰好拆分一次"这一不变量固定下来。
  • 旧 wheel 的 ImportError 回退分支零覆盖,与 docstring 承诺不符 @ rtp_llm/model_loader/test/test_stacked_moe_weight.py:401
    • 建议:补两条用例:其一让 fake 模块不定义 load_config(或使导入抛 ImportError),断言返回 3 * max_file_size;其二让 load_config()ValueError,断言同样回退且用 assertLogs 确认 warning 已发出,保证配置错误不会被无声吞掉;同时补 max_file_size=0 边界。
  • fastsafetensors 生产边界被手写 fake 完全替代,wheel 契约无 PR 门禁校验 @ rtp_llm/utils/test/ckpt_database_test.py:127
    • 建议:rtp_llm/models_py/standalone/BUILD:4 已通过 requirement(["fast-safetensors", "fastsafetensors"]) 在该 package 声明了真实 wheel 的别名目标,可直接补一条契约用例并依赖它:用 inspect.signature(AutoLoader.__init__) 断言其接受 local_copyout_filterdim0_split_templates,并确认该用例进入 cuda13 lane 的 PR 门禁;同时在 PR 描述中给出真实 wheel 下 per-expert 与 full-stacked 两种模式的峰值显存与权重一致性对比记录。
  • 6 份重复的 fake 脚手架与两种打桩写法并存 @ rtp_llm/utils/test/ckpt_database_test.py:90
    • 建议:抽出模块级 _install_fake_fastsafetensors(auto_loader_cls) 工厂与共享 FakeSingleGroup,各用例只传差异化的 FakeAutoLoader;并统一改用 patch.dict 管理 sys.modulesos.environ(异常安全且与仓库其余测试一致),去掉手工存取。
  • 文档把 full-stacked 写成仅供性能对比,实为 wheel 能力不足时的唯一回滚手段 @ docs/backend/server_arguments.md:229
    • 建议:补充说明 per-expert 默认路径要求所装 fastsafetensors 支持 dim0_split_templates(给出最低 wheel 版本/能力要求),否则加载以 RuntimeError 失败;把该句改为"用于受控性能对比,以及所装 fastsafetensors 不支持有界显存投递时的官方回滚开关",措辞与 database.py:368-373 的错误提示保持一致。
  • 文档 continue to use 措辞掩盖了两处默认行为变更 @ docs/backend/server_arguments.md:237
    • 建议:改写该段并补迁移说明:区分"库侧可配项"(bucket/queue/copier 现完全交由 fastsafetensors 配置入口,RTP 不再强制取值,并给出恢复旧 bucket 大小的 JSON 键名与库默认值)与"RTP 侧固定行为"(rank-local copyout 过滤本版本默认启用、按本 rank 所需 checkpoint key 推导、无 env 可关闭);把逐 expert 广播的描述标注为所依赖 wheel 的行为而非 RTP 保证,并去掉暗示行为未变的 continue to use 措辞。
  • 文档把生效前提写成显式 LOAD_METHOD,遗漏默认 auto 同样走 AutoLoader @ docs/backend/server_arguments.md:208
    • 建议:把适用条件改为"当实际选中 fastsafetensors 装载路径时(显式 LOAD_METHOD=fastsafetensors,或默认 auto 自动选中)",并补一句 auto 的选中条件(safetensors 权重 + 非 CPU convert device + 显存足够 + 模块可用),避免运维误判这些开关与自己无关。
  • NOGDS 兼容开关的优先级结论未验证,且覆写不可逆污染进程级 env @ docs/backend/server_arguments.md:223
    • 建议:去掉 therefore 的推导式表述,改为写明 RTP 只保证覆写 FASTSAFETENSORS_CONFIG_JSON、同时设置文件路径时的最终生效结果由库决定(并标注所依赖的 wheel 版本);补一句该覆写是进程级不可恢复写入、会覆盖用户自设 inline JSON,并提示 auto 模式预检读取的是覆写前配置;建议为"FASTSAFETENSORS_CONFIG 文件路径 + NOGDS"组合补一个用例。

P3

  • use_tqdm_on_load 成为死参数,加载进度可观测性静默丢失 @ rtp_llm/utils/database.py:312
    • 建议:要么删除该参数并同步更新调用方与测试,要么在接口 docstring 中注明其已被 fastsafetensors 配置接管、保留仅为兼容。
  • 预算 helper 的 docstring 字段名与实现不符,且异常捕获过宽 @ rtp_llm/model_loader/loader.py:352
    • 建议:修正 docstring 字段名为 estimated_peak_device_bytes;去掉冗余的 ModuleNotFoundErrorAttributeError;对配置解析类错误改为直接抛出并提示 env 名,仅对"wheel 版本过旧"保留回退,并在注释中记录所依赖的 wheel 最低能力,替代已删除的版本闸门语义。
  • 新增纯逻辑用例被 H20 GPU 目标门禁,文件头 Covers 清单与归类未更新 @ rtp_llm/model_loader/test/test_stacked_moe_weight.py:302
    • 建议:把无 GPU 依赖的用例拆到不带 H20 tag 与 exec_properties 的独立 py_test 目标,使其在所有平台 lane 都执行;同时把交付模式/copyout 用例移到独立测试类(如 TestFastsafetensorsDelivery)并补全文件头 Covers: 清单。
  • select 并列分支未复用仓库既有 config_setting_group 约定 @ rtp_llm/libs/BUILD:76
    • 建议:在根 BUILD 增加 selects.config_setting_group(name = "using_cuda13", match_any = [":using_cuda13_x86", ":using_cuda13_arm"]),本处 select 收敛为单分支,与仓库既有惯例保持一致。
  • dev 快照 wheel 缺少构建来源追溯,lock 生成方式待确认 @ deps/requirements_torch_gpu_cuda13.txt:30
    • 建议:在注释中补充这两个 wheel 的上游仓库、分支与 commit(含 fuse-shm 特性来源),保持与同文件其它自建 wheel 一致的追溯规范,并说明 dev 制品的保留策略与回滚方式(保留旧 URL 作注释);同时在 PR 描述中附三个 lock 的生成命令,若确为重新生成且依赖图无变化请注明。
  • cuda13 wheel 元数据 pin 分散三处无同步提示,且缺 cuda13_arm 分支 @ arch_config/arch_select.bzl:104
    • 建议:在 cuda13_x86 分支上方补一条与 ROCm 分支同风格的同步注释;并确认 cuda13_arm 的 wheel 元数据是否也应携带这些 pin,如是请在同一 PR 补齐该分支,避免 ARM wheel 的 install_requires 与实际安装制品长期不一致。
  • CUDA13 打包变更与本 PR 主题无关,缺少动机说明与构建证据 @ arch_config/arch_select.bzl:15
    • 建议:建议把 CUDA13 打包变更拆为独立提交或独立 PR,或在 PR 描述中补充动机、影响平台清单与一次 cuda13 x86/ARM 的 wheel 构建与加载验证记录,使打包变更的风险可独立评估与回滚。

Checklist Findings (22 fail / 48 total)

General Principles Checklist

  • [6.1] Architecture — 依赖方向:无循环依赖/跨层惊喜 → issue 平台无关宏无条件引用 CUDA-13 专用仓库,非 cuda13 平台通配构建会被动拉取
    copy_all_so() 第 15-28 行硬编码 copy_so("@flashinfer_cpp_cu13//:" + target),而同文件 flashinfer_deps()(:164-171)只在 cuda13_x86 使用该仓库;原有 4 个 copy_so 全是全平台可用的 @rtp_llm// 目标。rtp_llm/libs/BUILD:6 无条件调用该宏,因此 cuda12 / cuda12_9 / rocm / cpu / arm 配置下也会在该包生成 11 个 genrule,其源是需 nvcc 编译的 CUDA13 专属 cc_shared_librarydeps/git.bzl:88-109 独立 git 仓库)。消费端 select 已按配置收敛、定义端没有:任何通配构建或查询(//rtp_llm/libs:all//rtp_llm/...、compdb 刷新)都会拉取并编译 CUDA13 flashinfer,在 ROCm/CPU 上因无 nvcc 直接失败,在 cuda12 上是一次完全冗余的重编译。
  • [6.1] Architecture — 兼容性:外部 HTTP/RPC API、持久数据、配置、环境迁移安全 → issue cuda13 wheel 元数据 pin 分散三处无同步提示,且缺 cuda13_arm 分支
    _同一组 wheel URL 现需人工保持三处一致:whl_deps() 的 cuda13_x86 分支(:104-105)、deps/requirements_torch_gpu_cuda13.txt:34-35、对应 lock(:622、:629);同函数的 ROCm 分支在 :111-112 专门写了"Keep the ROCm AITER/FlyDSL pins synchronized with deps/requirements{,_lock}rocm.txt"的同步提示,新增的 cuda13 pin 没有。此外 whl_deps() 没有 using_cuda13_arm 分支(该配置按根 BUILD:44-59 是 using_cuda12 的严格特化,会落到 torch==2.6.0+cu126 分支),而 requirements_cuda13_arm.txt:19-20 已加这两个 pin,两侧口径不一致。
  • [6.1] Architecture — 分层边界:新概念在正确层级,不泄漏内部 → issue 平台无关宏无条件引用 CUDA-13 专用仓库,非 cuda13 平台通配构建会被动拉取
    copy_all_so() 第 15-28 行硬编码 copy_so("@flashinfer_cpp_cu13//:" + target),而同文件 flashinfer_deps()(:164-171)只在 cuda13_x86 使用该仓库;原有 4 个 copy_so 全是全平台可用的 @rtp_llm// 目标。rtp_llm/libs/BUILD:6 无条件调用该宏,因此 cuda12 / cuda12_9 / rocm / cpu / arm 配置下也会在该包生成 11 个 genrule,其源是需 nvcc 编译的 CUDA13 专属 cc_shared_librarydeps/git.bzl:88-109 独立 git 仓库)。消费端 select 已按配置收敛、定义端没有:任何通配构建或查询(//rtp_llm/libs:all//rtp_llm/...、compdb 刷新)都会拉取并编译 CUDA13 flashinfer,在 ROCm/CPU 上因无 nvcc 直接失败,在 cuda12 上是一次完全冗余的重编译。
  • [6.1] Architecture — 可观测性:日志/指标/超时可操作、非噪声 → issue 预算 helper 的 docstring 字段名与实现不符,且异常捕获过宽
    docstring 写"当 max_batch_bytes is unset 时保留旧估算"(:352),实现读取的却是 estimated_peak_device_bytes(:359),字段名不一致会误导后续维护者对 wheel 契约的理解。捕获列表 (ImportError, ModuleNotFoundError, AttributeError, ValueError)ModuleNotFoundErrorImportError 子类属冗余,AttributeErrorgetattr(..., None) 重复;ValueError 还会连带吞掉 json.JSONDecodeError,即 FASTSAFETENSORS_CONFIG_JSON 写错时探测阶段只打 warning,真正报错要等到 AutoLoader 构造,排障链路被拉长。
  • [6.1] Architecture — 回滚路径:风险行为存在运维回滚手段 → issue 文档 continue to use 措辞掩盖了两处默认行为变更
    文档称普通张量 "continue to use the FastSafeTensors bucket and rank-local-copy settings",continue 读作行为未变且均为既有可配项。实际两处变更:一是 database.py:352-363 现只传 pg/files/device 与 local_copyout_filter,全仓已搜不到 bbuf_size_kb,旧实现由 RTP 强制的 batch buffer 大小与 shm copier 均被移除,回落到库默认或 FASTSAFETENSORS_CONFIG_JSON,存量部署升级后装载耗时与峰值显存会静默改变;二是 rank-local copyout 过滤为本次新增,由 loader.py:490 无条件传入且无开关可关。另第 227-229 行描述的"source rank 先切片、各 rank 逐 expert 广播"已不再是 RTP 实现,而是对 wheel 内部行为的断言。本页对 --worker_info_port_num 与 Removed FMHA opti
  • [6.1] Architecture — 状态不变量:创建/更新/失败/重试/回滚路径有效 → issue NOGDS 兼容开关的优先级结论未验证,且覆写不可逆污染进程级 env
    文档先断言 inline JSON 优先于文件路径,再据此推出 NOGDS "therefore takes priority over other fastsafetensors configuration"。但 RTP 只覆写 FASTSAFETENSORS_CONFIG_JSON(database.py:344-347),从不触碰 FASTSAFETENSORS_CONFIG 文件路径,该优先级完全由第三方库决定,本仓无实现也无测试佐证(ckpt_database_test.py:352-353 只覆盖 CONFIG_JSON + NOGDS 组合)。文档也未说明该覆写是对 os.environ 的就地不可恢复写入(用例 :359-362 明确断言调用后仍是覆盖值),用户自设 inline JSON 被静默丢弃(仅一条 warning),且该覆写晚于 auto 模式的显存预检。
  • [6.1] Architecture — 错误语义:fail-fast/retry/fallback/silent 行为显式 → issue NOGDS 兼容开关的优先级结论未验证,且覆写不可逆污染进程级 env
    文档先断言 inline JSON 优先于文件路径,再据此推出 NOGDS "therefore takes priority over other fastsafetensors configuration"。但 RTP 只覆写 FASTSAFETENSORS_CONFIG_JSON(database.py:344-347),从不触碰 FASTSAFETENSORS_CONFIG 文件路径,该优先级完全由第三方库决定,本仓无实现也无测试佐证(ckpt_database_test.py:352-353 只覆盖 CONFIG_JSON + NOGDS 组合)。文档也未说明该覆写是对 os.environ 的就地不可恢复写入(用例 :359-362 明确断言调用后仍是覆盖值),用户自设 inline JSON 被静默丢弃(仅一条 warning),且该覆写晚于 auto 模式的显存预检。
  • [6.1] Quality — Commit 原子、message 与行为匹配 → issue CUDA13 打包变更与本 PR 主题无关,缺少动机说明与构建证据
    本 PR 主题是 fastsafetensors 加载路径下沉与 wheel 升级,但同时在 copy_all_so() 新增 11 个 CUDA13 flashinfer 共享库复制目标并改动 rtp_llm/libs/BUILD 的打包 select,两者无逻辑耦合,无法独立回滚或 bisect。该改动引入了上文两个跨平台一致性问题(无条件注入 cu13 仓库、ARM 变体不一致),却没有配套的构建/加载验证证据,动机(补齐 wheel 中缺失的 libflashinfer_*.so)需读者自行推断。
  • [6.1] Quality — Mega-PR 已拆分为独立变更 → issue CUDA13 打包变更与本 PR 主题无关,缺少动机说明与构建证据
    本 PR 主题是 fastsafetensors 加载路径下沉与 wheel 升级,但同时在 copy_all_so() 新增 11 个 CUDA13 flashinfer 共享库复制目标并改动 rtp_llm/libs/BUILD 的打包 select,两者无逻辑耦合,无法独立回滚或 bisect。该改动引入了上文两个跨平台一致性问题(无条件注入 cu13 仓库、ARM 变体不一致),却没有配套的构建/加载验证证据,动机(补齐 wheel 中缺失的 libflashinfer_*.so)需读者自行推断。
  • [6.1] Quality — PR description 说明动机与设计 → issue CUDA13 打包变更与本 PR 主题无关,缺少动机说明与构建证据
    本 PR 主题是 fastsafetensors 加载路径下沉与 wheel 升级,但同时在 copy_all_so() 新增 11 个 CUDA13 flashinfer 共享库复制目标并改动 rtp_llm/libs/BUILD 的打包 select,两者无逻辑耦合,无法独立回滚或 bisect。该改动引入了上文两个跨平台一致性问题(无条件注入 cu13 仓库、ARM 变体不一致),却没有配套的构建/加载验证证据,动机(补齐 wheel 中缺失的 libflashinfer_*.so)需读者自行推断。
  • [6.1] Quality — 逻辑变更未混入无关格式化 → issue 新增纯逻辑用例被 H20 GPU 目标门禁,文件头 Covers 清单与归类未更新
    新增的 copyout keys / stacked mode / transient budget 三组用例都是纯 Python 逻辑、不需要 GPU,但全部挂在 rtp_llm/model_loader/test/BUILD:5-13test_stacked_moe_weight 目标下,该目标带 tags = ["H20"]exec_properties = {'gpu': 'H20'},而本 PR 的目标平台是 cuda13 x86/ARM 与 cu129;同 BUILD 的 test_per_channel_fp8_helpers(:34-38)已示范无 GPU 门禁的写法。此外这些交付路径用例被塞进 TestBuildStackedKeyConfig(其 docstring 声明只测 _build_stacked_key_config),文件头 Covers: 清单(:3-6)仍只列旧的三项。
  • [6.1] Software Engineering — DRY:重复非平凡逻辑被抽取或显式复用 → issue cuda13 wheel 元数据 pin 分散三处无同步提示,且缺 cuda13_arm 分支
    _同一组 wheel URL 现需人工保持三处一致:whl_deps() 的 cuda13_x86 分支(:104-105)、deps/requirements_torch_gpu_cuda13.txt:34-35、对应 lock(:622、:629);同函数的 ROCm 分支在 :111-112 专门写了"Keep the ROCm AITER/FlyDSL pins synchronized with deps/requirements{,_lock}rocm.txt"的同步提示,新增的 cuda13 pin 没有。此外 whl_deps() 没有 using_cuda13_arm 分支(该配置按根 BUILD:44-59 是 using_cuda12 的严格特化,会落到 torch==2.6.0+cu126 分支),而 requirements_cuda13_arm.txt:19-20 已加这两个 pin,两侧口径不一致。
  • [6.1] Software Engineering — KISS/YAGNI:无投机性抽象 → issue use_tqdm_on_load 成为死参数,加载进度可观测性静默丢失
    改造后 fastsafetensors_weights_iterator 的函数体已不再使用 use_tqdm_on_load(进度显示随批次策略一并下沉给 wheel,:325-393 内部无任何引用,仅原样传给内层 iterator),但 loader.py:486-492 仍按位置固定传 True,形成无效果的参数契约,后续读者会误以为该参数仍能控制加载进度条。
  • [6.1] Tests — 分布式/跨平台变更有对应覆盖 → issue 新增纯逻辑用例被 H20 GPU 目标门禁,文件头 Covers 清单与归类未更新
    新增的 copyout keys / stacked mode / transient budget 三组用例都是纯 Python 逻辑、不需要 GPU,但全部挂在 rtp_llm/model_loader/test/BUILD:5-13test_stacked_moe_weight 目标下,该目标带 tags = ["H20"]exec_properties = {'gpu': 'H20'},而本 PR 的目标平台是 cuda13 x86/ARM 与 cu129;同 BUILD 的 test_per_channel_fp8_helpers(:34-38)已示范无 GPU 门禁的写法。此外这些交付路径用例被塞进 TestBuildStackedKeyConfig(其 docstring 声明只测 _build_stacked_key_config),文件头 Covers: 清单(:3-6)仍只列旧的三项。
  • [6.1] Tests — 新逻辑有聚焦单测 + 相关集成/smoke 测试 → issue 新增纯逻辑用例被 H20 GPU 目标门禁,文件头 Covers 清单与归类未更新
    新增的 copyout keys / stacked mode / transient budget 三组用例都是纯 Python 逻辑、不需要 GPU,但全部挂在 rtp_llm/model_loader/test/BUILD:5-13test_stacked_moe_weight 目标下,该目标带 tags = ["H20"]exec_properties = {'gpu': 'H20'},而本 PR 的目标平台是 cuda13 x86/ARM 与 cu129;同 BUILD 的 test_per_channel_fp8_helpers(:34-38)已示范无 GPU 门禁的写法。此外这些交付路径用例被塞进 TestBuildStackedKeyConfig(其 docstring 声明只测 _build_stacked_key_config),文件头 Covers: 清单(:3-6)仍只列旧的三项。
  • [6.1] Tests — 被删除测试有等价替代覆盖 → issue fastsafetensors 生产边界被手写 fake 完全替代,wheel 契约无 PR 门禁校验
    本 PR 把 fastsafetensors 跨大版本升级、API 从 ParallelLoader 改为 AutoLoader,并新增 local_copyout_filterdim0_split_templates 两个定制 kwarg 与 load_config().estimated_peak_device_bytes 字段。但 ckpt_database_test.py:90 起的 6 个用例全部用 types.ModuleType 伪造 fastsafetensors 注入 sys.modules(:146/:205/:249/:281/:302/:347),test_stacked_moe_weight.py:344-355 又把 _create_model_weights / _generate_weight_info / _build_stacked_key_config / database 整体 MagicMock。AutoLoader(...) 签名与 {expert_id} 模板占位约定只在测试内自
  • [6.1] Tests — 边界 case 覆盖(空、单元素、最大值) → issue 旧 wheel 的 ImportError 回退分支零覆盖,与 docstring 承诺不符
    loader.py:347-366 的 docstring 声称"Keep the historical three-shard estimate when loading an older wheel",其 except 捕获 ImportError/ModuleNotFoundError/AttributeError/ValueError 并回退 3 * max_file_size。但新增两个用例(:388、:401)都提供可用的 load_config,只区分 estimated_peak_device_bytes 有值与 None,即只覆盖 try 分支。"旧 wheel 没有 load_config"这一 docstring 明确承诺、也是最主要的兼容场景完全无用例;该返回值经 loader.py:335-344 直接决定是否放行 fastsafetensors 路径,且该 except 会把 FASTSAFETENSORS_CONFIG_JSON 配置错误(JSONDecodeErrorValueError)静默降级为 lega

RTP-LLM Checklist

  • [I] 代码质量 — 删除或重命名内部 file、registry entry、model name、metric enum、op binding、plugin symbol 时,必须全仓搜索消费者,并提供替代实现、迁移说明或 smoke 覆盖;只有暴露到 HTTP/RPC/config/persisted format 时才按外部兼容性处理 → issue fastsafetensors 生产边界被手写 fake 完全替代,wheel 契约无 PR 门禁校验
    本 PR 把 fastsafetensors 跨大版本升级、API 从 ParallelLoader 改为 AutoLoader,并新增 local_copyout_filterdim0_split_templates 两个定制 kwarg 与 load_config().estimated_peak_device_bytes 字段。但 ckpt_database_test.py:90 起的 6 个用例全部用 types.ModuleType 伪造 fastsafetensors 注入 sys.modules(:146/:205/:249/:281/:302/:347),test_stacked_moe_weight.py:344-355 又把 _create_model_weights / _generate_weight_info / _build_stacked_key_config / database 整体 MagicMock。AutoLoader(...) 签名与 {expert_id} 模板占位约定只在测试内自
  • [I] 代码质量 — 同一功能用统一工具函数 → issue select 并列分支未复用仓库既有 config_setting_group 约定
    新增 select 把同一个 cuda13_flashinfer_shared_libs 分别挂到 //:using_cuda13_x86//:using_cuda13_arm 两个分支。根 BUILD:108-124 为完全相同的诉求建立了 selects.config_setting_groupusing_cuda12_9using_cu12_9_or_13_x86),注释写明"Selects whose cuda13_x86 behavior is identical to cuda12_9_x86 use this group so we don't have to add a parallel branch to every select()"。后续若再有 cuda13 专属打包项,需在每个 select 重复维护两条分支。

Python Static-First Checklist

  • [P.A] 静态结构与类型纪律 — 字符串分发用 Enum/Literal → issue 新开关绕过 LoadConfig 配置面,取值集合三处重复且不入启动配置快照
    该开关直接读 os.environ(:410),是 loader.py 唯一裸 env 读取;同类开关 load_method / force_cpu_load_weights / loader_recycle_handles / moe_pure_tp_preshard 均声明在 py_config_modules.py:176-189LoadConfig、有 --flag 并进入 to_string() 启动快照(docs/backend/server_arguments.md:201-204 的表格即由此而来)。新开关无 flag、不出现在配置快照中,运维排障无法确认生效模式。字面量集合 {"per-expert","full-stacked"} 与报错文案在 loader.py:413 与 database.py:319-323 各写一遍,fastsafetensors_weights_iterator 还带第三份字符串默认值(database.py:315);仓库已有 LoadMethod 枚举先例但未沿用。
  • [P.B] 错误处理 — 禁止 bare except 或静默吞异常 → issue 预算 helper 的 docstring 字段名与实现不符,且异常捕获过宽
    docstring 写"当 max_batch_bytes is unset 时保留旧估算"(:352),实现读取的却是 estimated_peak_device_bytes(:359),字段名不一致会误导后续维护者对 wheel 契约的理解。捕获列表 (ImportError, ModuleNotFoundError, AttributeError, ValueError)ModuleNotFoundErrorImportError 子类属冗余,AttributeErrorgetattr(..., None) 重复;ValueError 还会连带吞掉 json.JSONDecodeError,即 FASTSAFETENSORS_CONFIG_JSON 写错时探测阶段只打 warning,真正报错要等到 AutoLoader 构造,排障链路被拉长。
  • [P.G] 测试规范 — mock/fake/stub 不得替代本次声称覆盖的生产边界 → issue fastsafetensors 生产边界被手写 fake 完全替代,wheel 契约无 PR 门禁校验
    本 PR 把 fastsafetensors 跨大版本升级、API 从 ParallelLoader 改为 AutoLoader,并新增 local_copyout_filterdim0_split_templates 两个定制 kwarg 与 load_config().estimated_peak_device_bytes 字段。但 ckpt_database_test.py:90 起的 6 个用例全部用 types.ModuleType 伪造 fastsafetensors 注入 sys.modules(:146/:205/:249/:281/:302/:347),test_stacked_moe_weight.py:344-355 又把 _create_model_weights / _generate_weight_info / _build_stacked_key_config / database 整体 MagicMock。AutoLoader(...) 签名与 {expert_id} 模板占位约定只在测试内自

Strengths

  • 用 wheel 的 dim0_split_templates 取代自研 ParallelLoader 子类,不再依赖 fb._get_rank_lidx / factory.tensors / free_dev_ptrs / fb.instantiated 等大批私有属性,跨版本静默破裂面显著收窄。
  • 删除收尾彻底:全仓搜索 PerExpertParallelLoader / per_expert_parallel_loader 均零命中,rtp_llm/utils/torch_patch.py:33-39 的 UE8M0 注释同步改写为 AutoLoader,未留过期描述。
  • 能力缺失走显式失败而非静默退化:database.py:364-374TypeError 转成带操作指引的 RuntimeError,并有 test_per_expert_mode_fails_fast_when_wrapper_lacks_split_capabilitytest_wrapper_without_auto_loader_fails_instead_of_legacy_fallback 两个用例真实驱动。
  • 模式开关是"安全默认 + 显式 opt-in":默认 per-expert(有界显存),非法值 fail-fast 且报错含合法取值,配套用例用 assertRaisesRegex 带 match 断言防止错误信息退化。
  • _build_fastsafetensors_local_copyout_keys 同时保留 raw stacked key 与展开后 per-expert key,使过滤在 wheel「split 前/后过滤」两种语义下都不漏 key,docstring 记录了原因。
  • test_full_stacked_mode_disables_prebroadcast_split 真实执行了 RTP 侧 dim0 拆分,既断言 dim0_split_templatesNone 又校验切片键名与数值;ckpt_database_test.py:91-117 完整保存并还原 sys.modules 与三个 FASTSAFETENSORS_* 变量(含"原本不存在"情形)。
  • 依赖与打包基础功课扎实:三平台 requirements 与 lock 的 URL/--hash=sha256 严格成对更新、whl_deps() 无版本漂移;arch_select.bzl:16-27 的 11 个目标与 flashinfer_cu13.BUILD:133-143sub_lib 逐项吻合,rtp_llm/libs/BUILD:8-20 抽成包级常量供两个 select 分支复用而非写两遍。

Comment thread rtp_llm/libs/BUILD Outdated
Comment thread deps/requirements_torch_gpu_cuda12_9.txt Outdated

@LLLLKKKK LLLLKKKK left a comment

Copy link
Copy Markdown
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

AI Code Review - PR #1354 (non-blocking suggestions)

27 条 P2/P3 建议,不阻塞合并。阻塞判定与完整摘要见上一条 review。

len(stacked_key_config),
)

required_checkpoint_keys = self._build_fastsafetensors_local_copyout_keys(

Copy link
Copy Markdown
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

[P2] copyout 谓词跨 rank 不对称,EP>1 下与集合通信语义冲突且零覆盖

required_checkpoint_keystensor_to_weight_map 派生,其 MoE key 经 ffn_weight.py:706-720load_config.py:93-97expert_per_ep * ep_rank 切片,故 EP>1 时各 rank 谓词集合必然不同;该谓词以 __contains__ 无条件下传(:490),而同时下传的 dim0_split_templates 是 rank 无关全量映射。本 PR 改写的 torch_patch.py:33-39 明确记载 AutoLoader 在多 rank 加载时通过 pg.broadcast 跨 rank 搬运权重;被删的 PerExpertParallelLoader 曾显式区分 pg.size()==1 与 broadcast 分支,该调度现全在 wheel 内。新增用例全为单 rank Fake(test_stacked_moe_weight.py:344-355),仓内无 EP>1 覆盖,也无 `--load_m...

建议: 三项任一即可解除阻塞:一是补 ep_size=2 的 fake-pg 用例或 stacked-MoE smoke 目标,断言各 rank 广播次数一致、权重逐元素相同且不挂起;二是在代码注释与 PR 描述中固化 wheel 契约——local_copyout_filter 仅作用于 rank 本地 copy-out、不参与任何集合通信的成组决策,并附一次 EP>1 实际加载记录;三是改为下传跨 rank 求并集后的 rank 无关 key 集合,EP 选择仍由 loader.py:497tensor_to_weight_map 过滤完成,从源头消除分歧。

@@ -332,12 +332,38 @@ def _is_memory_enough_for_fastsafetensor(self):
f"doubling model_mem estimate for fastsafetensor memory check"

Copy link
Copy Markdown
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

📍 实际位置 rtp_llm/model_loader/loader.py:267(不在 diff 展示范围内,就近挂载)

[P2] 删除唯一版本闸门后无能力探测,旧 wheel 环境由可降级变为硬失败

被删文件是仓内唯一显式版本校验点(_REQUIRED_FST_VERSION = "0.1.19"),删除后全仓已搜不到任何版本/能力门禁。AUTO 仅以 has_module("fastsafetensors") 判断(:267),随后 from fastsafetensors import AutoLoader(database.py:317)对旧 wheel 直接 ImportError,即装旧 0.1.x wheel 的既有环境不再降级 SCRATCH 而是加载阶段崩溃(ckpt_database_test.py:288 已把该硬失败固化为预期)。local_copyout_filter 更无任何兜底:database.py:352-374 的友好转译只匹配 dim0_split_templates,wheel 不认识该 kwarg 时抛裸 TypeError,且无 env 可关闭。同时 _is_memory_enough_for_fastsafetensor() 排在 has_module 之前,未装 wheel 的平台每次加载都...

建议: 把 AUTO 判定顺序调整为先 has_module(即可消除噪声告警),并把存在性判断收紧为能力判断(探测 AutoLoader 属性,或用 inspect.signature 校验 dim0_split_templates / local_copyout_filter),探测失败降级 SCRATCH 并 warning;若坚持 fail-fast,则在导入处给出带最低版本号与升级指引的错误信息以替代被删的版本护栏,并把两个定制 kwarg 用同一套 except TypeError 转译覆盖。同时在文档补一行最低 wheel 能力要求与旧环境处置方式(升级镜像或显式 --load_method scratch)。

from fastsafetensors import load_config

config = load_config()
estimate = getattr(config, "estimated_peak_device_bytes", None)

Copy link
Copy Markdown
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

[P2] estimated_peak_device_bytes 缺正值下界,异常上报会使显存闸门失效

_fastsafetensors_transient_budget_bytes 只判断 estimate is None(:359-360),其余取值一律直接返回。该返回值是唯一门槛(enough = (free_mem - model_mem) > transient_mem,:338),若 wheel 对未配置项上报 0 或异常小值,闸门退化为 (free_mem - model_mem) > 0,等于取消改动前 3 * max_file_size 的 OOM 保护,AUTO 会在显存明显不足时仍选 fastsafetensors;max_file_mem 已降级为纯日志字段。测试只覆盖 8*1024None(test_stacked_moe_weight.py:388-412),未覆盖 0/负值边界。

建议: 要求正整数才采用,例如 if not isinstance(estimate, int) or estimate <= 0: return legacy_budget,或加下界 max(estimate, max_file_size),回退时打日志说明原因;并在 TestFastsafetensorsTransientBudget 补 0 与负值两个参数化用例,锁定"异常上报不得绕过门禁"。

"""
legacy_budget = 3 * max_file_size
try:
from fastsafetensors import load_config

Copy link
Copy Markdown
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

[P2] load_config() 早于 NOGDS 环境归一化被调用,预检预算与实际配置不一致

AUTO 选路在 _is_memory_enough_for_fastsafetensor 内调用 load_config() 读取峰值估算(loader.py:335、355-360)。但 FASTSAFETENSORS_NOGDS=1FASTSAFETENSORS_CONFIG_JSON 的强制覆写发生在其后的 database.py:344-351(构造 AutoLoader 之前),且 ckpt_database_test.py:359-362 断言该覆写不可恢复地留在进程环境中。即选路时读到的是覆写前配置,实际加载用的是 base/nogds 配置;两者 batch buffer 记账不同时,闸门会基于错误预算放行或误判,前者带来加载期 OOM 风险。

建议: 把 NOGDS→FASTSAFETENSORS_CONFIG_JSON 的映射抽成幂等的配置准备函数(如 apply_fastsafetensors_env_overrides())在两处复用,在读取 load_config() 之前先调用,保证选路与加载看到同一份配置;或至少把当前 FASTSAFETENSORS_CONFIG_JSON 摘要打进预检日志便于事后核对。

Comment thread rtp_llm/utils/database.py Outdated
Comment thread rtp_llm/model_loader/test/test_stacked_moe_weight.py Outdated
Comment thread rtp_llm/libs/BUILD Outdated
Comment thread deps/requirements_torch_gpu_cuda13.txt
Comment thread arch_config/arch_select.bzl Outdated
Comment thread arch_config/arch_select.bzl Outdated
loomts

This comment was marked as off-topic.

@loomts
loomts dismissed stale reviews from LLLLKKKK and LLLLKKKK August 31, 2026 00:22

LGTM:阻断已解除(rtpcli 自动清除旧红标)

@LLLLKKKK LLLLKKKK left a comment

Copy link
Copy Markdown
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

AI Code Review - PR #1354 (non-blocking suggestions)

29 条 P2/P3 建议,不阻塞合并。阻塞判定与完整摘要见上一条 review。

len(stacked_key_config),
)

required_checkpoint_keys = self._build_fastsafetensors_local_copyout_keys(

Copy link
Copy Markdown
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

[P2] copyout 谓词跨 rank 不对称,EP>1 下与集合通信语义冲突且零覆盖

loader.py:465tensor_to_weight_map.keys() 构造过滤集,其 MoE key 来自 ffn_weight.py:706-720get_tensor_namesload_config.py:89-98get_selected_experts,后者按 expert_per_ep * ep_rank : expert_per_ep * (ep_rank + 1) 切片(开 EPLB 时还叠加 phy2log)。因此 ep_size>1 且 checkpoint 为非 stacked 的逐专家布局(stacked_ckpt_keys=False,如 Mixtral/Qwen-MoE)时,loader.py:490 传给 AutoLoader 的谓词在各 rank 上接受的真实 ckpt key 集合不同。被删的 _broadcast_per_expert 是对 range(num_experts) 全 rank 对称广播、由 RTP 侧再过滤;`torch_patch.py:3...

建议:_build_fastsafetensors_local_copyout_keys 的 docstring 中显式写下该契约并给出 wheel 侧依据(当前参数名与注释暗示 rank 本地语义,但未被验证);同时补一个 ep_size>1 的多 rank 集成或 smoke 用例,实跑逐专家布局 MoE 的 fastsafetensors 加载。若短期无法验证,保守做法是在 ep_size > 1 时对 MoE key 取全 rank 并集(用 range(expert_num) 而非 get_selected_experts 结果)使谓词 rank 不变,仅保留非 MoE key 的过滤收益。

@@ -332,12 +332,38 @@ def _is_memory_enough_for_fastsafetensor(self):
f"doubling model_mem estimate for fastsafetensor memory check"

Copy link
Copy Markdown
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

📍 实际位置 rtp_llm/model_loader/loader.py:267(不在 diff 展示范围内,就近挂载)

[P2] 删除唯一版本闸门后无能力探测,旧 wheel 环境由可降级变为硬失败

被删实现有 _REQUIRED_FST_VERSION = "0.1.19" 显式守卫,版本不符时抛带升级指引的 RuntimeError;这是全仓唯一一处对 wheel 版本的主动断言。新实现无任何版本/能力校验:loader.py:262-269 的 AUTO 分支仅用 has_module("fastsafetensors")utils/module_util.py:13 内部只做 find_spec)即选中 FASTSAFETENSORS,随后 database.py:317 执行 from fastsafetensors import AutoLoader, SingleGroup。旧 wheel 下抛裸 ImportError(ckpt_database_test.py:288 正是对此的断言),AUTO 路径无 SCRATCH 降级,服务启动直接失败;而 loader.py:348-353 的 docstring 仍声称支持「older wheel」,两处假设自相矛盾。文档新章节也未给出最低版本前提与回滚指引。

建议: 在 AUTO 选路阶段(has_module 之后)补一次能力探测:AutoLoader 不可导入时打告警并回落 LoadMethod.SCRATCH;显式 LOAD_METHOD=fastsafetensors 时抛出带最低 wheel 能力(需 AutoLoader/load_config()per-expert 还需 dim0_split_templates)与升级指引的错误替代裸 ImportError。同时在 docs/backend/server_arguments.md 新章节开头补一句版本前提(以 deps/requirements_torch_gpu_*.txt 的 pin 为准)与回滚路径(LOAD_METHOD=scratchfull-stacked),并修正 docstring 中「兼容旧 wheel」的表述。

Checklist: [I] 删除或重命名内部 file、registry entry、model name、metric enum、op binding、plugin symbol 时,必须全仓搜索消费者,并提供替代实现、迁移说明或 smoke 覆盖;只有暴露到 HTTP/RPC/config/persisted format 时才按外部兼容性处理

from fastsafetensors import load_config

config = load_config()
estimate = getattr(config, "estimated_peak_device_bytes", None)

Copy link
Copy Markdown
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

[P2] estimated_peak_device_bytes 缺正值下界与类型校验,异常上报会使显存闸门失效

loader.py:360return legacy_budget if estimate is None else estimate 只拦截 None。若 wheel 的 load_config()estimated_peak_device_bytes 上报为 0(字段惰性计算未就绪或配置未解析时的默认零值),loader.py:335-338 得到 transient_mem=0.0,准入判据退化为 free_mem > model_mem,改造前恒定要求的 3 * max_file_size 余量被完全抹掉,AUTO 会在原先回退 SCRATCH 的紧显存机器上改选 fastsafetensors 并在加载期 OOM;负值同理更宽松。签名标注 -> int 但返回值直接来自外部对象属性,若为 str(JSON 配置常见)则 loader.py:335 的除法抛 TypeError,该异常发生在 try 块之外、无法回退 legacy 估算。

建议:estimate 增加显式校验后再采用:仅当 isinstance(estimate, (int, float))estimate > 0 时使用,并对最终预算取下界 max(estimate, legacy_budget)(或至少 max_file_size),避免外部低报或异常值直接削弱门限;同时补 estimate=0、负值、非数值三个边界的单测。

"""
legacy_budget = 3 * max_file_size
try:
from fastsafetensors import load_config

Copy link
Copy Markdown
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

[P2] load_config() 早于 NOGDS 环境归一化被调用,预检预算与实际配置不一致

调用链顺序为 loader.py:266 先求值 _is_memory_enough_for_fastsafetensor():335:356-359load_config().estimated_peak_device_bytes;而把 FASTSAFETENSORS_NOGDS=1 映射为 FASTSAFETENSORS_CONFIG_JSON={"loader":"base","base":{"copier_type":"nogds"}} 的覆写写在 database.py:344-351,位于含 yielditerator 函数体内(database.py:395return iterator(...) 仅创建生成器),首次 next() 才执行。于是门限按覆写前的用户 config(可能是 GDS/fuse-shm)估算,实际运行的却是 base/nogds loader,两者 batch buffer 与 device 峰值不同;显式 `LOAD_METHOD=fastsafetenso...

建议: 把 NOGDS → FASTSAFETENSORS_CONFIG_JSON 的兼容映射抽成两处复用的辅助函数(例如 _apply_fastsafetensors_env_compat()),并在任何 load_config() 调用之前统一归一化一次,保证门限与实际 loader config 同源;同时把最终生效的 loader 名与关键配置摘要打进 fastsafetensor memory check 日志,便于线上回溯选路依据。

Comment thread rtp_llm/utils/database.py Outdated
Comment thread rtp_llm/model_loader/test/test_stacked_moe_weight.py Outdated
Comment thread deps/requirements_torch_gpu_cuda13.txt
Comment thread arch_config/arch_select.bzl
Comment thread rtp_llm/libs/BUILD Outdated
Comment thread arch_config/arch_select.bzl Outdated
@ABNER-1
ABNER-1 force-pushed the shuxing/dsv4-sleep-level2-fastsafetensors branch from 05413c2 to be48ee7 Compare August 31, 2026 02:52
@ABNER-1 ABNER-1 changed the title feat(loader): integrate rank-local FastSafeTensors copyout feat(loader): integrate bounded rank-local FastSafeTensors copyout Aug 31, 2026
loomts

This comment was marked as off-topic.

@LLLLKKKK LLLLKKKK left a comment

Copy link
Copy Markdown
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

AI Code Review - PR #1354

Status: BLOCKING

Summary: P0/0 · P1/1 · P2/18 · P3/4

Reviewed: commit be48ee7edaff · 2026-08-31 12:06 UTC+8

Blocking Issues

P1

  • 硬依赖 fastsafetensors 新版 AutoLoader 能力但未对齐 wheel pin,删除版本闸门后 auto 路径无探测也无回退 @ rtp_llm/utils/database.py:317
    • 建议:在本 PR 内二选一并写入 PR description:(1)同步升级 deps/requirements*requirements_lock_* 到提供 AutoLoader + local_copyout_filter + dim0_split_templates + estimated_peak_device_bytes 的 wheel,并确认 cuda12_9 / cuda13 / cuda13_arm 三平台能力一致、写明最低版本与升级顺序;(2)暂不升级则补等价护栏:把 AUTO 判定从 has_module 收紧为正向能力探测(inspect.signature(AutoLoader.__init__) 检查两个关键 kwarg,或校验版本下界),能力不足时降级为 LoadMethod.SCRATCH 并 warn,而非在权重加载中途抛裸 ImportError。同时在文档 ### FastSafeTensors loader configuration 小节声明所需最低 wheel 版本。

Non-blocking Suggestions

P2

  • copyout 谓词跨 rank 不对称,EP>1 语义未固化且零覆盖 @ rtp_llm/model_loader/loader.py:465
    • 建议:在 _build_fastsafetensors_local_copyout_keys 的 docstring 中显式声明该谓词允许跨 rank 分叉并给出上游语义依据;或在传入前跨 process group 校验键集合一致性(all_gather hash,不一致即 fail-fast 而非挂死)。补一个 ep_size=2 的用例(gloo + CPU 假 checkpoint 即可),断言两个 ep_rank 各自的 required_checkpoint_keys 恰好覆盖本 rank 所需 key 且 stacked raw key 在两 rank 上一致。另建议把 loader.py:556 的 fallback 日志从 info 升为 warning 或补一条 metric,使过滤误杀导致的静默回退可观测。
  • 能力错误映射只覆盖 dim0_split_templates,其余能力缺失无处置指引且静默降级不可观测 @ rtp_llm/utils/database.py:364
    • 建议:改为正向能力探测(显式检查 AutoLoader.__init__ 是否声明这两个 kwarg,或由 wheel 暴露能力标志)替代异常文本匹配,并让 local_copyout_filter 缺失时同样落入带指引的 RuntimeError;local_copyout_filter is None 时不放入 kwargs,避免旧 wheel 在非 MoE 路径上无谓失败。另在 per-expert 模式下若迭代仍收到原始 stacked key,输出一次 warning(如「per-expert requested but loader delivered stacked key X; peak memory not bounded」)。测试侧补两条 TypeError 用例:函数体内抛 TypeError("unrelated argument mismatch") 断言原样上抛不被转成 RuntimeError;抛 TypeError("dim0_split_templates must be a dict") 把字符串嗅探的误判风险显式暴露出来。
  • estimated_peak_device_bytes 缺正值下界与类型校验,异常上报会使显存闸门失效 @ rtp_llm/model_loader/loader.py:359
    • 建议:对上报值加类型与正值校验并取下界,例如 max(legacy_budget, int(estimate)),非正值或非整数时 warn 并退回 legacy 估计。若确实有意完全信任 wheel 上报,请在实现处注释说明门槛放宽是有意的,并在文档中提示新旧路径显存判定口径的差异,便于运维在升级后关注显存水位。
  • load_config() 早于 NOGDS 环境归一化被调用,预检预算与实际配置不一致 @ rtp_llm/model_loader/loader.py:356
    • 建议:把 NOGDS → FASTSAFETENSORS_CONFIG_JSON 的归一化抽成一个共用函数(例如 _normalize_fastsafetensors_config_env()),并在显存预检之前调用一次,使 _fastsafetensors_transient_budget_bytesAutoLoader 构造读取同一份配置;或在预算函数内先完成同样的归一化再 load_config(),避免两处配置来源分叉。
  • full-stacked 模式的额外显存峰值未纳入准入预算 @ rtp_llm/utils/database.py:387
    • 建议:把 stacked_moe_modestacked_key_config 传入 _is_memory_enough_for_fastsafetensor / 预算函数,在 full-stacked 下按 expert_num 与 stacked 张量规模额外计入整块张量的开销;若不便传参,至少在选择 full-stacked 时输出一条 warning,说明该模式下显存预检不覆盖整块 stacked 张量峰值,需要人工确认剩余显存。
  • 模式环境变量为空串时抛异常导致加载硬失败 @ rtp_llm/model_loader/loader.py:410
    • 建议:把空串视为未设置并回落默认值,例如 (os.environ.get(...) or "per-expert").strip() or "per-expert";并在 database.py:319 的二次校验处保持一致语义。若刻意要对空串 fail-fast,请在文档中明确写出「置空不等于取默认值」,避免运维按常规习惯清空变量后启动失败。
  • 新开关绕过 LoadConfig 配置面,取值集合多处重复且不入启动配置快照 @ rtp_llm/model_loader/loader.py:413
    • 建议:按仓库既有约定在 load_group_args.py 注册 --fastsafetensors_stacked_moe_modedefault="per-expert",取值用 choicesstr, Enum 约束)并 bind 到 LoadConfigloader.pydatabase.py 改为接收已校验的枚举,删除 database.py 的重复字面量分支,把取值集合以 LoadMethod 为先例收敛为单一来源。文档同步在 Load Config 表格补一行。若确定仅作临时性能对比开关,请在文档中标注为实验开关及预计移除时间。
  • 未安装 fastsafetensors 的平台每次加载都打印误导性 WARNING @ rtp_llm/model_loader/loader.py:362
    • 建议:把 has_module("fastsafetensors") 前移到 and 链中 _is_memory_enough_for_fastsafetensor() 之前(顺带省掉一次无意义的显存查询),或在预算函数内先判断模块可用性、不可用时改用 logging.debug;同时为 estimate is None 补一条 info 说明已退回 legacy 估计,使两条降级路径的日志级别与信息量一致。
  • 文档把生效前提写成显式 LOAD_METHOD,遗漏默认 auto 同样走 AutoLoader @ docs/backend/server_arguments.md:208
    • 建议:将生效条件改为「LOAD_METHOD=fastsafetensors,或默认 auto 自动选中 fastsafetensors 时」,并补一句 auto 的选中条件与回滚方式(显式 LOAD_METHOD=scratch),使运维能判断自己是否受影响、以及出问题时如何快速回退到 SCRATCH 路径。
  • NOGDS 兼容开关的优先级结论未验证,且覆写不可逆污染进程级 env @ docs/backend/server_arguments.md:223
    • 建议:在应用覆盖时同时 os.environ.pop("FASTSAFETENSORS_CONFIG", None),让优先级承诺由 RTP 自身保证;或改为 try/finally 还原原值,把覆盖限制在单次加载范围内。文档相应改为「优先级由 fastsafetensors 决定,请只保留一种配置方式」,并注明该覆盖是进程级、日志中会出现对应 warning。
  • 文档把 full-stacked 写成仅供性能对比,实为 wheel 能力不足时的回滚手段 @ docs/backend/server_arguments.md:229
    • 建议:补充 full-stacked 的两种用途(性能对比 + wheel 能力缺失时的临时兼容回退),注明其显存代价量级与「仅作临时措施、应尽快升级 wheel」的建议,使文档与错误信息的处置指引一致;补一句非法取值会 ValueError 快速失败,避免运维把拼写错误误判为静默降级;并在小节开头列出两种硬失败信号及对应处置方式。此外建议把 FASTSAFETENSORS_CONFIGFASTSAFETENSORS_CONFIG_JSONRTP_FASTSAFETENSORS_STACKED_MOE_MODE 补进本页第 199-204 行的 Load Config 表格(无对应 CLI 参数时标注 env-only),与本页 arg (ENV) 登记约定保持一致。
  • 文档 continue to use 措辞掩盖了默认调参变更且无回滚配置示例 @ docs/backend/server_arguments.md:237
    • 建议:改写该句,明确「bucket 大小、shm、copier 等参数不再由 RTP 传入,改由 fastsafetensors 默认值或 config JSON 决定」,并给出含 bucket/shm 字段的示例 JSON(键名与 wheel 侧一致),说明希望保持原有加载性能的部署应如何显式配置;同时在 PR description 补一组升级前后的加载耗时 / 峰值显存对比(至少一个大 MoE 模型、单机多卡),以支撑「默认值足够好」的判断。
  • per-expert 拆分用例由 fake 自行完成拆分,用例名与实际覆盖不符 @ rtp_llm/utils/test/ckpt_database_test.py:119
    • 建议:把用例改名为反映真实断言的内容(如 test_split_templates_are_forwarded_and_loader_is_closed),并补一条让 fake 产出真实 torch.Tensor 且 key 与 stacked_key_config 对齐的用例,真正走通 per-expert 拆分分支。另补一条针对真实 wheel 的契约用例:用 unittest.skipUnless 在装有 fastsafetensors 的目标上以 inspect.signature(AutoLoader.__init__) 断言两个关键 kwarg 存在,或在 smoke 层加一条 LOAD_METHOD=fastsafetensors 的 stacked MoE 用例,补回移除版本闸门后失去的漂移防护。
  • 缺少对 clone 语义的断言,去掉 clone 后测试仍会通过 @ rtp_llm/utils/test/ckpt_database_test.py:273
    • 建议:让 fake 持有源张量引用,在 list(...) 消费结束后执行 src.fill_(0),再断言已产出的两片切片数值未变;或直接断言 result[0][1].data_ptr() != src[0].data_ptr()。同时补一条 num_experts=1 的边界用例,确认单专家 stacked 张量仍产出恰好一个 key。
  • NOGDS 兼容开关只覆盖覆写方向,缺少反向断言与 database 侧非法模式断言 @ rtp_llm/utils/test/ckpt_database_test.py:321
    • 建议:补一条 NOGDS 未设置时的用例,断言 AutoLoader 观察到的配置与用户原设值一致;把现有用例的断言从「调用后环境变量是否残留」改为只校验传入时刻的有效配置(observed_config),避免把进程级副作用写死为期望行为;再补一条同时设置 FASTSAFETENSORS_CONFIG 与 inline JSON 的用例把优先级固化为可回归行为,以及一条直接调用 fastsafetensors_weights_iterator(..., stacked_moe_mode="surprise") 断言 ValueError 的用例。
  • 重复的 fake 脚手架与两种模块打桩写法并存 @ rtp_llm/utils/test/ckpt_database_test.py:90
    • 建议:抽一个参数化的 fake 工厂(例如 _install_fake_fastsafetensors(*, split_templates_sink=None, filter_sink=None, weights=(), support_split=True))供各用例复用,把构造签名收敛到单处;模块打桩统一改用 patch.dict(sys.modules, {...}),与 test_stacked_moe_weight.py 保持同一惯例,同时省掉手写的 sys.modules 保存/还原逻辑。
  • copyout filter 用例未隔离模式环境变量,文档给出的场景会直接使其失败 @ rtp_llm/model_loader/test/test_stacked_moe_weight.py:315
    • 建议:给该用例(或类级 setUp/tearDown)加显式隔离:patch.dict("os.environ", ...) 配合 os.environ.pop("RTP_FASTSAFETENSORS_STACKED_MOE_MODE", None),做法可参考同 PR FastsafetensorsAutoLoaderTest.setUp/tearDownFASTSAFETENSORS_* 的处理以保持同仓一致;并补一个只针对 _fastsafetensors_stacked_moe_mode() 的用例,在变量确定不存在与为空串两种情况下断言期望返回值。
  • 旧 wheel 的异常回退分支与 0 值边界零覆盖,与 docstring 承诺不符 @ rtp_llm/model_loader/test/test_stacked_moe_weight.py:401
    • 建议:补三条用例:构造无 load_config 属性的 types.ModuleType("fastsafetensors") 覆盖 ImportError/AttributeError 分支;让 load_configValueError 覆盖异常分支,两者均断言返回 3 * max_file_size 并用 assertLogs 校验降级日志已输出;再加 estimated_peak_device_bytes=0 与负值的边界断言,明确期望是「按配置放行」还是「视作未配置并回退」,并与实现侧的下界校验保持一致。

P3

  • use_tqdm_on_load 成为死参数,加载进度可观测性静默丢失 @ rtp_llm/utils/database.py:312
    • 建议:二选一:若上游 config 已提供等价的进度开关,把该参数映射到对应配置项并在文档中说明;若确定不再支持,删除 use_tqdm_on_load 形参与内部透传、同步修改 loader.py:487 与三处测试调用,避免留下让调用方误判的死参数。同时确认 loader.py:520-527 的周期性进度日志是否足以替代 tqdm,否则建议把采样间隔调密或改为按耗时打点。
  • 预算 helper 的 docstring 字段名与实现不符,且异常捕获过宽、错误语义不一致 @ rtp_llm/model_loader/loader.py:352
    • 建议:把 docstring 中的 max_batch_bytes 改为 estimated_peak_device_bytes;删去冗余的 ModuleNotFoundError 与不可达的 AttributeErrorestimate is None 时补一条 info 说明已退回 legacy 估计;并统一错误语义:定位为 best-effort 读取则把 OSError 一并纳入(收敛为 (ImportError, ValueError, OSError)),定位为 fail-fast 则移除 ValueError 的静默兜底,避免「看起来防御但真正的失败模式没兜住」。
  • 新增纯逻辑用例被 H20 GPU 目标门禁,归属类职责不符且文件头 Covers 未更新 @ rtp_llm/model_loader/test/test_stacked_moe_weight.py:302
    • 建议:把 copyout 与 stacked-moe-mode 相关用例拆到独立类(如 TestFastsafetensorsCopyoutFilterTestStackedMoeModeResolution),与已独立的 TestFastsafetensorsTransientBudget 风格一致;同步在文件头 Covers: 补上「rank-local copyout filter」「stacked MoE 模式解析」「fastsafetensors 瞬时内存预算」三项。若这批纯逻辑断言不需要真实 GPU,建议另建一个不带 H20 tag 的 py_test 目标承载,减少稀缺 GPU 占用并让它们在更多 CI 目标上执行。
  • UE8M0 broadcast shim 的适用性断言随 AutoLoader 迁移失去可验证依据 @ rtp_llm/utils/torch_patch.py:37
    • 建议:把注释中的断言改为可验证形式:明确写出「已验证的 wheel 版本 + loader 后端组合」,并说明切换后端需重新确认;更稳妥的做法是把 shim 扩展到 scatter / all_gather_into_tensor 等同类入口(同样只在 float8_e8m0fnu 上触发,代价极低),或在多 rank UE8M0 加载路径上补一条 smoke 覆盖,使后端切换导致的失效能被自动发现而非上线时暴露。

Checklist Findings (18 fail / 48 total)

General Principles Checklist

  • [6.1] Architecture — 兼容性:外部 HTTP/RPC API、持久数据、配置、环境迁移安全 → issue UE8M0 broadcast shim 的适用性断言随 AutoLoader 迁移失去可验证依据
    该 shim 只 patch dist.broadcasttorch_patch.py:68-77),用于绕开 NCCL 拒绝 Float8_e8m0fnu 的限制;原注释的依据是 RTP 自己实现/子类化了 ParallelLoader,可确认「每条 UE8M0 传输都走 pg.broadcast」。本 PR 把注释改为「AutoLoader routes UE8M0 transfers through pg.broadcast」,但 AutoLoader 是配置驱动的调度器,后端还可由最终用户通过 FASTSAFETENSORS_CONFIG_JSON(文档第 214 行示例 "loader":"base")自由切换,不同 copier 是否只用 broadcast、是否改用 scatter/all_gather 已不在本仓可验证范围内。若某后端使用 broadcast 之外的集合通信,DSv4-Flash 等 UE8M0 权重 scale 在多 rank 加载时会以 NCCL dtype 错误崩溃。
  • [6.1] Architecture — 分层边界:新概念在正确层级,不泄漏内部 → issue 新开关绕过 LoadConfig 配置面,取值集合多处重复且不入启动配置快照
    同一 Load Config 章节其余四个开关(--load_method / --force_cpu_load_weights / --loader_recycle_handles / --moe_pure_tp_preshard)都在 load_group_args.py:9-40 通过 add_argument(env_name=..., bind_to=...) 注册,可 CLI 设置、可进配置快照、启动期完成校验。新开关只在 loader.py:410 用裸 os.environ.get 读取:既不进 --help 与参数表,也无法 CLI 覆盖,非法值要等后端进程真正加载权重时才抛 ValueError。取值集合 {"per-expert","full-stacked"}loader.py:413(带 .strip())、database.py:319(不 strip)、database.py:315 默认值字面量、文档正文各写一份,新增第三种模式需同步四处。仓内已有 `LoadMethod(str, enum.
  • [6.1] Architecture — 可观测性:日志/指标/超时可操作、非噪声 → issue 预算 helper 的 docstring 字段名与实现不符,且异常捕获过宽、错误语义不一致
    docstring 第 352 行称「当 max_batch_bytes 未设置时保留历史估算」,代码实际读取的是 estimated_peak_device_bytes:359),字段名对不上,易误导维护者去找不存在的配置项。getattr 字面量探测在属性改名或 wheel 不支持时静默回落 legacy,且 estimate is None 这条路径没有任何日志。捕获列表中 ModuleNotFoundErrorImportError 子类(冗余),AttributeErrorgetattr(..., None) 下不可达;而 FASTSAFETENSORS_CONFIG 指向不存在文件时 load_config() 抛出的 OSError 不在捕获范围内会直接冒泡——同一函数对配置读取失败呈现「静默降级」与「直接崩溃」两种不一致语义。
  • [6.1] Architecture — 回滚路径:风险行为存在运维回滚手段 → issue 文档 continue to use 措辞掩盖了默认调参变更且无回滚配置示例
    文档称「ordinary tensors continue to use the FastSafeTensors bucket and rank-local-copy settings」,读起来像行为不变。但 diff 显示改造前 RTP 侧显式传入 bbuf_size_kb=1024*1024*2(2GB 量级批缓冲)、use_shm=not use_nogdsnogds=use_nogdsuse_tqdm_on_load,改造后 database.py:352-363 只传 pg、文件列表、device 与两个新 kwarg——bucket 大小、shm、copier 取值全部改由库默认或 FASTSAFETENSORS_CONFIG_JSON 决定。这是对所有既有 safetensors 部署(默认 auto 亦命中)的隐式调参变更:若库默认批缓冲显著小于 2GB,权重加载耗时可能回退,而文档既未标注为行为变更,也未给出恢复原取值的迁移映射。
  • [6.1] Architecture — 状态不变量:创建/更新/失败/重试/回滚路径有效 → issue NOGDS 兼容开关的优先级结论未验证,且覆写不可逆污染进程级 env
    文档据「inline JSON 优先于文件路径」推出 NOGDS「therefore takes priority over other fastsafetensors configuration」,但该优先级完全由 wheel 内部决定,仓内既无实现保证也无验证手段;database.py:344-351 对同时设置的 FASTSAFETENSORS_CONFIG 文件路径不做任何处理——若 wheel 实际以文件配置优先,兼容开关会在它本要修复的 dev 场景中静默失效。同时该覆写就地写入 os.environ 且不还原,用户原设值在本进程后续所有加载(含 ViT/EPLB 二次加载、子进程继承)中被永久替换,文档未说明该副作用不可逆。
  • [6.1] Architecture — 错误语义:fail-fast/retry/fallback/silent 行为显式 → issue UE8M0 broadcast shim 的适用性断言随 AutoLoader 迁移失去可验证依据
    该 shim 只 patch dist.broadcasttorch_patch.py:68-77),用于绕开 NCCL 拒绝 Float8_e8m0fnu 的限制;原注释的依据是 RTP 自己实现/子类化了 ParallelLoader,可确认「每条 UE8M0 传输都走 pg.broadcast」。本 PR 把注释改为「AutoLoader routes UE8M0 transfers through pg.broadcast」,但 AutoLoader 是配置驱动的调度器,后端还可由最终用户通过 FASTSAFETENSORS_CONFIG_JSON(文档第 214 行示例 "loader":"base")自由切换,不同 copier 是否只用 broadcast、是否改用 scatter/all_gather 已不在本仓可验证范围内。若某后端使用 broadcast 之外的集合通信,DSv4-Flash 等 UE8M0 权重 scale 在多 rank 加载时会以 NCCL dtype 错误崩溃。
  • [6.1] Quality — 逻辑变更未混入无关格式化 → issue 新增纯逻辑用例被 H20 GPU 目标门禁,归属类职责不符且文件头 Covers 未更新
    TestBuildStackedKeyConfig 的 docstring 声明只测 _build_stacked_key_config,但类内新增的 :302:315:361:373 四个用例分别测试 copyout key 构造、_load_from_fastsafetensor 接线与环境变量解析,与该类主题无关;文件头 Covers::3-7)三条清单也未增补新覆盖面。此外这批用例(含 TestFastsafetensorsTransientBudget)全是纯逻辑断言,却被 test/BUILD:5-13tags=["H20"] + exec_properties={'gpu':'H20'} 门禁,占用稀缺 GPU 执行槽且在无 H20 的环境无法本地直跑。
  • [6.1] Software Engineering — DRY:重复非平凡逻辑被抽取或显式复用 → issue 重复的 fake 脚手架与两种模块打桩写法并存
    FastsafetensorsAutoLoaderTest 的 6 个用例各自重复定义几乎相同的 FakeSingleGroupFakeAutoLoader:123-149:184-208:228-252:277-283:294-305:324-350),仅观察点不同;构造签名 (pg, files, device, local_copyout_filter, dim0_split_templates) 被手抄五遍,一旦真实 wheel 签名变化需同步修改五处。同时本 PR 引入了两种模块打桩写法:本文件用 sys.modules["fastsafetensors"] = fake_module 配合手写 setUp/tearDown 还原,test_stacked_moe_weight.py:395patch.dict(sys.modules, ...),同一功能两套惯例增加后续维护者的认知负担。
  • [6.1] Software Engineering — KISS/YAGNI:无投机性抽象 → issue use_tqdm_on_load 成为死参数,加载进度可观测性静默丢失
    改造前 use_tqdm_on_load 被透传为 ParallelLoader(use_tqdm_on_load=...),驱动加载进度显示;改造后 loader_kwargs 不再包含它,内部 def iterator(device, use_tqdm_on_load)database.py:325)与 return iterator(device, use_tqdm_on_load):395)仍保留形参,函数体内没有任何使用点。唯一生产调用方 loader.py:487 仍硬编码传 True,即调用方以为开启了进度显示、实际已完全失效。大模型权重加载耗时数分钟,进度输出丢失会影响现场排障(难以区分「加载慢」与「加载卡死」)。
  • [6.1] Software Engineering — SRP:模块/类职责单一 → issue 新增纯逻辑用例被 H20 GPU 目标门禁,归属类职责不符且文件头 Covers 未更新
    TestBuildStackedKeyConfig 的 docstring 声明只测 _build_stacked_key_config,但类内新增的 :302:315:361:373 四个用例分别测试 copyout key 构造、_load_from_fastsafetensor 接线与环境变量解析,与该类主题无关;文件头 Covers::3-7)三条清单也未增补新覆盖面。此外这批用例(含 TestFastsafetensorsTransientBudget)全是纯逻辑断言,却被 test/BUILD:5-13tags=["H20"] + exec_properties={'gpu':'H20'} 门禁,占用稀缺 GPU 执行槽且在无 H20 的环境无法本地直跑。
  • [6.1] Tests — 分布式/跨平台变更有对应覆盖 → issue copyout 谓词跨 rank 不对称,EP>1 语义未固化且零覆盖
    loader.py:490required_checkpoint_keys.__contains__ 传给参与 rank 间 broadcast 的 AutoLoader。该集合由 rank 无关的 stacked_key_configtensor_to_weight_maploader.py:616get_tensor_names)合并;后者对 MoE 权重经 ffn_weight.py:706-720 调用 load_config.get_selected_experts,而 load_config.py:93-97expert_per_ep * ep_rank 切片,故 ep_size>1 时该谓词在各 rank 返回不同结果。参数名 local_copyout_filter 暗示 rank 局部语义(故不判定为必然挂死),但该不变量既未在代码中声明也无校验:若过滤同时影响集合通信参与度会在加载期挂死,即使仅影响本地物化,误过滤也会静默走 loader.py:547 的 database 慢速回退(
  • [6.1] Tests — 新逻辑有聚焦单测 + 相关集成/smoke 测试 → issue 旧 wheel 的异常回退分支与 0 值边界零覆盖,与 docstring 承诺不符
    TestFastsafetensorsTransientBudget 只覆盖 estimated_peak_device_bytes 为具体值(:388)与为 None:401)两种情况。而 _fastsafetensors_transient_budget_bytes 的 docstring 声称主要兼容目标是「loading an older wheel」,对应 loader.py:361-366except (ImportError, ModuleNotFoundError, AttributeError, ValueError) 降级分支——零覆盖;结合 cuda12_9 当前仍锁 0.1.19rc5+ali,该分支恰是最可能真实生效的路径,也是未安装 fastsafetensors 时预检能否正确工作的唯一保障。此外 estimate=0 属「非 None」,会使返回 0,把准入判定放宽为 (free_mem - model_mem) > 0loader.py:338),该边界同样无用例守护。
  • [6.1] Tests — 边界 case 覆盖(空、单元素、最大值) → issue 旧 wheel 的异常回退分支与 0 值边界零覆盖,与 docstring 承诺不符
    TestFastsafetensorsTransientBudget 只覆盖 estimated_peak_device_bytes 为具体值(:388)与为 None:401)两种情况。而 _fastsafetensors_transient_budget_bytes 的 docstring 声称主要兼容目标是「loading an older wheel」,对应 loader.py:361-366except (ImportError, ModuleNotFoundError, AttributeError, ValueError) 降级分支——零覆盖;结合 cuda12_9 当前仍锁 0.1.19rc5+ali,该分支恰是最可能真实生效的路径,也是未安装 fastsafetensors 时预检能否正确工作的唯一保障。此外 estimate=0 属「非 None」,会使返回 0,把准入判定放宽为 (free_mem - model_mem) > 0loader.py:338),该边界同样无用例守护。

RTP-LLM Checklist

  • [I] 代码质量 — 删除或重命名内部 file、registry entry、model name、metric enum、op binding、plugin symbol 时,必须全仓搜索消费者,并提供替代实现、迁移说明或 smoke 覆盖;只有暴露到 HTTP/RPC/config/persisted format 时才按外部兼容性处理 → issue 硬依赖 fastsafetensors 新版 AutoLoader 能力但未对齐 wheel pin,删除版本闸门后 auto 路径无探测也无回退
    database.py:317 无条件 from fastsafetensors import AutoLoader:352-354 无条件传 local_copyout_filterloader.py:356-359load_config().estimated_peak_device_bytes。改动前仅 stacked MoE 才触达带闸门(_REQUIRED_FST_VERSION="0.1.19" + startswith)的子类,现在所有 fastsafetensors 加载都经 AutoLoader,闸门随文件删除且无替代。本 PR 7 个 diff 文件不含任何 deps/:cuda12_9 仍锁 0.1.19rc5+ali,cuda13/arm 为 0.1.20+ali,两者本就不一致。loader.py:262-269 的默认 AUTO 仅用 has_module()module_util.py:13 只查 find_spec),选中后 ImportError 无 SCRATCH 回退。`dat
  • [I] 代码质量 — 同一功能用统一工具函数 → issue 重复的 fake 脚手架与两种模块打桩写法并存
    FastsafetensorsAutoLoaderTest 的 6 个用例各自重复定义几乎相同的 FakeSingleGroupFakeAutoLoader:123-149:184-208:228-252:277-283:294-305:324-350),仅观察点不同;构造签名 (pg, files, device, local_copyout_filter, dim0_split_templates) 被手抄五遍,一旦真实 wheel 签名变化需同步修改五处。同时本 PR 引入了两种模块打桩写法:本文件用 sys.modules["fastsafetensors"] = fake_module 配合手写 setUp/tearDown 还原,test_stacked_moe_weight.py:395patch.dict(sys.modules, ...),同一功能两套惯例增加后续维护者的认知负担。

Python Static-First Checklist

  • [P.A] 静态结构与类型纪律 — 字符串分发用 Enum/Literal → issue 新开关绕过 LoadConfig 配置面,取值集合多处重复且不入启动配置快照
    同一 Load Config 章节其余四个开关(--load_method / --force_cpu_load_weights / --loader_recycle_handles / --moe_pure_tp_preshard)都在 load_group_args.py:9-40 通过 add_argument(env_name=..., bind_to=...) 注册,可 CLI 设置、可进配置快照、启动期完成校验。新开关只在 loader.py:410 用裸 os.environ.get 读取:既不进 --help 与参数表,也无法 CLI 覆盖,非法值要等后端进程真正加载权重时才抛 ValueError。取值集合 {"per-expert","full-stacked"}loader.py:413(带 .strip())、database.py:319(不 strip)、database.py:315 默认值字面量、文档正文各写一份,新增第三种模式需同步四处。仓内已有 `LoadMethod(str, enum.
  • [P.A] 静态结构与类型纪律 — 禁止 getattr/setattr literal 访问 → issue 预算 helper 的 docstring 字段名与实现不符,且异常捕获过宽、错误语义不一致
    docstring 第 352 行称「当 max_batch_bytes 未设置时保留历史估算」,代码实际读取的是 estimated_peak_device_bytes:359),字段名对不上,易误导维护者去找不存在的配置项。getattr 字面量探测在属性改名或 wheel 不支持时静默回落 legacy,且 estimate is None 这条路径没有任何日志。捕获列表中 ModuleNotFoundErrorImportError 子类(冗余),AttributeErrorgetattr(..., None) 下不可达;而 FASTSAFETENSORS_CONFIG 指向不存在文件时 load_config() 抛出的 OSError 不在捕获范围内会直接冒泡——同一函数对配置读取失败呈现「静默降级」与「直接崩溃」两种不一致语义。
  • [P.G] 测试规范 — mock/fake/stub 不得替代本次声称覆盖的生产边界 → issue copyout filter 用例未隔离模式环境变量,文档给出的场景会直接使其失败
    test_rank_local_copyout_filter_is_always_appliedassertEqual(observed_modes, ["per-expert"]):358)断言默认模式,但整个用例未 patch 也未清理 RTP_FASTSAFETENSORS_STACKED_MOE_MODE_fastsafetensors_stacked_moe_mode() 直接读宿主 os.environloader.py:410),所在类 TestBuildStackedKeyConfigsetUp/tearDown。本 PR 文档第 233 行正主动指导运维 export RTP_FASTSAFETENSORS_STACKED_MOE_MODE=full-stacked:该变量一旦留在开发机 shell 或 CI 容器中,用例即因环境而非代码失败;拼写错误还会抛出与用例意图无关的 ValueError。相邻的 :361:373 两个用例都已使用 patch.dict,隔离方式不一致。

Strengths

  • 删除 PerExpertParallelLoader 移除了对 fb._get_rank_lidxfb.rank_loadersfb.instantiatedfb.auto_mem_deletefactory.metadata.tensorsfactory.free_dev_ptrs 的侵入式依赖,以及一份从上游 _consume_single_batch 复制来的分支逻辑,把版本敏感实现责任交回 wheel,跨版本脆弱性显著下降。
  • 删除动作干净完整:全仓搜索 PerExpertParallelLoader / per_expert_parallel_loader / _REQUIRED_FST_VERSION 零命中,BUILDglob() 无需改动,torch_patch.py:29-39 中引用该类的 UE8M0 注释同步改写,未留悬空引用或过期注释,符合 R.I.2 的消费者搜索要求。
  • _build_fastsafetensors_local_copyout_keysloader.py:387-398)同时纳入 stacked raw key 与展开后的 per-expert key,使 copyout 过滤在「按原始键过滤」与「按拆分后键过滤」两种上游语义下都成立,避开了误杀 stacked MoE 的典型陷阱,docstring 解释的是 WHY 而非 WHAT。
  • 默认行为不变且回滚清晰:per-expert(有界显存)为默认、full-stacked 为显式 opt-in;能力缺失被固化为 fail-fast 而非静默退回旧路径(缺 AutoLoader → ImportError、缺 dim0_split_templates → 带处置指引的 RuntimeError、非法 mode → ValueError),三者均以带 matchassertRaisesRegex 校验。
  • 测试不依赖真实 wheel:通过 types.ModuleType 注入 fake 模块,FastsafetensorsAutoLoaderTest.setUp/tearDownckpt_database_test.py:91-117)完整保存并还原三个 FASTSAFETENSORS_* 变量与 sys.modules 条目,是标准 hermetic 范式,不污染同进程其他用例。
  • test_full_stacked_mode_disables_prebroadcast_split 用真实 torch.Tensor 驱动生产侧 dim0 切分并逐片比值,是本次唯一真正执行 RTP 侧拆分语义的用例。
  • 本次 diff 已把上一轮混入的 CUDA13 flashinfer 打包 / arch_select.bzl / 依赖 pin 改动全部移出,PR 收敛为单一主题的 7 个文件,commit 原子性与可 bisect 性明显改善。

Comment thread rtp_llm/utils/database.py Outdated

@LLLLKKKK LLLLKKKK left a comment

Copy link
Copy Markdown
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

AI Code Review - PR #1354 (non-blocking suggestions)

22 条 P2/P3 建议,不阻塞合并。阻塞判定与完整摘要见上一条 review。

len(stacked_key_config),
)

required_checkpoint_keys = self._build_fastsafetensors_local_copyout_keys(

Copy link
Copy Markdown
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

[P2] copyout 谓词跨 rank 不对称,EP>1 语义未固化且零覆盖

loader.py:490required_checkpoint_keys.__contains__ 传给参与 rank 间 broadcast 的 AutoLoader。该集合由 rank 无关的 stacked_key_configtensor_to_weight_maploader.py:616get_tensor_names)合并;后者对 MoE 权重经 ffn_weight.py:706-720 调用 load_config.get_selected_experts,而 load_config.py:93-97expert_per_ep * ep_rank 切片,故 ep_size>1 时该谓词在各 rank 返回不同结果。参数名 local_copyout_filter 暗示 rank 局部语义(故不判定为必然挂死),但该不变量既未在代码中声明也无校验:若过滤同时影响集合通信参与度会在加载期挂死,即使仅影响本地物化,误过滤也会静默走 loader.py:547 的 database 慢速...

建议:_build_fastsafetensors_local_copyout_keys 的 docstring 中显式声明该谓词允许跨 rank 分叉并给出上游语义依据;或在传入前跨 process group 校验键集合一致性(all_gather hash,不一致即 fail-fast 而非挂死)。补一个 ep_size=2 的用例(gloo + CPU 假 checkpoint 即可),断言两个 ep_rank 各自的 required_checkpoint_keys 恰好覆盖本 rank 所需 key 且 stacked raw key 在两 rank 上一致。另建议把 loader.py:556 的 fallback 日志从 info 升为 warning 或补一条 metric,使过滤误杀导致的静默回退可观测。

Checklist: [6.1] 分布式/跨平台变更有对应覆盖

Comment thread rtp_llm/utils/database.py Outdated
from fastsafetensors import load_config

config = load_config()
estimate = getattr(config, "estimated_peak_device_bytes", None)

Copy link
Copy Markdown
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

[P2] estimated_peak_device_bytes 缺正值下界与类型校验,异常上报会使显存闸门失效

loader.py:335-344 把原先与 checkpoint 相关的 3 * max_file_size 门槛整体替换为 _fastsafetensors_transient_budget_bytes(),后者只读 load_config().estimated_peak_device_bytes:358-360)——一个与实际 shard / 单张量大小无关的纯 loader 配置量。return legacy_budget if estimate is None else estimate 仅对 None 兜底:上报 0 或极小值时 transient_mem 被抹平,门槛退化为 free_mem > model_memmax_file_size 只剩打日志用途(:334)。预检假通过后 AUTO 已选定 fastsafetensors,不会再退回 SCRATCH,失败形式是加载期 OOM。

建议: 对上报值加类型与正值校验并取下界,例如 max(legacy_budget, int(estimate)),非正值或非整数时 warn 并退回 legacy 估计。若确实有意完全信任 wheel 上报,请在实现处注释说明门槛放宽是有意的,并在文档中提示新旧路径显存判定口径的差异,便于运维在升级后关注显存水位。

"""
legacy_budget = 3 * max_file_size
try:
from fastsafetensors import load_config

Copy link
Copy Markdown
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

[P2] load_config() 早于 NOGDS 环境归一化被调用,预检预算与实际配置不一致

_fastsafetensors_transient_budget_bytes_is_memory_enough_for_fastsafetensorloader.py:335)阶段调用 load_config() 读取预算,而把 FASTSAFETENSORS_NOGDS=1 归一化成 FASTSAFETENSORS_CONFIG_JSON 的逻辑位于其后的 database.py:344-351,只在真正构造 AutoLoader 之前执行。因此在 NOGDS 场景下,门槛判断依据的 config(用户原始配置或库默认)与实际生效的 base/nogds config 可能是两份不同配置,二者预算差异会直接导致准入判断偏乐观或偏保守。

建议: 把 NOGDS → FASTSAFETENSORS_CONFIG_JSON 的归一化抽成一个共用函数(例如 _normalize_fastsafetensors_config_env()),并在显存预检之前调用一次,使 _fastsafetensors_transient_budget_bytesAutoLoader 构造读取同一份配置;或在预算函数内先完成同样的归一化再 load_config(),避免两处配置来源分叉。

Comment thread rtp_llm/utils/database.py Outdated
Comment thread rtp_llm/model_loader/test/test_stacked_moe_weight.py Outdated
Comment thread rtp_llm/utils/database.py Outdated
Comment thread rtp_llm/model_loader/loader.py Outdated
Comment thread rtp_llm/model_loader/test/test_stacked_moe_weight.py Outdated
# RTP-LLM's ``PerExpertParallelLoader`` route every UE8M0 transfer
# through ``pg.broadcast`` (dim=-1 in fastsafetensors / per-expert
# broadcast in PerExpertParallelLoader); only the broadcast wrapper is
# not exercised by fastsafetensors -- ``AutoLoader`` routes UE8M0

Copy link
Copy Markdown
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

[P3] UE8M0 broadcast shim 的适用性断言随 AutoLoader 迁移失去可验证依据

该 shim 只 patch dist.broadcasttorch_patch.py:68-77),用于绕开 NCCL 拒绝 Float8_e8m0fnu 的限制;原注释的依据是 RTP 自己实现/子类化了 ParallelLoader,可确认「每条 UE8M0 传输都走 pg.broadcast」。本 PR 把注释改为「AutoLoader routes UE8M0 transfers through pg.broadcast」,但 AutoLoader 是配置驱动的调度器,后端还可由最终用户通过 FASTSAFETENSORS_CONFIG_JSON(文档第 214 行示例 "loader":"base")自由切换,不同 copier 是否只用 broadcast、是否改用 scatter/all_gather 已不在本仓可验证范围内。若某后端使用 broadcast 之外的集合通信,DSv4-Flash 等 UE8M0 权重 scale 在多 rank 加载时会以 NCCL dtype 错误崩溃。

建议: 把注释中的断言改为可验证形式:明确写出「已验证的 wheel 版本 + loader 后端组合」,并说明切换后端需重新确认;更稳妥的做法是把 shim 扩展到 scatter / all_gather_into_tensor 等同类入口(同样只在 float8_e8m0fnu 上触发,代价极低),或在多 rank UE8M0 加载路径上补一条 smoke 覆盖,使后端切换导致的失效能被自动发现而非上线时暴露。

Checklist: [6.1] 兼容性:外部 HTTP/RPC API、持久数据、配置、环境迁移安全;[6.1] 错误语义:fail-fast/retry/fallback/silent 行为显式

Keep planning and broadcast collective participation global while limiting post-broadcast copyout to tensors required by each rank. Bound stacked MoE broadcast memory and cover the rank-local and batch-cap behavior in loader tests.
@ABNER-1
ABNER-1 force-pushed the shuxing/dsv4-sleep-level2-fastsafetensors branch 2 times, most recently from 61bc76b to 9c76e93 Compare August 31, 2026 07:59

@LLLLKKKK LLLLKKKK left a comment

Copy link
Copy Markdown
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

AI Code Review - PR #1354

Status: BLOCKING

Summary: P0/0 · P1/1 · P2/12 · P3/5

Reviewed: commit 9c76e93ad022 · 2026-08-31 16:47 UTC+8

Blocking Issues

P1

  • 新增 py_test 缺少 unittest.main(),15 条策略用例全部空跑并报 PASS @ rtp_llm/model_loader/test/test_fastsafetensors_loader_policy.py:299
    • 建议:在文件末尾补 if __name__ == "__main__": + unittest.main(),与同目录既有约定一致;补齐后实跑该 target 并确认输出为 Ran 15 tests 而非 Ran 0 tests(静态走查未发现用例自身有断言错误)。建议同时全仓排查是否还有其他 py_test 源文件存在同类缺失;若希望长期免疫,可在 BUILD 层统一改用带 runner 的宏而非裸 py_test

Non-blocking Suggestions

P2

  • 默认 cuda12_9 wheel pin 未随新能力契约对齐,静默降级在 CI 与线上均不可观测 @ docs/backend/server_arguments.md:206
    • 建议:建议三项一起落地:一是文档补「能力 → 最低 fastsafetensors 版本 → 实际生效路径」矩阵(示例中的 parallel.use_tqdm_on_load 也应标注起始版本),并同步 bump deps/requirements_torch_gpu_cuda12_9.txt 及其 lock,使默认平台确实具备 per-expert 能力;二是让安装态契约测试在「应当支持」的镜像中 fail 而非 skip(例如以环境变量声明期望能力档位,未达到即断言失败),使降级在 CI 立即暴露;三是在加载入口固定打印一条 INFO 输出最终生效的 mode 与降级原因,或上报可告警的降级指标,使线上可自查。
  • 能力探测对 **kwargs 签名误判,使显存预算与实际交付方式不一致 @ rtp_llm/utils/database.py:81
    • 建议:让 per-expert 能力探测改用严格命名参数判定,与契约测试保持一致(不用 VAR_KEYWORD 兜底);若确需保留 **kwargs 兜底以适配上游包装器,则在仅靠 VAR_KEYWORD 通过时把 effective mode 降级为 full-stacked 并打 warning,使显存预算与实际交付方式始终同口径。该判定应只有一处实现,供 loader、database 与契约测试共同调用,避免生产与测试各写一套。
  • 显存预算完全信任上游上报值且无下界,AUTO 准入可能由回退 scratch 变为加载期 OOM @ rtp_llm/model_loader/loader.py:433
    • 建议:建议保留下界或余量,例如 budget = max(int(estimate), legacy_budget) 或与 model_mem 成比例的经验值,并在日志中同时打印 estimate 与最终采用的 budget,便于线上区分「包上报值生效」与「走 legacy 估算」。测试侧二选一:补一条极小正值被夹到 legacy 下界的用例,或在用例名与注释中写明「无条件信任上报值」这一取舍及 OOM 风险,避免后续读者误判为疏漏。
  • 显式 LOAD_METHOD=fastsafetensors 路径不做内存预检,降级为 full-stacked 时无预算兜底 @ rtp_llm/model_loader/loader.py:304
    • 建议:为显式 LOAD_METHOD=fastsafetensors 且发生 per-expert → full-stacked 降级的场景也执行一次内存预检,或至少把 warning 升级为带 max_file_size 与可用显存数值的显式提示,并在文档中明确「旧 wheel 上请改用 LOAD_METHOD=scratch」,使显式路径与 AUTO 路径的风险兜底口径一致。
  • 两处能力探测的异常集合不一致,AttributeError 会使「包过旧不致启动失败」的承诺失效 @ rtp_llm/model_loader/loader.py:454
    • 建议:统一两处的异常集合,使「包不兼容一律回退 scratch」在所有 import 期异常类型下成立;同时对「OSError / RuntimeError 环境故障」与「签名缺关键字的版本能力不足」两类原因在日志中区分措辞,避免运维把环境问题误判为 wheel 过旧。
  • NOGDS 兼容 env 覆写发生在首次 import fastsafetensors 之后,且不覆盖 FASTSAFETENSORS_CONFIG @ rtp_llm/model_loader/loader.py:292
    • 建议:把 _apply_fastsafetensors_env_compat() 提到任何能力探测(即第一次 import fastsafetensors)之前,或让 _fastsafetensors_capability_error 自身先应用 env 兼容再 import,文档表述同步收紧为「在读取上游配置与首次 import 之前」;在检测到 FASTSAFETENSORS_CONFIG 已设置时把 warning 措辞改为「可能不生效,最终优先级由安装包决定」,并在文档 230-236 段声明该限制。测试侧补一条不 mock _resolve_fastsafetensors_mode 的用例:用 fake module 记录 import 时刻的 FASTSAFETENSORS_CONFIG_JSON,断言其已是 nogds 配置。
  • 新增开关未注册进 server_args / LoadConfig,表格检索不到且不入启动配置日志 @ docs/backend/server_arguments.md:245
    • 建议:按既有约定注册 --fastsafetensors_stacked_moe_modeenv_name 保持不变、取值受限、默认 per-expert),登记进 LoadConfig 随启动 dump,并把该行补入 Load Config 表格,正文只保留背景说明。若坚持 env-only 过渡形态,请在小节显式写明「不提供命令行参数、不在 --help 展示、不进入启动配置 dump,per-expert 稳定后移除」,并至少在加载入口 INFO 日志固定打印一次最终生效的 mode 与降级原因。
  • 新开关的非法值 fail-fast 与「仅在 fastsafetensors 路径生效」两种语义均未文档化 @ docs/backend/server_arguments.md:248
    • 建议:在取值说明后补两句:一是「取值区分大小写且必须使用连字符,除 per-expert / full-stacked / 空值外的任何取值都会在权重加载阶段抛 ValueError 导致启动失败,不会回落默认值」;二是「该开关仅在实际走 fastsafetensors 路径时生效,LOAD_METHOD=scratch 或非 safetensors 权重下设置无效」。同时补充 auto 模式下显存预检不足同样会退回 scratch,避免运维把整节误读为「永不失败」。
  • 唯一触达真实 wheel 的契约用例被四层 skip 短路,且 skip 文案与生产降级语义不符 @ rtp_llm/utils/test/ckpt_database_test.py:409
    • 建议:把 418 行拆开:缺 AutoLoader 才用 scratch 措辞,缺 load_config 改为「仍走 fastsafetensors,使用 legacy 三分片估算」;422 行改为「仍走 fastsafetensors,全量物化 + 消费端过滤」,与 database.py / loader.py 及文档的三级降级语义一一对应。并参照同文件 ckpt_database_test_rocmenv + args 写法新增一个显式声明 fastsafetensors 依赖的严格目标,在该目标下缺能力即 assert 失败;至少把分类结果(scratch / full-stacked / per-expert)断言成显式枚举并打印到测试输出,使 CI 日志能看出镜像落在哪一档。
  • 决定加载方式的 _is_memory_enough_for_fastsafetensor 与 AUTO 成功主路径零覆盖 @ rtp_llm/model_loader/test/test_fastsafetensors_loader_policy.py:203
    • 建议:补四类用例:(1) object.__new__(ModelLoader) + 桩 _weights_info / _load_config 直测 _is_memory_enough_for_fastsafetensor,断言 device_mem_info is None 返回 False、同一 free_mem 下 per-expert 通过而 full-stacked 因 +1 shard 不通过、上报值远小于 3*max_file_size 时门限按上报值生效(验证单位换算);(2) AUTO 且预检通过时断言 _load_from_fastsafetensor 以解析后 mode 被调用;(3) 用 patch.dict(sys.modules, ...) 装一个不含 AutoLoader 的假模块,直接断言 _fastsafetensors_capability_error 非 None 且 _resolve_fastsafetensors_mode 返回 (None, reason);(4) 补 max_file_size=0 边界。
  • loader 跨模块导入 database 私有函数,fastsafetensors 策略逻辑分散两层并重复决策 @ rtp_llm/model_loader/loader.py:25
    • 建议:把「常量 + 归一化 + 能力探测 + env 兼容 + 降级决策」收敛到单一公开模块(如 rtp_llm/model_loader/fastsafetensors_policy.py),以公开名导出常量与函数,loader、database 与契约测试共同调用;database 侧只保留「入参已归一化」的断言而不再重复决策与告警,utils/database.py 专注 AutoLoader 构造与迭代适配。同时移除 _load_from_fastsafetensorstacked_moe_mode=None 默认值改为必填,消除隐式读 env 的旁路。
  • RTP 原先强制的 loader 调优值与加载进度移交上游,缺迁移对照与 breaking-changes 登记 @ docs/backend/server_arguments.md:252
    • 建议:在 docs/release/breaking-changes.md 增加一节并从本小节链接:列出被移除的旧 RTP 强制值(2GiB 读缓冲、shm/nogds 联动、强制开启进度条),给出恢复旧行为的等价 FASTSAFETENSORS_CONFIG_JSON 片段与对应上游键名,注明示例键路径适用的 fastsafetensors 版本,并列出识别降级用的告警日志关键字与回滚手段(LOAD_METHOD=scratch),使性能对照与回滚有明确落点。

P3

  • _load_weight 中模式解析与降级告警块重复两份 @ rtp_llm/model_loader/loader.py:306
    • 建议:抽一个私有方法(例如 _resolve_and_log_fastsafetensors_mode())返回 Optional[str] 并在内部完成 warning,AUTO 与显式分支各调一次;stacked_moe_mode is None 的哨兵语义也随之收敛到一处。
  • copy-out 允许集无条件放行全局 raw stacked key,上游查询口径未在仓内固化 @ rtp_llm/model_loader/loader.py:519
    • 建议:把该契约固化下来:在 _build_fastsafetensors_local_copyout_keys_iter_fastsafetensors_weights 处以 docstring + 断言写明上游对 dim0 拆分键的查询口径与切片起始约定(例如校验 tensor.shape[0] 与全局 expert 数一致,否则 fail-fast 而非静默按 0..N-1 映射),并显式记录跨 rank 非对称这一前提;同时补一条 world_size>1 / EP>1 的加载回归用例,使「谓词只影响本地 copy-out、不影响集合通信参与」这一假设在默认平台上也被固化。
  • UE8M0 broadcast shim 的适用性断言外移为对上游 AutoLoader 的假设 @ rtp_llm/utils/torch_patch.py:37
    • 建议:将断言可验证化:或对 _dist.scatter / _dist.all_gather 一并加同样的 uint8 view 兼容包装(成本低、幂等),或在注释中记录所依赖的上游版本与已核对的交付函数(参照现有 _TORCH_TESTED_MAJOR_MINOR 的版本门禁做法),并补一个 world_size>1 的 UE8M0 加载用例作为回归护栏。
  • 测试中存在冗余且更脆弱的断言,fake 模块隔离写法不统一 @ rtp_llm/utils/test/ckpt_database_test.py:249
    • 建议:删除 _base 断言,保留 data_ptr 比对表达「已 clone」语义;删除 366-369 行的精确字符串断言,或改为从 rtp_llm.utils.database 导入常量作为期望值,保留 json.loads 结构断言。把 _install_fake_fastsafetensors 改为返回上下文管理器(内部用 patch.dict(sys.modules, ...))由各用例 with 使用,与新文件写法统一;或至少给 InstalledFastsafetensorsContractTest 加 setUp 断言 sys.modules.get("fastsafetensors") 不是本文件构造的假模块,让泄漏立即失败而非降级为 skip。
  • 未安装 fastsafetensors 的平台会打印「incompatible」误导性告警 @ rtp_llm/model_loader/loader.py:280
    • 建议:把「包未安装」与「包已安装但能力不足」两类原因分开:前者用 INFO 级并明确措辞为「该平台未安装 fastsafetensors,使用 scratch」,后者保留 WARNING;文档 214 行相应改为「缺少 AutoLoader 或未安装该包时回落 scratch」,使日志与文档对同一现象的描述一致。

Checklist Findings (16 fail / 48 total)

General Principles Checklist

  • [6.1] Architecture — 依赖方向:无循环依赖/跨层惊喜 → issue loader 跨模块导入 database 私有函数,fastsafetensors 策略逻辑分散两层并重复决策
    loader.py:25-33 从 rtp_llm.utils.database 显式导入三个下划线私有函数(_apply_fastsafetensors_env_compat_callable_accepts_keyword_normalize_fastsafetensors_stacked_moe_mode),把 database 内部实现细节提升为跨模块契约。策略常量与工具落在 utils/database.py,决策落在 model_loader/loader.py,职责边界被切开:dim0_split_templates 判定在 loader.py:458 与 database.py:414-425 各做一次并各自 warning;_apply_fastsafetensors_env_compat 在两层各调一次(loader.py:292/323 与 database.py:411);_load_from_fastsafetensor(stacked_moe_mode=None)(loader.py:565)的默认值在生产路径不可达却
  • [6.1] Architecture — 兼容性:外部 HTTP/RPC API、持久数据、配置、环境迁移安全 → issue UE8M0 broadcast shim 的适用性断言外移为对上游 AutoLoader 的假设
    旧注释的依据是「ParallelLoader 与 RTP 自己的 PerExpertParallelLoader 都把 UE8M0 传输走 pg.broadcast」,后半段在仓内可逐行验证。改为「AutoLoader routes UE8M0 transfers through pg.broadcast」(torch_patch.py:36-39)后,dim0 切分交付已完全由第三方包实现,而 shim 只包装了 _dist.broadcast(torch_patch.py:68-77):若上游对 dim0 切片改用 scatter / all_gather,多卡加载 DSv4-Flash 的 UE8M0 scale 会重新命中 Float8_e8m0fnu 不被 NCCL 支持的错误。同文件对 torch 版本有 _TORCH_TESTED_MAJOR_MINOR 门禁并会告警,对上游包版本却无等价约束;该假设目前只由 SM100 / cuda13 的 DSV4 多卡 perf 目标间接覆盖,默认平台无回归护栏。
  • [6.1] Architecture — 分层边界:新概念在正确层级,不泄漏内部 → issue loader 跨模块导入 database 私有函数,fastsafetensors 策略逻辑分散两层并重复决策
    loader.py:25-33 从 rtp_llm.utils.database 显式导入三个下划线私有函数(_apply_fastsafetensors_env_compat_callable_accepts_keyword_normalize_fastsafetensors_stacked_moe_mode),把 database 内部实现细节提升为跨模块契约。策略常量与工具落在 utils/database.py,决策落在 model_loader/loader.py,职责边界被切开:dim0_split_templates 判定在 loader.py:458 与 database.py:414-425 各做一次并各自 warning;_apply_fastsafetensors_env_compat 在两层各调一次(loader.py:292/323 与 database.py:411);_load_from_fastsafetensor(stacked_moe_mode=None)(loader.py:565)的默认值在生产路径不可达却
  • [6.1] Architecture — 可观测性:日志/指标/超时可操作、非噪声 → issue 未安装 fastsafetensors 的平台会打印「incompatible」误导性告警
    _fastsafetensors_capability_error(loader.py:452-455)把 ImportError 也归入「能力错误」,AUTO 路径遂在 280-283 行打印「the installed fastsafetensors is incompatible: No module named 'fastsafetensors'」。但 deps/requirements_torch_gpu_cuda12.txtdeps/requirements_rocm.txt 均不含该包(仅 cuda12_9 / cuda13 / cuda13_arm 有),这些平台上「未安装」被表述为「已安装但不兼容」。文档 214 行同样写「Only a missing AutoLoader falls back to scratch」,未涵盖「包本身缺失」这一更常见的情形。
  • [6.1] Architecture — 回滚路径:风险行为存在运维回滚手段 → issue RTP 原先强制的 loader 调优值与加载进度移交上游,缺迁移对照与 breaking-changes 登记
    改动前 RTP 在构造 loader 时强制传入 bbuf_size_kb(2GiB 读缓冲)、use_shm=not use_nogds,并固定 use_tqdm_on_load=True 使加载进度始终可见;改动后 database.py:446-459 的 loader_kwargs 仅保留可选的 local_copyout_filter / dim0_split_templates,全仓已无这些 kwarg,默认值完全由安装包配置决定,加载进度可能从「默认开启」变为「默认关闭」。文档仅以「The installed FastSafeTensors version defines the precise configuration defaults and precedence」(docs:219-220)概括,既未记录旧的强制值,也未标注示例 JSON 中 base.copier_type / parallel.use_tqdm_on_load 适用的 wheel 版本,运维照抄若键名不符会静默无效。本仓已有 `docs/release/brea
  • [6.1] Architecture — 状态不变量:创建/更新/失败/重试/回滚路径有效 → issue NOGDS 兼容 env 覆写发生在首次 import fastsafetensors 之后,且不覆盖 FASTSAFETENSORS_CONFIG
    AUTO 路径先调 _resolve_fastsafetensors_mode(loader.py:276),其内部 _fastsafetensors_capability_error 已执行 from fastsafetensors import AutoLoader(loader.py:453),之后才在 292 行调 _apply_fastsafetensors_env_compat();显式分支顺序相同(307 → 323)。旧实现通过 nogds= / use_shm= 显式 kwargs 传参,不依赖 import 顺序;若安装包在 import 期固化配置单例,FASTSAFETENSORS_NOGDS=1 写入的 FASTSAFETENSORS_CONFIG_JSON 与实际生效 copier 可能不一致,而文档 231-233 承诺覆写发生在「memory preflight 或构造 AutoLoader 之前」。另 _apply_fastsafetensors_env_compat(database.py:29-43)只覆写 `F
  • [6.1] Architecture — 错误语义:fail-fast/retry/fallback/silent 行为显式 → issue 未安装 fastsafetensors 的平台会打印「incompatible」误导性告警
    _fastsafetensors_capability_error(loader.py:452-455)把 ImportError 也归入「能力错误」,AUTO 路径遂在 280-283 行打印「the installed fastsafetensors is incompatible: No module named 'fastsafetensors'」。但 deps/requirements_torch_gpu_cuda12.txtdeps/requirements_rocm.txt 均不含该包(仅 cuda12_9 / cuda13 / cuda13_arm 有),这些平台上「未安装」被表述为「已安装但不兼容」。文档 214 行同样写「Only a missing AutoLoader falls back to scratch」,未涵盖「包本身缺失」这一更常见的情形。
  • [6.1] Quality — PR description 说明动机与设计 → issue RTP 原先强制的 loader 调优值与加载进度移交上游,缺迁移对照与 breaking-changes 登记
    改动前 RTP 在构造 loader 时强制传入 bbuf_size_kb(2GiB 读缓冲)、use_shm=not use_nogds,并固定 use_tqdm_on_load=True 使加载进度始终可见;改动后 database.py:446-459 的 loader_kwargs 仅保留可选的 local_copyout_filter / dim0_split_templates,全仓已无这些 kwarg,默认值完全由安装包配置决定,加载进度可能从「默认开启」变为「默认关闭」。文档仅以「The installed FastSafeTensors version defines the precise configuration defaults and precedence」(docs:219-220)概括,既未记录旧的强制值,也未标注示例 JSON 中 base.copier_type / parallel.use_tqdm_on_load 适用的 wheel 版本,运维照抄若键名不符会静默无效。本仓已有 `docs/release/brea
  • [6.1] Software Engineering — DRY:重复非平凡逻辑被抽取或显式复用 → issue 测试中存在冗余且更脆弱的断言,fake 模块隔离写法不统一
    :249-250 用 result[0][1]._base is None 判断张量已拷贝,_base 为 torch 私有属性、跨版本无兼容承诺,而紧随的 :251-258 已用 untyped_storage().data_ptr() 比对证明脱离原 storage,属重复且更脆弱的断言。:366 以 '{"loader":"base","base":{"copier_type":"nogds"}}' 精确字符串断言环境变量,该字面量是 database.py:26 常量的复制,而 :370-373 已用 json.loads 结构化断言同一语义;生产侧改用 json.dumps(...) 或调整键序会行为等价却误报失败。另 _install_fake_fastsafetensors(:27-33)直接改写 sys.modules 且自身无还原机制,与新文件的 patch.dict 上下文写法并存;InstalledFastsafetensorsContractTest 无自身隔离,假模块泄漏会表现为静默 skip 而非失败。
  • [6.1] Software Engineering — SRP:模块/类职责单一 → issue loader 跨模块导入 database 私有函数,fastsafetensors 策略逻辑分散两层并重复决策
    loader.py:25-33 从 rtp_llm.utils.database 显式导入三个下划线私有函数(_apply_fastsafetensors_env_compat_callable_accepts_keyword_normalize_fastsafetensors_stacked_moe_mode),把 database 内部实现细节提升为跨模块契约。策略常量与工具落在 utils/database.py,决策落在 model_loader/loader.py,职责边界被切开:dim0_split_templates 判定在 loader.py:458 与 database.py:414-425 各做一次并各自 warning;_apply_fastsafetensors_env_compat 在两层各调一次(loader.py:292/323 与 database.py:411);_load_from_fastsafetensor(stacked_moe_mode=None)(loader.py:565)的默认值在生产路径不可达却
  • [6.1] Tests — 分布式/跨平台变更有对应覆盖 → issue UE8M0 broadcast shim 的适用性断言外移为对上游 AutoLoader 的假设
    旧注释的依据是「ParallelLoader 与 RTP 自己的 PerExpertParallelLoader 都把 UE8M0 传输走 pg.broadcast」,后半段在仓内可逐行验证。改为「AutoLoader routes UE8M0 transfers through pg.broadcast」(torch_patch.py:36-39)后,dim0 切分交付已完全由第三方包实现,而 shim 只包装了 _dist.broadcast(torch_patch.py:68-77):若上游对 dim0 切片改用 scatter / all_gather,多卡加载 DSv4-Flash 的 UE8M0 scale 会重新命中 Float8_e8m0fnu 不被 NCCL 支持的错误。同文件对 torch 版本有 _TORCH_TESTED_MAJOR_MINOR 门禁并会告警,对上游包版本却无等价约束;该假设目前只由 SM100 / cuda13 的 DSV4 多卡 perf 目标间接覆盖,默认平台无回归护栏。
  • [6.1] Tests — 新逻辑有聚焦单测 + 相关集成/smoke 测试 → issue UE8M0 broadcast shim 的适用性断言外移为对上游 AutoLoader 的假设
    旧注释的依据是「ParallelLoader 与 RTP 自己的 PerExpertParallelLoader 都把 UE8M0 传输走 pg.broadcast」,后半段在仓内可逐行验证。改为「AutoLoader routes UE8M0 transfers through pg.broadcast」(torch_patch.py:36-39)后,dim0 切分交付已完全由第三方包实现,而 shim 只包装了 _dist.broadcast(torch_patch.py:68-77):若上游对 dim0 切片改用 scatter / all_gather,多卡加载 DSv4-Flash 的 UE8M0 scale 会重新命中 Float8_e8m0fnu 不被 NCCL 支持的错误。同文件对 torch 版本有 _TORCH_TESTED_MAJOR_MINOR 门禁并会告警,对上游包版本却无等价约束;该假设目前只由 SM100 / cuda13 的 DSV4 多卡 perf 目标间接覆盖,默认平台无回归护栏。
  • [6.1] Tests — 边界 case 覆盖(空、单元素、最大值) → issue 决定加载方式的 \_is\_memory\_enough\_for\_fastsafetensor 与 AUTO 成功主路径零覆盖
    真正决定「走 fastsafetensors 还是 scratch」的 _is_memory_enough_for_fastsafetensor(loader.py:330-394)本次新增 stacked_moe_mode 形参、改用 transient budget 并做 bytes→MB 换算,却无任何用例(:203 整体 MagicMock),device_mem_info is None → return False 早退分支同样无覆盖。AUTO 是默认入口,但两条用例(:163 wrapper 不兼容、:186 内存不足)都固定失败退 scratch,缺「AUTO 且内存足够 → 以解析后 mode 调用 _load_from_fastsafetensor」与「AUTO 降级 full-stacked 时预检必须以 full-stacked 预算调用」的断言。「AutoLoader 缺失 → scratch」这条核心承诺也被三层 mock 顶替(:122 假模块 AutoLoader,:143 patch 掉 capability_error,:1

RTP-LLM Checklist

  • [I] 代码质量 — 同一功能用统一工具函数 → issue 测试中存在冗余且更脆弱的断言,fake 模块隔离写法不统一
    :249-250 用 result[0][1]._base is None 判断张量已拷贝,_base 为 torch 私有属性、跨版本无兼容承诺,而紧随的 :251-258 已用 untyped_storage().data_ptr() 比对证明脱离原 storage,属重复且更脆弱的断言。:366 以 '{"loader":"base","base":{"copier_type":"nogds"}}' 精确字符串断言环境变量,该字面量是 database.py:26 常量的复制,而 :370-373 已用 json.loads 结构化断言同一语义;生产侧改用 json.dumps(...) 或调整键序会行为等价却误报失败。另 _install_fake_fastsafetensors(:27-33)直接改写 sys.modules 且自身无还原机制,与新文件的 patch.dict 上下文写法并存;InstalledFastsafetensorsContractTest 无自身隔离,假模块泄漏会表现为静默 skip 而非失败。

Python Static-First Checklist

  • [P.B] 错误处理 — 禁止 bare except 或静默吞异常 → issue 两处能力探测的异常集合不一致,AttributeError 会使「包过旧不致启动失败」的承诺失效
    _fastsafetensors_capability_errorfrom fastsafetensors import AutoLoader 只捕获 (ImportError, OSError, RuntimeError)(loader.py:454),而同文件 _fastsafetensors_transient_budget_bytes 捕获 (ImportError, AttributeError, OSError, TypeError, ValueError)(loader.py:434)。若安装包在 import 期抛 AttributeError(常见于上游模块级初始化与新 torch 不兼容),异常会穿透 _resolve_fastsafetensors_mode 直接打挂加载,_load_weight 无兜底,与文档 216 行「package age alone does not fail model startup」及本 PR 核心承诺不符。此外该分支把 OSError / RuntimeError 一律翻译成「能力缺
  • [P.G] 测试规范 — mock/fake/stub 不得替代本次声称覆盖的生产边界 → issue 测试中存在冗余且更脆弱的断言,fake 模块隔离写法不统一
    :249-250 用 result[0][1]._base is None 判断张量已拷贝,_base 为 torch 私有属性、跨版本无兼容承诺,而紧随的 :251-258 已用 untyped_storage().data_ptr() 比对证明脱离原 storage,属重复且更脆弱的断言。:366 以 '{"loader":"base","base":{"copier_type":"nogds"}}' 精确字符串断言环境变量,该字面量是 database.py:26 常量的复制,而 :370-373 已用 json.loads 结构化断言同一语义;生产侧改用 json.dumps(...) 或调整键序会行为等价却误报失败。另 _install_fake_fastsafetensors(:27-33)直接改写 sys.modules 且自身无还原机制,与新文件的 patch.dict 上下文写法并存;InstalledFastsafetensorsContractTest 无自身隔离,假模块泄漏会表现为静默 skip 而非失败。

Strengths

  • 降级链分级完整且可与代码逐条对应:缺 AutoLoader → scratch(loader.py:478-479)、缺 dim0_split_templates → full-stacked(loader.py:480-486、database.py:414-425)、缺 local_copyout_filter → 全量物化 + RTP 消费端过滤(database.py:447-454),AUTO 与显式 LOAD_METHOD 两条入口均覆盖,wheel 版本差异不再像旧实现那样直接抛 RuntimeError 打挂启动。
  • inspect.signature 能力探测替换硬版本号前缀校验,契约从「版本号字符串」收敛到「实际关键字」,对上游打包与回合策略的鲁棒性显著提升。
  • _build_fastsafetensors_local_copyout_keys(loader.py:508-519)同时保留展开后的 per-expert key 与 stacked 原始 key,与 MoeAtomicWeight.get_tensor_names(ffn_weight.py:706-720)只返回本 rank selected_experts 的语义对齐;消费循环 loader.py:617-618 的 key not in tensor_to_weight_map: continue 为老 wheel 缺 local_copyout_filter 时提供可靠兜底。
  • _fastsafetensors_transient_budget_bytes 对上报值做了 bool / 非数值 / 非有限 / 非正的完整拒绝并回落 legacy 估算(loader.py:414-431),边界值 None/0/-1/"8192"/inf/True 在用例中逐一枚举;full-stacked 额外叠加一个 max shard(loader.py:440-445)把兼容路径峰值纳入 auto 预检。
  • _iter_fastsafetensors_weights(database.py:87-110)对每个 expert 切片显式 clone() 并注明「loader 可能在迭代推进后释放 batch buffer」,测试用 untyped_storage().data_ptr() 比对把该所有权不变量固化为可回归断言。
  • test_env_compat_is_applied_before_auto_memory_preflight 用 events 列表断言 ["env", "memory"],把隐式时序约束固化为可回归断言,且 patch 打在使用处符合 P.P.G.1。
  • stacked_moe_mode 在 AUTO 解析结果 → 显存预检 → _load_from_fastsafetensorfastsafetensors_weights_iterator 全链路显式参数传递,而非各层重复读环境变量;空值/纯空白回落默认(database.py:59-63),非法值在两侧都有带 match 的拒绝用例。
  • 新增 py_test 为 CPU-only(env = {"CUDA_VISIBLE_DEVICES": ""}、无 GPU tag / exec_properties),与同目录 test_per_channel_fp8_helpers / test_pure_tp_preshard 约定一致,不额外占用 H20 资源。
  • 文档主动披露 FASTSAFETENSORS_NOGDS 的进程级副作用,并主动划清 RTP 与上游的配置归属(bucket/copier/queue/producer/进度/顺序归上游,仅 rank-local copy-out 归 RTP),避免 RTP 再造重复配置面。

4096, FASTSAFETENSORS_STACKED_MOE_MODE_FULL_STACKED
),
12 * 1024,
)

Copy link
Copy Markdown
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

📍 实际位置 rtp_llm/model_loader/test/test_fastsafetensors_loader_policy.py:299(不在 diff 展示范围内,就近挂载)

[P1] 新增 py_test 缺少 unittest.main(),15 条策略用例全部空跑并报 PASS

新文件在 299 行结束时无 if __name__ == "__main__": unittest.main()test/BUILD:5-10 声明 py_testtools/build_rules/prelude_bazel:11-12 的同名覆写仅注入 gpu_count 后仍委托 native.py_test,不改 main 处理,故源文件以 __main__ 直接执行:模块只完成 import 与两个 TestCase(TestFastsafetensorsLoaderPolicy 11 个 + TestFastsafetensorsTransientBudget 4 个,共 15 个 test 方法)的定义即以 0 退出,target 报 PASSED 而 0 条用例执行。同目录另外 7 个 py_test 源文件全部带该入口(test_stacked_moe_weight.py:484、test_pure_tp_preshard.py:188、test_per_channel_fp8_helpers.py:128 等)。后...

建议: 在文件末尾补 if __name__ == "__main__": + unittest.main(),与同目录既有约定一致;补齐后实跑该 target 并确认输出为 Ran 15 tests 而非 Ran 0 tests(静态走查未发现用例自身有断言错误)。建议同时全仓排查是否还有其他 py_test 源文件存在同类缺失;若希望长期免疫,可在 BUILD 层统一改用带 runner 的宏而非裸 py_test

@LLLLKKKK LLLLKKKK left a comment

Copy link
Copy Markdown
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

AI Code Review - PR #1354 (non-blocking suggestions)

17 条 P2/P3 建议,不阻塞合并。阻塞判定与完整摘要见上一条 review。

| `--loader_recycle_handles` | ROCm + safetensors only: close consumed main-model shard handles to release mmap memory. Requires layer-numbered tensors and copies safetensors data out before closing; no effect on fastsafetensors, ViT, EPLB, or .bin weights. (`LOADER_RECYCLE_HANDLES`) | True |
| `--moe_pure_tp_preshard` | Disabled by default. Set true to pre-shard supported Qwen3-Next / Qwen3.5 MoE and offline FP8 weights under pure TP (`tp>1, dp=1, ep=1`) before device copy. Unsupported sources or layouts warn and use legacy full reads. (`MOE_PURE_TP_PRESHARD`) | False |

### FastSafeTensors loader configuration

Copy link
Copy Markdown
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

[P2] 默认 cuda12_9 wheel pin 未随新能力契约对齐,静默降级在 CI 与线上均不可观测

新实现依赖 AutoLoaderdim0_split_templates / local_copyout_filter / estimated_peak_device_bytes,被删文件原以 _REQUIRED_FST_VERSION="0.1.19" 硬门禁保证 per-expert 路径,现改为 warning 后静默降级(loader.py:280-291、311-322)。但 deps/requirements_torch_gpu_cuda12_9.txt:6 与其 lock 仍锁 fastsafetensors-0.1.19rc5+ali,cuda13 / cuda13_arm 已为 0.1.20+ali,本 PR 未 bump;文档 209-216 承诺完整能力集走 bounded per-expert 却全篇无最低版本。唯一触达真实 wheel 的 InstalledFastsafetensorsContractTest 逐级 skipTest,而全部 13 个 `--load_method fastsafetensors...

建议: 建议三项一起落地:一是文档补「能力 → 最低 fastsafetensors 版本 → 实际生效路径」矩阵(示例中的 parallel.use_tqdm_on_load 也应标注起始版本),并同步 bump deps/requirements_torch_gpu_cuda12_9.txt 及其 lock,使默认平台确实具备 per-expert 能力;二是让安装态契约测试在「应当支持」的镜像中 fail 而非 skip(例如以环境变量声明期望能力档位,未达到即断言失败),使降级在 CI 立即暴露;三是在加载入口固定打印一条 INFO 输出最终生效的 mode 与降级原因,或上报可告警的降级指标,使线上可自查。

Comment thread rtp_llm/utils/database.py Outdated
)
budget = legacy_budget
else:
budget = int(estimate)

Copy link
Copy Markdown
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

[P2] 显存预算完全信任上游上报值且无下界,AUTO 准入可能由回退 scratch 变为加载期 OOM

原判据为 (free_mem - model_mem) > 3 * max_file_mem,与 checkpoint 分片大小挂钩、自带经验余量。改后只要拿到有限正值即整体替换(loader.py:433 budget = int(estimate)),max_file_size 在该分支完全不参与计算,且无任何下界夹取;loader.py:387 仍以严格大于判定。预算只覆盖 loader 自有 buffer,未为 RTP 侧临时占用留余量:collector 累积的 per-expert clone、weight.load() 拼接、inline FP8 量化中间张量、非源 rank 的广播接收缓冲。测试侧 test_uses_positive_configured_bounded_peak 反把「任意有限正数一律信任、可下调安全余量」固化为期望行为(8192 < legacy 12288),却无任何用例约束下界:若上游回归上报极小正值(如 1),AUTO 会在本应退回 scratch 的场景选中 fastsafetensors。

建议: 建议保留下界或余量,例如 budget = max(int(estimate), legacy_budget) 或与 model_mem 成比例的经验值,并在日志中同时打印 estimate 与最终采用的 budget,便于线上区分「包上报值生效」与「走 legacy 估算」。测试侧二选一:补一条极小正值被夹到 legacy 下界的用例,或在用例名与注释中写明「无条件信任上报值」这一取舍及 OOM 风险,避免后续读者误判为疏漏。

@@ -275,13 +302,35 @@ def _load_weight(self, device: str):
)

if load_method.lower() == LoadMethod.FASTSAFETENSORS:

Copy link
Copy Markdown
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

[P2] 显式 LOAD_METHOD=fastsafetensors 路径不做内存预检,降级为 full-stacked 时无预算兜底

删除 per_expert_parallel_loader.py 后,per-expert 有界交付完全依赖安装包提供 dim0_split_templates;在原先能工作的 wheel 上,同一部署会静默降级为 full-stacked(database.py:414-425),峰值多出一份完整 stacked tensor。AUTO 路径尚可因 budget += max_file_size(loader.py:440-445)回退 scratch,但显式 LOAD_METHOD=fastsafetensors 分支(loader.py:304-324)完全不调用 _is_memory_enough_for_fastsafetensor(全仓仅 loader.py:293 一处调用),即使检测到 per-expert 不可用、需要多出一整个 shard 的显存,也会只打一条 warning 后直接进入 full-stacked 加载。

建议: 为显式 LOAD_METHOD=fastsafetensors 且发生 per-expert → full-stacked 降级的场景也执行一次内存预检,或至少把 warning 升级为带 max_file_size 与可用显存数值的显式提示,并在文档中明确「旧 wheel 上请改用 LOAD_METHOD=scratch」,使显式路径与 AUTO 路径的风险兜底口径一致。

Comment thread rtp_llm/model_loader/loader.py Outdated
Comment thread rtp_llm/model_loader/loader.py Outdated
Comment thread rtp_llm/model_loader/loader.py Outdated
# RTP-LLM's ``PerExpertParallelLoader`` route every UE8M0 transfer
# through ``pg.broadcast`` (dim=-1 in fastsafetensors / per-expert
# broadcast in PerExpertParallelLoader); only the broadcast wrapper is
# not exercised by fastsafetensors -- ``AutoLoader`` routes UE8M0

Copy link
Copy Markdown
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

[P3] UE8M0 broadcast shim 的适用性断言外移为对上游 AutoLoader 的假设

旧注释的依据是「ParallelLoader 与 RTP 自己的 PerExpertParallelLoader 都把 UE8M0 传输走 pg.broadcast」,后半段在仓内可逐行验证。改为「AutoLoader routes UE8M0 transfers through pg.broadcast」(torch_patch.py:36-39)后,dim0 切分交付已完全由第三方包实现,而 shim 只包装了 _dist.broadcast(torch_patch.py:68-77):若上游对 dim0 切片改用 scatter / all_gather,多卡加载 DSv4-Flash 的 UE8M0 scale 会重新命中 Float8_e8m0fnu 不被 NCCL 支持的错误。同文件对 torch 版本有 _TORCH_TESTED_MAJOR_MINOR 门禁并会告警,对上游包版本却无等价约束;该假设目前只由 SM100 / cuda13 的 DSV4 多卡 perf 目标间接覆盖,默认平台无回归护栏。

建议: 将断言可验证化:或对 _dist.scatter / _dist.all_gather 一并加同样的 uint8 view 兼容包装(成本低、幂等),或在注释中记录所依赖的上游版本与已核对的交付函数(参照现有 _TORCH_TESTED_MAJOR_MINOR 的版本门禁做法),并补一个 world_size>1 的 UE8M0 加载用例作为回归护栏。

Checklist: [6.1] 兼容性:外部 HTTP/RPC API、持久数据、配置、环境迁移安全;[6.1] 分布式/跨平台变更有对应覆盖;[6.1] 新逻辑有聚焦单测 + 相关集成/smoke 测试

Comment thread rtp_llm/utils/test/ckpt_database_test.py Outdated
Comment thread rtp_llm/model_loader/loader.py Outdated
@ABNER-1
ABNER-1 force-pushed the shuxing/dsv4-sleep-level2-fastsafetensors branch from 9c76e93 to 22833c8 Compare August 31, 2026 10:25
@rtp-llm-review-bot

rtp-llm-review-bot commented Aug 31, 2026

Copy link
Copy Markdown
Collaborator

PR #1354 第 23 轮评审 — BLOCKED(3)

  • 标题:feat(loader): integrate bounded rank-local FastSafeTensors copyout(@ABNER-1,open)
  • head 162e7fa658a4 · base f1a54a5f1171 · delta 8 文件 · discover 5/5 成功

阻塞项(P0/P1,support≥3 且过全部门)

[P1] 测试导入不存在的 FastSafeTensorsCompatibilityError,导致 ImportError

  • rtp_llm/utils/test/ckpt_database_test.py:17 · 类别 testing · 票数 5/5 · 首见 r15
  • 依据:rtp_llm/utils/test/ckpt_database_test.py:17 与 rtp_llm/model_loader/test/test_fastsafetensors_loader_policy.py:31 均顶层 from rtp_llm.utils.database import (..., FastSafeTensorsCompatibilityError, ...)。全仓 grep 该符号仅出现在这两个测试文件(ckpt_database_test.py:17/330/344、test_fastsafetensors_loader_policy.py:31/384),rtp_llm/utils/database.py 未定义也未导入它(grep 'Compatibility' 无命中)。因此运行任一测试时模块导入即抛 ImportError。实现层 database.py:408-481 的 fastsafetensors_weights_iterator 无任何 try/except:缺 AutoLoader 时仅 database.py:417 from fastsafetensors import AutoLoader, SingleGroup 抛原生 ImportError,AutoLoader 构造器异常(database.py:465)也不做重分类,故 test_wrapper_without_auto_loader_fails_instead_of_legacy_fallback(ckpt_database_test.py:330)与 test_constructor_abi_error_is_classified_as_compatibility_failure(ckpt_database_test.py:344)即使补上该符号,预期 assertRaisesRegex(FastSafeTensorsCompatibilityError,...) 也无法满足。另注:ckpt_database_test.py:19 还导入 _fastsafetensors_stacked_moe_keyword(用于 ckpt_database_test.py:499),该符号同样未在 database.py 定义,构成第二个 ImportError 源。
  • 建议:在 database.py 定义 FastSafeTensorsCompatibilityError 并在 fastsafetensors_weights_iterator 中对缺 AutoLoader/构造器 ABI 错误做重分类,或移除这些测试对不存在异常与重分类行为的断言。
  • 事实核验:hold — verified(ckpt_database_test.py 第17行顶层 from rtp_l);verified(test_fastsafetensors_loader_policy.py 第3);verified(FastSafeTensorsCompatibilityError 全仓仅出现在);verified(ckpt_database_test.py:19 还导入 _fastsafet);verified(fastsafetensors_weights_iterator 无 try/e);verified(运行任一测试模块时,顶层 import 必然执行、必然抛 ImportError);verified(即使补上该符号,test_wrapper_without_auto_loader)

[P1] cu130 与 cu129 的 x86_64 wheel 使用相同 SHA256 hash,疑似复制粘贴错误导致 cuda13 构建哈希校验失败

  • deps/requirements_lock_torch_gpu_cuda13.txt:630 · 类别 build · 票数 4/5 · 首见 r14
  • 依据:补丁中 requirements_lock_torch_gpu_cuda12_9.txt 将 cu129 wheel 的 hash 从 aafb2bc7492a5de970b03455e68b5c9e15034e5d31d86f4524523bee7d9ada29 改为 bb084a01e6b3d97a8790e583cb5c0fcadcef1960e64b069bb2a97fff0079fe40,requirements_lock_torch_gpu_cuda13.txt 将 cu130 wheel 的 hash 从 04f3a2e8b082af33e7c78536d79db2e6ebb72debebc934fc90087b9b873db552 也改为 bb084a01e6b3d97a8790e583cb5c0fcadcef1960e64b069bb2a97fff0079fe40。两个 URL 分别指向 /rtp_llm/cu129/ 与 /rtp_llm/cu130/ 目录下的 fastsafetensors-0.3.4.dev20260901%2Bali.fuseshm.g78ac75c8.aone67880226 wheel,但 SHA256 完全相同;而 cu130_arm 的 aarch64 wheel hash 为 95a89d0b641b7dd57f8e137a04a82d3dd9d09cf36378764d81662cfd0185f8c9(不同)。fastsafetensors 是含 CUDA 内核的原生扩展,cu129 与 cu130 构建产物字节级相同几乎不可能。若 cu130 的 hash 是从 cu129 复制而来且实际文件内容不同,pip install 校验失败,cuda13 构建/安装直接中断。
  • 建议:重新计算 cu130 x86_64 wheel 的实际 SHA256 并替换 requirements_lock_torch_gpu_cuda13.txt 第 630 行的 hash;确认 cu129 与 cu130 是否确实为同一文件,若为同一文件需在注释中说明,否则修正为各自真实 hash。
  • 事实核验:hold — verified(cu13 文件第630行 fastsafetensors x86_64 whee);verified(cu12_9 文件第769行 fastsafetensors x86_64 wh);verified(两个 URL 分别指向 /rtp_llm/cu129/ 与 /rtp_llm/c);verified(cu130_arm 的 aarch64 wheel hash 为 95a89d0);verified(本 PR 将 cu13 文件 fastsafetensors hash 从 04);verified(该 lock 文件在 cuda13 构建中被 pip_parse 消费并校验 h);unverifiable(cu129 与 cu130 的 x86_64 wheel 实际字节内容不同,因此)

[P1] cu129 与 cu130 的 fastsafetensors x86_64 wheel 在 whl_deps 中使用相同文件名与 SHA256,新位置复制粘贴疑点

  • arch_config/arch_select.bzl:93 · 类别 build · 票数 3/5 · 首见 r23
  • 依据:whl_deps() 中 using_cuda12_9_x86 分支引用 .../cu129/fastsafetensors-0.3.4.dev20260901%2Bali.fuseshm.g78ac75c8.aone67880226-cp310-cp310-linux_x86_64.whl#sha256=bb084a01e6b3d97a8790e583cb5c0fcadcef1960e64b069bb2a97fff0079fe40,using_cuda13_x86 分支引用 .../cu130/ 下完全相同文件名与相同 sha256=bb084a01...。两平台仅 URL 目录不同(cu129 vs cu130)而文件名与哈希完全一致,疑与台账中 requirements_lock 文件的同哈希问题同源,若 cu130 实际构建不同则 pip 哈希校验失败或静默装错 wheel。
  • 建议:核对 cu130 fastsafetensors wheel 的实际哈希,若与 cu129 不同则修正 sha256;若确为同一 CUDA 无关 wheel,则统一引用单一 URL 避免双目录同哈希的复制粘贴歧义。
  • 事实核验:hold — verified(using_cuda12_9_x86 分支引用 fastsafetensors );verified(using_cuda13_x86 分支引用同名 fastsafetensors );verified(两个分支的 fastsafetensors 引用除目录外文件名与哈希完全相同,构);verified(该同哈希与台账 requirements_lock 一致:cu12_9 锁文件与);verified(whl_deps() 的两个分支在生产构建中可达(被 rtp_llm/BUILD);unverifiable(cu130 的 fastsafetensors wheel 实际内容与 cu12)

非阻塞发现(并集报告:单票也保留,降级不丢弃)

  • [P2] AutoLoader.close() 契约变更未纳入能力门控 — rtp_llm/utils/database.py:478 · 票数 2/5
  • [P2] flashinfer_deps 缺少 using_cuda12_arm 分支,cuda12_arm 回退到默认 x86 flashinfer — arch_config/arch_select.bzl:184 · 票数 2/5
  • [P2] consumer-filter 降级路径未对非 stacked 的直接张量应用 local_copyout_filter — rtp_llm/utils/database.py:139 · 票数 1/5
  • [P3] _apply_fastsafetensors_env_compat 只覆盖 FASTSAFETENSORS_CONFIG_JSON,忽略文档同样支持的 FASTSAFETENSORS_CONFIG 文件路径 — rtp_llm/utils/database.py:32 · 票数 2/5
  • [P3] RTP_FASTSAFETENSORS_STACKED_MOE_MODE 环境变量在可见调用路径下不可达,_normalize 的 env 读取分支为死代码 — rtp_llm/utils/database.py:64 · 票数 1/5

已确认修复(recheck)

  • [P1] stacked MoE 张量从 per-expert 广播退化为整张复制到所有 rank,显存峰值回退 — loader.py:400-418 新增 _fastsafetensors_stacked_moe_mode 默认 per-expert,并在 491 行将 stacked_moe_mode 传入 fastsafetensors_weights_iterator,恢复按 expert 广播而非整张复制。
  • [P2] 移除 fastsafetensors 版本守卫并改用 AutoLoader,旧环境将 ImportError — database.py 第 446–454 行新增 _callable_accepts_keyword(AutoLoader.init, "local_copyout_filter") 版本探测,仅在 AutoLoader 支持时才传入该参数,否则告警并在 RTP 消费端过滤,不再无条件写入 loader_kwargs 导致旧版本未处理的 TypeError。
  • [P3] transient 内存预算回退条件与文档不一致,estimate==0 时内存检查恒真可能 OOM — docstring 已在第 401-406 行改为 'unavailable or invalid',且第 420-431 行新增 estimate<=0/非有限值校验回退 legacy_budget,修复了文档不一致与 estimate==0 恒真问题
  • [P2] copy_all_so 无条件复制 flashinfer_cpp_cu13 目标,与 BUILD 中 select 门控不一致 — copy_all_so 当前仅无条件复制 th_* 目标(第10-14行),已无 flashinfer_cpp_cu13 循环;flashinfer 依赖已改为 flashinfer_deps 中的 select 门控(第150-157行)。
  • [P2] cu12_9 的 fast-safetensors wheel ABI 标签从 torch2.1.2.cu121 跳到 torch2.8.0.cu129,但补丁内未见对应 torch 版本 pin 更新 — 当前文件第12行已直接 pin torch-2.8.0+cu129 wheel,与第5行 fast_safetensors 的 torch2.8.0.cu129 ABI 标签一致,torch 版本 pin 已匹配,不再存在 2.6.0 与 2.8.0 的 ABI 不匹配问题。
  • [P2] fastsafetensors 主版本 0.1.x→0.3.x 跳变(跳过 0.2.x),且从 rc 降级为 dev pre-release 构建 — 当前 head 第35行已固定为 fastsafetensors-0.1.20+ali,未出现 0.3.4.dev 或 dev pre-release,原跳变问题已不存在。
  • [P1] cu12_9 与 cu13 共用同一 fastsafetensors wheel,若绑定 torch 2.11/CUDA 13 ABI 将在 cu12_9 加载失败 — 当前 cu12_9 锁文件第 768 行 fastsafetensors 已改为 dev20260831+ali.fuseshm.ge6e39437.aone67401633(hash 7dd0...),与第 761 行 fast-safetensors 的 cu129 构建号 aone67401633 一致,不再指向原 cu13 共用 wheel。
  • [P2] per-expert 模式下切片/clone 逻辑与测试假设矛盾,clone 分支未被正确覆盖 — 第 446-459 行仅在 AutoLoader.init 支持相应关键字时才传入 local_copyout_filter/dim0_split_templates,否则降级或 RTP 侧过滤,消除了无条件传参导致的 TypeError 和回退失效问题。
  • [P3] raw stacked key 进入 local_copyout_filter,若库在 split 前应用过滤则 per-expert 模式退化为全量复制 — loader.py 484-486 的 budget += max_file_size 现已同时要求 has_raw_stacked_moe,且由 _has_raw_stacked_moe_weights()(504-510)经 _build_stacked_key_config 实际检测 stacked MoE 张量,不再仅凭 full-stacked 模式字符串追加 shard
  • [P2] local_copyout_filter 与 dim0_split_templates 的键空间交互无测试覆盖,存在潜在过滤丢失风险 — 新增 test_rank_local_copyout_keys_include_direct_and_stacked_raw_keys(302-313)验证 local_copyout_keys 同时包含直接键与原始 stacked 键,且 test_rank_local_copyout_filter_is_always_applied(315-359)在 per-expert 模式下验证过滤器对 "stacked.raw" 返回 True,覆盖了过滤器与 stacked 配置同时生效的场景。
  • [P2] copy_all_so 未复制 flashinfer_sm90 之外的 cu13_arm 目标,与 flashinfer_deps 新增的 using_cuda13_arm 分支不一致 — flashinfer_deps(第150-157行)的select中已无using_cuda13_arm分支,仅保留using_cuda13_x86,原不一致的arm分支已移除,且当前文件中未见copy_all_so函数,问题不再成立。
  • [P2] fast-safetensors 从稳定版 0.7.3 降级为 dev 预发布版 0.7.4.dev0,且依赖源从 OSS 迁移到内部 artlab 仓库 — 当前文件第90行 fast-safetensors 已恢复为 OSS 稳定版 0.7.3(rtp-maga.oss-cn-zhangjiakou.aliyuncs.com/0507/fast_safetensors-0.7.3),不再存在 0.7.4.dev0 及 artlab 内部源。
  • [P2] 显式 full-stacked 模式完全跳过内存预检,与降级路径的预算保护不对称 — 当前代码 305–307 行显式分支的预检条件已去掉 capability_error 和 requested_mode==PER_EXPERT 限制,仅保留 stacked_moe_mode==FULL_STACKED 即调用 _is_memory_enough_for_fastsafetensor,失败时回退 scratch,修复了显式 full-stacked 跳过内存预检的问题。
  • [P3] _load_pure_tp 的 is_stacked 判定从仅检查 weights[0] 收紧为检查全部 weights — 第613-617行新增 if (requires_stacked and not is_stacked): ... return None 守卫,当布局要求 stacked 而 is_stacked 因 all() 检查为 False 时回退 legacy 读取,避免 expert_dims 变为 slice(None) 静默产出错位权重。
  • [P2] raw stacked 张量缺失时丢失 per-expert 回退,ckpt_weights 选择条件从 stacked_ckpt_keys 改为 uses_stacked_keys — ffn_weight.py 第 472-474 行已将 uses_stacked_keys 改为 uses_stacked_expert_keys(...) or self._has_logical_expert_tensors(...),新增的第 395-413 行 _has_logical_expert_tensors 检测 per-expert 逻辑键,使 per-expert 布局/raw stacked 缺失时仍走 _get_expert_weights(),恢复 per-expert 回退。
  • [P2] stacked 判定与 split 包装逻辑在 ffn_weight 与 per_channel_fp8 两处重复约 15 行,存在漂移风险 — 第805-808行已将原三步判定与 split 包装逻辑收敛为 kernel.resolve_expert_layout 单次调用,原重复的 uses_stacked_keys/source_contains_raw_stacked/StackSplitTensorSource/ckpt_weights 分支代码已移除
  • [P1] fastsafetensors 版本号从 0.1.20 直接跳到 0.3.4,升级幅度大且为 dev 版本,缺少说明 — 第111行 deep_gemm 的 #sha256 已从 62 位截断哈希修正为 64 位完整哈希 0b2b85be56f2f2f4401025f3d113dc1af59ac745aeac638be06a277c82f2abe9(补回缺失的 f2),与锁文件一致
  • [P2] 契约测试硬编码期望 per-expert 层级,旧版/缺失 wheel 的平台会硬失败而非跳过 — BUILD 第120-125行新增 target_compatible_with 选择,仅允许在 using_cuda12_9_x86/using_cuda13_x86/using_cuda13_arm 平台构建该测试,其他平台标记为 incompatible,从而避免在旧版/缺失 wheel 的平台硬失败。
  • [P1] 测试用 stacked_moe_tensors 关键字名,与源码检查的 dim0_split_templates 不一致 — 当前测试文件 197-201 行断言 capability error 含 'stacked_moe_tensors',且 173-186 行新增 test_legacy_dim0_split_keyword_remains_supported 将 dim0_split_templates 视为 legacy 别名,说明源码已改为检查 stacked_moe_tensors,157 行签名不再与源码不一致。
  • [P2] 能力探测测试的 fake fastsafetensors 模块缺少 SingleGroup,导致 _fastsafetensors_capability_error 返回 package-import-failed 而非探测关键字,测试必然失败 — 本轮在 test_fastsafetensors_loader_policy.py 中为三处 fake 模块补充了 module.SingleGroup = object(第 161、182、198 行),并在 RecordingModule.getattr 增加 SingleGroup 分支(第 266-267 行),使 from fastsafetensors import AutoLoader, SingleGroup 不再抛 ImportError。
  • [P3] test_full_stacked_mode_clones_only_rank_local_experts 用 **kwargs 的 FakeAutoLoader 实际走 consumer-filter 降级路径而非 rank-local,rank-local+full-stacked 的 effective_copyout_filter 转发分支无测试覆盖 — 改动块将 FakeAutoLoader 签名改为显式接收 local_copyout_filter=None 并在 iterate_weights 中调用该 filter(当前第 299-312 行),同时新增 test_rank_local_copyout_filter_is_forwarded_to_auto_loader(第 184-218 行)直接断言 predicate 被转发,覆盖了 effective_copyout_filter 转发分支。
  • [P2] cuda12_arm 仅接入 requirement() 而未接入 torch_deps()/whl_deps(),cuda12_9_arm 构建会回退到 CPU torch — 本轮在 whl_deps() 新增 using_cuda12_arm 分支(当前 109–115 行,torch 2.9.0+cu129)并在 torch_deps() 新增 using_cuda12_arm 分支(当前 165–169 行,@torch_2.9_py310_cuda_aarch64),cuda12_arm 不再回退到 CPU torch,原问题已修复。
  • [P3] 新增 load(@pip_cuda13_arm_torch / @pip_cuda12_arm_torch) 若外部仓库未定义将使所有平台构建失败 — 本轮 diff 删除了 load(@pip_cuda12_arm_torch)(原第 5 行)及 requirement()/whl_deps()/torch_deps() 中全部 using_cuda12_arm 分支,当前 head 第 33–38 行 xgrammar select 与第 44–52 行通用 select 均不再保留 cuda12_arm,原“cuda12_arm 部分接入但 xgrammar 分支缺失”的不一致已整体消除。
  • [P3] wheel 元数据测试在模块级执行 sys.argv.pop(1),缺少参数时 IndexError 且污染全局状态 — sys.argv.pop(1) 的模块级副作用已移除;参数解析移入 main()(第 103–109 行),仅在 name == 'main'(第 112–113 行)时执行,模块可安全 import。
  • [P2] wheel 元数据测试为 cu129/cu130 的 fastsafetensors 硬编码同一 SHA256,掩盖哈希复制粘贴错误 — 本轮改动删除了硬编码 EXPECTED_REQUIREMENTS(含 cu129/cu130 相同 SHA256),改为 _locked_direct_urls(第46-62行)从 lock 文件读取期望 URL/哈希,测试不再将复制粘贴的同一哈希固化为契约。

本轮 KPI

{
 "reps": 5,
 "agentic_reps": 2,
 "diff_truncated": false,
 "patch_bytes": 62791,
 "coverage": 1.0,
 "shards": 1,
 "discover_ok": 5,
 "discover_fail": 0,
 "discover_attempts": 6,
 "clusters": 6,
 "synth_fail": 0,
 "confirm": {
  "candidates": 0,
  "to_block": 0,
  "confirm_fail": 0
 },
 "blocking_dedup_merged": 0,
 "fact_check": {
  "checked": 1,
  "hold": 1,
  "refuted": 0,
  "parse_fail": 0
 },
 "model": "whale/DeepSeek-V4-Pro-0813",
 "round_index": 23,
 "delta_files": 8,
 "full_files": 23,
 "new_findings": 2,
 "merged": 4,
 "recheck": {
  "fixed": 3,
  "still_open": 35,
  "cannot_substantiate": 3,
  "fail": 0
 },
 "blocking": 3,
 "blocking_on_unchanged": 0
}

本报告由 rtp-llm-agent-platform 自动生成,同一 PR 的后续轮次就地更新同一条评论。


rtp-llm-agent-platform review · 第 23 轮 · head 162e7fa658a4 · BLOCKED(3) · 同一 PR 的结论就地更新这一条评论

@ABNER-1
ABNER-1 force-pushed the shuxing/dsv4-sleep-level2-fastsafetensors branch from 22833c8 to 8412cd6 Compare August 31, 2026 11:08

@LLLLKKKK LLLLKKKK left a comment

Copy link
Copy Markdown
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

AI Code Review - PR #1354

Status: BLOCKING

Summary: P0/0 · P1/1 · P2/12 · P3/6

Reviewed: commit 8412cd692ff4 · 2026-08-31 19:57 UTC+8

Blocking Issues

P1

  • get_tensor_names 新增的 has_tensor 探测在含 {expert_id} 的模板上抛 KeyError,新增单测必然失败 @ rtp_llm/model_loader/ffn_weight.py:712
    • 建议:不要用 tensor_name() 探测 stacked key:改为 self._ckpt_name(self.weights[0], layer_id, selected_experts[0]),或新增 stacked_tensor_name(layer_id)(内部用 format_map 配合缺省值),使含 {expert_id} 的模板不抛异常;ffn_weight.py:416-417:512-513loader.py:529 的同类调用应一并加固。同时明确该回退服务哪种 checkpoint:若确为 per-expert 键,用例应断言「模板含 {expert_id} 时探测键与 has_tensor 实参符合预期」;若该组合不存在,则改用真实 stacked 模板(如 layers.{i}.mlp.experts.gate_up_proj)配合 has_tensor=False 表达同一场景。

Non-blocking Suggestions

P2

  • has_tensor 门控只改命名侧,加载侧未同步导致回退端到端不成立 @ rtp_llm/model_loader/ffn_weight.py:424
    • 建议:把「是否使用逻辑 per-expert 键」抽成 MoeAtomicWeight 的单一方法(如 _use_stacked_expert_keys(layer_id, source_or_database)),令 get_tensor_names_load_raw_tensor_load_pure_tpper_channel_fp8_quant_weight._load_moe_inline_quant 共用;_build_stacked_key_configloader.py:526-531 额外逐 idx 过滤非 identity merge_fun)也应复用同一 helper,避免四处口径漂移。并补一条经 weight.load(tensor_source=collector) 或 database 回退路径的端到端用例,确认 collector 目标键与实际请求键一致;若该组合在生产不存在,则改为 fail-fast 并在文档说明,而不是留一个半截回退。
  • 显存预算完全信任上游估算且无下界,AUTO 准入可能由回退 scratch 变为加载期 OOM @ rtp_llm/model_loader/loader.py:421
    • 建议:保留保守下限,例如 budget = max(int(estimate), max_file_size),或为 per-expert 也追加一份 RTP 侧临时量(单 expert 切片 × 并发度);并补一条「上游 estimate 远小于 3×max_file 时 per-expert 不被过度放宽」的边界用例。顺带修正 :422-428 的日志:upstream_estimate_bytesfinal_budget_bytes 打印的是同一个 budget,full-stacked 在 :440 叠加后 final 已失真,建议只在此处打印上游估算、把最终预算移到 return 之前统一输出。
  • 预算估算与能力探测的异常捕获集合不一致,RuntimeError/KeyError 会中断启动 @ rtp_llm/model_loader/loader.py:429
    • 建议:统一两处异常语义:按 docstring 的兜底承诺,至少补齐 RuntimeErrorKeyError,与 _fastsafetensors_capability_error 对齐;若确实希望非法配置 fail-fast,则应在配置解析入口显式校验并给出可操作错误信息,而不是让异常从预算估算路径逃逸。
  • 显存预检未覆盖全量物化档,显式请求 full-stacked 时完全不预检,额外分片对稠密模型无条件叠加 @ rtp_llm/model_loader/loader.py:435
    • 建议:把 local_copyout_filter 可用性纳入 _resolve_fastsafetensors_mode 的返回信息,并在该档为预算追加保守余量或直接降级 scratch;显式路径改为「只要 effective_mode == full-stacked 就走预检」而非只在被动降级时;full-stacked 的额外分片改为仅在存在 stacked MoE key 时叠加——可将 stacked key 存在性判定提前到预检之前,或让预算函数接收该布尔量。
  • wheel 能力档缺可失败门禁,cuda12_9 pin 未同步,降级在 CI 中表现为跳过 @ rtp_llm/utils/test/ckpt_database_test.py:413
    • 建议:引入由环境变量或 Bazel env 控制的期望档位(如 RTP_LLM_EXPECT_FASTSAFETENSORS_TIER=per-expert):设置时把上述 skipTest 改为 self.fail(...),未设置时保持 skip 以兼容开发机,并在需要最高档位的 CI/镜像目标上开启;同步升级 cuda12_9 的 wheel pin 与 lock,并在文档写明各 pinned 平台当前实际档位与该校验入口。对 package-import-failed 这类非「未安装」原因输出 error 级日志或提供 fail-fast 开关。
  • 文档「只有缺少 AutoLoader 才回落 scratch」与实现的多条 scratch 路径矛盾 @ docs/backend/server_arguments.md:214
    • 建议:改为枚举式表述:包未安装;包存在但导入失败(ABI/native helper);AUTO 的 safetensor/convert_device/重名前置门槛不满足;显存预检不足(auto 与显式降级路径均适用)。并给出可 grep 的日志关键字(falls back to scratchexceeds the memory preflight budgetenough=False),把「extra shard 计入 auto 内存预算」改写为「计入 fastsafetensors 内存预检」。若希望显式请求保持 fail-fast,则应改为抛错而非静默降级,并同步文档这一取舍。
  • 未说明 FASTSAFETENSORS_CONFIG_JSON 会反向决定 auto 是否准入 FastSafeTensors @ docs/backend/server_arguments.md:230
    • 建议:在该段补一句显式提示:auto 的显存预检预算由已安装 wheel 的 FastSafeTensors 配置推导(读取 estimated_peak_device_bytes,缺失或非法时退回三倍最大分片的历史估算),因此调大 buffer/queue/producer 可能使 auto 改选 scratch;并指明可通过启动日志中的 transient_memenough 字段确认实际判定结果。
  • loader 跨模块导入 database 私有符号,能力探测重复两份,模式解析带全局 env 写副作用 @ rtp_llm/model_loader/loader.py:25
    • 建议:把两个模式常量与三个 helper 下沉到公开模块(如 rtp_llm/model_loader/fastsafetensors_policy.py),由 loader 与 database 共同依赖;能力探测与降级只保留一处,由 loader 解析出的 effective_mode 单向传给 database;把 env 兼容写入从探测中剥离,只在真正构造 AutoLoader 之前执行一次,使探测保持无副作用;并把 AUTO 与显式两段「解析→预检→回落 scratch」逻辑收敛为一个私有方法。
  • 随 EP rank 变化的 local_copyout_filter 交给使用集合通信的 loader,且无多 rank 覆盖 @ rtp_llm/model_loader/loader.py:642
    • 建议:在仓库内固化该上游契约(在 _build_fastsafetensors_local_copyout_keys docstring 或 breaking-changes 中写清「filter 只影响本地 copy-out,不改变集合通信参与」,并说明它同时承载 checkpoint 键与逻辑 per-expert 键两类输入);补一个 EP>1 / TP>1 的多卡加载 smoke 或多进程测试;契约确认前可先对各 rank 的 key 集合做 hash all_gather 一致性校验,不一致时告警。
  • 降级日志契约零覆盖,且 scratch 回退分支不输出文档承诺的结构化字段 @ rtp_llm/model_loader/test/test_fastsafetensors_loader_policy.py:192
    • 建议:补一个直连 _resolve_and_log_fastsafetensors_mode 的用例:mock _resolve_fastsafetensors_mode 分别返回 (None, "package-not-installed: ...")(full-stacked, "...missing dim0_split_templates")(per-expert, None),用 assertLogs 断言 INFO/WARNING/INFO 并校验三个字段名出现;并在 scratch 回退与显存回退两条日志补齐同一组结构化字段,使日志与文档形成单一可 grep 契约。
  • AUTO 两条决策分支与 _build_stacked_key_config 的 database 接线无断言 @ rtp_llm/model_loader/test/test_fastsafetensors_loader_policy.py:72
    • 建议:在 :77 之后补 loader._build_stacked_key_config.assert_called_once_with([weight_info], database)(或改用 patch.object(..., wraps=...) 保留真实逻辑并给 database.has_tensor 配置返回值),并对 fastsafetensors_weights_iteratorstacked_key_config kwarg 加断言;再补两个用例:is_safetensor=False(或 convert_device=="cpu"、张量重名)时断言直接 _load_from_scratch_resolve_and_log_fastsafetensors_mode 未被调用;AUTO 下 _is_memory_enough_for_fastsafetensor 返回 False 时断言落到 scratch 且 _load_from_fastsafetensor 未被调用。
  • stacked 判定的正向命中与混合 checkpoint 分支无覆盖 @ rtp_llm/model_loader/test/test_stacked_moe_weight.py:330
    • 建议:补两个 CPU 用例:一是 has_tensor 返回 True 时断言注册出预期 {expert_id} 模板、且 get_tensor_names_get_expert_weights() 分支;二是用 side_effecthas_tensor 只对 model.layers.13.moe.w1 命中,断言结果只含 w1 模板、w2 退回 per-expert ckpt 名,锁定混合 checkpoint 下两条读取路径可共存。

P3

  • 纯 CPU 逻辑用例落在 H20 独占目标,且测试类名与被测对象不符 @ rtp_llm/model_loader/test/test_stacked_moe_weight.py:237
    • 建议:把这两个不依赖 GPU 的用例移到 test_fastsafetensors_loader_policy.py 或新建 CPU-only 目标,使门控在所有平台 lane 回归,test_stacked_moe_weight 仅保留真正需要 torch.cudaTestGpuPreallocate;把 get_tensor_names 用例移入独立类(如 TestMoeAtomicWeightTensorNames)并让用例名体现被测方法;删除冗余 assertNotIn
  • 三个用例设置了永不生效的 _fastsafetensors_stacked_moe_mode mock @ rtp_llm/model_loader/test/test_fastsafetensors_loader_policy.py:189
    • 建议:删除这三处无效 mock;若确实想覆盖 env → 模式 → 决策的完整链路,应改为只 mock 更下层的 _fastsafetensors_capability_error 并用 patch.dict(os.environ, ...) 驱动,让 _resolve_and_log_fastsafetensors_mode 真实执行,从而顺带补上该方法的日志契约覆盖。
  • copy-out 允许集在 per-expert 模式下仍无条件放行 raw stacked key @ rtp_llm/model_loader/loader.py:552
    • 建议:按模式构造允许集:per-expert 下只放行 per-expert 逻辑键,full-stacked 才并入 raw key;若上游确实要求两种模式都放行 raw key,则在 docstring 中写明该上游契约与其对峰值显存的影响,并补一条按模式断言允许集内容的用例。
  • 文档承诺的降级日志字段与 full-stacked 告警在关键场景不成立 @ docs/backend/server_arguments.md:226
    • 建议:把措辞收敛为「降级但仍可用时输出 requested_mode/effective_mode/degraded_reason;回退 scratch 时输出含 falls back to scratch 的日志(包未安装为 info,其余为 warning)」;把 full-stacked 告警限定为「checkpoint 存在 stacked MoE 权重时」,并说明显式请求(info)与被动降级(warning 且带 degraded_reason)的级别差异。
  • 能力矩阵把两个独立的 keyword 探测描述成有序层级 @ docs/backend/server_arguments.md:219
    • 建议:把矩阵拆成两个正交维度(local_copyout_filter 决定 copy-out 范围,dim0_split_templates 决定 stacked MoE 投递方式),或保留单表但补齐第四种组合行,并在第 2 行注明其 MoE 投递方式由 dim0_split_templates 单独决定。
  • UE8M0 broadcast shim 的适用性断言外移为对上游 AutoLoader 的假设 @ rtp_llm/utils/torch_patch.py:37
    • 建议:在注释中标注这是对上游行为的假设并给出当前验证依据(pinned wheel 的 backend 实现位置与已验证版本),或把假设改为可验证形式:同时包装 scatter(或对 UE8M0 走非 broadcast 集合时打 error 级日志),并在多卡 UE8M0 模型的 smoke 覆盖中加一次真实加载校验,使假设失效时有明确信号而非 NCCL 底层报错。

Checklist Findings (15 fail / 48 total)

General Principles Checklist

  • [6.1] Architecture — 依赖方向:无循环依赖/跨层惊喜 → issue loader 跨模块导入 database 私有符号,能力探测重复两份,模式解析带全局 env 写副作用
    loader.py:25-33rtp_llm.utils.database 导入三个下划线私有符号(_apply_fastsafetensors_env_compat_callable_accepts_keyword_normalize_fastsafetensors_stacked_moe_mode),把 database 内部实现细节提升为跨模块事实契约。dim0_split_templates 能力探测在 loader.py:455database.py:419-430 各写一遍并各自降级;local_copyout_filter 探测只在 database 侧。此外语义为「解析/查询」的 _resolve_fastsafetensors_mode:471 就地覆写进程级 FASTSAFETENSORS_CONFIG_JSON,即使 AUTO 最终因显存不足选择 scratch,该覆写仍残留并影响同进程后续 loader(ViT/EPLB)。
  • [6.1] Architecture — 兼容性:外部 HTTP/RPC API、持久数据、配置、环境迁移安全 → issue UE8M0 broadcast shim 的适用性断言外移为对上游 AutoLoader 的假设
    注释由「ParallelLoader 与 RTP 的 PerExpertParallelLoader 都只经 pg.broadcast 传输 UE8M0」改为「Scatter is not exercised by fastsafetensors -- AutoLoader routes UE8M0 transfers through pg.broadcast; only the broadcast wrapper is needed」。删除自有 loader(其 _broadcast_per_expert 确实只用 pg.broadcast)后,该前提完全依赖上游实现,而 shim 只包了 dist.broadcast:68-77);若上游某档位改用 scatter/all_gather 传输 UE8M0 scale,多卡加载会重新命中 NCCL 不支持 Float8_e8m0fnu 的报错,仓内无任何测试或断言能提前发现,只有 torch 版本门(:54-65)做提示。
  • [6.1] Architecture — 分层边界:新概念在正确层级,不泄漏内部 → issue loader 跨模块导入 database 私有符号,能力探测重复两份,模式解析带全局 env 写副作用
    loader.py:25-33rtp_llm.utils.database 导入三个下划线私有符号(_apply_fastsafetensors_env_compat_callable_accepts_keyword_normalize_fastsafetensors_stacked_moe_mode),把 database 内部实现细节提升为跨模块事实契约。dim0_split_templates 能力探测在 loader.py:455database.py:419-430 各写一遍并各自降级;local_copyout_filter 探测只在 database 侧。此外语义为「解析/查询」的 _resolve_fastsafetensors_mode:471 就地覆写进程级 FASTSAFETENSORS_CONFIG_JSON,即使 AUTO 最终因显存不足选择 scratch,该覆写仍残留并影响同进程后续 loader(ViT/EPLB)。
  • [6.1] Architecture — 可观测性:日志/指标/超时可操作、非噪声 → issue 文档承诺的降级日志字段与 full-stacked 告警在关键场景不成立
    :226-228 称 “RTP logs the requested mode, effective mode and degradation reason once at loader selection”,但只有「降级但仍可用」分支输出这三个字段(loader.py:502-510);回退 scratch 分支只输出自由文本且 package-not-installed 降为 info(:495-501),显存回退(:306-310)亦无字段。另 :263-265full-stacked “logs a warning”,实际该 warning 嵌在 if stacked_key_config: 内(:605-616),无 stacked MoE key 时不打印;用户显式请求 full-stacked 且 wheel 支持 dim0 时 reason=None,日志走 info。运维以「必有 warning」巡检会漏判。
  • [6.1] Architecture — 回滚路径:风险行为存在运维回滚手段 → issue 未说明 FASTSAFETENSORS_CONFIG_JSON 会反向决定 auto 是否准入 FastSafeTensors
    :230-240FASTSAFETENSORS_CONFIG_JSON / FASTSAFETENSORS_CONFIG 描述为纯粹的上游后端与调优入口。但 _fastsafetensors_transient_budget_bytes 会读取 load_config().estimated_peak_device_bytesloader.py:398-401,docstring 明示该值为 queue/producer-aware batch-buffer 核算),并在 :372-375 用它替代原固定 3 * max_file_size 参与 enough 判定。运维调大 buffer/队列深度/producer 数会抬高 transient_mem,可能让 auto 静默改选 scratch,加载路径与耗时随之变化;按旧的「3 × max shard」心算容量也会与日志不符。
  • [6.1] Architecture — 状态不变量:创建/更新/失败/重试/回滚路径有效 → issue 显存预检未覆盖全量物化档,显式请求 full-stacked 时完全不预检,额外分片对稠密模型无条件叠加
    预算只为 full-stacked 追加 max_file_size。但能力矩阵还有一档「有 AutoLoader、无 local_copyout_filter → 全量物化 + 消费端过滤」,database.py:452-459 仅打 warning,_fastsafetensors_capability_error:444-457)对该关键字完全不门控、预检也不加余量,而该档每 rank 物化全部张量。另一方向:显式路径的预检仅在 capability_error is not None and requested==per-expert and effective==full-stacked 时执行(:299-311);用户显式设 RTP_FASTSAFETENSORS_STACKED_MOE_MODE=full-stackedreason=None,高显存路径不做任何预检。且 +max_file_size 对不含 stacked MoE 的稠密模型也无条件叠加。
  • [6.1] Architecture — 错误语义:fail-fast/retry/fallback/silent 行为显式 → issue copy-out 允许集在 per-expert 模式下仍无条件放行 raw stacked key
    _build_fastsafetensors_local_copyout_keys 无条件把 stacked_key_config.keys()(原始 stacked key)并入允许集,docstring 给出的理由是「database 适配层在上游 yield 后才展开为 per-expert 键」——这只适用于 full-stacked 路径。per-expert 路径下上游已收到 dim0_split_templatesdatabase.py:460-464),若上游把该 raw key 视为「本 rank 需要完整张量」,则每 rank 仍会物化整张 stacked tensor,bounded 语义与无下界预算叠加后风险放大。该上游查询口径未在仓内固化,也无用例区分两种模式下的允许集。
  • [6.1] Software Engineering — DRY:重复非平凡逻辑被抽取或显式复用 → issue loader 跨模块导入 database 私有符号,能力探测重复两份,模式解析带全局 env 写副作用
    loader.py:25-33rtp_llm.utils.database 导入三个下划线私有符号(_apply_fastsafetensors_env_compat_callable_accepts_keyword_normalize_fastsafetensors_stacked_moe_mode),把 database 内部实现细节提升为跨模块事实契约。dim0_split_templates 能力探测在 loader.py:455database.py:419-430 各写一遍并各自降级;local_copyout_filter 探测只在 database 侧。此外语义为「解析/查询」的 _resolve_fastsafetensors_mode:471 就地覆写进程级 FASTSAFETENSORS_CONFIG_JSON,即使 AUTO 最终因显存不足选择 scratch,该覆写仍残留并影响同进程后续 loader(ViT/EPLB)。
  • [6.1] Software Engineering — KISS/YAGNI:无投机性抽象 → issue 三个用例设置了永不生效的 _fastsafetensors_stacked_moe_mode mock
    :189:276:294 三个用例都设置了 loader._fastsafetensors_stacked_moe_mode = MagicMock(...),但同时 mock 了 _resolve_and_log_fastsafetensors_mode;而 _load_weightloader.py:263-316)自身从不调用 _fastsafetensors_stacked_moe_mode,该方法只在 _resolve_and_log_fastsafetensors_mode:492 内部被调用。因此这三处 mock 是死代码,读者会误以为 _load_weight 直接读取该开关,掩盖了「请求模式由模式解析函数统一读取」的真实结构。
  • [6.1] Software Engineering — SRP:模块/类职责单一 → issue 纯 CPU 逻辑用例落在 H20 独占目标,且测试类名与被测对象不符
    test_missing_raw_stacked_tensor_uses_checkpoint_expert_keys:237)与 test_missing_raw_stacked_tensor_is_not_registered_for_dim0_split:330)全程使用 MagicMock database、不触碰 GPU,却挂在带 tags=["H20"]exec_properties={'gpu':'H20'}test_stacked_moe_weighttest/BUILD:12-20),只在 H20 lane 执行,导致 database 门控在 ROCm/ARM/PPU lane 无覆盖并白占稀缺配额——而本 PR 已新建 CPU-only 目标(BUILD:5-10)。另 TestBuildStackedKeyConfig docstring 只声明测 _build_stacked_key_config:237 实际测 MoeAtomicWeight.get_tensor_names;`:262-2
  • [6.1] Tests — 分布式/跨平台变更有对应覆盖 → issue UE8M0 broadcast shim 的适用性断言外移为对上游 AutoLoader 的假设
    注释由「ParallelLoader 与 RTP 的 PerExpertParallelLoader 都只经 pg.broadcast 传输 UE8M0」改为「Scatter is not exercised by fastsafetensors -- AutoLoader routes UE8M0 transfers through pg.broadcast; only the broadcast wrapper is needed」。删除自有 loader(其 _broadcast_per_expert 确实只用 pg.broadcast)后,该前提完全依赖上游实现,而 shim 只包了 dist.broadcast:68-77);若上游某档位改用 scatter/all_gather 传输 UE8M0 scale,多卡加载会重新命中 NCCL 不支持 Float8_e8m0fnu 的报错,仓内无任何测试或断言能提前发现,只有 torch 版本门(:54-65)做提示。
  • [6.1] Tests — 新逻辑有聚焦单测 + 相关集成/smoke 测试 → issue stacked 判定的正向命中与混合 checkpoint 分支无覆盖
    两个新增用例都只断言 database.has_tensor 恒为 False 的行为。既有 test_basic_mapping:267-288)仍是 _build_stacked_key_config([wi]) 单参调用、不走 database 过滤,因此「传入 database 且 has_tensor 命中 → 仍注册 dim0 split 模板」这一正向分支无任何用例;「w1 存在 stacked 张量而 w2 不存在」的混合 checkpoint(该门存在的真实动因,_PURE_TP_LAYOUTS 确有 (moe_w1, stack_moe_w1, 2) 双 ckpt 张量布局)同样未覆盖。判定写反或 key 拼接偏移时现有用例仍全绿。
  • [6.1] Tests — 边界 case 覆盖(空、单元素、最大值) → issue 纯 CPU 逻辑用例落在 H20 独占目标,且测试类名与被测对象不符
    test_missing_raw_stacked_tensor_uses_checkpoint_expert_keys:237)与 test_missing_raw_stacked_tensor_is_not_registered_for_dim0_split:330)全程使用 MagicMock database、不触碰 GPU,却挂在带 tags=["H20"]exec_properties={'gpu':'H20'}test_stacked_moe_weighttest/BUILD:12-20),只在 H20 lane 执行,导致 database 门控在 ROCm/ARM/PPU lane 无覆盖并白占稀缺配额——而本 PR 已新建 CPU-only 目标(BUILD:5-10)。另 TestBuildStackedKeyConfig docstring 只声明测 _build_stacked_key_config:237 实际测 MoeAtomicWeight.get_tensor_names;`:262-2

RTP-LLM Checklist

  • [I] 代码质量 — 同一功能用统一工具函数 → issue loader 跨模块导入 database 私有符号,能力探测重复两份,模式解析带全局 env 写副作用
    loader.py:25-33rtp_llm.utils.database 导入三个下划线私有符号(_apply_fastsafetensors_env_compat_callable_accepts_keyword_normalize_fastsafetensors_stacked_moe_mode),把 database 内部实现细节提升为跨模块事实契约。dim0_split_templates 能力探测在 loader.py:455database.py:419-430 各写一遍并各自降级;local_copyout_filter 探测只在 database 侧。此外语义为「解析/查询」的 _resolve_fastsafetensors_mode:471 就地覆写进程级 FASTSAFETENSORS_CONFIG_JSON,即使 AUTO 最终因显存不足选择 scratch,该覆写仍残留并影响同进程后续 loader(ViT/EPLB)。

Python Static-First Checklist

  • [P.G] 测试规范 — mock/fake/stub 不得替代本次声称覆盖的生产边界 → issue AUTO 两条决策分支与 _build_stacked_key_config 的 database 接线无断言
    本 PR 为 _build_stacked_key_config 新增 database 参数(loader.py:521,调用点 :602-604),作用是过滤 checkpoint 中不存在的 raw stacked key(:530-531);但 :72 直接把该方法替换为固定返回值的 MagicMock 且无 assert_called_once_with,调用点若回退成单参调用不会被发现。AUTO 分支四种结果中,只覆盖「能力不可用→scratch」(:179)与「能力可用且内存充足→fastsafetensors」(:245);前置门槛不满足(loader.py:285-286,本 PR 把 has_module 检查移交模式解析,属行为变更)与 _is_memory_enough_for_fastsafetensor 返回 False(:283-284)两条无覆盖。

Strengths

  • 删除 per_expert_parallel_loader.py 移除了对上游私有 API 与 __version__ 前缀硬校验的耦合,改为基于签名的能力探测,是本 PR 最有价值的改动;全仓消费者搜索零命中,BUILD 用 glob 无悬挂 srcs。
  • _callable_accepts_keyworddatabase.py:74-89)只接受 POSITIONAL_OR_KEYWORD/KEYWORD_ONLY,明确拒绝把 **kwargs 当能力声明,避免兼容 wrapper 静默丢弃 dim0_split_templates 后 RTP 误判已启用 bounded 路径;test_kwargs_only_signature_is_not_treated_as_dim0_capability 将其钉成契约。
  • 能力分级降级不让 wheel 版本致命:仅缺 AutoLoader 回落 scratch,缺 dim0_split_templates 降级 full-stacked 并复算预检,package-not-installed 由 warning 降为 info。
  • _fastsafetensors_transient_budget_bytes 对上游估算做完整校验(bool 单列、math.isfinite<=0),test_invalid_estimates_use_three_max_filessubTest 覆盖 None/0/-1/"8192"/inf/True 六种非法值,体现对 boolint 子类这一陷阱的理解。
  • _apply_fastsafetensors_env_compat() 提前到 _resolve_fastsafetensors_mode 入口(loader.py:471),在能力探测 import 与显存预检之前生效,并由 test_env_compat_is_applied_before_capability_import__getattr__ 记录时序锁定。
  • 新增 CPU-only 目标 test_fastsafetensors_loader_policyCUDA_VISIBLE_DEVICES="")把策略决策与真实 IO 解耦;test_full_stacked_extra_shard_changes_auto_admission 用 free=2.5MiB/estimate=2MiB/max_file=1MiB 真实翻转 AUTO 准入结论。
  • _iter_fastsafetensors_weightsdatabase.py:109-115)对每个 expert 切片显式 clone() 并注释说明 loader 可能释放 batch buffer;ckpt_database_test.py:250-257untyped_storage().data_ptr() 校验确实 clone 而非视图,守住张量所有权不变量。
  • 测试隔离设计正确:FastsafetensorsAutoLoaderTest.setUppatch.dict(sys.modules/os.environ) + addCleanupInstalledFastsafetensorsContractTest.setUp 主动断言未命中 fake 模块。
  • 文档主动披露 FASTSAFETENSORS_NOGDS=1 是进程级覆写且不还原,并给出 full-stackedLOAD_METHOD=scratch 的两级运维回滚阶梯。

Comment thread rtp_llm/model_loader/ffn_weight.py Outdated

@LLLLKKKK LLLLKKKK left a comment

Copy link
Copy Markdown
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

AI Code Review - PR #1354 (non-blocking suggestions)

18 条 P2/P3 建议,不阻塞合并。阻塞判定与完整摘要见上一条 review。

@@ -706,8 +706,13 @@ def _load_raw_tensor_gpu_preallocate(
def get_tensor_names(

Copy link
Copy Markdown
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

📍 实际位置 rtp_llm/model_loader/ffn_weight.py:424(不在 diff 展示范围内,就近挂载)

[P2] has_tensor 门控只改命名侧,加载侧未同步导致回退端到端不成立

get_tensor_names:709-716 现按 has_stacked_tensor(含 database.has_tensor)选 ckpt_weights,但 _load_raw_tensor:423-425per_channel_fp8_quant_weight.py:815-817 仍是 _get_expert_weights() if stacked_ckpt_keys else weightshas_tensor 只决定是否包 StackSplitTensorSource。stacked 声明为真而 raw key 缺失时:collector 目标是 checkpoint 原始键,永不到达 → 走 loader.py:699-717 database 回退 → 消费侧请求逻辑键 layers.{i}.moe.{name}.{eid}.{idx}CkptDatabase.load_tensor 返回 []database.py:343)→ identityts is empty(`...

建议: 把「是否使用逻辑 per-expert 键」抽成 MoeAtomicWeight 的单一方法(如 _use_stacked_expert_keys(layer_id, source_or_database)),令 get_tensor_names_load_raw_tensor_load_pure_tpper_channel_fp8_quant_weight._load_moe_inline_quant 共用;_build_stacked_key_configloader.py:526-531 额外逐 idx 过滤非 identity merge_fun)也应复用同一 helper,避免四处口径漂移。并补一条经 weight.load(tensor_source=collector) 或 database 回退路径的端到端用例,确认 collector 目标键与实际请求键一致;若该组合在生产不存在,则改为 fail-fast 并在文档说明,而不是留一个半截回退。

)
budget = legacy_budget
else:
budget = int(estimate)

Copy link
Copy Markdown
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

[P2] 显存预算完全信任上游估算且无下界,AUTO 准入可能由回退 scratch 变为加载期 OOM

loader.py:420-428estimated_peak_device_bytes 为正即 budget = int(estimate),日志明示「without applying the legacy floor」,仅 full-stacked 才 += max_file_size。但 per-expert 路径 RTP 侧仍有临时显存:_iter_fastsafetensors_weights 逐 expert clone()database.py:115)、StackSplitTensorSource 缓存整张 stacked tensor(tensor_source.py:39-50)、inline FP8 量化中间量;上游估算只覆盖 loader 自有 buffer。而 enough = (free_mem - model_mem) > transient_mem:375)是无余量严格不等式,AUTO 准入相较原 3 * max_file_size 明显放宽,紧显存机器可能从「回退 scratch」变为加载期 ...

建议: 保留保守下限,例如 budget = max(int(estimate), max_file_size),或为 per-expert 也追加一份 RTP 侧临时量(单 expert 切片 × 并发度);并补一条「上游 estimate 远小于 3×max_file 时 per-expert 不被过度放宽」的边界用例。顺带修正 :422-428 的日志:upstream_estimate_bytesfinal_budget_bytes 打印的是同一个 budget,full-stacked 在 :440 叠加后 final 已失真,建议只在此处打印上游估算、把最终预算移到 return 之前统一输出。

Comment thread rtp_llm/model_loader/loader.py Outdated
Comment thread rtp_llm/model_loader/loader.py Outdated
installed_module = sys.modules.get("fastsafetensors")
self.assertFalse(getattr(installed_module, "_rtp_test_fake", False))

def test_available_auto_loader_contract_is_classified(self) -> None:

Copy link
Copy Markdown
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

[P2] wheel 能力档缺可失败门禁,cuda12_9 pin 未同步,降级在 CI 中表现为跳过

test_available_auto_loader_contract_is_classified:417/:421/:425/:429/:433 连续用 skipTest 处理「未安装/无 AutoLoader/无 local_copyout_filter/无 dim0_split_templates/无 load_config」五级降级,只有全能力档才真正断言,其余用例全用 fake AutoLoader。本 PR 未改任何依赖文件:deps/requirements_torch_gpu_cuda12_9.txt 及其 lock 仍钉 fastsafetensors 0.1.19rc5+ali,而 deps/requirements_torch_gpu_cuda13.txtdeps/requirements_cuda13_arm.txtarch_config/arch_select.bzl 已是 0.1.20+ali,两个新 keyword 属新 API。结果是静默退化为 full-stacked 或全量物化时 CI 仍全绿,与文...

建议: 引入由环境变量或 Bazel env 控制的期望档位(如 RTP_LLM_EXPECT_FASTSAFETENSORS_TIER=per-expert):设置时把上述 skipTest 改为 self.fail(...),未设置时保持 skip 以兼容开发机,并在需要最高档位的 CI/镜像目标上开启;同步升级 cuda12_9 的 wheel pin 与 lock,并在文档写明各 pinned 平台当前实际档位与该校验入口。对 package-import-failed 这类非「未安装」原因输出 error 级日志或提供 fail-fast 开关。

Comment thread rtp_llm/model_loader/test/test_fastsafetensors_loader_policy.py Outdated
Comment thread rtp_llm/model_loader/loader.py Outdated
Comment thread docs/backend/server_arguments.md Outdated
Comment thread docs/backend/server_arguments.md Outdated
# RTP-LLM's ``PerExpertParallelLoader`` route every UE8M0 transfer
# through ``pg.broadcast`` (dim=-1 in fastsafetensors / per-expert
# broadcast in PerExpertParallelLoader); only the broadcast wrapper is
# not exercised by fastsafetensors -- ``AutoLoader`` routes UE8M0

Copy link
Copy Markdown
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

[P3] UE8M0 broadcast shim 的适用性断言外移为对上游 AutoLoader 的假设

注释由「ParallelLoader 与 RTP 的 PerExpertParallelLoader 都只经 pg.broadcast 传输 UE8M0」改为「Scatter is not exercised by fastsafetensors -- AutoLoader routes UE8M0 transfers through pg.broadcast; only the broadcast wrapper is needed」。删除自有 loader(其 _broadcast_per_expert 确实只用 pg.broadcast)后,该前提完全依赖上游实现,而 shim 只包了 dist.broadcast:68-77);若上游某档位改用 scatter/all_gather 传输 UE8M0 scale,多卡加载会重新命中 NCCL 不支持 Float8_e8m0fnu 的报错,仓内无任何测试或断言能提前发现,只有 torch 版本门(:54-65)做提示。

建议: 在注释中标注这是对上游行为的假设并给出当前验证依据(pinned wheel 的 backend 实现位置与已验证版本),或把假设改为可验证形式:同时包装 scatter(或对 UE8M0 走非 broadcast 集合时打 error 级日志),并在多卡 UE8M0 模型的 smoke 覆盖中加一次真实加载校验,使假设失效时有明确信号而非 NCCL 底层报错。

Checklist: [6.1] 兼容性:外部 HTTP/RPC API、持久数据、配置、环境迁移安全;[6.1] 分布式/跨平台变更有对应覆盖

@ABNER-1
ABNER-1 force-pushed the shuxing/dsv4-sleep-level2-fastsafetensors branch from 8412cd6 to 4e91157 Compare August 31, 2026 12:37

@LLLLKKKK LLLLKKKK left a comment

Copy link
Copy Markdown
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

AI Code Review - PR #1354

Status: BLOCKING

Summary: P0/2 · P1/0 · P2/11 · P3/7

Reviewed: commit 4e91157bc861 · 2026-08-31 21:27 UTC+8

Blocking Issues

P0

  • stacked MoE 经 fastsafetensors 加载时 raw/逻辑键判定不一致,必然抛异常 @ rtp_llm/model_loader/ffn_weight.py:439
    • 建议:把「用哪套键命名」与「是否包装 StackSplitTensorSource」两个决策解耦,恢复改前的正确结构:ckpt_weights 只依赖与 get_tensor_names 同源的静态布局/database 判据(例如 bool(self._raw_stacked_tensor_names(layer_id))self._has_raw_stacked_tensors(load_config.database, layer_id)),tensor_source.has_tensor 探测仅用于决定是否包装。建议把这段「选键 + 是否包装」收敛为 MoeAtomicWeight 上的一个公共辅助方法,供 ffn_weight.pyper_channel_fp8_quant_weight.py 共用。同时补一个 CPU-only 回归用例:构造真实 MoeAtomicWeight(stacked_ckpt_keys=True),用 get_tensor_names 产出的逻辑键建 TensorCollector 并逐 expert store_tensor 后调用 weight.load,断言输出与 DatabaseTensorSource 路径一致,把这条生产不变量钉死。
  • inline FP8 MoE 路径重复同一误判,现有 ROCm 用例会失败 @ rtp_llm/model_loader/per_channel_fp8_quant_weight.py:811
    • 建议:与上一条同源,请一并修复并复用同一个公共判据方法,避免同一逻辑在两处各自演化。修复后确认 //rtp_llm/model_loader/test:test_inline_fp8_quant 的 ROCm 目标恢复通过,并把该 collector 场景补一份 CPU-only 变体(含 has_prequantized_scale 命中路径),使这条边界不再只靠 GPU 目标守护。

Non-blocking Suggestions

P2

  • per-expert 模式把 raw stacked 键排除出 copy-out 白名单,依赖未经真 wheel 验证的上游过滤时机 @ rtp_llm/model_loader/loader.py:576
    • 建议:在该函数注释里把「上游先 split 后 filter」标注为显式契约假设,并把已安装 wheel 契约测试从「只校验签名」扩展到「同时装配 dim0_split_templates + local_copyout_filter 时 raw 键不会被提前丢弃、stacked 张量仍被切分投递」;再补一例 FakeAutoLoader 声明了 dim0_split_templatesiterate_weights 仍返回 raw 键的交叉场景,断言期望行为。保守替代方案是 per-expert 也并入 stacked_key_config.keys(),让过滤时机差异不再影响正确性。另建议给 loader.py:731 的兜底计数加 WARNING 阈值,让大面积静默回退可被告警发现。
  • 取消 3-shard 下限后,上游预估失真会把优雅降级变成加载期 OOM @ rtp_llm/model_loader/loader.py:425
    • 建议:为 per-expert 也保留一个可关闭的保守下限(例如 max(upstream_estimate, max_file_size))或可配安全系数;至少在采纳值明显小于单个 shard 时打 WARNING,并同时打印上游原值与最终采用值,把「上游可能低估」的风险前置到启动日志。同步在文档该段补一句双向说明:上游估计小于历史 3 × max checkpoint shard 时 AUTO 准入会比旧版更宽松,可通过 fastsafetensor memory checktransient_mem 字段核对实际生效预算。
  • AutoLoader 能力探测重复两份,database 侧降级分支与已固定的 copy-out 键集合不自洽 @ rtp_llm/model_loader/loader.py:645
    • 建议:保留单一决策点:由 ModelLoader._resolve_fastsafetensors_mode 决定最终 mode,fastsafetensors_weights_iterator 只消费传入的 stacked_moe_mode;若必须保留 database 侧防御,则应在降级时直接 raise(或回传实际 mode 供上层重建键集合并重打告警),而不是在键集合已固定的情况下静默换路。
  • _build_stacked_key_configdatabase=None 默认分支语义相反且存在无效计算 @ rtp_llm/model_loader/loader.py:540
    • 建议:把 database 改为必填(或直接读 self._load_config.database 并去掉静态方法),删除易误用的 None 兜底并同步更新四处单参测试调用;把 _raw_stacked_tensor_names 的调用移到跳过判断之后并与 _has_raw_stacked_tensors 合并计算,使「是否登记 stacked 键」与 get_tensor_names / _load_raw_tensor 共享唯一判据来源。
  • 新增策略测试全量 mock,两个 P0 恰落在被 mock 的加载边界上 @ rtp_llm/model_loader/test/test_fastsafetensors_loader_policy.py:54
    • 建议:补一个 CPU-only 端到端用例:构造真实 MoeAtomicWeight(stacked_ckpt_keys=True),用 get_tensor_names 产出的键建 TensorCollector,逐个逻辑 expert 键 store_tensor 后调用 weight.load(collector, ...),断言输出 shape 与 DatabaseTensorSource 路径一致——该用例可直接把两个 P0 钉死,成本很低。再补一个闭包不变量用例:把 _build_stacked_key_config 的模板按 range(expert_num) 展开,断言覆盖全部被选 expert 且是 get_tensor_names() 的子集。
  • 已安装 wheel 契约测试在其 target 中必然 skip,被删除的版本门禁无等价替代 @ rtp_llm/utils/test/ckpt_database_test.py:413
    • 建议:拆出一个能真正跑起来的 target(srcs/main 复用 ckpt_database_test.pyargs = ["InstalledFastsafetensorsContractTest"]),deps 追加 fastsafetensors requirement 别名(rtp_llm/models_py/standalone/BUILD:4 有可复用范式,新增策略测试已通过 py_standalone_testlib 拿到该 wheel),并显式 env = {"RTP_LLM_EXPECT_FASTSAFETENSORS_TIER": "per-expert"},使能力缺失按文档意图构成打包失败。若暂不打算强约束,请在文档中明确该守卫尚未接入 CI。
  • tier 分类自行实现且与生产判据分叉,也不校验 AutoLoader 真实调用形状 @ rtp_llm/utils/test/ckpt_database_test.py:428
    • 建议:契约测试直接复用 _callable_accepts_keyword 判定各关键字,使档位分类与生产降级同源;并补形状断言:校验 __init__ 前两个位置参数的名称与顺序、device 可作关键字传入、iterate_weights / close 为可调用属性。若允许构造成本,可用一个最小 safetensors 文件加 SingleGroup 做一次真实构造 + iterate_weights() + close() 冒烟。同时建议评估把 TypeError 纳入 _fastsafetensors_capability_error 的捕获集合,让上游签名漂移表现为降级而非启动崩溃。
  • assertLogs 的 level 是捕获下限,「包缺失记 INFO」的分级承诺未被真正校验 @ rtp_llm/model_loader/test/test_fastsafetensors_loader_policy.py:438
    • 建议:改为断言精确级别,例如捕获后 self.assertEqual([r.levelname for r in logs.records], [level]),或对目标记录单独比较 levelname,使级别回归可被 CI 发现。
  • 文档承诺的 falls back to scratch 标记不覆盖内存预检与 AUTO 前置条件回退 @ docs/backend/server_arguments.md:226
    • 建议:二选一并保持前后一致:(a)在 loader.py:284-289 与 :309-314 两条 warning 末尾补上同一标记,并为 AUTO 前置条件不满足分支补一条同格式日志,使该标记成为真正可 grep 的运维契约;或(b)把本文档与 docs/release/breaking-changes.md:29-30 的该句收窄为「能力/包相关的 scratch 回退含该标记」,并显式列出 memory-preflight-failedfull-stacked-memory-preflight-failed 两个 degraded_reason 取值,说明前置条件不满足只能依据 load method: 日志判断。
  • 文档称内存预检同样约束显式 fastsafetensors,实际默认 per-expert 完全跳过预检 @ docs/backend/server_arguments.md:216
    • 建议:按路径分别说明,不要把 auto 的行为推广到显式路径:明确预检只在 auto 选路时、以及显式请求且生效模式为 full-stacked 时执行;显式 LOAD_METHOD=fastsafetensors 且生效模式为 per-expert 时出于尊重用户显式请求不做显存降级,因此不会出现 fastsafetensor memory check 日志,需要兜底请用 autoLOAD_METHOD=scratch。若产品意图本就是显式路径也要兜底,则应修改 loader.py:305-308 的短路条件而非仅改文档。
  • 文档要求「安装匹配的 wheel」却无版本锚点,且各平台 pin 版本不一致 @ docs/backend/server_arguments.md:228
    • 建议:在该段写出提供各档位(per-expert / local_copyout_filter)所需的最低 fastsafetensors 版本,并说明当前各平台 pin 各自落在哪一档;若 cuda12_9 与 cuda13/arm 不同档,需显式点出平台差异及其显存影响,必要时同步 bump cuda12_9 的 pin。同时在需要 per-expert 的 CI 目标固定设置 RTP_LLM_EXPECT_FASTSAFETENSORS_TIER,让版本漂移在构建/测试阶段暴露而非依赖人读文档。

P3

  • 跨模块导入下划线私有符号,通用反射工具放错层 @ rtp_llm/model_loader/loader.py:30
    • 建议:把 mode 常量与 _normalize_* / _apply_* 收敛到一个独立的 fastsafetensors 策略模块(或去掉下划线成为该模块公开 API)由 loader 与 database 共同依赖;_callable_accepts_keyword 移入 rtp_llm/utils 下的通用工具模块,并在 _apply_fastsafetensors_env_compat 的 docstring 中醒目标注其进程级副作用。MoeAtomicWeight 侧建议把被三处复用的判据提升为公开方法(与 P0 的修复合并进行)。
  • 假 fastsafetensors 模块直接改写全局 sys.modules,隔离方式脆弱 @ rtp_llm/utils/test/ckpt_database_test.py:27
    • 建议:把 helper 改为返回作用域精确的 patcher(内部 patch.dict(sys.modules, {"fastsafetensors": module}),调用方 addCleanup(patcher.stop)),或让它接收 testcase 并自行 addCleanup,使安装与还原成对出现;同时移除 setUp 中对整个 sys.modules 的快照式还原。
  • tier 契约测试为精确相等断言,文档却表述为「仅更低档位会失败」 @ docs/backend/server_arguments.md:231
    • 建议:改为精确匹配语义的表述(「与期望值做精确断言,任何不一致(含实际高于期望)都会失败」),并补充:若只想做最低门槛校验,应把期望值设为实际部署的目标 tier,或在测试侧改为 tier 序关系断言。
  • 取值边界与 per-expert 投递机制的文档表述不够精确 @ docs/backend/server_arguments.md:288
    • 建议:把 :288-290 改为「去除首尾空白后为空则取默认值;其余不等于 per-expert / full-stacked 的取值抛 ValueError」。把 :262-264 改为描述意图与委托关系,例如「默认通过 dim0_split_templates 请求上游 AutoLoader 以有界显存逐 expert 投递,具体切片与 broadcast 时序由所安装的 fastsafetensors 版本决定」,避免把上游实现细节固化为 RTP 的对外承诺而随上游升级静默失真。
  • 能力表未说明缺失 local_copyout_filter 档位的显存代价,预算也未补偿 @ docs/backend/server_arguments.md:222
    • 建议:在能力表下方补一句:缺失 local_copyout_filter 时所有 rank 会物化全部 tensor,峰值显存高于 rank-local copy-out 档位,且当前内存预检不为该档位追加预算;显存紧张的部署应优先升级 wheel 或改用 LOAD_METHOD=scratch
  • _has_raw_stacked_tensors 的多 ckpt weight「全存在」语义缺少边界覆盖 @ rtp_llm/model_loader/test/test_fastsafetensors_loader_policy.py:477
    • 建议:补一个 weights=[CkptWeightInfo("...w_gate"), CkptWeightInfo("...w_up")]has_tensor 仅对其中之一返回 True 的用例,断言 get_tensor_names 回退到原始 ckpt 名而非逻辑 per-expert 名,并断言该 atomic weight 不会进入 _build_stacked_key_config 结果,把 all() 语义钉死。
  • UE8M0 broadcast shim 的适用性断言外移为对上游 AutoLoader 的假设 @ rtp_llm/utils/torch_patch.py:37
    • 建议:把该假设显式化为可检测项:或在 shim 处同样包装 scatter / all_gather(同为零拷贝 uint8 reinterpret,代价极低),或在已安装 wheel 契约测试中加一条针对 UE8M0 传输路径的断言/冒烟,并把 fastsafetensors 版本纳入注释中的验证范围说明,使上游升级时该假设失效能被发现而非表现为多 rank 加载崩溃。

Checklist Findings (17 fail / 48 total)

General Principles Checklist

  • [6.1] Architecture — 依赖方向:无循环依赖/跨层惊喜 → issue 跨模块导入下划线私有符号,通用反射工具放错层
    _loader.py:25-33 从 rtp_llm.utils.database 导入三个下划线私有函数(_apply_fastsafetensors_env_compat_callable_accepts_keyword_normalize_fastsafetensors_stacked_moe_mode)。其中 _callable_accepts_keyword 是与 checkpoint database 无关的通用签名反射工具,放在 database.py 造成层次错位;_apply_fastsafetensors_env_compat 会进程级改写 FASTSAFETENSORS_CONFIG_JSON(database.py:29-43),跨模块调用时副作用不易发现。同时 loader.py:545-547 与 per_channel_fp8_quant_weight.py:811-817 直接调用 MoeAtomicWeight_raw_stacked_tensor_names / `has_raw_stacked_te
  • [6.1] Architecture — 兼容性:外部 HTTP/RPC API、持久数据、配置、环境迁移安全 → issue UE8M0 broadcast shim 的适用性断言外移为对上游 AutoLoader 的假设
    torch_patch.py:36-39 的注释断言「Scatter is not exercised by fastsafetensors -- AutoLoader routes UE8M0 transfers through pg.broadcast; only the broadcast wrapper is needed」,据此只 patch 了 torch.distributed.broadcast(:68-77)。本 PR 把 loader 构造完全交给上游 AutoLoader(database.py:465-470),该「只走 broadcast」的传输路径成了纯上游实现假设。版本闸门(:54-65)只校验 torch 主次版本,不校验 fastsafetensors 版本,也没有任何测试覆盖多 rank UE8M0 路径;若上游改用 scatter / all_gather 投递 UE8M0 权重 scale,多 rank 加载会以 NCCL「data type is not supported」失败,而不会命中该 shim。
  • [6.1] Architecture — 分层边界:新概念在正确层级,不泄漏内部 → issue 跨模块导入下划线私有符号,通用反射工具放错层
    _loader.py:25-33 从 rtp_llm.utils.database 导入三个下划线私有函数(_apply_fastsafetensors_env_compat_callable_accepts_keyword_normalize_fastsafetensors_stacked_moe_mode)。其中 _callable_accepts_keyword 是与 checkpoint database 无关的通用签名反射工具,放在 database.py 造成层次错位;_apply_fastsafetensors_env_compat 会进程级改写 FASTSAFETENSORS_CONFIG_JSON(database.py:29-43),跨模块调用时副作用不易发现。同时 loader.py:545-547 与 per_channel_fp8_quant_weight.py:811-817 直接调用 MoeAtomicWeight_raw_stacked_tensor_names / `has_raw_stacked_te
  • [6.1] Architecture — 可观测性:日志/指标/超时可操作、非噪声 → issue 文档承诺的 falls back to scratch 标记不覆盖内存预检与 AUTO 前置条件回退
    文档 :226-227 声明「A scratch fallback contains falls back to scratch」,把该字符串定义为识别所有 scratch 回退的可 grep 统一标记,docs/release/breaking-changes.md:29-30 有同义表述。但实现中只有能力/包/import 类降级带该标记(loader.py:512-516)。两条内存预检回退分别只输出 degraded_reason=memory-preflight-failed(loader.py:284-289)与 full-stacked-memory-preflight-failed(loader.py:309-314),均不含该标记;AUTO 前置条件不满足(非 safetensor、convert_device == "cpu"、张量重名,loader.py:271-292)时完全不打降级日志。运维按文档 grep 做告警会系统性漏掉显存驱动与前置条件驱动的 scratch 回退,而这恰是加载性能回退最常见的原因。
  • [6.1] Architecture — 回滚路径:风险行为存在运维回滚手段 → issue 能力表未说明缺失 local_copyout_filter 档位的显存代价,预算也未补偿
    文档 :222 能力表把缺失 local_copyout_filter 的后果仅写为 full materialization, RTP consumer filtering,未说明这意味着每个 rank 都会在设备上物化全部 tensor(database.py:454-459 的 warning 印证),TP/EP 越大峰值显存代价越明显。同时 _fastsafetensors_transient_budget_bytes(loader.py:446-451)只为 full-stacked 追加一个 shard,对该 consumer-filter 档位不做任何预算补偿,AUTO 可能以偏低的 transient_mem 放行;:217 的 package age alone does not fail model startup 也未提示这一显存代价。
  • [6.1] Architecture — 状态不变量:创建/更新/失败/重试/回滚路径有效 → issue AutoLoader 能力探测重复两份,database 侧降级分支与已固定的 copy-out 键集合不自洽
    能力探测有两处实现:loader.py:472 的 _fastsafetensors_capability_error,以及 database.py:419-430 fastsafetensors_weights_iterator 内的同名 dim0_split_templates 检查。后者在缺该能力时自行把 per-expert 降级为 full-stacked,但此刻 required_checkpoint_keys(loader.py:645-647)已按 per-expert 构造(不含 raw stacked 键),并已作为 local_copyout_filter 传给 AutoLoader(database.py:452-453),上游会把整块 stacked 张量过滤掉;loader.py:638-643 的 full-stacked 高显存告警也不会打出。当前两处判据完全相同故该分支不可达,但任一侧改动即产生静默错误加载。
  • [6.1] Architecture — 错误语义:fail-fast/retry/fallback/silent 行为显式 → issue 文档称内存预检同样约束显式 fastsafetensors,实际默认 per-expert 完全跳过预检
    文档 :214-217 把「an insufficient memory preflight falls back to scratch」与包缺失、import/ABI 失败并列,紧接着声明「These compatibility paths apply to both auto and an explicit LOAD_METHOD=fastsafetensors」,:250 又让运维「Inspect the fastsafetensor memory check log and its enough field」。但 loader.py:305-308 中显式路径的预检被 stacked_moe_mode == FULL_STACKED 短路:生效模式为默认 per-expert 时 _is_memory_enough_for_fastsafetensor 根本不会被调用(直接走 :316),既不回退 scratch,也不会打印该预检日志。显存紧张节点上按文档预期存在兜底,实际会直接进入加载并可能 OOM 且无预检日志可查。
  • [6.1] Software Engineering — DRY:重复非平凡逻辑被抽取或显式复用 → issue tier 分类自行实现且与生产判据分叉,也不校验 AutoLoader 真实调用形状
    :428-434 用 inspect.signature(auto_loader.__init__).parametersnot in parameters 自行分档;生产走 _callable_accepts_keyword(database.py:74-89),额外要求参数 kind 属于 POSITIONAL_OR_KEYWORD / KEYWORD_ONLY。对 positional-only 签名两者结论相反:测试报 per-expert,生产降级为 full-stacked。该用例也从不构造 AutoLoader、不校验 iterate_weights / close,而生产调用形状是 AutoLoader(pg, hf_weights_files, device=device, **kwargs) 并在 finallyclose()(database.py:465-476)。若上游改名/重排前两个位置参数或改名 close(),tier 仍判 per-expert,而真实加载抛 TypeError / `
  • [6.1] Software Engineering — KISS/YAGNI:无投机性抽象 → issue ``_build_stacked_key_configdatabase=None` 默认分支语义相反且存在无效计算`
    _唯一生产调用方(loader.py:629-631)总是显式传入 `self._load_config.database`;`database=None` 分支只有既有测试(test_inline_fp8_quant.py:131、test_stacked_moe_weight.py:252/279/297 均为单参调用)与潜在误用会触达。两条分支语义相反:传库时跳过 ckpt 中不存在 raw stacked 张量的权重,不传库时对同一批权重全部登记,从而生成会被上游当作 `dim0_split_templates` 使用的错误键。此外 :545 的 `_raw_stacked_tensor_names` 在 :546-549 的跳过判断之前先行计算,而 `has_raw_stacked_tensors` 内部又重算一次,属无效开销。
  • [6.1] Tests — 分布式/跨平台变更有对应覆盖 → issue UE8M0 broadcast shim 的适用性断言外移为对上游 AutoLoader 的假设
    torch_patch.py:36-39 的注释断言「Scatter is not exercised by fastsafetensors -- AutoLoader routes UE8M0 transfers through pg.broadcast; only the broadcast wrapper is needed」,据此只 patch 了 torch.distributed.broadcast(:68-77)。本 PR 把 loader 构造完全交给上游 AutoLoader(database.py:465-470),该「只走 broadcast」的传输路径成了纯上游实现假设。版本闸门(:54-65)只校验 torch 主次版本,不校验 fastsafetensors 版本,也没有任何测试覆盖多 rank UE8M0 路径;若上游改用 scatter / all_gather 投递 UE8M0 权重 scale,多 rank 加载会以 NCCL「data type is not supported」失败,而不会命中该 shim。
  • [6.1] Tests — 新逻辑有聚焦单测 + 相关集成/smoke 测试 → issue 假 fastsafetensors 模块直接改写全局 sys.modules,隔离方式脆弱
    _install_fake_fastsafetensors 是模块级 helper,内部直接执行 sys.modules["fastsafetensors"] = module(:33)且自身不做还原,完全依赖 FastsafetensorsAutoLoaderTest.setUp(:107-110)的 patch.dict(sys.modules, {}, clear=False) 兜底。该还原方式退出时会先清空整个 sys.modules 再灌回快照,测试体内新导入的模块会被逐出并重跑模块级副作用。任何未带同等 patch 的新测试类若调用该 helper,假模块会泄漏到 InstalledFastsafetensorsContractTest.setUp(:409-411),使真实 wheel 契约检查以断言失败收场,掩盖真正问题。
  • [6.1] Tests — 被删除测试有等价替代覆盖 → issue 已安装 wheel 契约测试在其 target 中必然 skip,被删除的版本门禁无等价替代
    _test_available_auto_loader_contract_is_classified 仅在 RTP_LLM_EXPECT_FASTSAFETENSORS_TIER 非空时把低档位判为失败,否则 skipTest(:419-422、:441-442)。该用例只存在于 //rtp_llm/utils/test:ckpt_database_test,其 deps 为 utils/config/ft_pickler/lora(utils/test/BUILD:95-100),而 //rtp_llm:utils(rtp_llm/BUILD:159-177)不含 fastsafetensors requirement,故 import fastsafetensors(:416)在沙箱内必然 ImportError。全仓检索确认该环境变量仅出现在文档 :230 与用例 :414,无任何 target 或 CI 脚本设置它;同时 _REQUIRED_FST_VERSION 硬版本门已随本 PR 删除(零残留),wheel 能力漂移在 CI 中因此完全无拦截。
  • [6.1] Tests — 边界 case 覆盖(空、单元素、最大值) → issue ``_has_raw_stacked_tensors 的多 ckpt weight「全存在」语义缺少边界覆盖
    _ffn_weight.py:379-383 的语义是 `bool(names) and all(tensor_source.has_tensor(name) for name in names)`,即同一 atomic weight 的全部 raw 键都必须存在才走逻辑 per-expert 键,该判定同时影响 `build_stacked_key_config`(loader.py:546-549)。但新增用例只覆盖单个 ckpt weight(:477-496,断言 `has_tensor` 恰好调用一次)与不同 atomic weight 之间的混合情形(:498-526);「同一 atomic weight 含 w_gate/w_up 两个 ckpt weight、其中一个 raw 张量缺失」这一 `all()` 关键边界没有任何用例。

RTP-LLM Checklist

  • [I] 代码质量 — 同一功能用统一工具函数 → issue 跨模块导入下划线私有符号,通用反射工具放错层
    _loader.py:25-33 从 rtp_llm.utils.database 导入三个下划线私有函数(_apply_fastsafetensors_env_compat_callable_accepts_keyword_normalize_fastsafetensors_stacked_moe_mode)。其中 _callable_accepts_keyword 是与 checkpoint database 无关的通用签名反射工具,放在 database.py 造成层次错位;_apply_fastsafetensors_env_compat 会进程级改写 FASTSAFETENSORS_CONFIG_JSON(database.py:29-43),跨模块调用时副作用不易发现。同时 loader.py:545-547 与 per_channel_fp8_quant_weight.py:811-817 直接调用 MoeAtomicWeight_raw_stacked_tensor_names / `has_raw_stacked_te

Python Static-First Checklist

  • [P.F] 语言陷阱 — 禁止模块级 import 副作用 → issue 假 fastsafetensors 模块直接改写全局 sys.modules,隔离方式脆弱
    _install_fake_fastsafetensors 是模块级 helper,内部直接执行 sys.modules["fastsafetensors"] = module(:33)且自身不做还原,完全依赖 FastsafetensorsAutoLoaderTest.setUp(:107-110)的 patch.dict(sys.modules, {}, clear=False) 兜底。该还原方式退出时会先清空整个 sys.modules 再灌回快照,测试体内新导入的模块会被逐出并重跑模块级副作用。任何未带同等 patch 的新测试类若调用该 helper,假模块会泄漏到 InstalledFastsafetensorsContractTest.setUp(:409-411),使真实 wheel 契约检查以断言失败收场,掩盖真正问题。
  • [P.G] 测试规范 — mock.patch target 是使用处而非定义处 → issue 假 fastsafetensors 模块直接改写全局 sys.modules,隔离方式脆弱
    _install_fake_fastsafetensors 是模块级 helper,内部直接执行 sys.modules["fastsafetensors"] = module(:33)且自身不做还原,完全依赖 FastsafetensorsAutoLoaderTest.setUp(:107-110)的 patch.dict(sys.modules, {}, clear=False) 兜底。该还原方式退出时会先清空整个 sys.modules 再灌回快照,测试体内新导入的模块会被逐出并重跑模块级副作用。任何未带同等 patch 的新测试类若调用该 helper,假模块会泄漏到 InstalledFastsafetensorsContractTest.setUp(:409-411),使真实 wheel 契约检查以断言失败收场,掩盖真正问题。
  • [P.G] 测试规范 — mock/fake/stub 不得替代本次声称覆盖的生产边界 → issue tier 分类自行实现且与生产判据分叉,也不校验 AutoLoader 真实调用形状
    :428-434 用 inspect.signature(auto_loader.__init__).parametersnot in parameters 自行分档;生产走 _callable_accepts_keyword(database.py:74-89),额外要求参数 kind 属于 POSITIONAL_OR_KEYWORD / KEYWORD_ONLY。对 positional-only 签名两者结论相反:测试报 per-expert,生产降级为 full-stacked。该用例也从不构造 AutoLoader、不校验 iterate_weights / close,而生产调用形状是 AutoLoader(pg, hf_weights_files, device=device, **kwargs) 并在 finallyclose()(database.py:465-476)。若上游改名/重排前两个位置参数或改名 close(),tier 仍判 per-expert,而真实加载抛 TypeError / `

Strengths

  • _raw_stacked_tensor_names(ffn_weight.py:364-377)显式排除含 {expert_id} 的模板,修掉了旧代码对 per-expert 布局调用 tensor_name() 会抛 KeyError(或把 expert 0 误判为 stacked 张量)的真实缺陷,并把此前四处内联的 self.weights[0].tensor_name(layer_id) 收敛为单一判据,注释把动机写清楚了;test_per_expert_template_never_probes_raw_stacked_key 锁定该修复,上一轮 P1 确认已解决。
  • 删除了依赖上游约 9 个私有内部结构(fb._get_rank_lidxfb.instantiatedfactory.free_dev_ptrs 等)与硬编码 _REQUIRED_FST_VERSION="0.1.19"PerExpertParallelLoader。全仓检索确认 PerExpertParallelLoader / per_expert_parallel_loader / _REQUIRED_FST_VERSION 零残留(BUILD 用 glob(["*.py"]) 自动排除),并提供替代实现、迁移说明与双回滚路径,满足 R.I.2。
  • 把版本号前缀硬失败改为 inspect.signature 能力探测后,旧 wheel 表现为按档位降级而非启动失败;三级降级与 requested_mode / effective_mode / degraded_reason 结构化字段设计得当,「包未安装记 INFO、其余降级记 WARNING」的分级避免了噪声告警。
  • _fastsafetensors_transient_budget_bytes(loader.py:388-458)对上游 estimated_peak_device_bytes 做了完整脏值防御(Nonebool 特判、非数值、非有限、非正),test_invalid_estimates_use_three_max_filessubTest 覆盖 None/0/-1/"8192"/inf/True 六类边界,把 isinstance(True, int) 这一经典陷阱显式钉住。
  • _callable_accepts_keyword(database.py:74-89)明确拒绝把 **kwargs 当成能力声明,避免兼容层静默丢弃优化关键字后被误判为高阶能力,并有专门用例锁定;ckpt_database_test.py:250-257untyped_storage().data_ptr() 断言 full-stacked 路径真的 clone 而非返回视图,精准守护了「loader 可能在批次推进后释放 batch buffer」这一关键不变量。
  • 文档把 RTP_FASTSAFETENSORS_STACKED_MOE_MODE 明确定位为过渡开关(env-only、不进 --help、不进 config dump、非法值抛 ValueError),并如实写出 FASTSAFETENSORS_NOGDS=1 会进程级覆写 FASTSAFETENSORS_CONFIG_JSON 且对同进程后续 loader 持续生效(server_arguments.md:252-260 与 database.py:29-43 一致);对上游不由 RTP 保证的 precedence 诚实标注为 upstream contract,未过度承诺。
  • 新增策略用例通过 env = {"CUDA_VISIBLE_DEVICES": ""} 保持 CPU-only(model_loader/test/BUILD:5-10),把选路策略从 GPU 独占目标中剥离为可确定性运行的用例,与同目录既有约定一致。

Comment thread rtp_llm/model_loader/ffn_weight.py Outdated
Comment thread rtp_llm/model_loader/per_channel_fp8_quant_weight.py Outdated

@LLLLKKKK LLLLKKKK left a comment

Copy link
Copy Markdown
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

AI Code Review - PR #1354 (non-blocking suggestions)

18 条 P2/P3 建议,不阻塞合并。阻塞判定与完整摘要见上一条 review。

where RTP expands it after AutoLoader yields the complete tensor.
"""

keys = set(tensor_to_weight_map.keys())

Copy link
Copy Markdown
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

[P2] per-expert 模式把 raw stacked 键排除出 copy-out 白名单,依赖未经真 wheel 验证的上游过滤时机

_build_fastsafetensors_local_copyout_keys 仅在 full-stacked 模式把 raw stacked 键并入白名单(:577-579),per-expert 刻意排除,test_fastsafetensors_loader_policy.py:30-40 还断言结果不含 "stacked.raw"。这隐含假定上游 AutoLoader 先按 dim0_split_templates 展开、再对展开后的逻辑名调用 local_copyout_filter(database.py:460-464 把展开完全交由上游)。若上游实际先在 raw checkpoint 键上过滤,整块 stacked MoE 张量会被丢弃,所有 MoE 权重静默落回 loader.py:726-750 的 database 兜底,优化完全失效且线索只有 :735 一条 INFO。该语义目前只被 patch.dict(sys.modules, ...) 的 fake module 覆盖,且过滤集合随 EP rank 变化,无多 rank 覆盖。

建议: 在该函数注释里把「上游先 split 后 filter」标注为显式契约假设,并把已安装 wheel 契约测试从「只校验签名」扩展到「同时装配 dim0_split_templates + local_copyout_filter 时 raw 键不会被提前丢弃、stacked 张量仍被切分投递」;再补一例 FakeAutoLoader 声明了 dim0_split_templatesiterate_weights 仍返回 raw 键的交叉场景,断言期望行为。保守替代方案是 per-expert 也并入 stacked_key_config.keys(),让过滤时机差异不再影响正确性。另建议给 loader.py:731 的兜底计数加 WARNING 阈值,让大面积静默回退可被告警发现。

)
budget = legacy_budget
else:
budget = int(estimate)

Copy link
Copy Markdown
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

[P2] 取消 3-shard 下限后,上游预估失真会把优雅降级变成加载期 OOM

原判据固定为 (free_mem - model_mem) > 3 × max_shard。改动后只要上游 estimated_peak_device_bytes 为任意正数即整体替换该阈值,日志明确写 accepts positive upstream estimate without applying the legacy floor(:426-431)。若上游值只统计 loader 自有 buffer,未计入 RTP 侧 expert clone()(database.py:115)与 inline FP8 临时张量,AUTO 会把原本回退 scratch 的部署放行,失败形态从「自动降级」退化为加载期 CUDA OOM。per-expert 无任何下限保护,只有 full-stacked 才追加一份 max_file_size(:446-451)。文档 server_arguments.md:246-250 只描述了收紧方向,未说明该放松方向。

建议: 为 per-expert 也保留一个可关闭的保守下限(例如 max(upstream_estimate, max_file_size))或可配安全系数;至少在采纳值明显小于单个 shard 时打 WARNING,并同时打印上游原值与最终采用值,把「上游可能低估」的风险前置到启动日志。同步在文档该段补一句双向说明:上游估计小于历史 3 × max checkpoint shard 时 AUTO 准入会比旧版更宽松,可通过 fastsafetensor memory checktransient_mem 字段核对实际生效预算。

"or use LOAD_METHOD=scratch for the conservative rollback"
)

required_checkpoint_keys = self._build_fastsafetensors_local_copyout_keys(

Copy link
Copy Markdown
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

[P2] AutoLoader 能力探测重复两份,database 侧降级分支与已固定的 copy-out 键集合不自洽

能力探测有两处实现:loader.py:472 的 _fastsafetensors_capability_error,以及 database.py:419-430 fastsafetensors_weights_iterator 内的同名 dim0_split_templates 检查。后者在缺该能力时自行把 per-expert 降级为 full-stacked,但此刻 required_checkpoint_keys(loader.py:645-647)已按 per-expert 构造(不含 raw stacked 键),并已作为 local_copyout_filter 传给 AutoLoader(database.py:452-453),上游会把整块 stacked 张量过滤掉;loader.py:638-643 的 full-stacked 高显存告警也不会打出。当前两处判据完全相同故该分支不可达,但任一侧改动即产生静默错误加载。

建议: 保留单一决策点:由 ModelLoader._resolve_fastsafetensors_mode 决定最终 mode,fastsafetensors_weights_iterator 只消费传入的 stacked_moe_mode;若必须保留 database 侧防御,则应在降级时直接 raise(或回传实际 mode 供上层重建键集合并重打告警),而不是在键集合已固定的情况下静默换路。

Checklist: [6.1] 状态不变量:创建/更新/失败/重试/回滚路径有效


@staticmethod
def _build_stacked_key_config(weight_info_list) -> dict:
def _build_stacked_key_config(weight_info_list, database=None) -> dict:

Copy link
Copy Markdown
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

[P2] _build_stacked_key_configdatabase=None 默认分支语义相反且存在无效计算

唯一生产调用方(loader.py:629-631)总是显式传入 self._load_config.databasedatabase=None 分支只有既有测试(test_inline_fp8_quant.py:131、test_stacked_moe_weight.py:252/279/297 均为单参调用)与潜在误用会触达。两条分支语义相反:传库时跳过 ckpt 中不存在 raw stacked 张量的权重,不传库时对同一批权重全部登记,从而生成会被上游当作 dim0_split_templates 使用的错误键。此外 :545 的 _raw_stacked_tensor_names 在 :546-549 的跳过判断之前先行计算,而 _has_raw_stacked_tensors 内部又重算一次,属无效开销。

建议:database 改为必填(或直接读 self._load_config.database 并去掉静态方法),删除易误用的 None 兜底并同步更新四处单参测试调用;把 _raw_stacked_tensor_names 的调用移到跳过判断之后并与 _has_raw_stacked_tensors 合并计算,使「是否登记 stacked 键」与 get_tensor_names / _load_raw_tensor 共享唯一判据来源。

Checklist: [6.1] KISS/YAGNI:无投机性抽象

frozenset({"direct.weight", "expanded.experts.0", "stacked.raw"}),
)

def test_rank_local_copyout_filter_and_mode_are_forwarded(self):

Copy link
Copy Markdown
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

[P2] 新增策略测试全量 mock,两个 P0 恰落在被 mock 的加载边界上

test_rank_local_copyout_filter_and_mode_are_forwardedobject.__new__(ModelLoader) 绕过构造,把 _build_stacked_key_config_create_model_weights_generate_weight_infoweight.load 全部替换为 MagicMock(:55-90),只能验证参数透传。新增的 636 行用例中没有任何一个用真实 MoeAtomicWeight + 真实 TensorCollector 走通一次完整加载,而本次两个 P0 恰好落在 weight.load_load_raw_tensor 这条被 mock 掉的边界上。copy-out 键与逻辑键的闭包也只由独立字面量断言分别维护(:31 用合成键 {"stacked.raw": ...},:492/:525 各自钉住真实键与模板),没有一条用例把「真实 MoE weight → stacked_key_config → copy-out 集...

建议: 补一个 CPU-only 端到端用例:构造真实 MoeAtomicWeight(stacked_ckpt_keys=True),用 get_tensor_names 产出的键建 TensorCollector,逐个逻辑 expert 键 store_tensor 后调用 weight.load(collector, ...),断言输出 shape 与 DatabaseTensorSource 路径一致——该用例可直接把两个 P0 钉死,成本很低。再补一个闭包不变量用例:把 _build_stacked_key_config 的模板按 range(expert_num) 展开,断言覆盖全部被选 expert 且是 get_tensor_names() 的子集。

Comment thread docs/backend/server_arguments.md Outdated
`RTP_FASTSAFETENSORS_STACKED_MOE_MODE` is a transitional, environment-only
switch: it has no command-line flag, is not shown by `--help`, and is not part
of the startup config dump. It is read only when the FastSafeTensors path is
considered. Values are case-sensitive and use a hyphen; any non-empty value

Copy link
Copy Markdown
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

[P3] 取值边界与 per-expert 投递机制的文档表述不够精确

两处偏差。其一,:288-290 称「any non-empty value other than per-expert or full-stacked raises ValueError」,但 _normalize_fastsafetensors_stacked_moe_mode(database.py:59-63)先 strip(),纯空白值(如 " ")虽属 non-empty 却回落默认值而不抛错。其二,:262-264 把「source rank 先切片、各 rank 逐 expert broadcast」写成 RTP 的行为,但本 PR 已删除自实现的 per-expert loader,现在仅通过 database.py:460-464 的 dim0_split_templates 委托上游 AutoLoader,切片与 broadcast 时序不再由 RTP 决定。

建议: 把 :288-290 改为「去除首尾空白后为空则取默认值;其余不等于 per-expert / full-stacked 的取值抛 ValueError」。把 :262-264 改为描述意图与委托关系,例如「默认通过 dim0_split_templates 请求上游 AutoLoader 以有界显存逐 expert 投递,具体切片与 broadcast 时序由所安装的 fastsafetensors 版本决定」,避免把上游实现细节固化为 RTP 的对外承诺而随上游升级静默失真。


| Capability | Present | Missing |
|---|---|---|
| `local_copyout_filter` | rank-local copy-out | full materialization, RTP consumer filtering |

Copy link
Copy Markdown
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

[P3] 能力表未说明缺失 local_copyout_filter 档位的显存代价,预算也未补偿

文档 :222 能力表把缺失 local_copyout_filter 的后果仅写为 full materialization, RTP consumer filtering,未说明这意味着每个 rank 都会在设备上物化全部 tensor(database.py:454-459 的 warning 印证),TP/EP 越大峰值显存代价越明显。同时 _fastsafetensors_transient_budget_bytes(loader.py:446-451)只为 full-stacked 追加一个 shard,对该 consumer-filter 档位不做任何预算补偿,AUTO 可能以偏低的 transient_mem 放行;:217 的 package age alone does not fail model startup 也未提示这一显存代价。

建议: 在能力表下方补一句:缺失 local_copyout_filter 时所有 rank 会物化全部 tensor,峰值显存高于 rank-local copy-out 档位,且当前内存预检不为该档位追加预算;显存紧张的部署应优先升级 wheel 或改用 LOAD_METHOD=scratch

Checklist: [6.1] 回滚路径:风险行为存在运维回滚手段

)
database.has_tensor.assert_not_called()

def test_existing_raw_stacked_tensor_uses_logical_expert_keys(self):

Copy link
Copy Markdown
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

[P3] _has_raw_stacked_tensors 的多 ckpt weight「全存在」语义缺少边界覆盖

ffn_weight.py:379-383 的语义是 bool(names) and all(tensor_source.has_tensor(name) for name in names),即同一 atomic weight 的全部 raw 键都必须存在才走逻辑 per-expert 键,该判定同时影响 _build_stacked_key_config(loader.py:546-549)。但新增用例只覆盖单个 ckpt weight(:477-496,断言 has_tensor 恰好调用一次)与不同 atomic weight 之间的混合情形(:498-526);「同一 atomic weight 含 w_gate/w_up 两个 ckpt weight、其中一个 raw 张量缺失」这一 all() 关键边界没有任何用例。

建议: 补一个 weights=[CkptWeightInfo("...w_gate"), CkptWeightInfo("...w_up")]has_tensor 仅对其中之一返回 True 的用例,断言 get_tensor_names 回退到原始 ckpt 名而非逻辑 per-expert 名,并断言该 atomic weight 不会进入 _build_stacked_key_config 结果,把 all() 语义钉死。

Checklist: [6.1] 边界 case 覆盖(空、单元素、最大值)

# RTP-LLM's ``PerExpertParallelLoader`` route every UE8M0 transfer
# through ``pg.broadcast`` (dim=-1 in fastsafetensors / per-expert
# broadcast in PerExpertParallelLoader); only the broadcast wrapper is
# not exercised by fastsafetensors -- ``AutoLoader`` routes UE8M0

Copy link
Copy Markdown
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

[P3] UE8M0 broadcast shim 的适用性断言外移为对上游 AutoLoader 的假设

torch_patch.py:36-39 的注释断言「Scatter is not exercised by fastsafetensors -- AutoLoader routes UE8M0 transfers through pg.broadcast; only the broadcast wrapper is needed」,据此只 patch 了 torch.distributed.broadcast(:68-77)。本 PR 把 loader 构造完全交给上游 AutoLoader(database.py:465-470),该「只走 broadcast」的传输路径成了纯上游实现假设。版本闸门(:54-65)只校验 torch 主次版本,不校验 fastsafetensors 版本,也没有任何测试覆盖多 rank UE8M0 路径;若上游改用 scatter / all_gather 投递 UE8M0 权重 scale,多 rank 加载会以 NCCL「data type is not supported」失败,而不会命中该 shim。

建议: 把该假设显式化为可检测项:或在 shim 处同样包装 scatter / all_gather(同为零拷贝 uint8 reinterpret,代价极低),或在已安装 wheel 契约测试中加一条针对 UE8M0 传输路径的断言/冒烟,并把 fastsafetensors 版本纳入注释中的验证范围说明,使上游升级时该假设失效能被发现而非表现为多 rank 加载崩溃。

Checklist: [6.1] 兼容性:外部 HTTP/RPC API、持久数据、配置、环境迁移安全;[6.1] 分布式/跨平台变更有对应覆盖

@ABNER-1
ABNER-1 force-pushed the shuxing/dsv4-sleep-level2-fastsafetensors branch from 4e91157 to 66ef2a5 Compare August 31, 2026 14:00

@LLLLKKKK LLLLKKKK left a comment

Copy link
Copy Markdown
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

AI Code Review - PR #1354 (non-blocking suggestions)

5 条 P2/P3 建议,不阻塞合并。阻塞判定与完整摘要见上一条 review。

Comment thread rtp_llm/model_loader/loader.py Outdated
Comment thread docs/backend/server_arguments.md Outdated
self.assertFalse(getattr(installed_module, "_rtp_test_fake", False))

def test_available_auto_loader_contract_is_classified(self) -> None:
expected_tier = os.environ.get("RTP_LLM_EXPECT_FASTSAFETENSORS_TIER")

Copy link
Copy Markdown
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

[P2] 真实 wheel 能力契约在默认测试链路中可被跳过

未设置 RTP_LLM_EXPECT_FASTSAFETENSORS_TIER 时,缺包或低 tier 会跳过;仓库也未设置该变量。测试仅复刻签名分类并检查估算字段,未用真实 wheel 执行过滤、dim0 拆分、迭代及 tensor 生命周期契约。

建议: 增加依赖真实 wheel 且设置最低 tier 的必跑目标,用最小 stacked checkpoint 验证过滤、拆分、数值、所有权和多 rank 路径。

Checklist: [6.1] 分布式/跨平台变更有对应覆盖;[P.G] mock/fake/stub 不得替代本次声称覆盖的生产边界

Comment thread docs/backend/server_arguments.md Outdated
for resolved, level, expected in cases:
with self.subTest(resolved=resolved):
loader._resolve_fastsafetensors_mode = MagicMock(return_value=resolved)
with self.assertLogs(level=level) as logs:

Copy link
Copy Markdown
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

[P2] 日志级别契约未被真正断言,assertLogs 的 level 只是捕获阈值

assertLogs(level=level) 只设置最低捕获等级,随后仅检查消息文本。预期 INFO 的记录变成 WARNING/ERROR,或预期 WARNING 的记录变成 ERROR 时,测试仍会通过。

建议: 显式断言 logs.recordslevelno,并验证各场景不存在意外的更高等级记录。

Checklist: [6.1] 可观测性:日志/指标/超时可操作、非噪声;[6.1] 新逻辑有聚焦单测 + 相关集成/smoke 测试

@ABNER-1
ABNER-1 force-pushed the shuxing/dsv4-sleep-level2-fastsafetensors branch from 0f7c377 to 219491b Compare September 1, 2026 00:37

@LLLLKKKK LLLLKKKK left a comment

Copy link
Copy Markdown
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

AI Code Review - PR #1354

Status: BLOCKING

Summary: P0/0 · P1/2 · P2/6 · P3/0

Reviewed: commit 219491b644ff · 2026-09-01 09:05 UTC+8

Blocking Issues

P1

  • 显存预检丢弃 legacy floor 且未计入 RTP 侧 TensorCollector 常驻显存,默认 AUTO 可能误判可用并在加载期 OOM @ rtp_llm/model_loader/loader.py:425
    • 建议:至少取上游估值与集成侧安全下限的最大值,或显式计入 collector 与最终权重同时存活的峰值,并增加跨 batch 收集大权重的阈值测试。
  • AutoLoader 运行期不兼容不会回退 scratch @ rtp_llm/utils/database.py:417
    • 建议:完整探测基础接口,并在首个模型张量写入前捕获已知导入、构造及 ABI 异常;协调各 rank 关闭资源后回退 scratch,并补充真实构造和首次迭代测试。

Non-blocking Suggestions

P2

  • 无 stacked 权重仍会增加 full-stacked 显存预算 @ rtp_llm/model_loader/loader.py:446
    • 建议:先识别 checkpoint 是否存在原始堆叠键,仅在确实需要 dim0 split 时降级并增加预算;补充 dense 和原生 per-expert 用例。
  • 文档称内存预检同样约束显式 fastsafetensors,实际默认 per-expert 完全跳过预检 @ docs/backend/server_arguments.md:216
    • 建议:分别说明各模式的预检语义,或为显式 per-expert 补齐预检、回退和测试。
  • 真实 wheel 能力契约在默认测试链路中可被跳过 @ rtp_llm/utils/test/ckpt_database_test.py:414
    • 建议:增加依赖真实 wheel、按平台固定预期 tier 的测试目标,并使用小型 checkpoint 验证构造、拆分、过滤和关闭行为。
  • 文档承诺的 falls back to scratch 标记不覆盖两处内存预检回退,consumer-filter 档位也无结构化字段 @ docs/backend/server_arguments.md:226
    • 建议:通过统一日志辅助函数输出所有降级与回退事件,或收窄文档中的结构化日志承诺,并补充完整日志断言。
  • 日志级别契约未被真正断言,assertLogs 的 level 只是捕获阈值 @ rtp_llm/model_loader/test/test_fastsafetensors_loader_policy.py:443
    • 建议:断言 logs.records 中目标记录的 levelname,并隔离无关日志。
  • Inline FP8 测试未验证专家数据和 scale 的对应关系 @ rtp_llm/model_loader/test/test_fastsafetensors_loader_policy.py:575
    • 建议:保存逐 expert 的预期 FP8 tensor 与 scale,并分别校验输出值、顺序和对应关系。

Checklist Findings (9 fail / 104 total)

General Principles Checklist

  • [6.1] Architecture — 兼容性:外部 HTTP/RPC API、持久数据、配置、环境迁移安全 → issue 文档承诺的 falls back to scratch 标记不覆盖两处内存预检回退,consumer-filter 档位也无结构化字段
    AUTO 与显式 full-stacked 的内存回退日志均缺少文档承诺的 falls back to scratch;缺少 local_copyout_filter 时的警告也没有 requested_modeeffective_modedegraded_reason 字段。
  • [6.1] Architecture — 可观测性:日志/指标/超时可操作、非噪声 → issue 日志级别契约未被真正断言,assertLogs 的 level 只是捕获阈值
    assertLogs(level=level) 只设置最低捕获级别,随后测试仅检查消息文本;预期 INFO 的日志改成 WARNING 仍会通过,无法保护文档声明的日志级别契约。
  • [6.1] Architecture — 状态不变量:创建/更新/失败/重试/回滚路径有效 → issue 无 stacked 权重仍会增加 full-stacked 显存预算
    模式解析发生在 stacked_key_config 构建之前,并无条件检查 dim0_split_templates。旧 wheel 会令 dense 或原生 per-expert checkpoint 降级为 full-stacked,即使没有原始堆叠键也额外计入一个最大 shard,可能不必要地回退 scratch
  • [6.1] Architecture — 错误语义:fail-fast/retry/fallback/silent 行为显式 → issue 文档承诺的 falls back to scratch 标记不覆盖两处内存预检回退,consumer-filter 档位也无结构化字段
    AUTO 与显式 full-stacked 的内存回退日志均缺少文档承诺的 falls back to scratch;缺少 local_copyout_filter 时的警告也没有 requested_modeeffective_modedegraded_reason 字段。
  • [6.1] Tests — 分布式/跨平台变更有对应覆盖 → issue 真实 wheel 能力契约在默认测试链路中可被跳过
    默认 BUILD 目标未设置 RTP_LLM_EXPECT_FASTSAFETENSORS_TIER;缺包、能力层级不足或缺少 load_config 时测试均可跳过。其余用例使用伪造 AutoLoader,因此 CI 可能未验证真实 wheel 的构造和迭代契约。
  • [6.1] Tests — 新逻辑有聚焦单测 + 相关集成/smoke 测试 → issue Inline FP8 测试未验证专家数据和 scale 的对应关系
    测试为两个 expert 生成不同 tensor 和 scale,最终却只断言输出形状;重复 expert 0、交换 expert 顺序或关联错误 scale 均不会失败,未覆盖 W2 预量化路径的数值契约。

RTP-LLM Checklist

  • [H] 测试与 CI — mock/fake/stub 只能隔离非目标依赖,不能 stub 掉本次声称覆盖的生产边界;涉及 pybind/C++/runtime 的 bug 必须有真实边界集成或 smoke 覆盖 → issue 真实 wheel 能力契约在默认测试链路中可被跳过
    默认 BUILD 目标未设置 RTP_LLM_EXPECT_FASTSAFETENSORS_TIER;缺包、能力层级不足或缺少 load_config 时测试均可跳过。其余用例使用伪造 AutoLoader,因此 CI 可能未验证真实 wheel 的构造和迭代契约。
  • [H] 测试与 CI — 新增、迁移或删除测试必须证明目标行为仍在 CI 中执行;DISABLED_、#if 0、open_skip、导入即失败、未被 target 引用的用例不得计为覆盖 → issue 真实 wheel 能力契约在默认测试链路中可被跳过
    默认 BUILD 目标未设置 RTP_LLM_EXPECT_FASTSAFETENSORS_TIER;缺包、能力层级不足或缺少 load_config 时测试均可跳过。其余用例使用伪造 AutoLoader,因此 CI 可能未验证真实 wheel 的构造和迭代契约。

Python Static-First Checklist

  • [P.G] 测试规范 — mock/fake/stub 不得替代本次声称覆盖的生产边界 → issue 真实 wheel 能力契约在默认测试链路中可被跳过
    默认 BUILD 目标未设置 RTP_LLM_EXPECT_FASTSAFETENSORS_TIER;缺包、能力层级不足或缺少 load_config 时测试均可跳过。其余用例使用伪造 AutoLoader,因此 CI 可能未验证真实 wheel 的构造和迭代契约。

Strengths

  • 正确区分原始堆叠键与逻辑 expert 键。
  • 移除了对上游私有加载器实现的依赖。
  • 新增模式解析、内存预算、键过滤、FP8 与资源关闭测试。
  • rank-local copy-out 使用不可变键集合,边界清晰。

)
budget = legacy_budget
else:
budget = int(estimate)

Copy link
Copy Markdown
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

[P1] 显存预检丢弃 legacy floor 且未计入 RTP 侧 TensorCollector 常驻显存,默认 AUTO 可能误判可用并在加载期 OOM

任意正数 estimated_peak_device_bytes 都会替代 3 * max_file_size,但该值只覆盖 loader-owned buffers。TensorCollector 会跨迭代保留输入,weight.load() 又在 clear() 前分配最终权重;较小上游估值可能使 AUTO 通过预检后在输入、输出重叠阶段 OOM。

建议: 至少取上游估值与集成侧安全下限的最大值,或显式计入 collector 与最终权重同时存活的峰值,并增加跨 batch 收集大权重的阈值测试。

Comment thread rtp_llm/utils/database.py Outdated

@LLLLKKKK LLLLKKKK left a comment

Copy link
Copy Markdown
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

AI Code Review - PR #1354 (non-blocking suggestions)

6 条 P2/P3 建议,不阻塞合并。阻塞判定与完整摘要见上一条 review。

Comment thread rtp_llm/model_loader/loader.py Outdated
Comment thread docs/backend/server_arguments.md Outdated
self.assertFalse(getattr(installed_module, "_rtp_test_fake", False))

def test_available_auto_loader_contract_is_classified(self) -> None:
expected_tier = os.environ.get("RTP_LLM_EXPECT_FASTSAFETENSORS_TIER")

Copy link
Copy Markdown
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

[P2] 真实 wheel 能力契约在默认测试链路中可被跳过

默认 BUILD 目标未设置 RTP_LLM_EXPECT_FASTSAFETENSORS_TIER;缺包、能力层级不足或缺少 load_config 时测试均可跳过。其余用例使用伪造 AutoLoader,因此 CI 可能未验证真实 wheel 的构造和迭代契约。

建议: 增加依赖真实 wheel、按平台固定预期 tier 的测试目标,并使用小型 checkpoint 验证构造、拆分、过滤和关闭行为。

Checklist: [6.1] 分布式/跨平台变更有对应覆盖;[P.G] mock/fake/stub 不得替代本次声称覆盖的生产边界;[H] mock/fake/stub 只能隔离非目标依赖,不能 stub 掉本次声称覆盖的生产边界;涉及 pybind/C++/runtime 的 bug 必须有真实边界集成或 smoke 覆盖;[H] 新增、迁移或删除测试必须证明目标行为仍在 CI 中执行;DISABLED_、#if 0、open_skip、导入即失败、未被 target 引用的用例不得计为覆盖

Comment thread docs/backend/server_arguments.md Outdated
for resolved, level, expected in cases:
with self.subTest(resolved=resolved):
loader._resolve_fastsafetensors_mode = MagicMock(return_value=resolved)
with self.assertLogs(level=level) as logs:

Copy link
Copy Markdown
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

[P2] 日志级别契约未被真正断言,assertLogs 的 level 只是捕获阈值

assertLogs(level=level) 只设置最低捕获级别,随后测试仅检查消息文本;预期 INFO 的日志改成 WARNING 仍会通过,无法保护文档声明的日志级别契约。

建议: 断言 logs.records 中目标记录的 levelname,并隔离无关日志。

Checklist: [6.1] 可观测性:日志/指标/超时可操作、非噪声

torch.testing.assert_close(collector_result, database_result)
torch.testing.assert_close(collector_result, raw_tensor)

def test_inline_fp8_uses_logical_keys_from_collector(self):

Copy link
Copy Markdown
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

[P2] Inline FP8 测试未验证专家数据和 scale 的对应关系

测试为两个 expert 生成不同 tensor 和 scale,最终却只断言输出形状;重复 expert 0、交换 expert 顺序或关联错误 scale 均不会失败,未覆盖 W2 预量化路径的数值契约。

建议: 保存逐 expert 的预期 FP8 tensor 与 scale,并分别校验输出值、顺序和对应关系。

Checklist: [6.1] 新逻辑有聚焦单测 + 相关集成/smoke 测试

@LLLLKKKK LLLLKKKK left a comment

Copy link
Copy Markdown
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

AI Code Review - PR #1354

Status: BLOCKING

Summary: P0/0 · P1/2 · P2/7 · P3/0

Reviewed: commit f42155bc6059 · 2026-09-01 16:29 UTC+8

Blocking Issues

P1

  • 显存预检丢弃 legacy floor 且未计入 RTP 侧 TensorCollector 常驻显存,默认 AUTO 可能误判可用并在加载期 OOM @ rtp_llm/model_loader/loader.py:425
    • 建议:预算应同时覆盖上游估算和 RTP collector、合并及量化的峰值下限,并用真实 wheel 与 stacked-MoE checkpoint 校准 AUTO 边界。
  • AutoLoader 运行期不兼容不会回退 scratch @ rtp_llm/utils/database.py:417
    • 建议:预检全部必需符号和构造契约;对明确的兼容性异常清理未完成状态并从 scratch 重新加载,同时让 checkpoint 数据错误保持 fail-fast。

Non-blocking Suggestions

P2

  • 无 stacked 权重仍会增加 full-stacked 显存预算 @ rtp_llm/model_loader/loader.py:446
    • 建议:仅在 checkpoint 实际包含 raw stacked MoE 权重时增加额外预算,并补充无 stacked 权重的准入边界测试。
  • 文档称内存预检同样约束显式 fastsafetensors,实际默认 per-expert 完全跳过预检 @ docs/backend/server_arguments.md:216
    • 建议:明确显式 per-expert 尊重强制请求且不预检,或统一执行预检,并增加测试固定最终契约。
  • 真实 wheel 能力契约在默认测试链路中可被跳过 @ rtp_llm/utils/test/ckpt_database_test.py:414
    • 建议:为各发布平台增加依赖真实 wheel 且期望 per-expert 的契约目标,复用 _callable_accepts_keyword,并实际验证 split/filter 顺序及仅 filter 档位。
  • 文档承诺的 falls back to scratch 标记不覆盖两处内存预检回退,consumer-filter 档位也无结构化字段 @ docs/backend/server_arguments.md:226
    • 建议:统一输出 requested_modeeffective_modedegraded_reason 和 scratch 标记,或准确缩小文档承诺范围。
  • 日志级别契约未被真正断言,assertLogs 的 level 只是捕获阈值 @ rtp_llm/model_loader/test/test_fastsafetensors_loader_policy.py:443
    • 建议:逐场景断言捕获记录的 levelnolevelname,覆盖包缺失、能力降级、内存回退和正常选择。
  • Inline FP8 测试未验证专家数据和 scale 的对应关系 @ rtp_llm/model_loader/test/test_fastsafetensors_loader_policy.py:575
    • 建议:逐专家比较 FP8 数据与 scale,或反量化后与源数据比较,并覆盖专家顺序及 gate/up 拼接关系。
  • MoE 布局解析逻辑重复且跨类调用私有方法 @ rtp_llm/model_loader/per_channel_fp8_quant_weight.py:811
    • 建议:在 MoeAtomicWeight 提供统一的公开布局解析结果,供普通 MoE 与 inline FP8 路径复用。

Checklist Findings (12 fail / 121 total)

General Principles Checklist

  • [6.1] Architecture — 兼容性:外部 HTTP/RPC API、持久数据、配置、环境迁移安全 → issue 文档承诺的 falls back to scratch 标记不覆盖两处内存预检回退,consumer-filter 档位也无结构化字段
    固定标记只出现在能力探测回退;AUTO 与显式 full-stacked 的内存回退均缺少该标记,AUTO 前置条件失败也无决策原因。缺少 local_copyout_filter 时仅输出普通 warning,没有文档承诺的结构化字段,按该契约配置的告警会漏报。
  • [6.1] Architecture — 分层边界:新概念在正确层级,不泄漏内部 → issue MoE 布局解析逻辑重复且跨类调用私有方法
    普通 MoE 与 inline FP8 分别执行 database、logical key、raw stacked key 和 source 包装判定;量化类还直接调用 MoeAtomicWeight 的多个私有方法。布局规则变化需要同步两套实现,容易造成 weight 与 scale 路径漂移。
  • [6.1] Architecture — 可观测性:日志/指标/超时可操作、非噪声 → issue 日志级别契约未被真正断言,assertLogs 的 level 只是捕获阈值
    assertLogs(level=...) 只设置最低捕获等级,后续仅断言文本。因此预期 INFO 实际输出 WARNING、预期 WARNING 实际输出 ERROR 时测试仍会通过,无法保护文档公开的日志级别契约。
  • [6.1] Architecture — 回滚路径:风险行为存在运维回滚手段 → issue 无 stacked 权重仍会增加 full-stacked 显存预算
    只要模式为 full-stacked 就无条件增加一个最大分片,而此时尚未构建 stacked_key_config。dense、原生 per-expert 或没有 raw stacked key 的模型也可能因此被错误判定显存不足并回退 scratch。
  • [6.1] Architecture — 状态不变量:创建/更新/失败/重试/回滚路径有效 → issue 无 stacked 权重仍会增加 full-stacked 显存预算
    只要模式为 full-stacked 就无条件增加一个最大分片,而此时尚未构建 stacked_key_config。dense、原生 per-expert 或没有 raw stacked key 的模型也可能因此被错误判定显存不足并回退 scratch。
  • [6.1] Architecture — 错误语义:fail-fast/retry/fallback/silent 行为显式 → issue 文档承诺的 falls back to scratch 标记不覆盖两处内存预检回退,consumer-filter 档位也无结构化字段
    固定标记只出现在能力探测回退;AUTO 与显式 full-stacked 的内存回退均缺少该标记,AUTO 前置条件失败也无决策原因。缺少 local_copyout_filter 时仅输出普通 warning,没有文档承诺的结构化字段,按该契约配置的告警会漏报。
  • [6.1] Software Engineering — DRY:重复非平凡逻辑被抽取或显式复用 → issue MoE 布局解析逻辑重复且跨类调用私有方法
    普通 MoE 与 inline FP8 分别执行 database、logical key、raw stacked key 和 source 包装判定;量化类还直接调用 MoeAtomicWeight 的多个私有方法。布局规则变化需要同步两套实现,容易造成 weight 与 scale 路径漂移。
  • [6.1] Tests — 分布式/跨平台变更有对应覆盖 → issue 真实 wheel 能力契约在默认测试链路中可被跳过
    未设置 RTP_LLM_EXPECT_FASTSAFETENSORS_TIER 时,缺包或低能力会跳过,默认目标未设置该变量。测试还仅按参数名分类,没有复用生产端的关键字可调用判定,也没有通过真实 wheel 执行“先 split、后 local filter”的关键语义,制品能力回退仍可能假绿。
  • [6.1] Tests — 新逻辑有聚焦单测 + 相关集成/smoke 测试 → issue Inline FP8 测试未验证专家数据和 scale 的对应关系
    用例写入不同专家的 FP8 tensor 与 scale,最终却只断言输出 shape。专家顺序交换、重复专家或 weight/scale 错配均可保持形状不变并通过,而这些错误会直接改变推理结果。
  • [6.1] Tests — 边界 case 覆盖(空、单元素、最大值) → issue Inline FP8 测试未验证专家数据和 scale 的对应关系
    用例写入不同专家的 FP8 tensor 与 scale,最终却只断言输出 shape。专家顺序交换、重复专家或 weight/scale 错配均可保持形状不变并通过,而这些错误会直接改变推理结果。

RTP-LLM Checklist

  • [I] 代码质量 — 同一功能用统一工具函数 → issue MoE 布局解析逻辑重复且跨类调用私有方法
    普通 MoE 与 inline FP8 分别执行 database、logical key、raw stacked key 和 source 包装判定;量化类还直接调用 MoeAtomicWeight 的多个私有方法。布局规则变化需要同步两套实现,容易造成 weight 与 scale 路径漂移。

Python Static-First Checklist

  • [P.G] 测试规范 — mock/fake/stub 不得替代本次声称覆盖的生产边界 → issue Inline FP8 测试未验证专家数据和 scale 的对应关系
    用例写入不同专家的 FP8 tensor 与 scale,最终却只断言输出 shape。专家顺序交换、重复专家或 weight/scale 错配均可保持形状不变并通过,而这些错误会直接改变推理结果。

Strengths

  • 使用 AutoLoader 能力探测替代私有加载器 API。
  • stacked-MoE 布局改由 checkpoint database 判定,避免模板 key 误分类。
  • 多平台 requirements 与 lock 同步升级,并保留 scratch/full-stacked 回滚入口。
  • 新增 CPU-only 策略测试,覆盖模式解析、预算边界和 key 闭包。

)
budget = legacy_budget
else:
budget = int(estimate)

Copy link
Copy Markdown
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

[P1] 显存预检丢弃 legacy floor 且未计入 RTP 侧 TensorCollector 常驻显存,默认 AUTO 可能误判可用并在加载期 OOM

任意正数 estimated_peak_device_bytes 都会直接替代 3 × max_file_size。该估算只覆盖 loader 缓冲;TensorCollector 会保存组件的全部专家张量,随后 weight.load 分配最终输出,直到完成后才清理。AUTO 未为这段重叠占用预留空间,可能在紧显存部署中准入后 OOM。

建议: 预算应同时覆盖上游估算和 RTP collector、合并及量化的峰值下限,并用真实 wheel 与 stacked-MoE checkpoint 校准 AUTO 边界。

Comment thread rtp_llm/utils/database.py Outdated

@LLLLKKKK LLLLKKKK left a comment

Copy link
Copy Markdown
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

AI Code Review - PR #1354 (non-blocking suggestions)

7 条 P2/P3 建议,不阻塞合并。阻塞判定与完整摘要见上一条 review。

Comment thread rtp_llm/model_loader/loader.py Outdated
Comment thread docs/backend/server_arguments.md Outdated
self.assertFalse(getattr(installed_module, "_rtp_test_fake", False))

def test_available_auto_loader_contract_is_classified(self) -> None:
expected_tier = os.environ.get("RTP_LLM_EXPECT_FASTSAFETENSORS_TIER")

Copy link
Copy Markdown
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

[P2] 真实 wheel 能力契约在默认测试链路中可被跳过

未设置 RTP_LLM_EXPECT_FASTSAFETENSORS_TIER 时,缺包或低能力会跳过,默认目标未设置该变量。测试还仅按参数名分类,没有复用生产端的关键字可调用判定,也没有通过真实 wheel 执行“先 split、后 local filter”的关键语义,制品能力回退仍可能假绿。

建议: 为各发布平台增加依赖真实 wheel 且期望 per-expert 的契约目标,复用 _callable_accepts_keyword,并实际验证 split/filter 顺序及仅 filter 档位。

Checklist: [6.1] 分布式/跨平台变更有对应覆盖

Comment thread docs/backend/server_arguments.md Outdated
for resolved, level, expected in cases:
with self.subTest(resolved=resolved):
loader._resolve_fastsafetensors_mode = MagicMock(return_value=resolved)
with self.assertLogs(level=level) as logs:

Copy link
Copy Markdown
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

[P2] 日志级别契约未被真正断言,assertLogs 的 level 只是捕获阈值

assertLogs(level=...) 只设置最低捕获等级,后续仅断言文本。因此预期 INFO 实际输出 WARNING、预期 WARNING 实际输出 ERROR 时测试仍会通过,无法保护文档公开的日志级别契约。

建议: 逐场景断言捕获记录的 levelnolevelname,覆盖包缺失、能力降级、内存回退和正常选择。

Checklist: [6.1] 可观测性:日志/指标/超时可操作、非噪声

torch.testing.assert_close(collector_result, database_result)
torch.testing.assert_close(collector_result, raw_tensor)

def test_inline_fp8_uses_logical_keys_from_collector(self):

Copy link
Copy Markdown
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

[P2] Inline FP8 测试未验证专家数据和 scale 的对应关系

用例写入不同专家的 FP8 tensor 与 scale,最终却只断言输出 shape。专家顺序交换、重复专家或 weight/scale 错配均可保持形状不变并通过,而这些错误会直接改变推理结果。

建议: 逐专家比较 FP8 数据与 scale,或反量化后与源数据比较,并覆盖专家顺序及 gate/up 拼接关系。

Checklist: [6.1] 新逻辑有聚焦单测 + 相关集成/smoke 测试;[6.1] 边界 case 覆盖(空、单元素、最大值);[P.G] mock/fake/stub 不得替代本次声称覆盖的生产边界

Comment thread rtp_llm/model_loader/per_channel_fp8_quant_weight.py Outdated
@ABNER-1
ABNER-1 force-pushed the shuxing/dsv4-sleep-level2-fastsafetensors branch from 9780eff to c41fdd2 Compare September 1, 2026 10:31

@LLLLKKKK LLLLKKKK left a comment

Copy link
Copy Markdown
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

AI Code Review - PR #1354

Status: BLOCKING

Summary: P0/0 · P1/4 · P2/1 · P3/1

Reviewed: commit c41fdd23a8c3 · 2026-09-01 19:03 UTC+8

Blocking Issues

P1

  • CUDA 13 ARM 依赖锁未接入架构选择器 @ arch_config/arch_select.bzl:25
    • 建议:加载 CUDA 13 ARM 仓库,并为 requirement()torch_deps()whl_deps() 增加高优先级 using_cuda13_arm 分支及对应契约测试。
  • 兼容回退时 traceback 会阻止已加载 GPU 权重释放 @ rtp_llm/model_loader/loader.py:334
    • 建议:在异常块内仅保存字符串化原因,退出异常作用域后再清理显存并执行 scratch;增加部分加载后抛出兼容异常的显存生命周期测试。
  • wheel 契约测试未限制到支持的平台 @ rtp_llm/utils/test/BUILD:107
    • 建议:仅在提供新版 wheel 的配置启用该目标,或按平台拆分依赖和能力预期,并验证全部平台矩阵均可分析执行。
  • 真实 FastSafeTensors 多 rank 加载边界未被回归覆盖 @ rtp_llm/utils/test/ckpt_database_test.py:507
    • 建议:在受支持 GPU 平台使用锁定 wheel 和小型 stacked checkpoint,覆盖单 rank、双 rank、rank-local expert 集合、输出数值、资源关闭及峰值显存。

Non-blocking Suggestions

P2

  • full-stacked 开关会影响非 stacked checkpoint @ rtp_llm/model_loader/loader.py:321
    • 建议:仅在 _has_raw_stacked_moe_weights() 为真时应用 full-stacked 预检;其他 checkpoint 保持显式 per-expert 路径的行为。

P3

  • scratch fallback 日志级别说明与实现不一致 @ docs/backend/server_arguments.md:232
    • 建议:明确包缺失和正常前置条件不满足均使用 INFO,或将实现调整为文档承诺的 WARNING。

Checklist Findings (13 fail / 121 total)

General Principles Checklist

  • [6.1] Architecture — 依赖方向:无循环依赖/跨层惊喜 → issue CUDA 13 ARM 依赖锁未接入架构选择器
    pip_cuda13_arm_torch 已注册,但选择器未加载该仓库,也没有 using_cuda13_arm 分支。该配置不匹配 using_arm 或 x86 分支,导致 requirement()torch_deps() 落入 CPU 默认项,而 whl_deps() 匹配通用 CUDA 12 项;新增 ARM wheel 无法进入 Bazel 运行时。
  • [6.1] Architecture — 兼容性:外部 HTTP/RPC API、持久数据、配置、环境迁移安全 → issue full-stacked 开关会影响非 stacked checkpoint
    显式 FastSafeTensors 只要选择 full-stacked 就执行内存预检,尚未确认 checkpoint 是否包含 raw stacked 权重。密集或原生 per-expert checkpoint 也可能因该环境变量意外回退 scratch,违反该开关仅控制 stacked-MoE 交付方式的文档约定。
  • [6.1] Architecture — 可观测性:日志/指标/超时可操作、非噪声 → issue scratch fallback 日志级别说明与实现不一致
    文档称除包缺失外的 fallback 均为 WARNING,但 AUTO 前置条件不满足时实现使用 INFO。依赖该文档配置 WARNING 监控会漏掉此类回退。
  • [6.1] Architecture — 状态不变量:创建/更新/失败/重试/回滚路径有效 → issue full-stacked 开关会影响非 stacked checkpoint
    显式 FastSafeTensors 只要选择 full-stacked 就执行内存预检,尚未确认 checkpoint 是否包含 raw stacked 权重。密集或原生 per-expert checkpoint 也可能因该环境变量意外回退 scratch,违反该开关仅控制 stacked-MoE 交付方式的文档约定。
  • [6.1] Architecture — 错误语义:fail-fast/retry/fallback/silent 行为显式 → issue 兼容回退时 traceback 会阻止已加载 GPU 权重释放
    兼容异常可能在部分权重写入 model_weights 后抛出。当前在 except ... as error 作用域内清理并立即执行 scratch;活动异常及 traceback 仍引用 _load_from_fastsafetensor 帧和其中的 GPU tensor,清理无法释放这些显存,scratch 全量加载可能 OOM。
  • [6.1] Tests — 分布式/跨平台变更有对应覆盖 → issue 真实 FastSafeTensors 多 rank 加载边界未被回归覆盖
    删除私有 PerExpertParallelLoader 后,rank-local 过滤和 stacked-MoE 拆分交由上游 AutoLoader。行为测试替换了整个包,installed-wheel 测试仅检查构造签名和配置字段,未实例化加载器或读取 checkpoint,无法验证真实双 rank 的拆分、过滤、collective 对齐和数值正确性。
  • [6.1] Tests — 新逻辑有聚焦单测 + 相关集成/smoke 测试 → issue 真实 FastSafeTensors 多 rank 加载边界未被回归覆盖
    删除私有 PerExpertParallelLoader 后,rank-local 过滤和 stacked-MoE 拆分交由上游 AutoLoader。行为测试替换了整个包,installed-wheel 测试仅检查构造签名和配置字段,未实例化加载器或读取 checkpoint,无法验证真实双 rank 的拆分、过滤、collective 对齐和数值正确性。
  • [6.1] Tests — 被删除测试有等价替代覆盖 → issue 真实 FastSafeTensors 多 rank 加载边界未被回归覆盖
    删除私有 PerExpertParallelLoader 后,rank-local 过滤和 stacked-MoE 拆分交由上游 AutoLoader。行为测试替换了整个包,installed-wheel 测试仅检查构造签名和配置字段,未实例化加载器或读取 checkpoint,无法验证真实双 rank 的拆分、过滤、collective 对齐和数值正确性。

RTP-LLM Checklist

  • [H] 测试与 CI — BUILD、py_test、cc_test、genrule 变更必须验证 srcs/data/runfiles/testdata 相对路径、import path 和 target 可执行性;genrule glob 不得捕获无关构建产物 → issue wheel 契约测试未限制到支持的平台
    该目标没有 target_compatible_with 或平台标签,却固定依赖 //rtp_llm:fastsafetensors 并要求 per-expert。CPU、CUDA 12 和 ROCm 锁未提供该新版依赖,跨平台通配测试会在依赖分析或能力断言阶段失败。
  • [H] 测试与 CI — mock/fake/stub 只能隔离非目标依赖,不能 stub 掉本次声称覆盖的生产边界;涉及 pybind/C++/runtime 的 bug 必须有真实边界集成或 smoke 覆盖 → issue 真实 FastSafeTensors 多 rank 加载边界未被回归覆盖
    删除私有 PerExpertParallelLoader 后,rank-local 过滤和 stacked-MoE 拆分交由上游 AutoLoader。行为测试替换了整个包,installed-wheel 测试仅检查构造签名和配置字段,未实例化加载器或读取 checkpoint,无法验证真实双 rank 的拆分、过滤、collective 对齐和数值正确性。
  • [H] 测试与 CI — 新增、迁移或删除测试必须证明目标行为仍在 CI 中执行;DISABLED_、#if 0、open_skip、导入即失败、未被 target 引用的用例不得计为覆盖 → issue 真实 FastSafeTensors 多 rank 加载边界未被回归覆盖
    删除私有 PerExpertParallelLoader 后,rank-local 过滤和 stacked-MoE 拆分交由上游 AutoLoader。行为测试替换了整个包,installed-wheel 测试仅检查构造签名和配置字段,未实例化加载器或读取 checkpoint,无法验证真实双 rank 的拆分、过滤、collective 对齐和数值正确性。
  • [I] 代码质量 — 删除或重命名内部 file、registry entry、model name、metric enum、op binding、plugin symbol 时,必须全仓搜索消费者,并提供替代实现、迁移说明或 smoke 覆盖;只有暴露到 HTTP/RPC/config/persisted format 时才按外部兼容性处理 → issue 真实 FastSafeTensors 多 rank 加载边界未被回归覆盖
    删除私有 PerExpertParallelLoader 后,rank-local 过滤和 stacked-MoE 拆分交由上游 AutoLoader。行为测试替换了整个包,installed-wheel 测试仅检查构造签名和配置字段,未实例化加载器或读取 checkpoint,无法验证真实双 rank 的拆分、过滤、collective 对齐和数值正确性。

Python Static-First Checklist

  • [P.G] 测试规范 — mock/fake/stub 不得替代本次声称覆盖的生产边界 → issue 真实 FastSafeTensors 多 rank 加载边界未被回归覆盖
    删除私有 PerExpertParallelLoader 后,rank-local 过滤和 stacked-MoE 拆分交由上游 AutoLoader。行为测试替换了整个包,installed-wheel 测试仅检查构造签名和配置字段,未实例化加载器或读取 checkpoint,无法验证真实双 rank 的拆分、过滤、collective 对齐和数值正确性。

Strengths

  • 统一了 stacked-MoE 布局解析及 inline FP8 加载接口,减少重复逻辑。
  • 显存预算补充了 RTP 常驻开销,并仅对真实 stacked 权重增加额外预算。
  • 能力探测、错误分类、降级日志和 CPU 策略测试覆盖较完整。

Comment thread arch_config/arch_select.bzl Outdated
return self._load_from_scratch(device)
try:
return self._load_from_fastsafetensor(device, stacked_moe_mode)
except FastSafeTensorsCompatibilityError as error:

Copy link
Copy Markdown
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

[P1] 兼容回退时 traceback 会阻止已加载 GPU 权重释放

兼容异常可能在部分权重写入 model_weights 后抛出。当前在 except ... as error 作用域内清理并立即执行 scratch;活动异常及 traceback 仍引用 _load_from_fastsafetensor 帧和其中的 GPU tensor,清理无法释放这些显存,scratch 全量加载可能 OOM。

建议: 在异常块内仅保存字符串化原因,退出异常作用域后再清理显存并执行 scratch;增加部分加载后抛出兼容异常的显存生命周期测试。

Checklist: [6.1] 错误语义:fail-fast/retry/fallback/silent 行为显式

Comment thread rtp_llm/utils/test/BUILD
)

py_test(
name = "ckpt_database_fastsafetensors_contract_test",

Copy link
Copy Markdown
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

[P1] wheel 契约测试未限制到支持的平台

该目标没有 target_compatible_with 或平台标签,却固定依赖 //rtp_llm:fastsafetensors 并要求 per-expert。CPU、CUDA 12 和 ROCm 锁未提供该新版依赖,跨平台通配测试会在依赖分析或能力断言阶段失败。

建议: 仅在提供新版 wheel 的配置启用该目标,或按平台拆分依赖和能力预期,并验证全部平台矩阵均可分析执行。

Checklist: [H] BUILD、py_test、cc_test、genrule 变更必须验证 srcs/data/runfiles/testdata 相对路径、import path 和 target 可执行性;genrule glob 不得捕获无关构建产物

installed_module = sys.modules.get("fastsafetensors")
self.assertFalse(getattr(installed_module, "_rtp_test_fake", False))

def test_available_auto_loader_contract_is_classified(self) -> None:

Copy link
Copy Markdown
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

[P1] 真实 FastSafeTensors 多 rank 加载边界未被回归覆盖

删除私有 PerExpertParallelLoader 后,rank-local 过滤和 stacked-MoE 拆分交由上游 AutoLoader。行为测试替换了整个包,installed-wheel 测试仅检查构造签名和配置字段,未实例化加载器或读取 checkpoint,无法验证真实双 rank 的拆分、过滤、collective 对齐和数值正确性。

建议: 在受支持 GPU 平台使用锁定 wheel 和小型 stacked checkpoint,覆盖单 rank、双 rank、rank-local expert 集合、输出数值、资源关闭及峰值显存。

Checklist: [6.1] 分布式/跨平台变更有对应覆盖;[6.1] 新逻辑有聚焦单测 + 相关集成/smoke 测试;[6.1] 被删除测试有等价替代覆盖;[P.G] mock/fake/stub 不得替代本次声称覆盖的生产边界;[H] mock/fake/stub 只能隔离非目标依赖,不能 stub 掉本次声称覆盖的生产边界;涉及 pybind/C++/runtime 的 bug 必须有真实边界集成或 smoke 覆盖;[H] 新增、迁移或删除测试必须证明目标行为仍在 CI 中执行;DISABLED_、#if 0、open_skip、导入即失败、未被 target 引用的用例不得计为覆盖;[I] 删除或重命名内部 file、registry entry、model name、metric enum、op binding、plugin symbol 时,必须全仓搜索消费者,并提供替代实现、迁移说明或 smoke 覆盖;只有暴露到 HTTP/RPC/config/persisted format 时才按外部兼容性处理

@LLLLKKKK LLLLKKKK left a comment

Copy link
Copy Markdown
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

AI Code Review - PR #1354 (non-blocking suggestions)

2 条 P2/P3 建议,不阻塞合并。阻塞判定与完整摘要见上一条 review。

if stacked_moe_mode is None:
return self._load_from_scratch(device)
if (
stacked_moe_mode == FASTSAFETENSORS_STACKED_MOE_MODE_FULL_STACKED

Copy link
Copy Markdown
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

[P2] full-stacked 开关会影响非 stacked checkpoint

显式 FastSafeTensors 只要选择 full-stacked 就执行内存预检,尚未确认 checkpoint 是否包含 raw stacked 权重。密集或原生 per-expert checkpoint 也可能因该环境变量意外回退 scratch,违反该开关仅控制 stacked-MoE 交付方式的文档约定。

建议: 仅在 _has_raw_stacked_moe_weights() 为真时应用 full-stacked 预检;其他 checkpoint 保持显式 per-expert 路径的行为。

Checklist: [6.1] 兼容性:外部 HTTP/RPC API、持久数据、配置、环境迁移安全;[6.1] 状态不变量:创建/更新/失败/重试/回滚路径有效

When a degraded FastSafeTensors mode remains usable, RTP logs
`requested_mode`, `effective_mode` and `degraded_reason`; rank-local copy-out
degradation uses the same fields with `effective_mode=consumer-filter`. Every
scratch fallback contains `falls back to scratch`; package absence is INFO and

Copy link
Copy Markdown
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

[P3] scratch fallback 日志级别说明与实现不一致

文档称除包缺失外的 fallback 均为 WARNING,但 AUTO 前置条件不满足时实现使用 INFO。依赖该文档配置 WARNING 监控会漏掉此类回退。

建议: 明确包缺失和正常前置条件不满足均使用 INFO,或将实现调整为文档承诺的 WARNING。

Checklist: [6.1] 可观测性:日志/指标/超时可操作、非噪声

@ABNER-1
ABNER-1 force-pushed the shuxing/dsv4-sleep-level2-fastsafetensors branch from c41fdd2 to 6747631 Compare September 1, 2026 12:11

@LLLLKKKK LLLLKKKK left a comment

Copy link
Copy Markdown
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

AI Code Review - PR #1354

Status: BLOCKING

Summary: P0/0 · P1/4 · P2/0 · P3/0

Reviewed: commit 67476312abe0 · 2026-09-01 20:46 UTC+8

Blocking Issues

P1

  • CUDA 12.9 ARM 混用不同架构和版本的 Torch @ arch_config/arch_select.bzl:50
    • 建议:增加匹配 CUDA 12.9 ARM 的 aarch64 Torch archive,并让 requirement()torch_deps()whl_deps() 使用同一 Torch/CUDA 版本。
  • CUDA 13 ARM wheel 通过明文 HTTP 获取可执行依赖 @ arch_config/arch_select.bzl:102
    • 建议:迁移到可信 HTTPS 制品源,并在直接依赖 URL 中附加 SHA256 摘要,确保发布元数据与 lockfile 指向同一受控制品。
  • 检查点 I/O 错误不会按文档承诺保持 fail-fast @ rtp_llm/utils/database.py:120
    • 建议:仅转换具有明确导入、动态库或 ABI 特征的 OSError;让检查点 I/O 异常原样传播,并补充构造和迭代阶段的测试。
  • 真实 FastSafeTensors 多 rank 加载边界未被回归覆盖 @ rtp_llm/utils/test/ckpt_database_test.py:507
    • 建议:使用真实 wrapper/native wheels、最小 safetensors 检查点和至少两个 GPU rank,执行构造、迭代、过滤、拆分、广播及关闭流程。

Checklist Findings (5 fail / 121 total)

General Principles Checklist

  • [6.1] Architecture — 兼容性:外部 HTTP/RPC API、持久数据、配置、环境迁移安全 → issue 检查点 I/O 错误不会按文档承诺保持 fail-fast
    _is_fastsafetensors_compatibility_error() 将所有 OSError 视为兼容性错误;构造和迭代阶段的 FileNotFoundError、存储读取故障也会被包装,随后 ModelLoader 回退 scratch。这与 checkpoint/data 错误保持 fail-fast 的文档契约不符,并可能掩盖根因、重复加载模型。
  • [6.1] Architecture — 错误语义:fail-fast/retry/fallback/silent 行为显式 → issue 检查点 I/O 错误不会按文档承诺保持 fail-fast
    _is_fastsafetensors_compatibility_error() 将所有 OSError 视为兼容性错误;构造和迭代阶段的 FileNotFoundError、存储读取故障也会被包装,随后 ModelLoader 回退 scratch。这与 checkpoint/data 错误保持 fail-fast 的文档契约不符,并可能掩盖根因、重复加载模型。
  • [6.1] Tests — 分布式/跨平台变更有对应覆盖 → issue 真实 FastSafeTensors 多 rank 加载边界未被回归覆盖
    安装 wheel 契约测试仅检查 AutoLoader 签名和 load_config();加载、过滤、拆分及异常测试均使用假模块,也未初始化多 rank。删除私有多 rank 加载器后,真实 wrapper/native ABI、rank-local 过滤、stacked-MoE 拆分及广播回归仍可能通过门禁。
  • [6.1] Tests — 新逻辑有聚焦单测 + 相关集成/smoke 测试 → issue 真实 FastSafeTensors 多 rank 加载边界未被回归覆盖
    安装 wheel 契约测试仅检查 AutoLoader 签名和 load_config();加载、过滤、拆分及异常测试均使用假模块,也未初始化多 rank。删除私有多 rank 加载器后,真实 wrapper/native ABI、rank-local 过滤、stacked-MoE 拆分及广播回归仍可能通过门禁。

Python Static-First Checklist

  • [P.G] 测试规范 — mock/fake/stub 不得替代本次声称覆盖的生产边界 → issue 真实 FastSafeTensors 多 rank 加载边界未被回归覆盖
    安装 wheel 契约测试仅检查 AutoLoader 签名和 load_config();加载、过滤、拆分及异常测试均使用假模块,也未初始化多 rank。删除私有多 rank 加载器后,真实 wrapper/native ABI、rank-local 过滤、stacked-MoE 拆分及广播回归仍可能通过门禁。

Strengths

  • CUDA 13 ARM 的独立依赖锁、libtorch archive 与 FlashInfer 路由已接通。
  • MoE 布局解析和 FastSafeTensors 能力降级逻辑得到统一。
  • 兼容回退前会释放异常 traceback 和 GPU 权重引用。
  • 单元测试覆盖模式解析、内存预算、资源关闭及 FP8 加载顺序。

Comment thread arch_config/arch_select.bzl Outdated
Comment thread arch_config/arch_select.bzl Outdated
Comment thread rtp_llm/utils/database.py Outdated
installed_module = sys.modules.get("fastsafetensors")
self.assertFalse(getattr(installed_module, "_rtp_test_fake", False))

def test_available_auto_loader_contract_is_classified(self) -> None:

Copy link
Copy Markdown
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

[P1] 真实 FastSafeTensors 多 rank 加载边界未被回归覆盖

安装 wheel 契约测试仅检查 AutoLoader 签名和 load_config();加载、过滤、拆分及异常测试均使用假模块,也未初始化多 rank。删除私有多 rank 加载器后,真实 wrapper/native ABI、rank-local 过滤、stacked-MoE 拆分及广播回归仍可能通过门禁。

建议: 使用真实 wrapper/native wheels、最小 safetensors 检查点和至少两个 GPU rank,执行构造、迭代、过滤、拆分、广播及关闭流程。

Checklist: [6.1] 分布式/跨平台变更有对应覆盖;[6.1] 新逻辑有聚焦单测 + 相关集成/smoke 测试;[P.G] mock/fake/stub 不得替代本次声称覆盖的生产边界

@ABNER-1
ABNER-1 force-pushed the shuxing/dsv4-sleep-level2-fastsafetensors branch from 6747631 to 0bcf271 Compare September 1, 2026 12:56

@LLLLKKKK LLLLKKKK left a comment

Copy link
Copy Markdown
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

AI Code Review - PR #1354

Status: BLOCKING

Summary: P0/0 · P1/1 · P2/1 · P3/0

Reviewed: commit 0bcf271ee1b4 · 2026-09-01 21:29 UTC+8

Blocking Issues

P1

  • CUDA 12.9 x86 wheel 元数据与构建依赖不一致 @ arch_config/arch_select.bzl:88
    • 建议:增加 using_cuda12_9_x86 专用 wheel 依赖分支,与 CUDA 12.9 锁文件保持一致,并增加生成 wheel 的 Requires-Dist 断言。

Non-blocking Suggestions

P2

  • CUDA 13 ARM 缺少真实 FastSafeTensors 加载覆盖 @ rtp_llm/utils/test/BUILD:144
    • 建议:为 CUDA 13 ARM 增加真实 wheel 运行目标,至少覆盖单 rank 构造、读取和关闭;具备多卡环境时复用双 rank 拆分、过滤与广播用例。

Checklist Findings (3 fail / 121 total)

General Principles Checklist

  • [6.1] Architecture — 兼容性:外部 HTTP/RPC API、持久数据、配置、环境迁移安全 → issue CUDA 12.9 x86 wheel 元数据与构建依赖不一致
    CUDA 12.9 x86 的锁文件和 Bazel 依赖使用 Torch 2.8 与 FastSafeTensors 0.3.4,但 whl_deps() 缺少 using_cuda12_9_x86 分支,只命中通用 using_cuda12,使发布 wheel 仍声明 Torch 2.6 且遗漏 FastSafeTensors。干净环境安装后会得到与编译和运行时契约不一致的依赖。
  • [6.1] Tests — 分布式/跨平台变更有对应覆盖 → issue CUDA 13 ARM 缺少真实 FastSafeTensors 加载覆盖
    ARM 合约目标仅检查已安装 AutoLoader 的签名和能力字段;实际构造加载器、读取 checkpoint、执行 collective 并验证关闭语义的目标仅允许 CUDA x86 且固定使用 H20。因此 ARM 专用 wheel 的构造、原生读取和通信生命周期未被真实执行。
  • [6.1] Tests — 新逻辑有聚焦单测 + 相关集成/smoke 测试 → issue CUDA 13 ARM 缺少真实 FastSafeTensors 加载覆盖
    ARM 合约目标仅检查已安装 AutoLoader 的签名和能力字段;实际构造加载器、读取 checkpoint、执行 collective 并验证关闭语义的目标仅允许 CUDA x86 且固定使用 H20。因此 ARM 专用 wheel 的构造、原生读取和通信生命周期未被真实执行。

Strengths

  • 统一 stacked-MoE 布局解析,并复用于加载和 FP8 量化路径。
  • 能力降级、检查点错误语义及资源关闭边界清晰。
  • 新增真实双 rank 测试,覆盖拆分、过滤、广播和关闭流程。
  • CUDA ARM 依赖已按平台路由并固定版本与摘要。

Comment thread arch_config/arch_select.bzl Outdated

@LLLLKKKK LLLLKKKK left a comment

Copy link
Copy Markdown
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

AI Code Review - PR #1354 (non-blocking suggestions)

1 条 P2/P3 建议,不阻塞合并。阻塞判定与完整摘要见上一条 review。

Comment thread rtp_llm/utils/test/BUILD
"//rtp_llm:utils",
],
exec_properties = {"gpu": "H20", "gpu_count": "2"},
target_compatible_with = select({

Copy link
Copy Markdown
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

[P2] CUDA 13 ARM 缺少真实 FastSafeTensors 加载覆盖

ARM 合约目标仅检查已安装 AutoLoader 的签名和能力字段;实际构造加载器、读取 checkpoint、执行 collective 并验证关闭语义的目标仅允许 CUDA x86 且固定使用 H20。因此 ARM 专用 wheel 的构造、原生读取和通信生命周期未被真实执行。

建议: 为 CUDA 13 ARM 增加真实 wheel 运行目标,至少覆盖单 rank 构造、读取和关闭;具备多卡环境时复用双 rank 拆分、过滤与广播用例。

Checklist: [6.1] 分布式/跨平台变更有对应覆盖;[6.1] 新逻辑有聚焦单测 + 相关集成/smoke 测试

@ABNER-1
ABNER-1 requested a review from LLLLKKKK September 1, 2026 14:44

@LLLLKKKK LLLLKKKK left a comment

Copy link
Copy Markdown
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

AI Code Review - PR #1354

Status: BLOCKING

Summary: P0/0 · P1/1 · P2/3 · P3/1

Reviewed: commit 82e98bfc0d03 · 2026-09-01 23:14 UTC+8

Blocking Issues

P1

  • CUDA 13 wheel 元数据变更没有对应发布门禁 @ rtp_llm/utils/test/BUILD:175
    • 建议:为 CUDA 13 x86、CUDA 13 ARM 分别增加 wheel 元数据目标,并参数化校验对应锁文件中的关键依赖、版本、URL 与哈希。

Non-blocking Suggestions

P2

  • CUDA 13 ARM wheel 未固定所需的 ARM z3-solver 构建 @ arch_config/arch_select.bzl:108
    • 建议:将锁文件中的 ARM z3-solver 直接依赖及哈希加入该 wheel 分支,并验证干净 ARM 环境的安装与 TileLang 加载。
  • 新增及更新的 wheel 二进制依赖缺少哈希约束 @ arch_config/arch_select.bzl:108
    • 建议:将对应锁文件中的哈希附加到本次新增或更新的所有直接 URL 依赖。
  • full-stacked 内存预检被描述为无条件执行 @ docs/backend/server_arguments.md:218
    • 建议:明确说明显式 full-stacked 仅对 raw stacked MoE checkpoint 执行预检;若预期始终预检,则同步调整实现和测试。

P3

  • full-stacked 的上游 rank-local 过滤谓词转发分支未被测试命中 @ rtp_llm/utils/test/ckpt_database_test.py:294
    • 建议:让 fake 显式声明并执行 local_copyout_filter,断言 raw stacked key 被接纳且展开后仅保留本 rank expert。

Checklist Findings (5 fail / 121 total)

General Principles Checklist

  • [6.1] Architecture — 兼容性:外部 HTTP/RPC API、持久数据、配置、环境迁移安全 → issue ``full-stacked 内存预检被描述为无条件执行
    文档称显式 `full-stacked` 会保留内存预检,但实现仅在检测到 raw stacked MoE 权重时执行;dense 或已按 expert 存储的 checkpoint 会完全跳过预检,文档后文也给出了不同限定。
  • [6.1] Tests — 分布式/跨平台变更有对应覆盖 → issue CUDA 13 ARM wheel 未固定所需的 ARM z3-solver 构建
    CUDA 13 ARM requirements 与锁文件显式固定专用 z3-solver,TileLang 及运行时代码依赖其 libz3;但 wheel 分支只直接加入 TileLang。安装 wheel 时可能从软件源解析到未经该平台验证的 z3 构建。
  • [6.1] Tests — 新逻辑有聚焦单测 + 相关集成/smoke 测试 → issue full-stacked 的上游 rank-local 过滤谓词转发分支未被测试命中
    该测试的 FakeAutoLoader 仅声明 **kwargs,能力探测不会将其视为支持 local_copyout_filter,因此只覆盖 consumer-filter 路径,未执行向 AutoLoader 转发扩展后过滤谓词的分支;真实双卡测试固定使用 per-expert。

RTP-LLM Checklist

  • [H] 测试与 CI — mock/fake/stub 只能隔离非目标依赖,不能 stub 掉本次声称覆盖的生产边界;涉及 pybind/C++/runtime 的 bug 必须有真实边界集成或 smoke 覆盖 → issue full-stacked 的上游 rank-local 过滤谓词转发分支未被测试命中
    该测试的 FakeAutoLoader 仅声明 **kwargs,能力探测不会将其视为支持 local_copyout_filter,因此只覆盖 consumer-filter 路径,未执行向 AutoLoader 转发扩展后过滤谓词的分支;真实双卡测试固定使用 per-expert。
  • [H] 测试与 CI — 新增、迁移或删除测试必须证明目标行为仍在 CI 中执行;DISABLED_、#if 0、open_skip、导入即失败、未被 target 引用的用例不得计为覆盖 → issue CUDA 13 wheel 元数据变更没有对应发布门禁
    唯一的 wheel 元数据测试仅在 CUDA 12.9 x86 生效。本次 CUDA 13 x86 和 ARM 均变更了平台专属依赖,但其最终 Requires-Dist 未被构建或校验,错误的平台、ABI、URL 或哈希可通过发布流程,直至用户安装时暴露。

Strengths

  • 统一了 MoE 布局解析与在线 FP8 加载契约。
  • FastSafeTensors 能力探测、降级及资源清理覆盖较完整。
  • 新增 x86、ARM 双卡真实集成测试,覆盖按秩过滤、广播与存储所有权。
  • CUDA 12.9 wheel 依赖已与锁文件对齐并增加元数据测试。

Comment thread rtp_llm/utils/test/BUILD
}),
)

py_test(

Copy link
Copy Markdown
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

[P1] CUDA 13 wheel 元数据变更没有对应发布门禁

唯一的 wheel 元数据测试仅在 CUDA 12.9 x86 生效。本次 CUDA 13 x86 和 ARM 均变更了平台专属依赖,但其最终 Requires-Dist 未被构建或校验,错误的平台、ABI、URL 或哈希可通过发布流程,直至用户安装时暴露。

建议: 为 CUDA 13 x86、CUDA 13 ARM 分别增加 wheel 元数据目标,并参数化校验对应锁文件中的关键依赖、版本、URL 与哈希。

Checklist: [H] 新增、迁移或删除测试必须证明目标行为仍在 CI 中执行;DISABLED_、#if 0、open_skip、导入即失败、未被 target 引用的用例不得计为覆盖

@LLLLKKKK LLLLKKKK left a comment

Copy link
Copy Markdown
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

AI Code Review - PR #1354 (non-blocking suggestions)

4 条 P2/P3 建议,不阻塞合并。阻塞判定与完整摘要见上一条 review。

"fastsafetensors@https://rtp-maga.oss-cn-zhangjiakou.aliyuncs.com/0502/fastsafetensors-0.1.20%2Bali-cp310-cp310-linux_x86_64.whl",
"fastsafetensors@https://rtp-opensource.oss-cn-hangzhou.aliyuncs.com/rtp_llm/cu130/fastsafetensors-0.3.4.dev20260901%2Bali.fuseshm.g78ac75c8.aone67880226-cp310-cp310-linux_x86_64.whl",
],
"@rtp_llm//:using_cuda13_arm": [

Copy link
Copy Markdown
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

[P2] CUDA 13 ARM wheel 未固定所需的 ARM z3-solver 构建

CUDA 13 ARM requirements 与锁文件显式固定专用 z3-solver,TileLang 及运行时代码依赖其 libz3;但 wheel 分支只直接加入 TileLang。安装 wheel 时可能从软件源解析到未经该平台验证的 z3 构建。

建议: 将锁文件中的 ARM z3-solver 直接依赖及哈希加入该 wheel 分支,并验证干净 ARM 环境的安装与 TileLang 加载。

Checklist: [6.1] 分布式/跨平台变更有对应覆盖

"fastsafetensors@https://rtp-maga.oss-cn-zhangjiakou.aliyuncs.com/0502/fastsafetensors-0.1.20%2Bali-cp310-cp310-linux_x86_64.whl",
"fastsafetensors@https://rtp-opensource.oss-cn-hangzhou.aliyuncs.com/rtp_llm/cu130/fastsafetensors-0.3.4.dev20260901%2Bali.fuseshm.g78ac75c8.aone67880226-cp310-cp310-linux_x86_64.whl",
],
"@rtp_llm//:using_cuda13_arm": [

Copy link
Copy Markdown
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

[P2] 新增及更新的 wheel 二进制依赖缺少哈希约束

CUDA 13 ARM 新增的多数直接二进制依赖未携带锁文件已有的 SHA-256,CUDA 13 x86 更新后的 fastsafetensors 也缺失哈希。远端对象变化时,wheel 安装无法拒绝与构建环境不一致的产物。

建议: 将对应锁文件中的哈希附加到本次新增或更新的所有直接 URL 依赖。

consumer-side filtering. A missing package/`AutoLoader`, an import/ABI failure,
an unmet AUTO prerequisite, or an insufficient AUTO memory preflight falls back
to `scratch`. Explicit `LOAD_METHOD=fastsafetensors` treats `per-expert` as a
user override and skips the memory preflight; explicit `full-stacked` keeps the

Copy link
Copy Markdown
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

[P2] full-stacked 内存预检被描述为无条件执行

文档称显式 full-stacked 会保留内存预检,但实现仅在检测到 raw stacked MoE 权重时执行;dense 或已按 expert 存储的 checkpoint 会完全跳过预检,文档后文也给出了不同限定。

建议: 明确说明显式 full-stacked 仅对 raw stacked MoE checkpoint 执行预检;若预期始终预检,则同步调整实现和测试。

Checklist: [6.1] 兼容性:外部 HTTP/RPC API、持久数据、配置、环境迁移安全

source_tensor.untyped_storage().data_ptr(),
)

def test_full_stacked_mode_clones_only_rank_local_experts(self) -> None:

Copy link
Copy Markdown
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

[P3] full-stacked 的上游 rank-local 过滤谓词转发分支未被测试命中

该测试的 FakeAutoLoader 仅声明 **kwargs,能力探测不会将其视为支持 local_copyout_filter,因此只覆盖 consumer-filter 路径,未执行向 AutoLoader 转发扩展后过滤谓词的分支;真实双卡测试固定使用 per-expert。

建议: 让 fake 显式声明并执行 local_copyout_filter,断言 raw stacked key 被接纳且展开后仅保留本 rank expert。

Checklist: [6.1] 新逻辑有聚焦单测 + 相关集成/smoke 测试;[H] mock/fake/stub 只能隔离非目标依赖,不能 stub 掉本次声称覆盖的生产边界;涉及 pybind/C++/runtime 的 bug 必须有真实边界集成或 smoke 覆盖

@ABNER-1
ABNER-1 requested a review from LLLLKKKK September 1, 2026 15:31

@LLLLKKKK LLLLKKKK left a comment

Copy link
Copy Markdown
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

AI Code Review - PR #1354

Status: BLOCKING

Summary: P0/0 · P1/4 · P2/4 · P3/0

Reviewed: commit 5148cce29d36 · 2026-09-02 00:08 UTC+8

Blocking Issues

P1

  • CUDA 12 ARM 专属依赖仓库缺少构建所需包 @ arch_config/arch_select.bzl:50
    • 建议:补齐该平台实际支持的 requirements/lock 制品,或从 CUDA 12 ARM BUILD 分支移除未发布依赖,并增加对应配置的 Bazel 分析和 wheel 构建测试。
  • CUDA 12.9 wheel 强制安装与 Torch/CUDA 不匹配的原生扩展 @ arch_config/arch_select.bzl:96
    • 建议:提供针对 Torch 2.8+cu129 构建的扩展 wheel,同步 requirements、lock 与 whl_deps(),并在干净环境中验证安装、导入和真实 AutoLoader 加载。
  • 清理阶段的兼容性异常不会按文档回退 @ rtp_llm/utils/database.py:573
    • 建议:对 close() 应用相同的兼容性分类,并在存在主异常时保留主异常;补充缺失及失败 close() 的回退测试。
  • CUDA 12 ARM wheel 依赖分支缺少元数据回归测试 @ rtp_llm/utils/test/BUILD:175
    • 建议:增加 CUDA 12 ARM 期望映射和对应 Bazel 测试目标。

Non-blocking Suggestions

P2

  • wheel 元数据测试未验证锁文件与平台依赖全集 @ rtp_llm/utils/test/rtp_llm_wheel_metadata_test.py:136
    • 建议:解析平台锁文件或从单一清单生成两侧数据,并对平台敏感直接依赖执行集合全等校验。
  • 真实多卡测试未覆盖 UE8M0 广播兼容路径 @ rtp_llm/utils/test/ckpt_database_fastsafetensors_multirank_test.py:108
    • 建议:增加 UE8M0 双 rank 广播场景,按生产入口加载补丁,并逐 rank 校验 dtype 与原始字节。
  • 双 rank 用例未跨越配置的分块边界 @ rtp_llm/utils/test/ckpt_database_fastsafetensors_multirank_test.py:43
    • 建议:加入超过 64 KiB 的张量或累计超限的多个张量,并保留按秩键值及关闭后存储有效性断言。
  • wheel 元数据测试在模块导入阶段修改命令行参数 @ rtp_llm/utils/test/rtp_llm_wheel_metadata_test.py:10
    • 建议:将参数解析移入主入口,并显式传递平台和 wheel 路径。

Checklist Findings (10 fail / 121 total)

General Principles Checklist

  • [6.1] Architecture — 依赖方向:无循环依赖/跨层惊喜 → issue CUDA 12 ARM 专属依赖仓库缺少构建所需包
    requirement() 将 CUDA 12 ARM 全部路由到专属锁文件,但该锁缺少下游 BUILD 在此配置选择的 deep_gemmdeep_eprtp-kernel、FlashAttention 及多个 FlashInfer 缓存包。分析这些目标时对应 pip 仓库标签不存在,会阻断 CUDA 12 ARM 构建。
  • [6.1] Architecture — 兼容性:外部 HTTP/RPC API、持久数据、配置、环境迁移安全 → issue 清理阶段的兼容性异常不会按文档回退
    导入、构造和迭代异常会转换为 FastSafeTensorsCompatibilityError,但 finally 直接调用 loader.close()。缺失或不兼容的 close() 会原样逃逸并绕过 ModelLoader 的 scratch 回退;若已有迭代异常,清理异常还会覆盖原异常。
  • [6.1] Architecture — 状态不变量:创建/更新/失败/重试/回滚路径有效 → issue 清理阶段的兼容性异常不会按文档回退
    导入、构造和迭代异常会转换为 FastSafeTensorsCompatibilityError,但 finally 直接调用 loader.close()。缺失或不兼容的 close() 会原样逃逸并绕过 ModelLoader 的 scratch 回退;若已有迭代异常,清理异常还会覆盖原异常。
  • [6.1] Architecture — 错误语义:fail-fast/retry/fallback/silent 行为显式 → issue 清理阶段的兼容性异常不会按文档回退
    导入、构造和迭代异常会转换为 FastSafeTensorsCompatibilityError,但 finally 直接调用 loader.close()。缺失或不兼容的 close() 会原样逃逸并绕过 ModelLoader 的 scratch 回退;若已有迭代异常,清理异常还会覆盖原异常。
  • [6.1] Software Engineering — DRY:重复非平凡逻辑被抽取或显式复用 → issue wheel 元数据测试未验证锁文件与平台依赖全集
    名为 match_platform_lock_file 的测试未读取锁文件,只比较手写期望子集,也不拒绝额外的平台敏感依赖。锁文件与测试复制相同错误,或 wheel 混入其他平台依赖时仍会通过。
  • [6.1] Tests — 分布式/跨平台变更有对应覆盖 → issue 真实多卡测试未覆盖 UE8M0 广播兼容路径
    checkpoint 仅包含 float32 张量,测试也未按生产入口加载 torch_patch,因此新增的 UE8M0 到 uint8 广播兼容逻辑从未触发;该 shim 失效时双卡测试仍会通过。
  • [6.1] Tests — 新逻辑有聚焦单测 + 相关集成/smoke 测试 → issue 真实多卡测试未覆盖 UE8M0 广播兼容路径
    checkpoint 仅包含 float32 张量,测试也未按生产入口加载 torch_patch,因此新增的 UE8M0 到 uint8 广播兼容逻辑从未触发;该 shim 失效时双卡测试仍会通过。
  • [6.1] Tests — 边界 case 覆盖(空、单元素、最大值) → issue 双 rank 用例未跨越配置的分块边界
    I/O 与 batch 上限均为 64 KiB,但 checkpoint 仅包含 10 个 float32 元素。虽然启用了 chunked_loading,实际未覆盖多 chunk 切换、刷新或跨 chunk 存储生命周期。

RTP-LLM Checklist

  • [I] 代码质量 — 同一功能用统一工具函数 → issue wheel 元数据测试未验证锁文件与平台依赖全集
    名为 match_platform_lock_file 的测试未读取锁文件,只比较手写期望子集,也不拒绝额外的平台敏感依赖。锁文件与测试复制相同错误,或 wheel 混入其他平台依赖时仍会通过。

Python Static-First Checklist

  • [P.F] 语言陷阱 — 禁止模块级 import 副作用 → issue wheel 元数据测试在模块导入阶段修改命令行参数
    模块导入时无条件执行两次 sys.argv.pop(1)。其他测试发现器或导入工具可能触发 IndexError,也可能意外消费调用方参数。

Strengths

  • 统一 MoE 布局解析,减少普通加载与在线量化路径漂移。
  • FastSafeTensors 能力降级、显存预检和 scratch 回滚设计清晰。
  • CUDA 13 wheel 元数据、哈希固定及 ARM 专属依赖已有平台级校验。
  • 新增真实双卡测试,覆盖按秩过滤、广播和存储所有权。

Comment thread arch_config/arch_select.bzl Outdated
# installing the RTP-LLM wheel cannot silently select another ABI.
"torch@https://rtp-opensource.oss-cn-hangzhou.aliyuncs.com/rtp_llm/cu129/torch-2.8.0%2Bcu129-cp310-cp310-manylinux_2_28_x86_64.whl#sha256=54d240b5d3b1f9075d4ee6179675a22c1974f7bef1885d134c582678d5180cd3",
"torchvision@https://rtp-opensource.oss-cn-hangzhou.aliyuncs.com/rtp_llm/cu129/torchvision-0.23.0%2Bcu129-cp310-cp310-manylinux_2_28_x86_64.whl#sha256=5690810877f2d7d1a2b432e31d68d4a9ccbb695a9a8fa0e27bbad44c6a90a181",
"fast-safetensors@https://rtp-opensource.oss-cn-hangzhou.aliyuncs.com/rtp_llm/cu129/fast_safetensors-0.7.3%2Btorch2.1.2.cu121-cp310-cp310-linux_x86_64.whl#sha256=dd760931feb6dd585cc0b14b1bacf39c1e31a39bb9f8e12a8c62720caf1ccc1f",

Copy link
Copy Markdown
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

[P1] CUDA 12.9 wheel 强制安装与 Torch/CUDA 不匹配的原生扩展

CUDA 12.9 wheel 固定 Torch 2.8+cu129,却同时安装文件名明确针对 Torch 2.1.2+cu121 构建的 fast-safetensors 原生扩展。默认 FuseShm 路径会加载该扩展,可能产生 ABI 错误并导致快速加载退化或启动失败。

建议: 提供针对 Torch 2.8+cu129 构建的扩展 wheel,同步 requirements、lock 与 whl_deps(),并在干净环境中验证安装、导入和真实 AutoLoader 加载。

Comment thread rtp_llm/utils/database.py Outdated
Comment thread rtp_llm/utils/test/BUILD
}),
)

py_test(

Copy link
Copy Markdown
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

[P1] CUDA 12 ARM wheel 依赖分支缺少元数据回归测试

whl_deps() 新增独立的 using_cuda12_arm 分支,但期望表和 BUILD 目标仅覆盖 CUDA 12.9 x86、CUDA 13 x86 与 CUDA 13 ARM。该平台的依赖缺失、哈希错误或架构漂移不会被此发布门禁发现。

建议: 增加 CUDA 12 ARM 期望映射和对应 Bazel 测试目标。

@LLLLKKKK LLLLKKKK left a comment

Copy link
Copy Markdown
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

AI Code Review - PR #1354 (non-blocking suggestions)

4 条 P2/P3 建议,不阻塞合并。阻塞判定与完整摘要见上一条 review。



class RtpLlmWheelMetadataTest(unittest.TestCase):
def test_direct_requirements_match_platform_lock_file(self) -> None:

Copy link
Copy Markdown
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

[P2] wheel 元数据测试未验证锁文件与平台依赖全集

名为 match_platform_lock_file 的测试未读取锁文件,只比较手写期望子集,也不拒绝额外的平台敏感依赖。锁文件与测试复制相同错误,或 wheel 混入其他平台依赖时仍会通过。

建议: 解析平台锁文件或从单一清单生成两侧数据,并对平台敏感直接依赖执行集合全等校验。

Checklist: [6.1] DRY:重复非平凡逻辑被抽取或显式复用;[I] 同一功能用统一工具函数

)
with tempfile.TemporaryDirectory() as tmp_dir:
checkpoint_path = os.path.join(tmp_dir, "model.safetensors")
save_file(

Copy link
Copy Markdown
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

[P2] 真实多卡测试未覆盖 UE8M0 广播兼容路径

checkpoint 仅包含 float32 张量,测试也未按生产入口加载 torch_patch,因此新增的 UE8M0 到 uint8 广播兼容逻辑从未触发;该 shim 失效时双卡测试仍会通过。

建议: 增加 UE8M0 双 rank 广播场景,按生产入口加载补丁,并逐 rank 校验 dtype 与原始字节。

Checklist: [6.1] 分布式/跨平台变更有对应覆盖;[6.1] 新逻辑有聚焦单测 + 相关集成/smoke 测试

# the integration test cheap.
os.environ["FASTSAFETENSORS_NOGDS"] = "0"
os.environ.pop("FASTSAFETENSORS_CONFIG", None)
os.environ["FASTSAFETENSORS_CONFIG_JSON"] = json.dumps(

Copy link
Copy Markdown
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

[P2] 双 rank 用例未跨越配置的分块边界

I/O 与 batch 上限均为 64 KiB,但 checkpoint 仅包含 10 个 float32 元素。虽然启用了 chunked_loading,实际未覆盖多 chunk 切换、刷新或跨 chunk 存储生命周期。

建议: 加入超过 64 KiB 的张量或累计超限的多个张量,并保留按秩键值及关闭后存储有效性断言。

Checklist: [6.1] 边界 case 覆盖(空、单元素、最大值)

Comment thread rtp_llm/utils/test/rtp_llm_wheel_metadata_test.py Outdated
@ABNER-1
ABNER-1 requested a review from LLLLKKKK September 1, 2026 16:30

@LLLLKKKK LLLLKKKK left a comment

Copy link
Copy Markdown
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

AI Code Review - PR #1354

Status: BLOCKING

Summary: P0/0 · P1/4 · P2/0 · P3/0

Reviewed: commit 162e7fa658a4 · 2026-09-02 01:15 UTC+8

Blocking Issues

P1

  • CUDA 12 ARM 专属依赖仓库缺少构建所需包 @ arch_config/arch_select.bzl:50
    • 建议:在 requirement() 中接入 pip_cuda12_arm_torch,补齐 ARM 锁文件所需包,并为 torch_deps() 注册匹配的 CUDA 12 AArch64 Torch;否则移除该配置及对应 CI。
  • CUDA 12 ARM wheel 依赖分支缺少元数据回归测试 @ rtp_llm/utils/test/BUILD:179
    • 建议:增加独立的 using_cuda12_arm wheel 依赖分支,并添加基于 requirements_lock_cuda12_arm.txt 的元数据测试,校验平台、架构、URL 和哈希全集。
  • CUDA 12.9 wheel 强制安装与 Torch/CUDA 不匹配的原生扩展 @ arch_config/arch_select.bzl:94
    • 建议:提供针对 Torch 2.8/CUDA 12.9 重编译的制品,同步更新源需求、锁文件和 wheel 元数据,并用最终 wheel 执行原生导入及真实 AutoLoader 加载测试。
  • 固定 2 GiB 预留无法约束 stacked-MoE 权重拼装峰值 @ rtp_llm/model_loader/loader.py:465
    • 建议:按本 rank 专家数量、形状、dtype 和 TP 切分计算 RTP 侧重叠上界;完成量测前至少保留旧预算下界,并增加组件峰值超过 2 GiB 的 stacked-MoE 预检测试。

Checklist Findings (5 fail / 121 total)

General Principles Checklist

  • [6.1] Architecture — 依赖方向:无循环依赖/跨层惊喜 → issue CUDA 12 ARM 专属依赖仓库缺少构建所需包
    cuda12_9_arm 设置 using_cuda12_arm=true,因此不匹配要求该值为 false 的 cuda_pre_12_9requirement() 没有 CUDA 12 ARM 分支,会落到 CPU 仓库;torch_deps() 同样落到 x86 CPU Torch。CPU 锁中不存在 BUILD 请求的 fast-safetensorsfastsafetensors 等目标,保留的 ARM CI 配置会分析失败或选错 Torch。
  • [6.1] Architecture — 兼容性:外部 HTTP/RPC API、持久数据、配置、环境迁移安全 → issue CUDA 12.9 wheel 强制安装与 Torch/CUDA 不匹配的原生扩展
    CUDA 12.9 wheel 同时固定 Torch 2.8+cu129 与文件名明确标记为 Torch 2.1.2+cu121 的 fast-safetensors 原生扩展。锁文件和元数据测试复制了相同组合,只能验证声明一致,无法保证 Torch/CUDA ABI;干净安装后导入或 FuseShm 加载可能因符号不兼容失败。
  • [6.1] Architecture — 状态不变量:创建/更新/失败/重试/回滚路径有效 → issue 固定 2 GiB 预留无法约束 stacked-MoE 权重拼装峰值
    任意正数 estimated_peak_device_bytes 都会取代旧的 3 * max_file_size 下界,并仅增加固定 2 GiB。TensorCollector 会保留一个 rank-local MoE 组件的全部专家张量,weight.load 又分配最终合并张量,完成后才清空 collector。该重叠随专家数、形状和 dtype 增长,可超过 2 GiB,导致 AUTO 误判并在启动时 OOM。
  • [6.1] Tests — 分布式/跨平台变更有对应覆盖 → issue CUDA 12 ARM wheel 依赖分支缺少元数据回归测试
    当前仅定义 CUDA 12.9 x86、CUDA 13 x86 和 CUDA 13 ARM 的 wheel 元数据测试。CUDA 12 ARM 仍是保留的构建配置,却没有对应测试;其 whl_deps() 会命中通用 using_cuda12 分支,写入 x86 CUDA 12.6 Torch 且缺少 FastSafeTensors 直接依赖,现有测试无法发现该错误。
  • [6.1] Tests — 边界 case 覆盖(空、单元素、最大值) → issue 固定 2 GiB 预留无法约束 stacked-MoE 权重拼装峰值
    任意正数 estimated_peak_device_bytes 都会取代旧的 3 * max_file_size 下界,并仅增加固定 2 GiB。TensorCollector 会保留一个 rank-local MoE 组件的全部专家张量,weight.load 又分配最终合并张量,完成后才清空 collector。该重叠随专家数、形状和 dtype 增长,可超过 2 GiB,导致 AUTO 误判并在启动时 OOM。

Strengths

  • AutoLoader 能力协商、兼容性降级和数据错误 fail-fast 语义清晰。
  • MoE 布局解析集中到统一入口,减少普通与在线 FP8 路径的判断偏差。
  • 真实双 rank 测试覆盖分片、rank-local copyout、UE8M0 广播和 FuseShm 分块边界。
  • wheel 元数据测试已覆盖 CUDA 12.9 x86、CUDA 13 x86 和 CUDA 13 ARM。

"@rtp_llm//:using_cuda12_9_x86": [requirement_gpu_cuda12_9(name)],
"@rtp_llm//:using_cuda13_arm": cuda13_arm_deps,
"@rtp_llm//:using_rocm": [requirement_gpu_rocm(name)],
"@rtp_llm//:using_arm": [requirement_arm(name)],

Copy link
Copy Markdown
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

[P1] CUDA 12 ARM 专属依赖仓库缺少构建所需包

cuda12_9_arm 设置 using_cuda12_arm=true,因此不匹配要求该值为 false 的 cuda_pre_12_9requirement() 没有 CUDA 12 ARM 分支,会落到 CPU 仓库;torch_deps() 同样落到 x86 CPU Torch。CPU 锁中不存在 BUILD 请求的 fast-safetensorsfastsafetensors 等目标,保留的 ARM CI 配置会分析失败或选错 Torch。

建议:requirement() 中接入 pip_cuda12_arm_torch,补齐 ARM 锁文件所需包,并为 torch_deps() 注册匹配的 CUDA 12 AArch64 Torch;否则移除该配置及对应 CI。

Checklist: [6.1] 依赖方向:无循环依赖/跨层惊喜

Comment thread rtp_llm/utils/test/BUILD
}),
)

py_test(

Copy link
Copy Markdown
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

[P1] CUDA 12 ARM wheel 依赖分支缺少元数据回归测试

当前仅定义 CUDA 12.9 x86、CUDA 13 x86 和 CUDA 13 ARM 的 wheel 元数据测试。CUDA 12 ARM 仍是保留的构建配置,却没有对应测试;其 whl_deps() 会命中通用 using_cuda12 分支,写入 x86 CUDA 12.6 Torch 且缺少 FastSafeTensors 直接依赖,现有测试无法发现该错误。

建议: 增加独立的 using_cuda12_arm wheel 依赖分支,并添加基于 requirements_lock_cuda12_arm.txt 的元数据测试,校验平台、架构、URL 和哈希全集。

Checklist: [6.1] 分布式/跨平台变更有对应覆盖

# installing the RTP-LLM wheel cannot silently select another ABI.
"torch@https://rtp-opensource.oss-cn-hangzhou.aliyuncs.com/rtp_llm/cu129/torch-2.8.0%2Bcu129-cp310-cp310-manylinux_2_28_x86_64.whl#sha256=54d240b5d3b1f9075d4ee6179675a22c1974f7bef1885d134c582678d5180cd3",
"torchvision@https://rtp-opensource.oss-cn-hangzhou.aliyuncs.com/rtp_llm/cu129/torchvision-0.23.0%2Bcu129-cp310-cp310-manylinux_2_28_x86_64.whl#sha256=5690810877f2d7d1a2b432e31d68d4a9ccbb695a9a8fa0e27bbad44c6a90a181",
"fast-safetensors@https://rtp-opensource.oss-cn-hangzhou.aliyuncs.com/rtp_llm/cu129/fast_safetensors-0.7.3%2Btorch2.1.2.cu121-cp310-cp310-linux_x86_64.whl#sha256=dd760931feb6dd585cc0b14b1bacf39c1e31a39bb9f8e12a8c62720caf1ccc1f",

Copy link
Copy Markdown
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

[P1] CUDA 12.9 wheel 强制安装与 Torch/CUDA 不匹配的原生扩展

CUDA 12.9 wheel 同时固定 Torch 2.8+cu129 与文件名明确标记为 Torch 2.1.2+cu121 的 fast-safetensors 原生扩展。锁文件和元数据测试复制了相同组合,只能验证声明一致,无法保证 Torch/CUDA ABI;干净安装后导入或 FuseShm 加载可能因符号不兼容失败。

建议: 提供针对 Torch 2.8/CUDA 12.9 重编译的制品,同步更新源需求、锁文件和 wheel 元数据,并用最终 wheel 执行原生导入及真实 AutoLoader 加载测试。

Checklist: [6.1] 兼容性:外部 HTTP/RPC API、持久数据、配置、环境迁移安全

)
budget = legacy_budget
else:
budget = int(estimate)

Copy link
Copy Markdown
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

[P1] 固定 2 GiB 预留无法约束 stacked-MoE 权重拼装峰值

任意正数 estimated_peak_device_bytes 都会取代旧的 3 * max_file_size 下界,并仅增加固定 2 GiB。TensorCollector 会保留一个 rank-local MoE 组件的全部专家张量,weight.load 又分配最终合并张量,完成后才清空 collector。该重叠随专家数、形状和 dtype 增长,可超过 2 GiB,导致 AUTO 误判并在启动时 OOM。

建议: 按本 rank 专家数量、形状、dtype 和 TP 切分计算 RTP 侧重叠上界;完成量测前至少保留旧预算下界,并增加组件峰值超过 2 GiB 的 stacked-MoE 预检测试。

Checklist: [6.1] 状态不变量:创建/更新/失败/重试/回滚路径有效;[6.1] 边界 case 覆盖(空、单元素、最大值)

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

4 participants