Files
worldmodel/plans/PRISM/18_lyra_inspirations.md
T
gaojie dbcbdbb59e chore: 为所有 md 文件添加 Hugo front matter
- 处理: 74 个 .md 文件
- 跳过: 0 个(无已存在的 front matter)
- 异常: 3 个(H1 缺失,用文件名兜底)
  - plans/PRISM/.research/readmes/3d-llm.md
  - plans/PRISM/.research/readmes/openmask3d.md
  - plans/PRISM/.research/readmes/openscene.md
2026-05-20 22:42:22 +08:00

266 lines
19 KiB
Markdown
Raw Blame History

This file contains ambiguous Unicode characters
This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.
---
title: "Chapter 18 — Lyra 2.0 启发的设计原则"
date: 2026-05-20
draft: false
tags: ["PRISM", "世界模型", "空间记忆", "SLAM", "点云", "综述"]
categories: ["worldmodel"]
---
# Chapter 18 — Lyra 2.0 启发的设计原则
> 本章目标:把 Lyra 2.0Self-Distillation Bootstraps 3D World Models from 2D Video Diffusion, 2025)译读 [`research/lyra2_review.md`](../../research/lyra2_review.md) 第 8.4 节归纳出的 **3 条核心思想** 正式纳入 PRISM 设计哲学——分别约束 **L2 ↔ L3 ↔ L4 的写入语义**、**SpatialMemory 的证据保留策略** 与 **Pipeline D 的巩固训练范式**。本章是 PRISM v1.5.0 的新增内容。
---
## 18.1 章节目的
Lyra 2.0 是 2025 年 NVIDIA 用 2D 视频扩散模型"自蒸馏"出一个 3D 世界模型的工作;它的"3D 缓存"在工程上和 PRISM 的"空间记忆"是**同类问题**:都需要在多帧观测之间保留 3D 一致性、又都必须容忍**几何精度不够好**这一事实。Lyra 没有 SLAM、没有 TSDF,却用三个看似反直觉的工程决策——**几何只做路由、per-frame 缓存绝不融合、巩固期用自己的不完美输出再训练**——把"精度不够"的几何先验稳稳压在了"够用"的工作点上。这些决策与 PRISM 当下的痛点(L2 漂移、L3 写入污染、Pipeline D 缺少自监督信号)高度对应,因此值得作为**独立章节**沉淀下来,避免在后续 v1.x 演进中被遗忘或被工程惯性悄悄抹去。本章按"原则陈述 → 工程对应 → 风险约束"的顺序组织:每条原则先讲 Lyra 怎么做、再讲 PRISM 该怎么对应,最后在 § 18.6 集中说明哪些地方**不**能照搬。更深的技术细节请回看 [`research/lyra2_review.md`](../../research/lyra2_review.md) § 3.23D 缓存设计)与 § 3.3self-augmentation 公式)。
---
## 18.2 原则一:几何只做路由,不做合成
### 18.2.1 问题描述
PRISM v1.4 之前的写入逻辑里,L2 既要"提供占据栅格供避障",又要"把局部几何投到 L3 节点的子图里当内容"。这意味着 **L2 的几何误差会污染 L3 的内容**——例如 TSDF 在长走廊里漂了 30 cmL3 中"走廊节点"挂的那块点云也跟着歪 30 cm,后续 L4 的 bbox 估计也会跟着歪。
Lyra 2.0 § 3.2(a) 的做法给出了一个干净的解耦:**3D 缓存只用来"挑选哪一帧 keyframe 该被注意到",真正的内容(颜色、纹理、语义)由原始 2D 帧的 cross-attention 提供**。换言之,几何只回答"路由问题"who should write where),不回答"内容问题"what to write)。
### 18.2.2 PRISM 旧逻辑 vs PRISM 新逻辑
```mermaid
flowchart TB
subgraph OLD["PRISM v1.4 旧:L2 既路由又写 L3"]
direction LR
O_L1["L1 keyframe<br/>(rgb+depth)"]
O_L2["L2 TSDF/Octomap"]
O_L3["L3 节点子图"]
O_L1 --> O_L2
O_L2 -- "投影点云<br/>(内容)" --> O_L3
O_L2 -- "路由<br/>(选哪个节点)" --> O_L3
end
subgraph NEW["PRISM v1.5 新:L2 只路由,L3 内容来自 L1"]
direction LR
N_L1["L1 keyframe<br/>(rgb+depth)"]
N_L2["L2 TSDF/Octomap<br/>(几何精度允许低)"]
N_L3["L3 节点子图"]
N_L1 --> N_L2
N_L2 -- "路由<br/>(only: select node)" --> N_L3
N_L1 -. "内容<br/>(keyframe ref)" .-> N_L3
end
style OLD fill:#fde2e2,stroke:#a33
style NEW fill:#d4f0d4,stroke:#2e7d32
```
关键差异:**新逻辑下 L3 节点存的不是"L2 几何投影出来的点云",而是"指向 L1 keyframe 的引用 + L2 给出的路由决策"**。L2 即便漂 30 cm,只要它能正确挑出"这一帧属于走廊节点而不是卧室节点",下游就不受影响——内容由 L1 原始观测兜底。
### 18.2.3 伪代码
```python
# prism/write/route_l3.py (v1.5 新增)
def route_and_write_l3(
keyframe: L1Keyframe, # 原始观测:rgb + depth + pose
l2: MetricLayer, # 可能有漂移的 TSDF/Octomap
l3: TopologicalLayer, # 节点 + 边
) -> None:
"""
几何只做路由:用 L2 决定 keyframe 该挂到哪个 L3 节点;
L3 的"内容"始终是 keyframe 的引用,不复制几何。
"""
# ---- 步骤 1: 用 L2 做路由(几何精度低也无妨) ----
pose_xy = keyframe.pose.translation[:2]
candidate_nodes = l2.query_room_id(pose_xy) # 返回若干候选节点
node_id = l3.disambiguate(candidate_nodes, keyframe) # 用 keyframe 视觉再确认
# ---- 步骤 2: L3 只写引用 + 路由元数据,不写几何 ----
l3.nodes[node_id].keyframe_refs.append(keyframe.id)
l3.nodes[node_id].routing_log.append({
"kf_id": keyframe.id,
"l2_pose": pose_xy.tolist(),
"l2_uncert": l2.local_uncertainty(pose_xy), # 路由置信度
"ts": keyframe.ts,
})
# ---- 步骤 3: 内容查询时,按需从 L1 读回 ----
# L3.get_content(node_id) 实现里只做 L1Keyframe 的解引用,
# 不缓存任何 L2 投影点云。这是与旧版的根本区别。)
```
设计含义:**L2 漂移不再是 L3 的故障,而只是 L3 路由的噪声**——可以通过 § 18.3 的 keyframe 独立证据来事后翻案,而不必反向修补 L2。另一个常被忽视的好处是:当未来引入 NeRF / 3DGS 之类的精细几何表示时,它们也只是 L3 的"另一种内容引用"**不会与 L2 抢"几何真相代言人"的位置**——L2 始终只代表"路由用的粗几何",L3 内容由谁提供、提供得多精细,是写入策略的自由度而非架构约束。这一点对应 Lyra § 3.2(d) 中 canonical coordinates **只参与 Q/K 不参与 V** 的设计:粗坐标只用于"挑出谁该被注意到(Q/K 路由)",但模型实际看到的内容(V)来自原始 2D 帧。
详见对 [`plans/PRISM/03_data_schema.md`](03_data_schema.md) 与 [`plans/PRISM/06_pipeline_C_online_perception.md`](06_pipeline_C_online_perception.md) 的影响(§ 18.5 总表)。
---
## 18.3 原则二:Per-frame 独立 keyframe 证据,而非全局融合
### 18.3.1 问题描述
PRISM 现行的 L2 是**融合表示**:TSDF 把每一帧深度都"加权累计"到体素里、OctoMap 把每一帧 ray 都更新到八叉树占据概率上。融合带来两个好处(紧凑、平滑)和一个致命缺点:**一旦累计了漂移,原始证据就不可逆地丢了**——你拿不回"第 t=12.3 s 那一帧 ZED 看到桌子在哪",因为它已经被融进了 240 万个体素的加权平均里。
Lyra 2.0 § 3.2(a) 把这点写得很明白:"**3D 缓存绝不融合(never fuse**"——每个 keyframe 是一条独立的、可追溯的证据,模型在 cross-attention 时挑出最相关的几条 keyframe,而不是查询一个"已经融合过的全局体素"。
### 18.3.2 三种策略对比
| 维度 | OctoMap-onlyPRISM v1.0 | TSDF-onlyPRISM v1.3 | Lyra-style per-frame | **PRISM v1.5 选择** |
|------|---|---|---|---|
| 表示 | 八叉树占据概率 | 体素 SDF | keyframe 列表(pose + depth + 特征) | **TSDF(路由)+ keyframe 列表(证据)** |
| 漂移可逆 | ✗(已融合) | ✗(已融合) | ✓(每帧独立) | ✓(keyframe 兜底) |
| 内存 | O(体素数) | O(体素数) | O(帧数 × 单帧大小) | **O(体素 + 关键帧子集)** |
| 避障查询 | 快(直接查体素) | 中 | 慢(要做近邻) | **快(用 TSDF** |
| "翻案"能力 | 无 | 无 | 强 | **强(保留 keyframe** |
| 写入语义 | 累加 | 加权融合 | append-only | **append-only on keyframes** |
PRISM v1.5 不是把 TSDF 扔掉,而是**让 TSDF 和 keyframe 列表并存**TSDF 负责 § 18.2 的"路由 + 避障"两个对几何精度要求不高的任务;keyframe 列表负责"翻案"——当 L4 发现某个语义节点和 L3 节点对不齐时,可以回退到 keyframe 重新估计 bbox。
### 18.3.3 SpatialMemory 新增字段 schema
```python
# prism/schema/spatial_memory.py (v1.5 新增字段)
@dataclass
class KeyframeEvidence:
"""
每个 L1 keyframe 在巩固后保留的"独立证据"
一律 append-only,绝不被 L2 融合操作覆盖。
"""
kf_id: str # 全局唯一,匹配 L1.frames[i].id
ts: float # 采集时间戳 (epoch sec)
pose: SE3 # 该帧位姿 (世界系)
pose_uncert: np.ndarray # 6x6 协方差 (路由置信度的来源)
depth_ref: str # 指向 L1 存储的深度图 blob (lazy load)
feat_ref: str # 指向 L1 存储的视觉特征 blob (DINO/CLIP)
routed_l3: Optional[str] # 当时路由到的 L3 节点 id (可空)
routed_l4: List[str] # 当时关联的 L4 实体 id 列表
fused_into_l2: bool = False # 是否曾参与 L2 TSDF 融合
immutable: bool = True # 一律 True;写入后不可被覆盖
@dataclass
class SpatialMemory:
l1: L1Buffer
l2: MetricLayer
l3: TopologicalLayer
l4: SemanticGraph
# ---- v1.5 新增 ----
keyframe_evidence: List[KeyframeEvidence] # append-only,巩固期挑选关键帧入库
```
实现要点:
1. **append-only**`KeyframeEvidence` 一旦写入即 `immutable=True`,禁止任何 pipeline 反向修改;
2. **lazy load**`depth_ref / feat_ref` 只存路径,原始张量留在 L1 的 zarr/parquet 里,避免内存爆掉;
3. **不是全部 keyframe 都进**Pipeline D 巩固期会按"信息增益"挑一个子集(如每 0.5 m 或每 30° 视角变化保留一帧),典型规模 200–2000 帧/场景。
详见 § 18.5 对 [`plans/PRISM/03_data_schema.md`](03_data_schema.md) 的影响。
---
## 18.4 原则三:巩固期的 Self-Augmentation
### 18.4.1 问题描述
Pipeline D(巩固期,离线 / 夜间)目前的逻辑是:拿白天采集的 L1 keyframe,运行更慢更准的离线管线(高分辨率 depth、bundle adjustment、全局优化),把结果写回 L3/L4。这个过程**没有自监督信号**——它假设"离线版的输出就是 ground-truth",但实际工程中离线版本身也会犯错,且模型从不学会"识别并纠正自己之前的错"。
Lyra 2.0 § 3.3(b) 给了一个简洁的 self-augmentation 公式:**用模型自己之前的不完美输出作为输入,用干净的 ground-truth 作为监督**。具体地,对训练样本的潜变量 $z$,以概率 $p_{\text{aug}}=0.7$ 做扰动:
$$
\tilde z_0 = z_t - t \cdot v_\theta(z_t, t, c), \quad t \sim \mathcal{U}(0, 0.5)
$$
其中 $v_\theta$ 是当前正在训练的流匹配模型自己。这相当于让模型把"自己一步去噪后的结果"当成新输入,再去预测真值——模型在训练中**反复见到自己会犯的错**,因此学会了自我纠错。
### 18.4.2 在 PRISM 巩固期的对应
把上面的范式翻译到 PRISM Pipeline D
- **z**:当前场景的 L3/L4 表示(拓扑节点 + 场景图 bbox);
- **不完美输入 $\tilde z_0$**:用 Pipeline C 在线版(实时但粗)的 L3/L4 输出;
- **ground-truth 监督**:用 Pipeline A 离线版(慢但准)的 L3/L4 输出。
模型(这里指 L3/L4 的精炼网络,未来 v2.0 的研究方向)学会的不是"从零产生 L3/L4",而是"**从一份带错的 L3/L4 + 当时的 keyframe 证据**,产生干净的 L3/L4"——这恰好就是"巩固"的本质。
### 18.4.3 伪代码
```python
# prism/pipeline_d/self_aug.py (v1.5 新增,实际实现见 v2.0 路线图)
def consolidate_with_self_aug(
online_l3l4: SceneRepr, # Pipeline C 的不完美输出
offline_l3l4: SceneRepr, # Pipeline A 的"较干净"输出 (监督信号)
kf_evidence: List[KeyframeEvidence],
refiner: RefinerNet, # 待训练的精炼网络
p_aug: float = 0.7,
t_max: float = 0.5,
) -> RefinerNet:
"""
巩固期 self-augmentation:
以 p_aug 概率用模型自己产生的"伪不完美样本"替换 online_l3l4,
用 offline_l3l4 作为干净监督。
"""
for batch in iterate_scenes():
# ---- 1. 决定本步是否使用 self-aug ----
if np.random.rand() < p_aug:
# 用模型自己生成一个"扰动版"的输入
t = np.random.uniform(0.0, t_max)
z_clean = encode(offline_l3l4) # 干净潜变量
z_t = add_flow_noise(z_clean, t) # 沿流方向加噪
v_pred = refiner.predict_velocity(z_t, t, kf_evidence)
z_tilde = z_t - t * v_pred # 模型一步去噪结果
x_in = decode(z_tilde) # 解回 L3/L4 表示
else:
# 1 - p_aug = 0.3 概率用真实的"在线不完美输出"
x_in = online_l3l4
# ---- 2. 统一的监督:始终向 offline 版对齐 ----
x_pred = refiner(x_in, kf_evidence) # keyframe 证据可被检索
loss = scene_repr_loss(x_pred, offline_l3l4)
loss.backward(); refiner.step()
return refiner
```
### 18.4.4 关于 $p_{\text{aug}} = 0.7$ 的取值讨论
Lyra 2.0 实验里取 $p_{\text{aug}}=0.7$ 而非 0.5 或 1.0,有两个工程意涵值得我们沿用:
1. **0.7 > 0.5 表示模型主要见到的是"自己生成的扰动样本"**——这是它真正会犯的错;如果 $p$ 太低(如 0.3),模型大部分时间在做"干净到干净"的精炼,巩固期就退化成普通监督学习,失去自我纠错能力。
2. **0.7 < 1.0 留了 30% 真实的"在线不完美样本"**——这部分确保模型不会沉迷于自己的失败模式,仍然能见到 Pipeline C 在真实工况下产生的、分布与 self-aug 不一样的错(如 ZED 在暗光下的深度毛刺,模型自己生成的样本里不一定包含)。
经验上:当 Pipeline C 已经相当稳定(错误率低且类型集中)时,可降到 0.5;当 Pipeline C 仍在快速演化、错误模式多样时,可推到 0.8。PRISM v1.5 起步采用 **0.7**,作为后续 ablation 的中点。
$t \sim \mathcal{U}(0, 0.5)$ 的含义是:只在流匹配的"前半程"加噪——避免把样本扰动到几乎全噪声,那样监督信号会失效。
详见 § 18.5 对 [`plans/PRISM/07_pipeline_D_consolidation.md`](07_pipeline_D_consolidation.md) 的影响。
---
## 18.5 与 PRISM 现有章节的关系
本章的三条原则并不是"另起炉灶",而是**约束既有章节在 v1.5 及之后的演进方向**。下表列出影响面:
| 本章原则 | 影响的现有章节 | 具体影响内容 | 回链 |
|---|---|---|---|
| § 18.2 几何只做路由 | Chapter 02 架构 | L2 ↔ L3 边的语义从"投影内容 + 路由"收窄为"只做路由" | [`plans/PRISM/02_architecture.md`](02_architecture.md) |
| § 18.2 几何只做路由 | Chapter 03 数据 schema | `L3Node.content` 从"几何点云"改为"keyframe 引用列表" | [`plans/PRISM/03_data_schema.md`](03_data_schema.md) |
| § 18.2 几何只做路由 | Chapter 06 Pipeline C 在线 | `route_and_write_l3()` 替换原"投影 + 写内容"两步 | [`plans/PRISM/06_pipeline_C_online_perception.md`](06_pipeline_C_online_perception.md) |
| § 18.3 keyframe 独立证据 | Chapter 03 数据 schema | 新增 `SpatialMemory.keyframe_evidence: List[KeyframeEvidence]` 字段 | [`plans/PRISM/03_data_schema.md`](03_data_schema.md) |
| § 18.3 keyframe 独立证据 | Chapter 13 评估 | 新增"翻案能力"指标:被 keyframe 推翻的 L4 bbox 占比 | [`plans/PRISM/13_evaluation.md`](13_evaluation.md) |
| § 18.4 self-augmentation | Chapter 07 Pipeline D 巩固 | 巩固期训练范式从"监督学习"升级为"self-aug 监督学习" | [`plans/PRISM/07_pipeline_D_consolidation.md`](07_pipeline_D_consolidation.md) |
| § 18.4 self-augmentation | Chapter 13 评估 | 新增"巩固后纠错率"指标:online → offline 之间被纠正的错误数 | [`plans/PRISM/13_evaluation.md`](13_evaluation.md) |
上述章节本次 v1.5.0 升级**暂不强制改动**——本章先以"设计原则"形式独立存在;后续 v1.6 / v2.0 在演进对应章节时,再逐条把约束落地。
---
## 18.6 风险与限制
本章列出的三条原则源自 Lyra 2.0 的工程实践,但 Lyra 与 PRISM 在**问题设定上有根本差异**,因此必须把"借鉴"与"复制"严格区分:
1. **Lyra 是生成式,PRISM 是判别式 + 真实传感器**。Lyra 的"3D 缓存"服务于像素生成(视频扩散解码),它的几何粗糙是可以容忍的,因为下游 cross-attention 会用 2D 帧把内容补回;PRISM 的 L2 服务于**机器人避障**,几何粗糙的容忍度有刚性下限(栅格分辨率不能粗于半个机器人宽度)。**§ 18.2"几何只做路由"不能被滥用为"几何精度可以任意低"**——它只是说"L2 精度不要影响 L3 内容",并不是说"L2 精度可以任意差到避障也失败"。
2. **Lyra 的训练数据是合成的(视频扩散先验),PRISM 的数据是真实 ZED / iPhone**。Self-augmentation 在 Lyra 里之所以好用,部分是因为合成数据的"分布"和模型 capacity 是匹配的;PRISM 的真实数据带有显著的传感器噪声(ZED 在反光面、低纹理面会大面积失败),把模型自己生成的样本当训练源,**可能把传感器特有的失败模式当成"正常分布"学下来**。§ 18.4 中保留 30% 真实在线样本($1 - p_{\text{aug}} = 0.3$)就是为了对冲这个风险,但仍需要在 Pipeline D 的实施中加 ablation 验证。
3. **per-frame 证据保留有存储代价**。Lyra 的 keyframe 数量受限于扩散模型的 context 长度(数十帧);PRISM 在长期部署中一个酒店场景可能积累数万帧。§ 18.3 的"保留子集"策略(每 0.5 m 或每 30° 视角一帧)是经验值,**长期边界尚未被验证**——可能需要 v2.0 引入"keyframe 退役 / 压缩"机制,否则会成为新的内存瓶颈。
4. **原则之间也存在张力**。"§ 18.2 只用 L2 路由"要求 L2 几何只承担轻任务;"§ 18.3 保留 keyframe 翻案"要求事后能纠正 L4——但**到底何时触发翻案?由谁判定 L4 出错?** 当前章节未给出闭环规则,留给 [`plans/PRISM/13_evaluation.md`](13_evaluation.md) 在新增"翻案能力"指标时配套定义。
综上,本章是 PRISM 在 v1.5 节点上对 Lyra 2.0 的**有节制的吸收**:原则被写下来,但落地节奏由后续章节按版本逐步推进,确保每一条都经过实验回归而非仅凭直觉。一个简明的检验标准是:v1.6 在改动 [`plans/PRISM/03_data_schema.md`](03_data_schema.md) 引入 `keyframe_evidence` 字段时,必须同步在 [`plans/PRISM/13_evaluation.md`](13_evaluation.md) 加入"翻案命中率"与"翻案误报率"两项指标——只有这两个数能稳定测出来,§ 18.3 的原则才算真正落地;否则就只是"看上去更优雅"的架构装饰。Self-aug 的 $p_{\text{aug}}$ 与 § 18.2 路由置信度阈值同理,必须以**可被 ablation 推翻的形式**写进评估章节,本章才算完成它的设计哲学使命。
---
**章节版本**v1.0(新增于 PRISM v1.5.0
**估计阅读时间**810 分钟
**关键收获**:几何只做路由 / 不做合成;keyframe 独立证据;巩固期 self-aug。