具身数据

从 LeRobot 数据平台到 AI 数据控制平面:我想继续做深的几个问题

从项目已有的 Episode、版本化 QC、冻结 Manifest 和血缘出发,思考如何把机器人数据管理逐步做成可信数据生产与交付平台。

1. 上传完成以后,问题才真正开始

做数据平台,很容易沿着一条熟悉的路往前走:上传文件、展示列表、加筛选条件,再接一个向量检索和聊天入口。每加一个功能,页面都会更完整,也更像一个平台。

但继续做 lerobot-data-platform 时,我越来越在意另一个问题:如果有人拿平台里的数据训练了一个模型,过了两周再回来问“当时到底用了哪些数据”,我能不能给出一个准确的答案?

这个答案应该包含当时选中的 Episode、数据来源、质量检查依据、构建参数,以及最后交到训练端的具体产物。最好还能沿着记录往回找,看到某段数据为什么进入这个版本,某个警告由谁复核。

这也是我想调整项目方向的原因。上传和检索依然有用,但后续工作的重心应该放在数据的生产与交付过程上。我想逐步把它做成一个 AI 数据控制平面:让人和程序能够围绕固定的数据版本协作,让每一次交付都有可以查验的依据。

“可信数据供应链”是我对这个方向的概括。这里的可信,需要靠来源、规则、版本和交付记录一层层建立。

2. 机器人数据,让这些问题变得具体

机器人是一个很好的起点,因为它会不断逼着我解释数据的含义。

一段 Episode 可能同时包含相机画面、关节状态、动作和时间戳。两份数据的动作维度都为 14,也可能使用不同的关节顺序或单位;视频能够播放,也可能与状态序列存在时间偏移。

这些差异在文件列表里看不出来,进入训练以后却不能忽略。

LeRobot v3 的官方文档也体现了这种分离:多个 Episode 可以放在同一个 Parquet 或 MP4 分片里,Episode 的边界通过元数据确定。因此,平台不能用文件名猜测一段采集的身份,也不能把数据库里的 Episode ID 当成源数据的 episode_index。

这让我开始把三个对象分开理解:

对象 我需要解释的问题
文件或 Asset 字节存在哪里,内容有没有变化?
Episode 这段交互来自哪里,时间和字段怎样解释?
DatasetVersion 本次固定选中了哪些 Episode,依据是什么?

文件哈希能帮助检查内容一致性,却不能证明采集标注正确。一个数据集版本名能方便人引用,却不能自动保证成员不再变化。每个对象都有自己的责任,也有自己的边界。

机器人数据首先把这些问题暴露出来。将来再考虑 SFT 数据、Agent 轨迹或评估数据时,我希望复用的是这套管理方法,同时保留各自的领域语义。

3. 现在的项目,已经走到哪里

截至 2026 年 10 月 8 日,项目在仓库中使用的产品名称是 Embodied DataHub,代码目录仍叫 lerobot-data-platform。它已经围绕 Episode 建立了一条较清楚的主线:

text11 行
上传与来源登记
       ↓
Asset → 摄取 → Episode
                  ↓
              QC / Review
                  ↓
              Selection
                  ↓
       DatasetVersion + Frozen Manifest
                  ↓
                Build

Java 后端负责权限、元数据、事务和任务状态,Python 数据面负责 LeRobot、MCAP、Parquet、视频与质量计算。这种分工已经有实际代码支撑:例如 DatasetVersionService 负责冻结输入和发布约束,Python 的 l2_operators.py 负责信号质量计算。

当前构建使用 Java 17,Java 21 仍是目标。对于这篇文章来说,版本数字不是重点;更值得保留的是控制面与数据面的职责边界。

从现有实现和进度记录看,项目已经具备上传会话、Asset 与 SHA256、幂等摄取、版本化质量规则、冻结 Manifest、版本差异和血缘查询。MCP 也已有五个只读工具,可以查询 Episode、QC、数据集 Manifest、血缘和训练记录。

