Prhub

#3086 dashboard: pin the anatomy lane to a duplicated index's first leaf

原始 PR 作者 Shi-Dong 合并时间 2026-09-04 08:42 文件变更 1 提交数 1 评论 1 代码增减 +5 / -1

执行摘要

修复 Dashboard 轨迹面板数据映射错误,确保标签与点击行为指向同一叶子样本。

本 PR 是 PR#2881 的后续修复。PR body 明确指出,随着 PR#2881 的合并,一个 TITO 索引(sample_index)可能包含多个摘要行(每个 sample_occurrence 对应一行)。原有的 new Map(rows.map((r) => [r.sample_index, r])) 构建方式会导致“最后写入者胜出”(last-one-wins),使得面板(anatomy lane)标记(label)的是最后一个叶子的信息,但点击该行时,onClickSample 硬编码地打开 sample_occurrence: 0 的 token 视图,造成了标签与内容不符的用户体验 bug。

此 PR 值得精读,特别是对于参与 Dashboard 开发的工程师。它展示了一个典型的“数据一致性”修复模式:当业务数据模型(如支持多叶子的 TITO 索引)发生变化时,需要审视所有消费该数据的组件(如 Map 构建)是否仍然适用。修复本身简洁有效,且附有清晰的解释性注释,是维护代码可读性的好实践。对于理解 PR#2881 的完整影响至关重要。

讨论亮点

Review 讨论主要由 claude[bot] 发起,结论清晰:

  1. 核心验证:claude[bot] 通过代码检查确认,onClickSample 函数始终打开 sample_occurrence: 0,因此新的过滤逻辑(只保留 occurrence-0 的行放入 rowsByIndex)能正确地让面板显示的标签与点击后打开的内容对齐,解决了 last-one-wins 的不匹配问题。
  2. 风险评估:claude[bot] 认为此变更风险低(Low),是客户端渲染逻辑的小幅、自包含修改,不涉及安全或数据暴露问题。
  3. 测试覆盖:claude[bot] 指出前端模块无测试框架,但鉴于变更简单,通过代码推理已足够验证。
  4. 最终决策:Zhichenzzz 给出 LGTM 批准。整个讨论确认了修复的正确性和低风险性。

实现拆解

  1. 变更入口:修改 miles/dashboard/static/views_rollout.js 文件中 samplesTab 函数内构建 createAnatomy 面板参数的逻辑。
  2. 核心逻辑修正:将 rowsByIndex 的构建方式从 new Map(rows.map((r) => [r.sample_index, r])) 改为 new Map(rows.filter((r) => (r.sample_occurrence ?? 0) === 0).map((r) => [r.sample_index, r]))。此过滤确保了 Map 中每个 sample_index 对应的行是 sample_occurrence 为 0(或空值视为 0)的那一行,即第一个叶子。
  3. 文档注释:在修改的代码行上方添加了四行注释,解释了 TITO 索引可能存在多个叶子的情况,以及为什么现在需要固定到第一个叶子(first leaf),同时说明了页面下方的 samples 表格仍然可以访问所有 (index, occurrence) 组合的行。
  4. 配套验证:PR 描述中提到 node --check 通过了语法检查。由于 dashboard 前端没有测试框架,本次未增加自动化测试,但变更通过人工推理确认是正确且自包含的。
文件 模块 状态 重要度
miles/dashboard/static/views_rollout.js 轨迹面板 modified 4.79

关键符号

createAnatomy openTokens samplesTab

关键源码片段

miles/dashboard/static/views_rollout.js core-logic

这是本次修复的唯一变更文件。其核心逻辑是构建 `createAnatomy` 面板所需的 `rowsByIndex` 映射表,修复了因数据模型变化(多叶子样本)导致的显示与交互不一致问题。

// 从 rows 数组构建行数据的索引映射(Map),供 anatomy 面板使用
rowsByIndex: new Map(
  rows
    // 过滤:仅保留 sample_occurrence 为 0(或未设置视为 0)的行。
    // 因为一个 sample_index 可能对应多个叶子(occurrence > 0)。
    // 动作执行生命周期面板展示的是所有叶子共享的执行过程,
    // 我们固定展示并打开第一个叶子(occurrence 0)以保持一致性。
    // 页面下方的 samples 表格仍可访问所有 (index, occurrence) 的行。
    .filter((r) => (r.sample_occurrence ?? 0) === 0)
    .map((r) => [r.sample_index, r])
),

评论区精华

验证修复逻辑与 `onClickSample` 的一致性 正确性

`claude[bot]` 通过代码检查确认 `onClickSample` 函数硬编码地打开 `sample_occurrence: 0` 的 token 视图,因此新的过滤逻辑(只保留 occurrence-0 的行放入 `rowsByIndex`)能正确解决 `last-one-wins` 导致的标签与内容不匹配问题。

结论:修复逻辑正确且自包含,面板标签与点击行为现已对齐。 · 已解决

评估前端变更的测试策略与风险 测试

`claude[bot]` 指出 dashboard 前端无测试框架,但鉴于此次变更非常简单(单行过滤加注释),通过人工推理代码足够验证其正确性。

结论:变更无需自动化测试覆盖,但承认了前端缺乏测试基础设施的现状。 · 已解决

风险与影响

  1. 回归风险:低。变更影响范围严格限于 Dashboard 的 Trajectories 面板中的 anatomy lane(生命周期面板),不影响下方的 samples 表格(使用完整 rows 数组)或其他功能。
  2. 功能风险:极低。修改本质是数据源过滤,确保了 UI 数据的一致性。逻辑简单,onClickSample 的硬编码值与过滤条件匹配。
  3. 测试风险:存在。PR 明确说明 dashboard 前端无测试框架,因此本次修复没有自动化测试覆盖。虽然通过代码审查可确认逻辑,但缺乏测试意味着未来相关代码变更可能意外破坏此行为,缺乏自动化的回归保障。
  1. 用户影响:直接影响使用 Dashboard 查看训练轨迹(Trajectories)的用户。修复前,用户看到的生命周期面板标签信息(奖励、长度等)可能属于一个样本,但点击后查看的 token 视图是另一个样本,造成混淆。修复后,两者将保持一致,提升数据观测的准确性和用户体验。
  2. 系统影响:无。这是纯前端展示逻辑的修正,不涉及后端数据流、API 或训练核心逻辑。
  3. 团队影响:这是一个维护性修复,清理了 PR#2881 引入的一个细微数据不一致问题,保持了代码库的健康度。它提醒团队在处理具有多态索引的数据结构时,需要注意映射(Map)键的唯一性隐含假设。
前端无测试覆盖

关联 Issue

未识别关联 Issue

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

完整报告

参与讨论