当LLM遇见知识图谱:如何让数据库诚实地说“我不知道”

Helio用知识图谱做企业知识代理,核心结论是定义“正确”比优化模型更难也更重要。
Helio 是一个基于 FalkorDB 知识图谱的企业知识代理,用 7 种节点、14 种边模拟 120 人金融科技组织,回答“谁了解支付服务、宕机影响什么、决策在哪定”。文章的核心不在检索,而在如何确信 LLM 输出正确。团队指出 LLM 自我评判是循环论证,幻觉与正确答案在结构上无法区分,因此在实现前先手写 20 条标准答案键,其中 5 条刻意无解,把“我不知道”设为有评分的特性。文章还拆解了数量与时效混淆、SUPERSEDES 边证明过时、验证门 AND/ANY_OF 误判、SSE 全量快照、未闭合 div 导致静默删除等一系列“看起来正确、实际错误”的坑,并给出先写答案键、指标坏了别修模型、让破坏性操作大声失败等建议。
企业知识是天然图谱:服务依赖服务,团队拥有服务,决策覆盖决策。但大多数企业搜索仍停留在“找文档”层面。Helio 是一个基于知识图谱的企业知识代理,它试图回答“谁了解支付服务?它宕机了会影响什么?这个决策在哪里定的?答案有多新?”——一次遍历,路径可见。