仓库最新台账记录了一次本地 Golden Path 整跑:完成真实上传、摄取、QC、版本冻结和构建,包含浏览器页面取证。不过,这次演示脚本没有实际的 Delivery 环节,台账明确记载当次 delivery 表没有记录。构建侧有产物哈希,不能据此写成“交付产物哈希已经验证”。官方 LeRobot reader 读回和干净检出的完整复现,也仍是后续任务。

这些是仓库已有运行记录,本次写作没有重新运行。它们说明项目有了可以继续演进的基础,也提醒我:一条流程能够演示,并不意味着每个出口都已经闭合。

4. 我最想做深的,是数据集版本的权威性

如果只能选一个方向继续投入,我会先选 Dataset Control Plane。

这里的核心,是让数据集版本成为训练输入的可靠引用。一个目录可能一直叫 dataset-v3,里面的文件却被替换;一个筛选条件可能一直没变,每天选出的成员却不同。

因此,动态筛选条件和冻结版本需要分开:前者表达“我想找什么”,后者记录“这一次实际找到了什么”。

项目已有的 Frozen Manifest 正在承担后一项责任。它保存成员与必要输入,经过规范化序列化计算哈希,再交给构建任务。服务端也已经有拒绝重写冻结输入、限制发布后修改的逻辑。

我希望继续沿着这条线补齐三个问题:输入能否重新定位,构建产物能否检查,交付端能否读回。只有最后一个问题得到验证,训练方才真正拿到了可用的数据。

这也让我重新看待与行业工具的关系。DVC 的流水线定义已经包含依赖、输出、参数与指标,不能简单概括成“只做文件版本”。我更愿意借用这些成熟思想,把自己的工作集中在 Episode 的质量准入、冻结成员、人工复核和交付语义上。

平台可以维护版本关系和血缘投影,但成员事实应该始终回到 Frozen Manifest。图里有一条 CONTAINS 边,不能成为绕过冻结记录、重新解释版本内容的理由。

5. Controller 值得借鉴,但先别急着写 CRD

下一步很自然会想到 Kubernetes。

Kubernetes Controller持续比较期望状态与当前状态,并推动两者接近。这种思路很适合数据生产:用户提出需要什么数据,系统检查已有结果,再安排摄取、质量计算和构建任务。

下面是我希望未来能够表达的意图,只是设计示例,尚不是项目支持的 API 或 Kubernetes CRD:

yaml7 行
kind: DatasetBuildRequest
spec:
  sourceRevision: pinned-revision
  task: dual-arm-pick
  qualityProfileRevision: manipulation-v1
  contractRevision: aloha-contract-v1
  deliveryFormat: lerobot-v3

真正困难的地方,在 YAML 后面。

Controller 重启以后,怎样识别已经创建的任务?租约过期以后,旧 Worker 怎样被阻止提交?质量画像发生变化以后,怎样避免用新规则解释旧版本?同一个构建请求被重复执行,又怎样保持输入不变?

项目现有 Job 已经有 claim、lease、heartbeat、attempt 和 fencing 的机制。后续 Controller 应当复用这条执行链路,通过稳定的请求身份和状态核对来推进任务。

我会先尝试应用内的 reconcile,再根据部署和使用需求决定是否引入真正的 Kubernetes CRD。声明式接口可以帮助表达需求,但服务端规则、幂等性和恢复行为需要先站稳。

还有一个约束必须守住:筛选结果一旦冻结,后来新增的数据只能进入新版本。Controller 可以不断工作,历史版本却不能跟着滚动变化。

6. 质量引擎,要先学会解释“不知道”

质量页面最容易做得漂亮的方式,是给每段数据一个分数。完整性、画面、运动各占一定权重,最后得到一个总分,筛选也很方便。

但在当前项目里,我更愿意先把每一项判断解释清楚。

