4. 模型证据链的元数据设计

模型证据链要真正可追溯、可审计、可复现,光有“证据文件”本身是不够的。一个模型文件、一份验证报告、一段训练日志,如果缺少描述它“是谁、从哪来、何时产生、由谁负责、覆盖到什么程度”的信息,它在证据链中就只是一个孤立的二进制块。元数据设计要解决的,正是把孤立产物变成可被检索、可被引用、可被追责的证据节点。

一、元数据模型:把证据节点拆成可查询的字段

元数据模型是证据链的骨架。建议采用“核心层 + 扩展层”的两级结构:核心层是所有证据节点都必须具备的最小字段集,扩展层按证据类型(数据、模型、训练、验证、部署)追加专属字段。核心层至少包含六类信息:标识、时间、来源、责任、粒度、关系。

以一次模型验证为例,其核心元数据可设计为如下结构(示例为合理假设的教学样例):

{
  "evidence_id": "EVD-VAL-20240612-0007",
  "evidence_type": "validation_report",
  "created_at": "2024-06-12T14:32:08+08:00",
  "source": {
    "pipeline": "ci-val-pipeline-v3",
    "commit": "a1b2c3d",
    "dataset_ref": "DS-TEST-2024Q2-v2"
  },
  "owner": {
    "team": "model-risk",
    "operator": "zhang.wei",
    "approver": "li.na"
  },
  "granularity": {
    "scope": "binary_classification",
    "sample_count": 50000,
    "metrics": ["auc", "ks", "psi"]
  },
  "relations": {
    "derived_from": ["EVD-TRAIN-20240610-0003"],
    "supersedes": "EVD-VAL-20240520-0002"
  }
}

这个结构的关键在于:每个字段都对应一个可回答的审计问题。evidence_id 回答“是哪条证据”,created_at 回答“何时产生”,source 回答“从哪条流水线、哪个代码版本、哪份数据来”,owner 回答“谁生成、谁批准”,granularity 回答“覆盖什么范围”,relations 回答“与哪些证据存在派生或替代关系”。字段设计不必追求大而全,但必须保证每个字段都有明确的查询用途。

二、标识体系:让每条证据有唯一且可读的“身份证”

标识体系要同时满足唯一性和可读性。纯 UUID 虽然唯一,但人工排查时几乎无法辨认;纯自然语言命名又容易冲突。推荐采用“类型前缀 + 日期 + 序列号”的结构化标识,例如 EVD-VAL-20240612-0007。其中 EVD 表示证据,VAL 表示验证报告,20240612 是生成日期,0007 是当日序列号。

标识一旦分配就不可修改,证据内容更新时应生成新标识,并通过 supersedes 字段指向被替代的旧证据。这样既保留了历史版本,又避免了“同一标识指向不同内容”的追溯断裂。对于跨系统引用,建议在标识前附加系统命名空间,如 riskplat:EVD-VAL-20240612-0007,防止不同平台之间发生标识碰撞。

三、时间戳:区分“发生时间”与“记录时间”

时间戳最容易踩的坑,是把所有时间都记成一个字段。证据链中至少需要区分三类时间:事件发生时间(如训练实际开始与结束)、证据生成时间(报告落盘时刻)、记录写入时间(元数据进入证据库的时刻)。三者可能相差数小时甚至数天,尤其在离线补录场景下。

时间戳必须带时区偏移,推荐统一使用 ISO 8601 格式,如 2024-06-12T14:32:08+08:00。如果团队跨时区协作,建议内部统一存储为 UTC,展示时再转换为本地时间。此外,对于训练、验证这类有持续过程的证据,应同时记录 started_at 和 finished_at,仅记录单一时间点会导致无法判断证据覆盖的时间窗口。

四、来源标注与责任主体:把“从哪来”和“谁负责”分开

来源标注描述证据的技术出处:来自哪条流水线、哪个代码提交、哪份数据集、哪个模型版本。责任主体描述证据的组织归属:哪个团队、哪位操作人、哪位审批人。两者不能混为一谈——同一条流水线可能被不同团队使用,同一个团队也可能运行多条流水线。

来源标注建议采用“可解析引用”而非自由文本。例如数据集不写“测试集”,而写 DS-TEST-2024Q2-v2,并保证该标识能在数据目录中查到对应的版本快照。责任主体则应至少包含 operator 和 approver 两个角色,前者对证据生成过程负责,后者对证据结论负责。对于自动化流水线生成的证据,operator 可填写流水线服务账号,但 approver 必须是具体的人。

五、证据粒度设计:决定证据“管多宽、管多细”

粒度设计是元数据中最容易被忽视、却最影响可用性的一环。粒度过粗,一条证据覆盖整个模型,出问题时无法定位到具体子模块;粒度过细,每个特征、每个样本都生成一条证据,证据库会被噪声淹没。

建议按“验证目标”确定粒度,而不是按“文件数量”确定。例如:整体模型性能验证对应模型级粒度;某类客群的公平性验证对应切片级粒度;某次数据漂移检测对应特征级粒度。粒度字段应明确记录 scope(作用域)、sample_count(样本量)、metrics(指标集),使审计人员能快速判断这条证据是否足以支撑当前结论。

模型证据链元数据模型:核心层与扩展层 每条证据 = 唯一标识 + 三类时间 + 技术来源 + 责任主体 + 粒度声明 + 关系引用 核心层 · 所有证据节点必填 标识 evidence_id 唯一 · 不可变 时间戳 created_at 含时区 · 三类时间 来源标注 source 流水线/提交/数据 责任主体 owner 操作人/审批人 证据粒度 granularity 作用域/样本/指标 关系 relations 派生/替代 扩展层 · 按证据类型追加 数据证据 schema_version row_count / null_rate 模型证据 framework / version hyperparams_hash 验证证据 threshold / metric pass_fail / slice 部署证据 env / endpoint rollback_ref 关系链示例: 数据证据 DS-TEST-2024Q2-v2 → 训练证据 EVD-TRAIN-20240610-0003 → 验证证据 EVD-VAL-20240612-0007 每条证据通过 relations.derived_from 指向上游,形成可回溯的派生链

六、落地建议:从最小可用字段集开始

元数据设计不必一步到位。建议先落地一个最小可用字段集:evidence_id、evidence_type、created_at、source.pipeline、source.commit、owner.operator、granularity.scope、relations.derived_from。这八个字段能覆盖大多数审计场景的基本追问。在此基础上,再按证据类型逐步补充扩展字段。

实践提示:元数据写入应与证据生成在同一流水线步骤中完成,避免事后人工补录。补录的时间戳和来源信息可信度会显著下降,审计时容易被质疑。如果确实需要补录,应在元数据中显式标记 backfilled: true 并记录补录人。
常见误区:把“模型名称”当作标识使用。模型名称会随版本迭代重复出现,无法唯一指向某次训练产物。标识必须是机器生成、全局唯一、与内容绑定的字符串,而不是人类可读的名称。

总结来看,元数据设计的核心不是字段越多越好,而是每个字段都能回答一个具体的追溯问题。标识回答“是哪条”,时间回答“何时”,来源回答“从哪来”,责任回答“谁负责”,粒度回答“管多宽”,关系回答“和谁有关”。这六类信息构成证据链的最小闭环,也是后续实现自动化审计和证据检索的基础。