知识图谱如何构建

文档被切成一个个窗口,交给大语言模型并发抽取实体和关系;每个窗口独立成败,收敛器在固定内存里把它们合并成带血缘的规范事实。图谱允许部分完成,但永远会如实标出“部分”,不会把残缺的图当成完整的图。

知识图谱回答的是“谁和谁有什么关系”。它的原料是文档片段,加工者是大语言模型,产物是实体、关系,以及每条事实来自哪里的记录。听起来简单,难点在规模和可靠性:一份几百页的文档要调用几十上百次模型,任何一次都可能超时、限流或输出异常。

ApeMind 的图谱构建围绕三个约束设计:内存有上限,不随文档变大而增长;失败有边界,一个窗口失败不连累其他窗口;事实可追溯,每个实体和关系都能回到原文片段。

从片段到可查询的图谱

01文档片段
02并发窗口抽取
03先落对象,再写指针
对象→指针
04有界收敛
逐页合并 · 分批写入
05带血缘的规范事实
06实体向量投影
hash(name+type)→ 向量
  1. 从解析产物开始

    图谱不重新读源文件,直接使用解析阶段产出的片段。重新解析会生成新的片段,图谱随之重建。

  2. 按窗口并发抽取

    连续的若干片段组成一个 窗口,固定数量的执行器并发处理。先从样本里发现实体类型,再逐窗口抽取实体和关系。

  3. 先落对象,再写指针

    每个成功窗口的结果写成一个有大小上限的不可变对象,对象提交成功后,才在数据库里记下“这个窗口成功了”。

  4. 有界收敛

    所有窗口都结束后,收敛器分页读取成功对象,在固定内存预算里按规范键合并,达到预算就分批写入图数据库,再清空这一页继续。

  5. 发布规范事实

    相同实体合并类型和血缘,相同关系合并证据。事实一经发布就能查询,并明确标注完整或部分完成。

  6. 异步维护实体向量

    实体的名称和类型变化后,后台工作器重新生成向量,用于语义找实体。向量慢一点或失败,都不影响已发布的事实。

窗口:失败的最小单位

把整篇文档一次性交给模型不可行,超出上下文窗口;逐片段调用又会丢掉片段之间的关联。窗口是两者的折中:足够大,能看到一段完整的上下文;足够小,失败了只需重试这一块。

每个窗口都有稳定的身份和内容哈希、自己的状态和尝试次数。一个窗口失败,其他窗口的成果原样保留。下面可以亲手跑一次:调整窗口数和永久失败的窗口数,看最终会发布什么。

待处理 抽取中 成功 重试中 永久失败
成功0
失败0
待处理0

动画为示意;容忍上限的计算规则与产品一致。

判定规则只有三条:

容忍上限按窗口总数计算:目标为 5%,至少按 3 个窗口算,同时不超过总数的 25%。还有重试机会的窗口不算失败,会先进入有限次自愈。

先落对象,再写指针

窗口成功后,结果不会直接写进图数据库,而是先序列化、校验结构、分别检查压缩前和压缩后的大小,写成一个不可变对象;对象提交成功后,才在数据库里写下指向它的指针。

这个顺序保证了一件事:数据库里说“成功”的窗口,一定能找到它的结果。反过来,只有对象没有指针的,是崩溃留下的孤儿,由清理器回收。超过大小上限的窗口会以明确的错误失败并有限次重试,不在运行中临时拆分,避免引入分片提交和部分恢复这类复杂协议。

有界收敛

收敛器是把几十个窗口结果合成一张图的环节,也是最容易爆内存的环节。如果它把整篇文档的实体和关系全部装进内存再写入,文档越大,内存越大,迟早会被一份超大文档压垮。

ApeMind 的收敛器不保留全集。它一页一页地读成功对象,只在当前预算内按规范键合并;预算或键数量到达上限,就把这一批写进图数据库,清空后继续。去重同时发生在两层:内存页内精确合并,图数据库按唯一键幂等写入并合并血缘。最终正确性依赖数据库的唯一键,而不是进程里那份无上限的全集。

收敛器崩溃后不需要“从第几页继续”的恢复表,直接从全部成功对象重放即可。写入和血缘合并都是幂等的,重放多少次结果都一样。

血缘:删掉一篇文档会发生什么

同一个实体常常由多篇文档共同贡献。“区域总监”可能同时出现在审批权限表和组织架构里。图谱为每个实体和关系记录 血缘,删除文档时只摘掉这篇文档的血缘:还有其他来源的事实继续保留,失去最后一个来源的事实才会被回收。

点左侧的文档把它移出知识库,观察哪些实体留下、哪些被回收,以及右侧的待刷新队列如何决定实体向量的去留。点实体可以查看它的血缘。

知识库中的文档
实体详情
实体待刷新队列

示例数据为演示用途。连线越粗,表示这条关系被越多文档共同支持。

实体向量是投影,不是事实

图谱有两层结果:图谱事实是权威层,包括实体、关系和血缘;实体向量是派生层,只是规范实体当前“名称 + 类型”的向量化投影,用来在查询时按语义找到实体。

两层被刻意解耦:

关系本身不生成向量,它们以事实的形式存在于图数据库里,服务于邻居、路径和证据查询。

换一种图数据库也成立

图谱事实可以存放在 PostgreSQL、Neo4j 或 NebulaGraph 里。PostgreSQL 后端把事实、血缘和向量待办写在同一个事务里,天然一致。Neo4j 和 NebulaGraph 无法与应用数据库组成跨库事务,系统先把受影响实体的待办持久化并加租约,再修改图数据库:如果图变更前崩溃,实体仍在,工作器幂等写入;如果变更后崩溃,实体已不在,工作器删除向量点。无论停在哪一步,结果都会收敛到正确状态。

查询时图谱扮演什么角色

图谱在检索中是第三条召回通道:先用实体向量或关键词找到实体,向外扩展邻居,再沿血缘回到原文片段,和向量、全文的结果一起融合。详见 三种索引如何分工。

图谱结果是导航和证据定位的线索。智能体最终引用的是原文片段,而不是模型抽取出的一条关系,这样即使抽取有偏差,回答也总能落到可核对的原文上。

边界

出问题时查哪一环

文档的图谱状态显示“部分完成”

少数窗口永久失败,但没有超过容忍上限,已有事实已经发布并可查询。可以对这篇文档重建图谱索引,重建只读取已有解析产物,不重新解析源文件。

图谱索引直接失败

通常是系统性原因:模型鉴权失败、额度耗尽,或失败窗口过多。先检查知识库绑定的模型是否可用、额度是否充足,再重建。

图谱已完成,但按语义找不到某个实体

实体向量由后台异步维护,可能还在排队。按名称关键词搜索、邻居和路径查询不依赖向量,可以先用这些方式确认实体是否存在。

给想深入的读者:哪些状态是权威的

“哪些窗口成功了”以数据库里的成功指针为准,对象存储里没有指针的对象视为孤儿。文档级图谱状态只有一个,即图谱事实的状态。实体向量没有文档级状态,它唯一持久的待办来源是知识库级的待刷新记录,以“知识库 + 规范实体名”去重。所有清理和重试都是幂等的,并由持有者和租约隔离保护。