例如,检查动作是否超出范围,需要动作单位和对应设备的限制。只知道数组长度,无法推出合法范围。缺少这些依据时,返回 UNKNOWN 比猜一个阈值更有价值。

项目已有的 L2 算子遵循了这个方向:缺少 fps、动作限制等判断依据时返回 UNKNOWN,读取或计算异常单独表达为 ERROR;规则结果保留测量值、版本和证据。

不过,规则结论与质量闸门结论仍要分别读。最新台账记录的某次运行,闸门为 PASS,而其中 ACTION_RANGE_VALID 为 UNKNOWN。这说明 PASS 是在特定画像和准入策略下的结论,不能读成“所有规则均已通过”。

同一份记录还指出,11 条规则都有 evidence 和 rule_version,但只有 4 条的 threshold_json 有值。后续需要逐条说明:哪些规则本来没有数值阈值,哪些字段确实需要补齐。一个绿色状态不能替代这些解释。

因此,我想做深的 Quality Profile 至少要回答:规则适用于哪类数据、哪些结果阻断训练、哪些警告允许复核、检查覆盖了全量还是抽样,以及当前结论依据哪个版本。

综合评分可以以后再研究。等到有明确用途、校准数据和评价依据,再决定它是否比逐项证据更能帮助使用者。

7. Data Contract 应该约束含义,也约束用途

质量检查通常在问“这份数据有没有问题”,数据契约还要问“它是否满足这个消费者的要求”。

例如,一个训练任务要求固定相机分辨率、动作维度和关节顺序。新数据即使结构完整,也可能不满足这个输入约定。

下面同样是未来契约的示意,并非现有接口:

yaml11 行
contractRevision: aloha-contract-v1
camera:
  resolution: [640, 480]
  fps: 30
action:
  dimension: 14
  unit: radians
  jointOrderRef: aloha-joints-v1
timestamp:
  monotonic: true
  clockDomain: observation-stream

数组维度之外,单位、关节顺序和时钟域尤其值得写清楚。两个时间戳都单调递增,并不能证明两路相机已经同步。

契约也需要区分不同用途。15 fps 的数据可能不满足某个训练任务,但仍然值得保留,用于故障分析。更合理的处理,是允许它作为来源资产进入平台,再明确拒绝它进入不兼容的训练交付。

项目现在已有质量画像、适用性检查和版本化契约文件。统一、面向消费者的数据契约仍是我想继续抽出来的一层:让接入检查、质量规则、构建验证和训练输入使用同一个有版本的约定。

8. 血缘能缩小排查范围,还不能替人判断原因

血缘是我希望继续完善的另一条主线:

text5 行
来源 / Asset → Episode → DatasetVersion → Delivery
                                             ↓
                                        Training Run
                                             ↓
                                         Model / Eval

项目已有血缘查询和前端展示,也有多跳 fixture 的验证记录,能够围绕来源、Episode、版本、交付、训练和评估对象展开关系。这说明查询机制已经有了基础。

但 fixture 中存在一条完整链路,不代表项目已经完成对应的真实训练或机器人部署。MLflow 目前也主要是外部运行链接登记,不能写成完整的训练集成。

我更看重后续能不能把真实交付与外部训练结果接起来:训练端实际消费的产物,是否对应某个固定版本?评估失败用的是原训练样本,还是后来新采集的数据?模型记录所指向的运行,能否找到准确输入?

这些关系能帮助缩小排查范围。要说“某段数据导致机器人失败”,还需要评估、对照实验和具体分析。血缘提供的是调查入口。

9. Agent 可以先帮助查证,再参与生产

有了版本、质量和血缘,再接 Agent 才更有意义。

当前 MCP 只读工具已经提供了一个合适的起点。Agent 可以查询某个版本的 Manifest,解释 Episode 为什么被排除,或者顺着模型记录找到关联数据。

未来用户也许会提出这样的需求:

