老王开了一家私房菜馆,招牌菜是红烧肉。一天,一位老顾客吃完后过敏进了医院。老王慌了:这道菜到底用了哪批猪肉?肉是哪个供应商送的?谁掌的勺?调料放了多少?更麻烦的是——如果猪肉有问题,这几天还有哪些菜、哪些客人也“中了招”?老王翻遍手账,发现只有“菜名+日期”,完全对不上号。痛定思痛,他决定给厨房建一套“食材溯源系统”:每一袋食材贴上产地批次标签,每一道菜记录菜谱、火候、掌勺师傅,所有记录连成一张“从农场到餐桌”的流向图。一旦出事,顺藤摸瓜,秒级定位。这套思路,正是 AI 工程里的“模型血缘追踪”。数据是食材,代码是菜谱,超参数是火候与调料用量,模型是出炉的成品菜。而血缘追踪要做的,就是把这整个过程串成一张可审计、可复现、可查案的“家大图谱”。
掌握模型血缘追踪,你将具备 AI 团队里“事故破案员”与“合规守门人”的核心能力:快速定位模型问题根因、满足监管审计要求、自动化评估变更风险,是 MLOps 工程体系的关键一环。
可视化演示
展示数据→特征→模型→评估的DAG依赖链路,变更影响分析标注受影响节点的严重级别。
本节配有交互动效(进入视口后自动加载,约 3KB)。
血缘DAG图 D1→F1/F2→M1/M2→E1,8条依赖边构成完整血缘链路 DAG拓扑排序保证无环依赖 事件驱动自动采集元数据,构建可追溯的血缘图谱
血缘基础概念
老王过去的手账本里,每道菜只记了“菜名+日期”。真出了事,他完全答不出“这块肉是哪来的”。后来他给每道菜建立了“身世档案”:食材进货批次、菜谱版本、掌勺师傅、火候与调料用量。血缘(Lineage)就是给模型写身世档案——把模型生命里每个“参与者”之间的依赖关系完整记下来。
在 AI 工程里,模型不是凭空诞生的。一份训练数据、一段特征工程代码、一堆超参数、一次训练运行、一个评估指标,最后才产出一个模型版本。所以血缘通常覆盖四个维度:数据血缘(训练集、验证集从哪张表来)、代码血缘(哪个 commit、哪个镜像)、超参数血缘(学习率、批次大小等旋钮)和产物血缘(模型文件、特征库、部署版本)。把这些实体的关系放进一张图,就构成了血缘图:
有了这张图,老王至少收获三样东西:复现——照着身世档案原样再做一遍;审计——出了问题能证明“这菜确实是用那批肉做的”;影响评估——肉有问题时,立刻圈出所有受害菜品。这就是血缘的核心价值:让模型从“黑箱产物”变成“有据可查的档案”。
- G 表示整张血缘图G 是 Lineage Graph 的缩写,是所有血缘信息的容器。
- V 是顶点集合每个顶点代表一个血缘实体,比如数据表、特征、训练作业、模型版本。
- E 是边集合每条边代表一条依赖关系,例如“作业读取了某张表”“模型由某次训练产出”。
- 有向边连接边从上游指向下游,数据沿着“数据→特征→模型→服务”的方向流动,不能倒流。
元数据采集
老王定下规矩:每袋食材到货,必须贴标签,写清产地、批次、到货日期;每道菜出锅,必须记录师傅工号、火候、调料克数。标签贴得越全,溯源图画得越准。血缘系统的地基,正是元数据(metadata)——“描述数据的数据”。
采集内容通常分四类:数据元数据(表的 schema、版本、分区、行数)、代码元数据(Git commit、代码仓路径、容器镜像哈希)、运行元数据(作业名、运行 ID、起止时间、输入输出实例)、超参数(学习率、批量大小、随机种子)。采集方式主要有三种:在调度平台(Airflow、Dagster)的每个任务节点埋点;在数据存储层监听操作日志;在训练脚本中注入回调,让训练框架自动上报配置。
为了让不同引擎上报的“标签”长一个样,业界提出了 OpenLineage 标准。它定义了一套统一的事件格式:一次运行 COMPLETE 时,发出一个包含作业名(job)、命名空间(namespace)、输入列表(inputs)、输出列表(outputs)、运行 ID(runId)的事件。无论底层是 Spark 跑 SQL,还是 PyTorch 训模型,上报的都是同一种“食材溯源码”。血缘平台的完整度可以用覆盖率来衡量:
老王很快发现,标签贴得再漂亮,如果不统一编码,三家分店各写各的,汇总时照样对不上。OpenLineage 就是那份“全国通用食材编码表”——它让跨团队、跨引擎的血缘上报有了共同语言,是后续所有血缘分析的地基。
- 分子 m_recorded实际成功记录到平台的血缘事件数量,比如某次训练任务成功上报了输入输出。
- 分母 m_total所有应当被记录的关键运行事件总数,包括没接入埋点的老任务。
- 比值 C取值在 0 到 1 之间,越接近 1 说明厨房里带标签的食材越多,溯源越可信。
DAG血缘图
老王把标签贴满整面墙,用彩色毛线把“食材→半成品→菜品→上桌”连了起来。他还立了条铁规矩:毛线只能往前穿,绝不能绕成圈——否则“鸡生蛋、蛋生鸡”就永远查不清源头了。这条铁规矩,正是血缘图的核心结构:DAG(有向无环图)。有向,指依赖有方向;无环,指不存在 A 依赖 B、B 又依赖 A 的死循环。
在血缘 DAG 中,节点是各种实体,边则携带语义。常见语义有三类:输入边(下游作业读取了上游数据集,记为 “读取”)、产出边(作业产出了模型或特征表,记为 “产出”)、派生边(特征列由某表某列计算而来,记为 “派生”)。当数据更新版本时,会生成新的数据节点,旧节点继续保留——所以血缘图会有“版本分支”,这正是可复现性的来源:你能在图中找到当年训练用的那一个版本。
有了 DAG,最有力的一个操作是计算传递闭包:从任意节点出发,沿着边的方向能走到哪些节点。它对应的概念叫下游影响集:
老王把毛线墙挂好后,再也不怕“查漏”了:以前他只能想到直接用猪肉的厨师,现在他能顺着毛线把所有用过同批猪肉的试吃装、外卖菜品全部揪出来。DAG 的价值,就是把“人脑只看得见一跳”的局限,升级成“机器算得到全链路”。
- v 是变更源节点影响分析的起点,比如某张被改动的数据表或某个特征版本。
- E⁺ 表示传递闭包不只包含直接相连的边,还包含走两步、走三步能到达的所有路径。
- u 是可达的下游节点只要存在一条从 v 出发、沿箭头方向到达 u 的路径,u 就在影响集内。
- I(v) 汇总影响集把所有可达下游收进一个集合,就是“坏食材连累清单”。
字段级血缘
老王的溯源又进了一步:光知道“这道菜用了猪肉”还不够,他想知道“这道菜里的白糖是哪一批的、醋是哪一批的”。对应到血缘,就是字段级血缘(Column-level Lineage):不止追踪到“哪张表”,而是精确到“哪一个列”。
表级血缘回答“订单表→用户特征表”,字段级血缘则要回答:用户特征表里的 avg_price_7d 这一列,是从订单表里的 price 列经过“7 天窗口求平均”得到的。获取字段级血缘主要有三条路。第一条是 SQL 解析:把一段 SQL 变成语法树,顺着 SELECT 子句和 JOIN 条件分析每个输出列的来源表达式,这是最常见的做法。第二条是算子级运行时追踪:在 Spark 等引擎的执行计划里,每个算子都会记录输入列和输出列的 provenance,从运行时拿到精确映射。第三条是人工标注:对 Python 脚本、存储过程等难以静态解析的代码,由开发者补充说明。
多条转换链路拼接起来,就形成一条“列的血缘链”。把每层转换看作一个函数,目标字段就是从源头一路复合过来的结果:
有了字段级血缘,老王能回答更刁钻的问题:“顾客说这道菜太甜,是白糖批次的问题还是配方变了?”他会直接查白糖列的来源批次与用量参数,而不是把整道菜倒掉重做。这也是数据团队做“列级变更评估”时最依赖的能力:改一个字段,先看哪些上下游会遭殃。
- t₁ 到 t_k 是转换层每一层是一次数据处理,比如过滤、聚合、JOIN 或自定义函数。
- g 是单层字段映射把某一层的输入列集合映射到该层的输出列,记录“这一列由哪几列算出”。
- 复合映射 f_col从最底层开始逐层复合,最后得到目标列与源头列的完整对应关系。
变更影响分析
一天清晨,供应商通知老王:前两批猪腩肉疑似有问题。老王立刻冲到毛线墙前,从“猪腩肉”节点出发,沿箭头扫了一遍——不仅是红烧肉,还有上周发给会员的“黑椒猪柳”试吃装也用了同批肉。他当场列出受影响菜品和已购买顾客清单,逐一电话召回。这就是变更影响分析:当上游发生变更(数据更新、字段删除、代码重构)时,自动找出所有被波及的下游实体。
影响分析的流程很标准:第一步,定位变更节点;第二步,沿边的方向做一次全图遍历;第三步,按“传了几手”对受影响节点分层;第四步,生成影响清单并评估处置优先级。遍历可以用 BFS 或 DFS,关键是必须走完整条链路,而不是只看直接下游。影响“传了几手”用影响距离来度量:
实际系统中,还会给每个节点设置重要度权重 w_u——比如在线服务的模型权重高、离线报表权重低。于是影响清单可以按风险分数排序,让团队先处理“离变更最近、伤得最重”的环节。老王也因此练就了一个本领:顾客过敏事件发生后的十分钟内,他就能给出完整的“召回名单”。
- v 是变更源节点影响分析的起点,可以是数据表、作业或模型版本。
- u 是下游受影响节点来自 v 的下游影响集 I(v),即所有可达节点。
- 最短路径长度从 v 到 u 最少需要经过几条边,体现风险传导了几层。
- 风险分层聚合把不同距离的节点按权重汇总成风险分数,距离越近权越高,优先处理。
血缘查询API
老王给每位服务员配了一台手持终端:输入菜名,立刻显示这道菜的完整身世(上游来源);输入供应商,立刻显示这家供应商供过哪些食材(下游去向);输入“猪腩肉”,一键导出召回清单。这套终端背后的能力,就是血缘查询 API——给前端和自动化系统使用的“溯源查询入口”。
血缘查询的后端存储很关键。中小规模团队常用图数据库(如 Neo4j):节点和边就是原生结构,多跳遍历一条 Cypher 语句搞定。超大规模场景用分布式图存储(如 JanusGraph)或“关系表存边 + 应用层做 BFS”。API 设计通常提供三类核心接口:上游溯源 getUpstream(id)、下游影响 getDownstream(id)、路径查询 getPath(src, dst),并统一返回结构:
血缘图规模动辄上百万节点,查询性能的关键在于遍历代价。BFS 遍历一张图的时间与图的规模成正比:
为了让服务员终端“秒出结果”,老王还做了两件事:给高频菜品加缓存,给毛线墙按楼层分区索引。对应到血缘系统,就是图数据库的索引、查询缓存和时间维度过滤(只看某版本之前的血缘)。再配上前端可视化——力导向图把血缘画成一张可拖拽的大网,点击任意节点即可展开上下游,整个“厨房地图”尽收眼底。
- |V| 是顶点总数血缘图中全部实体节点,包括数据表、特征、作业、模型、服务。
- |E| 是边的总数全部依赖关系的数量,通常比顶点数大一个数量级。
- 线性遍历成本BFS 在最坏情况下要把每个顶点和每条边访问一次,总代价是二者之和。
{ "entities": [...], "edges": [...], "depth": 2, "generated_at": "..." }实践与落地
老王把溯源系统推广到三家分店时遇到了新麻烦:每家店的标签格式五花八门,有的写“猪腩 5kg”,有的写“Pork-01“。于是他请人制定了统一的”食材编码标准“,各分店自动上报,总店大屏汇总成一张供应链全景图。血缘领域的”食材编码标准”,就是 OpenLineage——一个由 Linux 基金会托管的开放标准。
OpenLineage 定义的血缘事件大致长这样:一次运行完成时,发出一个事件,声明“我(job)这次运行(run)读入了哪些输入(inputs),产出了哪些输出(outputs)”,并附上命名空间和唯一 ID。Airflow、Spark、dbt 等主流引擎都有官方集成,事件统一送入血缘平台(如 Marquez)进行图构建与展示。落地时最典型的挑战有三个:冷启动——存量任务过去没打点,历史血缘一片空白,只能从当前开始增量积累;多引擎适配——Spark、Flink、Python 训练脚本各有各的运行模型,需要逐一接入并统一语义;图数据膨胀——每次运行都产生新节点,血缘图规模会线性增长,需要制定生命周期策略清理退役节点。
血缘系统是否真正可用,最后要看一张“完整度”指标:
老王的故事到这里闭环了:从给食材贴标签(元数据采集),到墙上拉毛线(DAG 构建),到查白糖批次(字段级血缘),到召回顾客(影响分析),再到总店大屏(查询 API 与可视化)——这就是一条完整的模型血缘落地链路。任何一家想做到“模型可溯源、事故可定位、变更可评估”的 AI 团队,都值得照这个顺序搭一遍自己的“厨房溯源系统”。
- 分子 |V_linked|已经成功挂到血缘图上、具备上下游查询能力的实体数量。
- 分母 |V_all|当前系统中所有应当被追踪的实体总数,包括没接入的老系统。
- 比值 S取值 0 到 1,工程上建议以“核心链路 100%、全链路逐步逼近”作为治理目标。
AI 应用场景
金融风控模型合规审计
阶段:模型治理与合规审计
解决的问题:监管要求银行对风控模型的决策依据做出解释:训练数据来自哪里、特征如何加工、模型版本如何迭代。传统做法靠人工整理 Word 文档,数据一更新文档就过期,审计时无法自证清白。
具体案例:某银行信贷审批模型被监管问询“逾期标签的历史来源”。血缘平台自动导出该模型的上游链路:原始放款表(数据血缘)→ 特征脚本 commit a1b2c3(代码血缘)→ 训练超参数 batch_size=256(超参血缘)→ 模型 v3.2 产物(产物血缘)。审计人员一键生成报告,三天工作缩到三小时。
推荐系统线上事故根因定位
阶段:模型运维与故障排查
解决的问题:线上 CTR 突降时,算法与数据团队互相“甩锅”:算法说特征变了,数据说表没问题。传统排查靠开会逐个确认,效率极低。
具体案例:某电商推荐团队用血缘 API 从线上模型反查上游:模型 ← 特征表 ← 特征作业 ← 原始订单表,发现昨夜的订单表新增了一个上游 job,修改了 price 字段的 schema,导致特征计算静默失败。血缘图五分钟锁定根因,回滚后指标恢复。
数据仓库表结构变更自动化评估
阶段:数据治理与变更管理
解决的问题:数据团队计划删除一张废弃表,但不知道有哪些 ETL 作业和下游模型在“隐性依赖”它。人工排查靠问、靠搜,漏一个就酿成生产事故。
具体案例:某互联网公司数据平台上线了“变更影响分析”服务:提交删表工单时系统自动跑下游影响集,列出受影响的 12 个作业、3 个特征表和 2 个模型,并标记高危变更要求双人审批。上线半年拦截了 40+ 次潜在事故。
Python 演示
# -*- coding: utf-8 -*-"""简易模型血缘追踪 - 老王私房菜馆溯源系统"""from collections import defaultdict, deque class LineageNode: """血缘实体: 数据/特征/作业/模型""" def __init__(self, nid, kind, attrs): self.id = nid # 唯一 ID, 相当于食材溯源码 self.kind = kind # 实体类型 self.attrs = attrs # 元数据标签 def metadata(self): return self.attrs class LineageGraph: """血缘图: 实体为节点, 依赖为有向边""" def __init__(self): self.node_map = {} self.edge_list = [] def add_node(self, node): self.node_map[node.id] = node def add_edge(self, src, dst, relation): if src in self.node_map and dst in self.node_map: self.edge_list.append((src, dst, relation)) def downstream(self, src_id): """影响分析: BFS 沿下游收集所有受影响节点""" adj = defaultdict(list) for s, d, _ in self.edge_list: adj[s].append(d) result, seen, queue = [], {src_id}, deque([src_id]) while queue: cur = queue.popleft() for nxt in adj[cur]: if nxt not in seen: seen.add(nxt) queue.append(nxt) result.append(self.node_map[nxt]) return result def upstream(self, dst_id): """溯源查询: 反向 BFS 收集上游来源""" radj = defaultdict(list) for s, d, _ in self.edge_list: radj[d].append(s) result, seen, queue = [], {dst_id}, deque([dst_id]) while queue: cur = queue.popleft() for prv in radj[cur]: if prv not in seen: seen.add(prv) queue.append(prv) result.append(self.node_map[prv]) return result def lineage_of(self, nid): return self.upstream(nid) def build_lineage(): g = LineageGraph() g.add_node(LineageNode("raw_order", "data", {"批次": "B202401", "来源": "数仓"})) g.add_node(LineageNode("feat_user", "feature", {"窗口": "7天聚合"})) g.add_node(LineageNode("job_train", "job", {"git": "a1b2c3", "镜像": "train:1.2"})) g.add_node(LineageNode("model_ctr", "model", {"版本": "v2.1", "AUC": 0.82})) g.add_edge("raw_order", "feat_user", "衍生") g.add_edge("feat_user", "job_train", "输入") g.add_edge("job_train", "model_ctr", "产出") return g def main(): g = build_lineage() print("=== 模型上游血缘 ===") for n in g.lineage_of("model_ctr"): print(" -", n.id, n.kind, n.metadata()) print("=== 数据变更的影响面 ===") for n in g.downstream("raw_order"): print(" -", n.id, n.kind) if __name__ == "__main__": main()
self.node_map = {}相当于厨房的“食材登记表”,用唯一 ID 快速找到实体。adj[s].append(d)把每条有向边建成邻接表,记录“从 s 能直接到谁”。result, seen, queue = [], {src_id}, deque([src_id])影响分析从变更节点出发,用 set 防止重复遍历。for nxt in adj[cur]BFS 逐层向外扩散,走完所有下游链路而不是只看一跳。radj[d].append(s)反向邻接表是“溯源”的关键:把边方向反过来,反向 BFS 一次就能拿到全部上游。if __name__ == "__main__":保证脚本既可被导入复用,也能直接运行演示。
常见误区
误区我把每次训练的日志、数据文件、代码包都存下来了,这不就是血缘吗?
正解日志是无结构的文本,而血缘是结构化的“实体—依赖”图。就像老王的手账只写“今天做了红烧肉”,没写“猪肉批次 A-201 来自某某牧场”,出事时根本查不到。血缘要求每个实体有唯一 ID、每条依赖有方向和语义,并且可以程序化查询——日志只是血缘的原料,不是血缘本身。
为何常见:血缘系统确实要收集日志信息,但“采集”和“建模成图”是两件事,初学者往往只看到了前半截。
误区字段级血缘必须通过 SQL 语法树精确解析出来,解析不了就是系统不合格。
正解现实中大量转换发生在 Python 脚本、存储过程甚至手工处理里,静态解析根本无能为力。业界普遍采用“SQL 解析 + 算子级运行时追踪 + 人工标注”的混合策略,还会给血缘结果打置信度。就像菜谱里“少许盐”无法精确量化,老师傅凭经验补全,血缘系统也一样要接受“部分靠推断”。
为何常见:教程最爱讲 SQL 解析,因为它干净漂亮,容易让人误以为解析是唯一且完备的手段。
误区血缘图画完一次就永远不变了,直接查就行。
正解模型不断重训、数据天天更新分区,血缘本质是由事件流驱动的“活图”。每次运行都会产生新事件、新版本节点,旧版本退役,查询还必须支持时间维度——“三个月前的模型 v2 用了哪批数据”。老王的食材供应链天天进新货,溯源墙上的毛线每天都在变,血缘系统同理。
为何常见:单次演示只展示一张静态 DAG,让初学者忽略了血缘随运行持续演化的本质。
误区这张表被改了,只需要看直接读它的那个作业,其他不用管。
正解影响必须沿有向边做传递闭包:表→特征作业→特征表→训练作业→模型→在线服务,每一跳都可能放大风险。老王查“坏猪肉”如果只看直接做菜的那位厨师,就会漏掉用同批肉做的试吃装和外卖菜品。血缘的价值恰恰在于多跳关联,而不是一跳邻居。
为何常见:人脑天然习惯看一步,而图算法解决的就是“人眼看不完多跳链路”的问题。
误区装了 OpenLineage,血缘系统就有了,打开就能看到血缘图。
正解OpenLineage 是一套规范——事件格式、命名空间约定、引擎集成标准,相当于“全国通用食材编码表”。你还需要一个平台(如 Marquez 或自研)来接收事件、构建血缘图、提供查询 API 和可视化。编码表不等于仓库管理系统,规范也不等于现成的血缘平台。
为何常见:OpenLineage 提供了大量连接器,装完确实有事件在跑,让人误以为“开箱即用”。
面试题
Q1. 模型血缘追踪中,“血缘图”通常被建模成什么结构?
- A.无序无向的树形结构
- B.有向无环图(DAG)← 正确答案
- C.带头尾的单向链表
- D.不加约束的循环图
答案:B。血缘图必须是有向无环图:有向表示依赖有方向(数据流向模型),无环保证不会出现“鸡生蛋蛋生鸡”的死循环。树和链表无法表达多对多的依赖关系,循环图则会导致溯源无法终止。
Q2. OpenLineage 项目主要提供什么?
- A.血缘事件的开放标准规范← 正确答案
- B.一个训练神经网络的框架
- C.在线推理的模型服务系统
- D.特征存储的分布式数据库
答案:A。OpenLineage 是 Linux 基金会托管的血缘元数据开放标准,定义统一的事件格式,让不同引擎(Spark、Airflow、dbt)用同一种“食材溯源码”上报血缘。它不是训练框架、推理服务或特征库。
Q3. 元数据中,用于记录“代码来源”的典型字段是?
- A.数据表分区和行数统计
- B.Git commit 与镜像哈希← 正确答案
- C.模型推理的 QPS 指标
- D.前端页面的加载耗时
答案:B。代码血缘的核心是“哪段代码、哪个版本产出了这个结果”,所以 Git commit 哈希和容器镜像哈希是标准字段。分区行数属于数据元数据,QPS 属于运行监控,加载耗时与血缘无关。
Q4. 在 DAG 血缘图中,边的方向通常表示什么?
- A.箭头指向上游的数据出处
- B.数据从上游流向下游的依赖← 正确答案
- C.边越长表示耗时越长
- D.边的粗细表示数据大小
答案:B。血缘边统一从上游指向下游,例如“数据表→特征作业→模型”,下游依赖上游。边长度和粗细只影响可视化布局,不代表耗时或数据量,方向语义才是关键。
Q5. 字段级血缘的常见获取手段有哪些?
- A.对 SQL 做语法树解析← 正确答案
- B.追踪执行计划算子的列来源← 正确答案
- C.仅记录文件的大小与时间
- D.人工标注非 SQL 转换映射← 正确答案
答案:ABD。字段级血缘靠 SQL 语法树、执行计划算子追踪和人工标注三种手段混合获取。只记录文件大小和时间是表级元数据,无法回答“某一列从哪来”的问题。
Q6. 变更影响分析的核心算法思路是?
- A.只检查变更节点的直接邻居
- B.沿有向边做 BFS 全链路传播← 正确答案
- C.对模型做随机扰动消融实验
- D.比较前后两版数据的相似度
答案:B。影响分析必须从变更节点出发,沿有向边做传递闭包式的全图遍历,把所有可达下游都纳入影响集。只看直接邻居会漏掉“表→特征→模型→服务”这类多跳链路;随机扰动和相似度比较都不是血缘图的标准做法。
Q7. 血缘查询 API 通常返回什么统一结构?
- A.{entities, edges, depth}← 正确答案
- B.{loss, accuracy, f1}
- C.{cpu, memory, latency}
- D.{schema, partitions, rows}
答案:A。血缘查询的结果本质是一张子图,需要返回实体列表、边列表和影响深度,前端据此渲染血缘图。loss/accuracy 是训练指标,cpu/memory 是资源指标,schema/partitions 是表结构信息,均非血缘查询的返回结构。
Q8. 关于血缘查询的后端存储,正确的说法有哪些?
- A.图数据库擅长多跳遍历查询← 正确答案
- B.关系表存边也可配合 BFS← 正确答案
- C.Redis 计数器适合存大图血缘
- D.血缘图可以不存在任何存储
答案:AB。图数据库(如 Neo4j)原生支持节点和边,多跳遍历效率高;关系数据库存边表加应用层 BFS 在小规模下也可行。Redis 计数器适合计数场景,不适合存复杂图结构;血缘图必须有持久化存储,否则无法支撑审计追溯。
Q9. 血缘覆盖率 C = m_recorded / m_total 反映的是什么?
- A.模型推理的实时响应速度
- B.血缘事件采集的完整程度← 正确答案
- C.训练数据的标签准确率
- D.上线模型的数量占比
答案:B。覆盖率 = 已采集到的血缘事件数 ÷ 应采集事件总数,衡量的是“身世档案记全了没有”。它不反映推理速度、标签质量或模型数量,只反映血缘采集的完整度——覆盖率低意味着溯源盲区大。
Q10. 模型血缘在合规审计中的价值包括哪些?
- A.证明模型的训练数据来源← 正确答案
- B.还原训练的代码与超参数← 正确答案
- C.代替人工做全部代码审查
- D.自动修复线上数据的错误
答案:AB。血缘能提供数据来源、代码版本、超参数等“身世证据”,支撑监管审计和可复现性。但血缘是记录与查询系统,不具备代码审查能力和自动修复数据的能力,这两项分别属于静态检查和数据质量系统的职责。