知识图谱把实体、关系和主张组织成相互连接的模型。当 AI 应用需要遍历显式关系、保留证据谱系、执行领域约束或聚合跨文档事实时,它才具备独特价值。知识图谱不等于图数据库,GraphRAG也不是关键词、向量或混合检索的通用替代品。
本文把图谱定义为受治理的派生视图:每条主张回指原始来源片段与版本,每条检索路径继承授权边界,每种 GraphRAG 模式都必须在目标工作负载上击败更简单的基线。
目录
- 核心要点
- 知识图谱、图数据库与本体
- 生产架构
- 以主张和来源为建模核心
- 约束关系抽取与实体消歧
- 选择 RDF、属性图或关系存储
- 按查询类型路由 GraphRAG
- 安全执行图查询
- 统一授权与证据边界
- 分层评估知识图谱
- 运行增量更新、删除与回滚
- 常见失败模式
- 常见问题
- 参考资料
核心要点
- 知识图谱是一种知识表示;图数据库只是一种实现选择。
- 把抽取结果存为带来源、版本和状态的主张,不要当作永恒事实。
- 关系抽取和实体消歧都是可测量、可回滚的数据流水线。
- 只有图上下文优于关键词、向量或混合检索基线时才采用 GraphRAG。
- 禁止执行不受约束的 LLM 生成 Cypher,也不能信任查询携带的授权字段。
- 图路径说明检索用了什么证据,不揭示模型隐藏推理,也不证明结论正确。
- 抽取、消歧、图质量、检索、生成、安全和生命周期必须分层评测。
知识图谱、图数据库与本体
知识图谱是实体与主张的连接式表示,图数据库则是存储和查询图结构的软件。分清二者,才能避免让某个数据库产品反向决定知识模型。
| 概念 | 定义什么 | 不保证什么 |
|---|---|---|
| 知识图谱 | 实体、主张、关系、标识符与语义 | 真实性、完整性或特定数据库 |
| 图数据库 | 存储、索引、事务与遍历查询 | 本体质量或来源可靠性 |
| RDF 图 | 由 IRI 标识的主语-谓语-宾语三元组集合 | 未配置蕴涵机制时的丰富推理 |
| 属性图 | 带标签和属性的节点与关系 | 跨系统共享语义 |
| 本体 | 词汇、类、属性以及部分约束或规则 | 实例数据正确 |
| GraphRAG | 使用图派生上下文的检索架构族 | 每类查询都更优 |
稳定的 W3C RDF 1.1 Concepts Recommendation 将 RDF 图定义为三元组集合,将 RDF Dataset 定义为一个默认图和零个或多个命名图。RDF 1.2 仍在演进,生产契约不能把 Working Draft 写成最终标准。
属性图便于表达面向应用的关系遍历;RDF 强调全局标识、图交换和显式语义;关系数据库仍擅长事务、约束和有界 JOIN。生产系统可以组合多种模型,但实体身份、来源谱系和删除语义必须一致。
生产架构
生产级知识图谱应拆分来源记录、抽取、消歧、图发布、检索和答案生成。分层后,团队才能重跑某一环节,而不是在无感知状态下改变全部下游答案。
离线路径负责生成派生制品,在线路径只能检索调用方有权访问的制品。每个生成主张都应回答四个问题:
- 哪些原始来源片段支持它?
- 哪个抽取器和消歧器版本生成了图制品?
- 哪次授权决策允许召回?
- 当时启用了哪个图快照和索引快照?
任何答案缺失,代表系统存在可观测性缺口,而不是具备了解释能力。
以主张和来源为建模核心
更稳健的图模型把抽取边视为有证据支持的主张,而不是无条件事实。当来源冲突、随时间变化或只在特定范围内成立时,这个边界至关重要。
{
"claim_id": "clm_01J...",
"subject_id": "org:acme",
"predicate": "HEADQUARTERED_IN",
"object_id": "place:singapore",
"source_document_id": "doc_842",
"source_revision": "sha256:8f1...",
"source_span": {"start": 418, "end": 476},
"extractor_version": "relations-2026-08-01",
"valid_from": "2026-04-01",
"valid_to": null,
"tenant_id": "tenant_17",
"policy_scope": ["research"],
"state": "candidate"
}
原始文档及其版本才是引用边界。社区摘要、Embedding、消歧后的实体和图边都是派生辅助信息,必须回指原始边界,不能互相循环引用。
以下无第三方依赖的校验器展示了最小摄入契约:
from dataclasses import dataclass
from typing import Optional
ALLOWED_RELATIONS = {"HEADQUARTERED_IN", "OWNS", "DEPENDS_ON"}
@dataclass(frozen=True)
class Claim:
subject_id: str
predicate: str
object_id: str
source_document_id: str
source_revision: str
span_start: int
span_end: int
extractor_version: str
tenant_id: str
valid_to: Optional[str] = None
def validate_claim(claim: Claim, source_length: int) -> None:
if claim.predicate not in ALLOWED_RELATIONS:
raise ValueError("关系类型不在版本化词表中")
if not (0 <= claim.span_start < claim.span_end <= source_length):
raise ValueError("来源片段超出指定来源版本")
required = (
claim.subject_id,
claim.object_id,
claim.source_document_id,
claim.source_revision,
claim.extractor_version,
claim.tenant_id,
)
if any(not value.strip() for value in required):
raise ValueError("主张谱系与租户范围不能为空")
example = Claim(
subject_id="org:acme",
predicate="HEADQUARTERED_IN",
object_id="place:singapore",
source_document_id="doc_842",
source_revision="sha256:8f1",
span_start=10,
span_end=42,
extractor_version="relations-v3",
tenant_id="tenant_17",
)
validate_claim(example, source_length=100)
print("valid")
# 输出:valid
生产字段还应包含置信度、审核状态、时间范围、摄入时间、策略标签和被取代关系。置信度只能用于排序,不能成为发布无来源主张的许可。
约束关系抽取与实体消歧
关系抽取和实体消歧都是含噪推断任务,需要显式 Schema、标注测试集、审核队列和回滚能力。通用预训练语言模型加一组临时编造的标签,并不会自动变成关系分类器。
采用受约束的抽取契约:
- 定义版本化关系词表及合法的主客体类型。
- 每个候选实体和关系必须保留来源片段。
- 拒绝未知谓词,禁止运行时随意创建新边类型。
- 使用稳定标识符和可审计特征解析实体身份。
- 将低置信度或高影响合并送入人工审核。
- 分离候选、已接受和已拒绝主张。
实体消歧必须拥有独立发布门禁。有害合并会把两个不同实体污染到大量路径;有害拆分会制造重复身份并隐藏证据。除 pairwise precision/recall 外,还应按实体类型和语言统计有害合并率与有害拆分率。
不要覆盖冲突。保留主张级来源与时间范围,让检索能够显式暴露分歧,或选择某个时间点有效的主张。
选择 RDF、属性图或关系存储
存储模型应由工作负载与治理要求决定,而不是按厂商或数据规模套用一句口号。选型前要用代表性数据、遍历、更新和授权过滤执行基准测试。
| 决策因素 | RDF 存储 | 属性图 | 关系或混合存储 |
|---|---|---|---|
| 共享标识和标准化交换 | 适合 | 需要自定义约定 | 需要映射 |
| 本体和显式蕴涵 | 结合指定语义机制时适合 | 通常由应用管理 | 通常由应用管理 |
| 关系遍历型应用查询 | 可行,需实测 SPARQL 负载 | 通常表达自然 | 适合有界关系 |
| 事务记录和严格约束 | 取决于具体产品 | 取决于具体产品 | 通常是首选 |
| 复用现有运维平台 | 可能增加新技术栈 | 可能增加新技术栈 | 增量成本通常较低 |
| 细粒度授权 | 必须设计并验证 | 必须设计并验证 | 方案成熟度取决于模型 |
| 可移植性 | RDF 标准利于交换 | 查询方言与特性不同 | SQL 广泛,但扩展不同 |
数据库选型需要评估查询语言兼容性、事务与一致性、索引行为、遍历扇出、批量与增量摄入、备份恢复、可观测性、策略执行、托管或自建约束,以及实测总体成本。只列产品名无法完成这些判断。
按查询类型路由 GraphRAG
GraphRAG 是一组图增强检索架构,不同查询模式服务于不同任务。系统应按已评测的问题类型路由,而不是把所有请求都送入成本最高的路径。
Microsoft 的 GraphRAG 查询文档区分:
- Basic Search:向量 RAG 基线路径。
- Local Search:组合文本块、图实体、关系与相关报告。
- Global Search:围绕社区报告执行 map-reduce,回答全语料问题。
- DRIFT Search:利用社区信息扩展局部搜索。
原始 GraphRAG 论文在特定语料和评价标准下评估全局意义归纳,并未证明图检索对所有任务占优。独立的 WildGraphBench也表明收益依赖问题类型:图方法可能改善多事实聚合,BM25 对直接查找仍有竞争力,图聚合还可能丢失细节。
| 查询类型 | 起始基线 | 何时升级为图检索 |
|---|---|---|
| 精确标识符或原文事实 | 关键词/BM25 | 实体别名或关联记录提高召回 |
| 局部语义问题 | 向量或混合检索 | 邻接关系增加有来源证据 |
| 关联多事实问题 | 混合检索基线 | 有界遍历提高证据覆盖 |
| 全语料主题 | 聚合基线 | 社区报告在可接受成本下提高完整性 |
| 事务查询 | 权威数据库/API | 通常不经过 GraphRAG |
路由器应优先使用确定性特征,例如操作类型、识别出的实体、预期聚合范围和授权策略。LLM 可以参与意图分类,但输出仍需通过 Schema 校验并提供安全回退。
安全执行图查询
安全图检索应把已校验意图映射到预审查询模板,绝不能把模型生成的任意查询文本直接发送到数据库。
from dataclasses import dataclass
from enum import Enum
from typing import Any
class Intent(str, Enum):
ENTITY_PROFILE = "entity_profile"
DEPENDENCY_NEIGHBORS = "dependency_neighbors"
@dataclass(frozen=True)
class QueryPlan:
cypher: str
parameters: dict[str, Any]
TEMPLATES = {
Intent.ENTITY_PROFILE: """
MATCH (e:Entity {tenant_id: $tenant_id, id: $entity_id})
WHERE e.policy_scope IN $allowed_scopes
RETURN e.id AS id, e.name AS name, e.type AS type
LIMIT 1
""",
Intent.DEPENDENCY_NEIGHBORS: """
MATCH (e:Entity {tenant_id: $tenant_id, id: $entity_id})
-[r:DEPENDS_ON]->(n:Entity {tenant_id: $tenant_id})
WHERE e.policy_scope IN $allowed_scopes
AND n.policy_scope IN $allowed_scopes
RETURN n.id AS id, n.name AS name, r.claim_id AS claim_id
ORDER BY n.id
LIMIT $row_limit
""",
}
def build_plan(
intent: Intent,
*,
entity_id: str,
authoritative_tenant_id: str,
authoritative_scopes: list[str],
requested_limit: int = 25,
) -> QueryPlan:
if not entity_id or len(entity_id) > 128:
raise ValueError("实体标识不合法")
if not authoritative_scopes:
raise PermissionError("调用方没有已授权策略范围")
return QueryPlan(
cypher=TEMPLATES[intent],
parameters={
"entity_id": entity_id,
"tenant_id": authoritative_tenant_id,
"allowed_scopes": authoritative_scopes,
"row_limit": min(max(requested_limit, 1), 100),
},
)
plan = build_plan(
Intent.DEPENDENCY_NEIGHBORS,
entity_id="service:checkout",
authoritative_tenant_id="tenant_17",
authoritative_scopes=["operations"],
requested_limit=500,
)
print(plan.parameters["row_limit"])
# 输出:100
Neo4j Cypher 注入防护文档解释了为什么字面值必须参数化:查询文本与参数会分离编译。但这只是必要控制,不是完整安全方案。
生产系统必须同时执行:
- 从可信身份和策略服务取得租户、对象与目的范围。
- 使用只读、最小权限数据库角色。
- Allowlist 查询模板、标签、关系类型和可排序属性。
- 限制遍历深度、扇出、返回行数、时间和内存。
- 对字面值进行参数化。
- 数据库错误进入模型或客户端前必须脱敏。
- 记录模板 ID、策略决策、快照、脱敏参数、时延和结果行数。
参数化可以阻断字面值注入,不能完成授权。动态标签、关系类型、属性名与查询子句也不能因为放进参数就自动安全。
统一授权与证据边界
授权必须让原始文本、向量块、图主张和生成摘要得到同一个访问结论,否则图索引会成为绕过文档权限的侧信道。
授权应在检索前和检索中执行:
- 从权威服务解析调用方身份、租户、用途和对象权限。
- 按这些权限过滤候选索引。
- 在图查询模板内强制租户和策略范围。
- 组装 Prompt 前重新校验每个来源片段。
- 拒绝指向授权证据集之外的生成引用。
- 记录策略决策与图/索引快照以供审计。
禁止让模型生成 tenant_id、allowed_scopes 或访问控制谓词。查询文本不是身份来源。
社区报告等图摘要必须继承源文档的权限。一个混合了允许和禁止文档的摘要,不能通过隐藏引用变成安全内容;它必须针对当前授权证据重新构建,否则就应排除。
分层评估知识图谱
单一答案分数无法定位回归来自抽取、消歧、检索、生成还是策略,因此需要分层门禁,并在每次发布评测中保留更简单的检索基线。
| 层级 | 指标示例 | 严重失败 |
|---|---|---|
| 抽取 | 实体/关系 precision、recall、F1,来源片段有效率,词表违规率 | 无来源或不可追踪主张 |
| 消歧 | Pairwise precision/recall/F1,有害合并率,有害拆分率 | 跨实体污染 |
| 图质量 | 来源覆盖率、过期边率、孤立率、重复实体率 | 已接受边没有有效证据 |
| 检索 | 证据 Recall@K、路径/证据覆盖、引用覆盖 | 漏掉授权证据或返回越权证据 |
| 生成 | 正确性、主张支持、完整性、拒答、冲突处理 | 关键主张无证据支持 |
| 安全 | 越权内容召回率、跨租户泄漏、模板绕过攻击 | 任何未授权披露 |
| 运维 | p50/p95 时延、索引成本、刷新延迟、更新放大 | 违反 SLO 或删除期限 |
以下无依赖示例分别计算证据召回率与引用精度,避免把两者混为一个指标:
def retrieval_metrics(
required_evidence: set[str],
retrieved_evidence: list[str],
cited_evidence: list[str],
) -> dict[str, float]:
retrieved = set(retrieved_evidence)
cited = set(cited_evidence)
recall = len(required_evidence & retrieved) / max(len(required_evidence), 1)
citation_precision = len(cited & retrieved) / max(len(cited), 1)
return {
"evidence_recall": round(recall, 3),
"citation_precision": round(citation_precision, 3),
}
print(retrieval_metrics(
required_evidence={"span:A", "span:B"},
retrieved_evidence=["span:A", "span:C"],
cited_evidence=["span:A", "span:X"],
))
# 输出:{'evidence_recall': 0.5, 'citation_precision': 0.5}
结果应按问题类型、语言、租户、实体类型、图深度和来源新鲜度切片,并把质量、时延和成本一起报告。全语料综合有所提升,并不代表直接事实查询也应该走更慢、更不精确的路径。
生产级 RAG 评估指南提供更完整的发布门禁设计;GraphRAG 高级工程指南深入讲解抽取契约和基线实验;语义搜索指南覆盖混合检索和授权过滤。
运行增量更新、删除与回滚
生产图谱是版本化派生视图,因此更新和删除必须传播到所有衍生物。只更新来源文档,会让旧主张、Embedding、社区报告和缓存继续生效。
维护完整依赖清单:
来源版本
-> 文本分段
-> 候选主张
-> 消歧实体
-> 已接受图快照
-> 关键词/向量索引
-> 社区划分
-> 生成摘要
-> 检索与答案缓存
每次来源变更应执行:
- 创建不可变的新来源版本。
- 重新抽取受影响片段并比较主张差异。
- 只对受影响候选重新执行实体消歧。
- 原子发布新的图与索引快照。
- 失效依赖已变主张的摘要和缓存。
- 保留上一快照用于回滚。
删除时应立即 Tombstone 来源并阻止召回,删除或撤回依赖主张,重建受影响摘要,清除缓存,并在约定期限内验证传播完成。删除覆盖率和传播延迟都应进入发布指标。
常见失败模式
危害最大的故障通常跨越多个层级,因此单一答案质量指标看不到它们。
| 失败 | 根因 | 生产控制 |
|---|---|---|
| 把知识图谱当事实库 | 抽取边丢失来源语境 | 主张节点、来源片段、审核状态、时间范围 |
| 不同实体被合并 | 身份特征弱或全局阈值粗糙 | 分类型阈值、审核队列、可回滚 |
| 同一实体被拆分 | 别名和多语言匹配缺口 | 稳定 ID、别名来源、pairwise 评测 |
| GraphRAG 替代所有基线 | 先选架构、后评工作负载 | 查询类型路由与基线门禁 |
| 把路径当解释 | 混淆检索产物与推理 | 路径标记为证据,并引用原始片段 |
| 执行生成 Cypher | 模型输出越过信任边界 | 预审模板与严格参数 |
| 租户过滤来自 Prompt | 把查询数据误当授权 | 权威身份与策略服务 |
| 删除来源仍影响答案 | 派生制品缺少依赖谱系 | 删除清单、传播 SLO、结果核验 |
| 社区摘要成为权威来源 | 引用生成文本而非原文 | 摘要到片段谱系与引用校验 |
常见问题
所有知识图谱都基于 RDF 吗?
不是。RDF 是基于三元组和 IRI 的标准化图数据模型,知识图谱也可以使用属性图、关系模型、搜索索引或它们的组合。无论选择哪种存储,都应保留实体身份、语义、来源与生命周期边界。
构建知识图谱必须先有本体吗?
不一定。小型应用可以从受约束的实体和关系 Schema 起步。当团队需要共享语义、互操作、推理规则或形式化约束时,本体更有价值,但它不能验证来源真实性,也不会消除实体消歧错误。
GraphRAG 能减少幻觉吗?
它可能为部分任务提供更完整的证据,但不能保证答案真实。风险仍取决于抽取质量、检索覆盖、授权、Prompt 组装、模型行为和主张级核验。应测量主张支持率与拒答能力,而不是假设有图就不会幻觉。
图遍历应该设置多深?
没有通用深度。针对产品真正需要的关系编写固定 Allowlist 模板,再评测覆盖、扇出、时延和错误关联。无界或由模型自由选择的深度会增加成本、泄漏风险和无关路径。
什么情况下不应采用 GraphRAG?
当权威数据库、BM25、向量或混合检索已经满足质量与时延目标;当源文档权限无法传播到图制品;或团队无法维护抽取、消歧、更新、删除和分层评测时,都不应引入 GraphRAG。
参考资料
- RDF 1.1 Concepts and Abstract Syntax — W3C Recommendation
- GraphRAG Query Overview — Microsoft
- From Local to Global: A Graph RAG Approach to Query-Focused Summarization
- WildGraphBench: Benchmarking Graph-Based Retrieval-Augmented Generation
- Protecting against Cypher Injection — Neo4j
总结
知识图谱只有把身份、关系、来源、策略和生命周期显式化,才会形成长期 AI 工程价值。将图谱构建成权威来源的版本化派生视图,让抽取与消歧可逆,只在评测证明收益时路由 GraphRAG,并通过有界模板执行图查询。最终得到的不是自动真实,也不是隐藏推理的窗口,而是一套证据和治理契约可测量的检索系统。