找出过去一个月双臂抓取任务中,失败率低于 2% 的数据,给我生成一个候选版本。

这句话包含很多需要澄清的条件。失败率来自任务标签、人工复核还是模型评估?分母按 Episode 还是尝试次数?过去一个月使用采集时间还是上传时间?

如果这些概念没有定义,Agent 即使返回了一个列表,也很难证明自己找对了数据。

因此,我希望它先展示查询解释、候选成员、排除理由和证据缺口,再调用受权限与策略约束的业务接口。冻结和发布继续由控制面执行,Agent 的总结附在结果旁边。

当前五个 MCP 工具都是只读工具,自动生成版本、冻结或发布尚未实现。把这一点写清楚,也有助于后续按风险和价值逐步开放能力。

10. 存储继续演进,数据身份保持稳定

Lance 是值得观察的方向,但当前项目不需要先进行格式迁移。

项目的 ADR 已把它放在“可选读取后端”的位置,状态仍是 PROPOSED / SPIKE ONLY。默认路线继续面向官方 LeRobot 的 Parquet、MP4 和元数据组织,Lance 作为派生读取对象做实验。

这种安排的价值,是让业务版本与存储实现分开:同一份冻结输入可以产生不同交付产物,每份产物分别记录转换工具、参数、URI 和 digest。某个 Lance snapshot 的版本号,也不能替代平台 DatasetVersion 的身份。

后续是否采用它,要看相同样本上的读回一致性和实际收益。远端随机读取是否更快,是否减少网络字节,转换成本有多高,都需要公平的对照实验。目前我没有可以据此下结论的项目性能数据。

11. 下一步,我想先让别人真正用上这份数据

“AI 数据控制平面”这个方向,可以容纳很多功能。对当前项目来说,我想用一条具体的验收路径约束它:

固定一份输入,生成一个不可变版本,交付给官方 reader,再沿训练记录查回准确来源。

接下来可以分成几个递进阶段:

阶段 重点工作 我希望拿到的证据
补齐交付闭环 Delivery 记录、产物哈希、官方 reader 读回、干净环境复现 接收方实际读到的数据与冻结输入逐项对应
深化控制面 应用内 reconcile、版本化 Data Contract、质量准入说明 重复请求与失败恢复可解释,历史输入不被改变
开放 Agent 协作 从只读问答走向候选集生成,再考虑受控写入 查询条件明确,成员和排除理由可查验
尝试第二个领域 选择一种 SFT、评估或 Agent 轨迹数据 复用公共生命周期,同时保留领域契约

这些是文章提出的演进方向,不是已经完成的新版本清单。仓库现有 P0/P1/P2 台账仍按自己的任务与验收状态管理。

从更长的学习主线看,数据平台可以与 Agent 控制、算力执行和运行时通过版本引用与证据衔接:数据平台解释输入,算力平台执行任务,运行时记录行为,评估再把问题带回数据生产端。它们各自做好职责,再通过明确接口连接。

我暂时还在把第一条链路补完整。下一次打开项目时,比起增加一个新菜单,我更想先确认:这份冻结的数据,别人能不能按约定读到;读到以后,能不能知道它为什么被交付。

来源与写作范围

项目现状依据本地 lerobot-data-platform 的 README.md、docs/embodied-datahub-orchestration.md、docs/p1a-dataset-contract.md、docs/p0c-quality-contract.md、docs/lineage-real-data-proof.md、docs/adr-0001-lerobot-lance.md 和 MCP README,并对照数据集版本服务、领域模型与 L2 算子实现。运行结论引用仓库记录,本次未重跑;不据此声明生产部署、训练效果或真机能力。

公开资料用于理解格式、流水线与控制器机制:LeRobotDataset v3、DVC 流水线定义、Kubernetes Controllers。行业资料帮助确定分工,没有替代本项目的验证。

相关阅读

← 返回文章