但真正棘手的问题不在检索,而在于你如何确信一个 LLM 生成的结果是正确的。本文拆解了 Helio 团队踩过的坑,核心结论是:在 AI 系统里,定义“正确”比优化模型更难,也更重要。
检索的信任危机:循环验证陷阱
Helio 团队用 FalkorDB 构建了一个包含 7 种节点类型、14 种边类型的合成金融科技知识图谱,模拟 120 人在支付迁移中的组织。然后他们把 LLM 接到图谱上,通过工具调用循环工作。
检索部分很快跑通了。紧接着一个理所当然的问题浮出水面:你怎么知道它没有胡编?
常规做法是让 LLM 自我评判——问模型“这个答案对吗?”。但作者明确指出:这是循环论证。一个幻觉的所有权链路和一个正确的所有权链路在结构上完全相同:都是基于格式良好的边生成的流畅文本,都提到服务、团队、日期和文档。当评判模型被问“这看起来对吗?”,它看到的证据在两种情况下一模一样。
失败在构造上就是不可见的。没有任何信号会提前警告你。
LLM-as-a-Judge(模型即评判者) 是当前评估生成式AI系统的主流范式:用另一个(通常更强的)LLM对候选答案打分或判断对错。它的吸引力在于成本低、可扩展,且能处理开放式输出。但其根本缺陷在于评判者与被评判者共享同一套语言先验——两者都会把“格式良好、术语一致、逻辑通顺”误认为“事实正确”。在知识图谱检索场景中,这一点尤其致命:无论答案是否真的对应图中的边,只要文本读起来像那么回事,评判模型就倾向于给高分。学界因此提出“参照锚定评估”(reference-anchored evaluation),即先固定人工标注的标准答案,再让自动评分对齐该答案,而非让模型自由裁量。Helio 的 GROUND_TRUTH.md 正是这一思路的工程化落地:把“正确”外置为不可被模型漂移污染的固定文件。
先写答案键:把“正确”定义在实现之前
团队做了一个当时觉得反直觉的决定:在生成任何一行数据之前,先在 GROUND_TRUTH.md 中手写 20 条关于公司的事实。
这颠倒了通常的顺序。多数人先建系统,再凭肉眼判断它是否能工作。而 Helio 先锁定“正确”的含义,生成器必须满足这个答案键,而不是反过来。
更关键的是:这 20 个问题中有 5 个在图谱中没有答案。这是有意设计的。例如:
"谁拥有 config-service?"
→ "图谱中不存在 OWNED_BY 边。没有团队拥有它。"
这个回答就是产品本身。不是道歉,不是含糊,不是猜测——因为缺失的边是一个真实的、正确的答案,而不是数据的缺口。在这里发明一个所有者的代理已经失败了,即使句子读起来完美无缺。团队把这一点设为显式的评分类别,而不是脚注。
这个框架改变的不只是测试,还有优化目标。一旦“拒绝回答”成为与“正确回答”同权重的评分行为,提示词就不再关于“如何更有用”,而开始关于“如何更可验证”。
图谱才能抓到的两类错误
数量与时间的混淆陷阱
Priya Sharma 在 payments-gateway 上有最多的提交——14 次。她最后一次提交是 2026-04-15,也就是她离开公司的那天。
一个 ORDER BY count DESC 会返回 Priya。这个查询在数量上技术正确,但作为答案完全错误。任何把“谁了解这个”压缩成一个数字的系统,都会自信地产生这种错误,而且输出里没有任何可疑迹象。
Helio 的解法是返回两个独立信号并拒绝混合:
平台团队拥有支付服务。Ravi Menon 最近仍在处理它(2026-09-28)。Priya Sharma 提交最多(14 次),但她的最后接触是 2026-04-15,被标记为过时。去问 Ravi Menon。
修复不是靠更聪明的模型,而是不在本应有两个事实的地方只放一个数字。数量和时效是两条独立边的独立属性,合并它们是建模错误,不是智能问题。
带引用的矛盾
一份三月文档和一个三月 Slack 线程都说“单一供应商,Stripe”。而决策 D-19(2026-05-06)说“双供应商,Adyen 主,Stripe 备”。
两个来源都已过时,图谱可以证明这一点——因为 SUPERSEDES 是一条边,不是推理。这是嵌入向量做不到的事:嵌入可以告诉你这些文档相似,但无法告诉你其中一份已经被一个你能叫出名字的决策正式废弃。引用让过时变得可操作;没有这条边,“这个文档过时了”会让读者无法判断它到底推翻了哪个现行决策。
SUPERSEDES 边属于知识图谱中的时序/版本关系建模。它与普通的“相关”边有本质区别:相关边只表达语义接近,而 SUPERSEDES 表达“B 正式取代了 A”,从而让系统能回答“当前有效的是什么”而非仅仅“有哪些相似文档”。在向量检索中,两份内容相近的文档会得到几乎相同的嵌入,系统无法区分哪份已失效;而在图谱中,一条 SUPERSEDES 边就把“过时”从模糊判断变成了可遍历、可引用、可审计的事实。这也是为什么带引用的矛盾检测必须依赖图结构:引用需要指向一个具名的、可定位的取代者(如决策 D-19),否则“这份文档过时了”只是一句无法验证的断言。
最值钱的 bug:自己的验证门在说谎
项目进行到中途,他们的验证门报告四个必须失败的测试问题全部错误。而事实上,它们都是正确且完整的拒绝回答:
Q16 "图谱中不存在 config-service 的 OWNED_BY 边……"
→ 匹配了 8 种措辞中的 1 种
Q17 "图谱中不存在摘要提及定价的决策。"
→ 匹配了 10 种中的 1 种
Q20 "图谱中不存在 dispute-service 的 SLA 条目。"
→ 匹配了 7 种中的 1 种
每一个语义上都是完美的拒绝。每一个都被判失败。
原因是验证门要求“不”的八种拼写必须出现在同一个句子里。按 AND 逻辑读,它要求一句话说八遍“不不不不不不不”——没有一个正确答案会这么做。
他们发布了一个恰好朝浪费时间方向倒退的门。 它被优化为看起来严谨,同时精确惩罚了他们声称想要的行为。
更值得记录的是他们首先尝试的修复:扩大词汇表。结果通过率下降了。扩大 AND 列表严格来说会更难——每个新增词都是另一个合取项。
修复的是匹配规则,不是词汇表。
拒绝有很多拼写方式,没有一个答案包含全部。所以必须失败的用例采用 ANY_OF,而肯定性用例保持 AND——因为要证明你理解哪个决策是现行的,“D-19”和“取代”都必须出现,但“没有所有者”只需要一种诚实的表达。
这个教训可以推广到项目之外:当一个指标朝错误方向移动时,指标本身通常就是 bug。 他们差点去“修复”模型,而模型一直是好的。
验证门(verification gate) 是 CI/CD 中阻止不合格产物进入下一环节的自动化检查。在 AI 系统中,它通常表现为一组“必须通过/必须失败”的断言测试。设计验证门时最容易犯的错误是混淆两类逻辑:肯定性用例要求关键要素全部出现(AND),而否定性/拒绝用例只要求任一合理措辞出现即可(ANY_OF)。若对拒绝用例误用 AND,门就会要求一句话同时包含所有同义词,从而系统性判错正确输出。更隐蔽的是,这种错误会让指标朝“更严格”的方向移动,看起来像是质量提升,实则惩罚了系统应有的诚实行为。因此验证门本身也需要被测试——用已知正确的样本反向校验门是否会误杀,是防止“门在说谎”的必要手段。
其他被踩碎的假设
SSE 每一帧发送完整快照,不是增量。 处理器必须替换而不是追加。追加只在一帧内看起来正确,这正是它能通过随意测试、然后在生产环境复制整个答案轨迹的原因。协议假设就是代码。
六个图谱事实代理在结构上无法触及。 不是“答错了”,而是无法到达。Cypher 正确,遍历正确,但返回行的形状没有提供模型会走的路径。一个正确的查询藏在一个不可触及的表面后面,仍然不可触及。
工具结果触发了 413。 一个 6.5k token 的工具结果大到直接被拒绝。修复是返回轨迹而不是原始行——这反而成了更好的产品设计,因为轨迹正是人想看到的东西。
代理结果每次运行不稳定。 模型是采样的,单次扫描说明不了什么。任何从一次运行得出的结论——包括“修复生效了”——几乎毫无价值。这就是为什么标准答案集是固定且手写的:它不会随模型漂移。
前端与删除的教训
网站起步于另一个产品的逆向工程捕获,意味着继承了整个代码库——包括加载的 12 个第三方脚本,其中一个从他们的域名拉取,还有一个资源节省脚本在解析中途删除 DOM 节点,导致 hydration 不匹配。全部移除后:0 控制台错误。
真正硬核的教训来自删除操作。捕获的 HTML 有未闭合的 <div>,这意味着显而易见的做法——数 <div> 和 </div> 直到深度归零——会静默地越过元素的真实结尾。那一次删掉了页脚和四个完整章节。切割看起来平衡,没有任何东西报错。这是最糟糕的 bug 类型:失败不可见,直到你发现某个章节消失了。
修复是停止信任结构,开始检查它:用真正的 HTML 解析器推导范围,并且在哨兵计数(</main>、<footer> 等)存活之前拒绝写入。一个不会静默失败的删除,比一个通常正确的删除更有价值。
CSS 里也有对称的教训:他们试图通过分层捕获的样式表让工具类赢,按钮上完美工作,但把页面每个章节砍半,因为标记使用了两个样式表都拥有的通用类名。真正的机制一直是加载顺序。
Hydration 不匹配是服务端渲染(SSR)框架中的一类经典故障:服务器生成的 HTML 与客户端首次渲染的虚拟 DOM 不一致,框架在“接管”页面时检测到差异,轻则警告、重则丢弃并重渲染整棵子树。常见诱因包括第三方脚本在解析途中修改 DOM、浏览器扩展注入节点、以及依赖时间或随机数的渲染逻辑。文中“资源节省脚本在解析中途删除 DOM 节点”正是典型触发场景——服务器输出的结构与客户端预期结构对不上。移除这类脚本后控制台归零,说明 hydration 的稳定性高度依赖“服务端与客户端看到同一棵 DOM 树”这一隐含契约,任何破坏该契约的优化都会以难以定位的方式失败。
给后来者的几条建议
先写答案键。 当正确性在实现存在之前被定义,下游一切都会变便宜。
把“我不知道”当作有评分特性。 如果拒绝不被测量,模型就会因为猜测而得到奖励。
永远不要让一个数字代表两个事实。 数量/时效陷阱不是 AI 失败,而是多年前在 LLM 出现之前做出的数据建模选择。
指标坏了就别修模型。 他们的验证门一天内判错了四个正确答案,扩大词汇让情况更糟。模型一直是正确的。
让破坏性操作大声失败。 未闭合 div 和分层 CSS 的 bug 有相同根因:看起来正确,实际错误。两者都是通过问“我需要检查什么才能知道这是安全的”发现的,而不是靠看得更仔细。
所有数据均为合成。
相关推荐

零成本搭建AI超级员工系统:智能体自动工作流全解析
深度拆解B站演示的AI超级员工系统:Agent智能体编排、数字人口播、地图与企业获客、24小时智能客服及法务模块全覆盖。分析零成本开户背后的商业逻辑与合规风险,帮助创业者判断这套AI数字员工系统的真实投产比。

Chatbot与AI Agent的本质区别:从对话到执行的跨越
Chatbot和AI Agent有什么区别?本文基于Learn Tech频道的MCP系列讲解,用订机票、笔记摘要等实例说明:Chatbot只给答案,Agent通过思考-行动-观察循环真正完成任务,并拆解模型、工具、记忆、目标四大部件及MCP的桥梁作用,同时讨论Agent的适用边界与权限风险。

免费GitHub仓库:342小时AI课程,从数学到MCP服务器
一个免费GitHub仓库提供342小时AI课程,包含523节课、20个阶段,覆盖数学基础到Agent构建和MCP服务器。支持目标驱动学习,每节课产出可留存的prompt、skill或agent,已有近10万人开始学习。