Skip to content

Prediction Schema 适配器陷阱

症状

AI 预标注任务后端跑成功(prediction_jobs 表里 succeeded,predictions 表里有行),但前端工作台打开任务、看不到任何候选框;或前端报错 Cannot read property 'class_name' of undefined

v0.9.4 SAM/DINO 真接通后才暴露:v0.9.7 端到端跑通时发现历史 32 条 predictions 在前端读路径全部丢失。

根因

DB 里存的是 LabelStudio 标准格式(保导出/CVAT 兼容性):

json
{
  "type": "rectanglelabels",
  "value": {
    "x": 12, "y": 34, "width": 56, "height": 78,
    "rectanglelabels": ["dog"]
  },
  "score": 0.91
}

但前端 predictionsToBoxes 期望内部 schema

json
{
  "type": "rectanglelabels",
  "class_name": "dog",
  "geometry": { "x": 12, "y": 34, "width": 56, "height": 78 },
  "confidence": 0.91
}

两端各自演化,没人在中间做适配,前端自然渲染不出来。

修复

不动 DB 写路径(保 LabelStudio 标准),在读路径to_internal_shape 适配器:

  • apps/api/app/api/v1/tasks.py::get_predictions
  • apps/api/app/api/v1/annotation.py::accept_prediction

适配器三层 fallback(容忍历史数据):

  1. LabelStudio 标准:value.{type}[0] self-referential(type=rectanglelabelsvalue.rectanglelabels[0]
  2. 老格式:value.labels[0]
  3. 老格式:value.class

scoreconfidence 同样 fallback。已是内部 schema 的输入直接 pass-through(idempotent)。

10 单测覆盖:LabelStudio / value.labels / value.class / pass-through / score↔confidence / 非法输入。

防御性收口

v0.9.8 同步引入 schema 边界文档

  • docs-site/dev/architecture/api-schema-boundary.md — 明确「写路径用 LabelStudio 标准、读路径过 adapter 出内部 schema」
  • apps/web/src/api/transforms.ts — 5 黄金样本 + 3 idempotent/边界 case,走 codegen 派生类型

教训

跨语言(Python ↔ TS)schema 没有单一来源时,要么强制走 OpenAPI codegen,要么显式声明 adapter 层。手写两端 dataclass 注定漂移。

相关

  • commit: 0a99cc6 feat(v0.9.7) — 含 adapter 落地
  • commit: d41236b feat(v0.9.8) — schema 边界文档化 + transforms.ts 单测
  • 文档:API Schema 边界
  • 代码:apps/api/app/services/predictions/adapter.py

Released under the MIT License.