向量库为什么回答不了"为什么"
Semantica 的仓库里有一个乍看小题大做的测试:它验证当有人把因果关系录入成小写的 "causes" 时,系统遍历因果链还能不能找到这条边。
为这一个大小写,项目维护了两套因果词汇表和一份别名映射,写入时归一、读取时宽容,外加一条专门的回归测试(issue #1184)。
为什么对一条边的可见性这么偏执?因为这个项目面向的是审计场景:一条边录进去了、遍历时却查不到,因果链就静默少了一环。而对审计来说,静默少一环和编造一样不可接受——你的解释不再是被记录的事实,而是碰运气的采样。
这个偏执背后,是一个向量库和 RAG 压根没打算回答的问题:AI 做完一个决策之后,它能不能说清楚为什么。在信贷、医疗、招聘这些场景里,这个问题正在被越来越认真地追问。但先把技术账算清楚:今天的主流架构,回答不了它。
之前我们聊过一篇"AI 为什么总是看不懂你的数据",答案是元数据——把"数据是什么、谁拥有、能不能信"钉进结构里。今天我想更进一步聊这个问题:AI 基于这些数据做出的决策,它自己说得清吗?
结论也是显而易见的:这个问题靠向量库解决不了,靠让大模型"再解释一遍"也解决不了。因为可解释不是生成出来的,是记录下来的。而一个愿意为 "causes" 的大小写专门维护回归测试的项目,恰好把这句话做到了工程细节里。
一,先算技术账:为什么回答不了
向量检索解决的是"什么和什么在语义上相近"。Embedding 把文本映射成向量,检索时寻找的是距离更近的内容。这套机制在"找东西"上很好用。
但"相似"与"因果"是两种完全不同的关系。
你检索"为什么拒贷",可以找到"拒贷原因""拒贷案例""拒贷政策""拒贷结果"——但检索系统本身并不知道,其中哪一段是导致这次决策的证据,哪一段只是语义相关。
它能把相关内容找出来,却不能保证把决策依据的关系结构找出来。
那让模型事后解释自己呢?把决策的输入输出喂给大模型,让它生成一段解释。这个做法越来越普遍,问题是根本性的:模型给出的理由,是它照着结果编出来的事后叙事,不是决策当时的真实依据。这件事有一对术语可以区分:rationalization 和 provenance。前者是事后合理化:生成一个与结果相容、听起来合理的解释;后者是溯源:还原实际发生过什么、使用了什么依据、经过了什么推理路径。大模型流畅的解释,你无法判断是哪一种——这本身就是问题。
所以结论只剩一个:"为什么"必须在决策发生的那一刻就写进结构里。
决策是节点,依据是边,每条边带时间戳、带置信度。
解释的时候不生成,只遍历。
读过上一篇知识编译那篇的话,这句话你应该觉得耳熟。当时我们说,知识要编译到文档层——实体、关系、规则、证据。后来元数据平台把它编译到数据层。现在 Semantica 往前走了一步,编译到了决策层:决策本身进图,因果变成可遍历的结构。
二,Semantica 是个什么东西
它的定位是:把企业数据编译成带溯源和决策记录的知识图谱,在图上做可解释推理。开源,MIT,纯 Python。它不做大模型,也不做 Agent 框架,把自己放在这些东西底下的语义上下文层,主打回答一句话:AI 为什么这么做。
流水线长这样:
数据源 → 接入 → 解析/归一/分块 → 抽取 → 冲突检测/去重
→ 知识图谱 → [本体 · 推理 · 溯源 · 决策] → 增强图谱
→ 向量库 + 图存储 → REST / MCP / CLI / Python 库
流水线本身不新鲜,新鲜的是三个"确定性":建图、推理(前向链、Rete、Datalog、SPARQL)、溯源(W3C PROV-O),全都不依赖 LLM。LLM 在里面只是可选件,而且厂商中立。也就是说,解释不是"模型这次生成得像不像",是从图里算出来的。同样的图,算两次,结果一样。
决策在图里是一等公民:record_decision 记录决策,因果关系限定三种类型——CAUSED(导致)、INFLUENCED(影响)、PRECEDENT_FOR(成为先例),每条因果边写入时盖一个 recorded_at 时间戳。
框架就介绍到这,再往下就成 README 翻译了。真正有意思的是因果链遍历的实现,核心文件 context_graph.py 大约 5000 行。我从里面挑了四个细节,都不起眼,但每个背后都是一个取舍。
三,5000 行源码里的四个细节
1. 全局 visited 会静默丢链
写过图遍历的人第一反应:防环用全局 visited 集合,访问过就标记,下次跳过。教科书般的标准答案。
但在审计场景里,这个标准答案是错的。审计要的是每一条因果链:从决策 D 往回追,一条链走 A→B→D,另一条走 A→C→D,两条都得拿出来。全局 visited 走完第一条,把途经节点都标记了;再走第二条,走到 D 发现标记过,跳过。第二条链就这么没了。图还是那张图,数据一个字没少,但你的"解释"少了一条,而且没有任何人告诉你。
Semantica 的做法:环检测不用全局 visited,用跟着路径走的 frozenset。每条路径只检查"我是否已经出现在这条路径里",路径之间互不干扰。代价是路径数可能指数爆炸,于是拿两个参数兜底:max_depth(默认 5)限制单链长度,max_chains(默认 10000)限制链的总数。
还有个佐证。同一个项目里另有一个 BFS 版的 get_causal_chain,它就老老实实用全局 visited,因为它回答的问题是"哪些决策和 D 有因果关系",可达性语义下丢路径反而是对的。"有没有路"和"有哪些路"是两个问题,两个算法各为其主,写在同一个文件里。
2. 绝不静默
max_chains 设了上限,下一个问题来了:达到上限怎么办?多数系统的做法是停下来,把手里的返回给你,什么也不说。
Semantica 会在返回结果里显式追加一条 {"truncated": True, "message": ...} 标记,同时打 warning 日志。你拿到的链可能不完整,但它永远不会假装完整。
这个立场贯穿整个 API。add_causal_relationship 传进一个不存在的节点 ID,或者一个不是决策类型的节点,返回 False 加 warning,绝不静默成功。遍历整体出异常,也兜住并返回 error 结构,而不是装作没事。
开头那个小写 "causes" 的测试,也是同一立场。系统对自己的行为必须诚实:要么给全,要么明说少了什么。对一个解释系统来说,静默丢链在审计场景等于藏证据。解释别人的系统,自己的行为也得经得起解释。
3. 推断必须标注为推断
因果边有两个来源。一个是显式断言:人或上游系统录入的 CAUSED 边,它代表系统当前记录的事实关系。同一对节点之间有多条平行边时,全部上报,互不覆盖。
另一个是启发式推断:两个决策共享实体、且一个时间戳更早,系统推断出一条 influences 推断边。这种边属于系统推断,不是显式记录,Semantica 把它单独标出来:遍历结果的每一跳都带 type 字段,读的人一眼能分清哪一跳是显式断言,哪一跳是系统推断。
更重要的是,置信度不是只给整条链一个模糊的数字。每一跳都有自己的权重,逐跳衰减,报告里记录 weakest_link——链条中最薄弱的那一环;最终的解释措辞按衰减后的置信度分成四档,从"直接因果"一直到"弱证据"。
还有个容易看漏的保护:edge_weight 等于 0.0 时按 0 算,只有 None 才回退成 1.0。"置信度为零"和"没填置信度"是两件事,不能混。
因果强度的衰减要可量化,更要可指认:审计的人应该能指着某一跳说,问题出在这里。
4. 用当时所知,解释当时的决策
审计还有一个隐蔽的坑:事后信息。三月做的决策,依据的是当时掌握的情况;六月新证据进来,因果图更新了。九月你去审计三月的决策,如果直接在当前的图上遍历,就会用六月的信息解释三月的行为——这不叫解释,叫污染。
Semantica 给了 trace_at_time:遍历时只走 recorded_at 小于等于给定时刻的边。你给它一个时间点,它还原那个时间点上世界看起来的样子。前面说每条因果边写入时都盖 UTC 时间戳,那个戳就是为这一刻准备的。
换句话说,审计的不是"今天看来这个决定为什么成立",而是"在当时已经知道什么的前提下,这个决定为什么成立"。
四个细节,没有一个和算法炫技有关,全是立场问题:审计场景要的不是一个"差不多对"的解释,是一个每一环都能被问责的解释。
四,回到那张图:Metadata Plane 和 AI Plane
之前一篇讲数据基础设施的分化:Compute Plane、Storage Plane、Metadata Plane、AI Plane。DataHub、OpenMetadata、Gravitino 占的是 Metadata Plane,解决"AI 读不懂数据"。
如果沿用上一篇的分层方式,Semantica 可以放在 AI Plane 中负责"决策记录与解释"的这一侧:它不管数据目录,专管 AI 做了什么决策、为什么。两层不冲突,理论上可以叠放:OpenMetadata 告诉 Agent 数据是什么,Semantica 记录和解释 Agent 用这些数据做了什么决策、为什么。
上一篇还有一个我很认同的方法论:AI 需求驱动治理,先治理再做 AI 的路线会让治理永远做不完。可解释性同理。决策日志不是审计上门再补的东西。审计上门时你还没记,链条已经断了,事后重建的就只能是 rationalization,和让大模型再解释一遍没有区别。结构要在决策发生的那天就钉下来。
五,收尾
回到开头的问题:AI 做完一个决策,它能不能说清楚为什么。
向量库回答什么相关。知识图谱回答什么是什么。因果图才回答为什么。
可解释 AI 有两条路:让模型事后解释自己,或者让决策本身就是可解释的结构。前者是在生成解释,后者是在记录解释所依据的事实。
而可解释性从来不是宏大架构,是愿不愿意为一条小写的边,写一条回归测试。
如果你对可解释 AI、知识工程和决策基础设施的实践感兴趣,欢迎关注、点赞和转发。也可以GitHub找到Molio,star一下随时了解我们的实践之路。下一篇想聊聊这套因果图怎么和 Agent 框架接起来。