RAG从根本上改变了我们处理信息检索的方式。我们已经从关键词匹配的刚性世界,迈入了语义搜索这一更加流动和直觉化的领域。这种转变使我们能够基于概念含义来查找文档,而不仅仅依赖其中包含的特定词汇。尽管有这些优势,仅依赖向量搜索或混合搜索构建的RAG系统,在处理需要更精确地理解实体间关系的查询时,仍然可能力不从心。这个问题的产生是因为向量搜索处理的是概率和相似度,而非确定性的事实。以下是几个例子:
时间约束型事实
语义搜索不擅长回答依赖于特定时间点的问题,因为嵌入向量往往会将过去和现在的信息模糊在一起。¹
例如,"2022年10月Twitter的CEO是谁?"这样的查询,可能会返回提及Elon Musk、Jack Dorsey或Parag Agrawal的文本块,具体取决于检索到的文本内容,而无法与所请求的日期明确对齐。这通常会导致一个错误的回答,或者LLM试图提供所有选项而无法锁定2022年的具体正确答案。
多约束条件的交叉
当一个问题需要同时满足多个条件时,语义搜索倾向于返回松散相关的文本,而非保证条件的重叠覆盖。
以查询"哪些药物同时与华法林和葡萄柚汁存在相互作用?"为例。语义搜索可能会返回关于华法林相互作用的文本块,或关于葡萄柚汁相互作用的文本块,但不一定能找到一个同时涵盖两者的文本块。在这种情况下,你的RAG系统只有在某个返回的文本块恰好同时讨论了两者时,才能给出准确的答案。
链式或多跳推理
向量搜索处理的是主题相似性,但它不会遵循逐步的关系链。
对于查询"2014年由执导了《盗梦空间》的那个人执导的电影的主演是谁?",向量搜索可能返回关于《盗梦空间》的文本块,其中可能提到Christopher Nolan或他的影片列表,但LLM可能无法可靠地将这些信息串联成类似"Christopher Nolan → 《星际穿越》→ Matthew McConaughey"的推理链。
值得注意的是,正如我们在第7章中讨论的,AI智能体可能能够通过仔细地将查询分解为子查询并迭代地使用工具,来完全处理这些场景。尽管如此,在本章中,我们想要探讨的是:是否有一种方法可以在不依赖AI智能体的情况下提高RAG的检索准确性?
事实证明,知识图谱(KG)可以成为处理这类查询的有力工具,当这类复杂查询频繁出现,且其未能提供高质量回答会实质性地影响业务结果时,构建和部署知识图谱的生产复杂性就是合理的。
让我们深入了解知识图谱,理解它们的本质,以及如何将它们集成到你的RAG工作流中。
知识图谱:概述
知识图谱是一个由相互连接的实体组成的网络,以机器可读的形式编码事实性知识。²为了说明知识图谱在实践中如何运作,我们将使用IMDb数据集,该数据集提供了关于电影、电视节目、视频游戏及其参与人员的结构化数据,每一条记录都通过唯一的IMDb ID进行标识。
知识图谱的核心组件是节点和边:
节点(或实体)
图中的节点代表现实世界中的实体,如物体、人物、地点或概念。在IMDb的案例中,节点包括Movie(电影)、Person(人物)、Genre(类型)、Character(角色)等。节点通常具有属性,用于提供关于每个节点的附加信息。例如,一个Movie节点可以具有发行年份等属性。
边(或关系)
边是节点之间的连接,定义了它们彼此之间的关系。在IMDb的案例中,图的边可以是ACTED_IN(出演)、DIRECTED(执导)、HAS_GENRE(属于类型)、BELONGS_TO(属于)、APPEARS_IN(出现在)或MENTIONS(提及)。
让我们看一个描述与电影相关的节点和关系的简单知识图谱示例(图9-1)。
图9-1. 电影知识图谱示例
这里我们有两种类型的节点:Person(左侧方框)和Movie(右侧方框),以及两种类型的边:ACTED_IN和DIRECTED。
查询知识图谱不是关于寻找相似性(如向量搜索的情况),而是关于遍历已知事实或实体的路径。例如,要回答我们的多跳问题("2014年由执导了《盗梦空间》的那个人执导的电影的主演是谁?"),我们可以执行一个结构化查询:找到节点Inception;沿DIRECTED边遍历找到Christopher Nolan,然后遍历所有从他出发的DIRECTED边找到他的其他电影,保留2014年的电影;最后沿每部电影节点的ACTED_IN边找到主演。
从这个简单的例子中,很容易理解为什么搜索节点可以提供精确的结果,并解决语义搜索难以完成的问题。
如何搜索知识图谱?
图数据库是一种专门的NoSQL数据库,以图状结构存储数据,强调数据点之间的关系。与使用行和列的表的传统关系型数据库不同,图数据库使用节点和边来表示图数据,并且专为高效执行图查询而设计。
最突出的图数据库示例包括Neo4j、Amazon Neptune、Kuzu和TigerGraph。要与图数据库交互并从中检索信息,你需要使用图查询语言,如Cypher或SPARQL。这些专用语言旨在高效地遍历节点和边的网络,使你能够对数据中的关系提出复杂的问题。
Cypher
Cypher最初为Neo4j数据库开发,以其直观且高度可读的语法著称,在视觉上类似于图结构本身。
在Cypher中,节点用圆括号表示:(),边(关系)用方括号表示:[]。让我们看一个简单的模式。要查找执导了一部电影的人,你可以写:
(p:Person)-[:DIRECTED]->(m:Movie)
其中:
(p:Person)选择所有标记为Person的节点。我们给它一个变量名p。(m:Movie)选择所有标记为Movie的节点。我们给它一个变量名m。[:DIRECTED]描述边,指定关系类型为DIRECTED。->表示关系的方向——这个人执导了这部电影。
要将其转换为一个完整的查询,检索执导了电影《奥本海默》的人的名字,查询变为:
MATCH (p:Person)-[:DIRECTED]->(m:Movie)
WHERE m.title = 'Oppenheimer'
RETURN p.name
该查询告诉数据库MATCH(匹配)指定的模式,WHERE(在)电影标题为Oppenheimer处进行过滤,然后RETURN(返回)找到的人物节点的name属性。
在我们的简单图示例中,该查询返回"Christopher Nolan"。
SPARQL
SPARQL是资源描述框架(RDF)三元组存储的标准化查询语言,这是一种专门的知识图谱类型。它使用声明式模式匹配语法来查询三元组,三元组是构成图的三部分语句:
- 主语(subject)是被描述的资源。
- 谓语(predicate)是属性或关系。
- 宾语(object)是值或相关资源。
例如,查找《奥本海默》导演的同一查询在SPARQL中如下所示:
SELECT ?personName
WHERE {
?movie :title "Oppenheimer" .
?person :directed ?movie .
?person :name ?personName .
}
在这个SPARQL查询中,?person、?movie和?personName是变量。WHERE子句中的每一行都是数据库必须匹配的三元组模式。例如,?movie :title "Oppenheimer"告诉SPARQL我们要匹配标题为"Oppenheimer"的任何电影的三元组。
虽然在视觉上不如Cypher美观,但SPARQL是一个强大的万维网联盟(W3C)标准,用于查询图中的链接数据,旨在让你精确指定所需的数据。它更关注数据交付的塑造和优化,而非图论的探索。
在实践中,两者都可以用来实现类似的结果——这实际上取决于你的图数据库提供什么以及你对什么更熟悉。在本章的其余部分,我们使用Cypher提供示例,尽管我们也可以轻松使用SPARQL——这并不表示对其中任何一个的偏好。要了解更多关于图数据库和图查询语言的信息,你可以查阅全面涵盖该主题的其他书籍,如O'Reilly的《构建知识图谱》(Building Knowledge Graphs)。
本体与模式
在知识图谱的世界中,你经常会听到本体(ontology)和模式(schema)这两个术语。虽然它们密切相关,但在系统设计中服务于不同的目的。
本体是你领域的正式抽象模型,定义了知识图谱的"现实规则"。它不关心具体的数据点(如Christopher Nolan);相反,它定义了类别以及这些类别如何交互的逻辑约束。例如,在电影领域,本体规定"一个Person可以DIRECT一部Movie"但"一部Movie不能DIRECT一个Person",它定义了Movie必须有Release Year,等等。
模式是该本体的数据库级实现。它是你应用于图数据库的特定标签集、关系类型和数据约束,以便系统知道如何存储和索引数据。例如,如果本体说电影有发行年份,模式就定义数据库中的Movie节点将有一个名为release_year的属性,存储为Integer类型。
正如我们将在下一节中看到的,在与RAG一起使用时,你的本体帮助LLM理解数据的逻辑(例如,"要查找导演的演员,我必须通过Movie节点进行遍历"),而模式是你提供给LLM的东西(通常是文本描述),以便它在发出图数据库查询时能够生成正确的Cypher或SPARQL代码来获取数据。
现在我们已经基本了解了知识图谱如何存储在图数据库中以及如何使用图查询语言查询图,让我们看看如何将知识图谱集成到RAG中。
在RAG中使用知识图谱
为了演示知识图谱如何在RAG中使用,我们将扩展电影领域的示例,使用两个互补的数据源构建一个关于电影的知识图谱:
- IMDb(这里我们使用了非商业用途的IMDb数据集),如前所述,提供了基础的节点和关系集:经过验证的电影"谁、什么、何时"信息。我们将创建Movie、Person、Character和Genre等节点,以及电影的发行年份或人物角色等节点属性。
- 电影剧本来自Hugging Face上的MovieSum数据集,包含对话和场景描述。我们将把这些电影剧本分割成文本块,并填充Chunk节点。
让我们逐步了解如何从IMDb和MovieSum数据集构建这个特定的知识图谱。稍后在"构建知识图谱"部分,我们将讨论构建知识图谱的更通用方法。
为电影构建知识图谱
首先,我们需要安装Neo4j并设置带有用户名和密码的帐户(同样,这里任何类型的图数据库都可以)。
下一步是处理电影剧本本身。对于每个剧本,我们首先清理文本中的XML标签,然后使用LangChain将每个剧本分割成文本块,如下所示:
text_splitter = RecursiveCharacterTextSplitter(
chunk_size=CHUNK_SIZE,
chunk_overlap=CHUNK_OVERLAP,
length_function=len,
is_separator_regex=False,
)
cleaned_script = re.sub(r'<[^>]+>', ' ', script_content)
cleaned_script = re.sub(r'\s+', ' ', cleaned_script).strip()
chunks = text_splitter.split_text(cleaned_script)
在将这些文本块作为Chunk节点添加到图之前,我们使用一种命名实体识别(NER)来识别剧本中的Character实体。幸运的是,电影剧本有一种通用结构,角色名称使用大写字母,这使得使用正则表达式来识别它们相对容易,例如:
# 模式1:以角色名称开头的行(全大写,后跟冒号或换行)
# 示例: "JOHN:", "MARY\n"
char_pattern1 = re.findall(
r'^([A-Z][A-Z\s]{2,20}?)(?::|$)', script_text, re.MULTILINE
)
characters.update(
[name.strip() for name in char_pattern1 if len(name.strip()) > 2]
)
# 模式2:括号中的角色名称
# 示例: "(JOHN enters)", "(MARY speaking)"
char_pattern2 = re.findall(
r'(([A-Z][A-Z\s]{2,15}?)(?:\s+[a-z]|))', script_text
)
characters.update(
[name.strip() for name in char_pattern2 if len(name.strip()) > 2]
)
使用这些正则表达式,一些提取的角色名称是不正确的,因此我们添加了(参见完整的Jupyter notebook)一些更特定的解析逻辑使其更健壮:
- 任何有效的角色名称需要在剧本中至少出现三次
- 移除一些可能被误识别为角色名称的常见词,如THE、AND、WITH、HIM等。
这说明了一个事实:构建(和维护)知识图谱是一项困难的任务,需要领域专业知识。与电影剧本不同(电影剧本提供了可预测的格式和清晰的线索,如全大写的角色名称),企业数据——如客户合同、支持工单和系统日志——通常是杂乱的,格式不一致。弥合这种干净、结构化的示例与现实世界数据的模糊性之间的差距,正是知识图谱构建仍然是一项高投入工作的原因,这个话题我们将在"构建知识图谱"部分更详细地讨论。
继续我们的示例,最后一步是在图中构建关系。在这种情况下,我们将把Chunk节点链接到Movie节点和Character节点。
以下是来自电影《黄金眼》的一个示例文本块:
a sidearm -- watches the needle flutter behind her. Kolkhaznha's manner is friendly, avuncular... [原文示例文本块]
我们可以看到这里提到了几个角色:KOLKHAZHNA、MARINA和BOND。对于此文本块中提到的每个角色,我们可以将以下关系添加到图结构中:
(Chunk)-[:MENTIONS]->(Character)
(Character)-[:APPEARS_IN]->(Movie)
MovieSum数据集的部分到此为止。现在我们转向IMDb数据集,它有关于电影的额外有用信息,填充诸如Person、Movie、Character和Genre等额外节点,并添加如下关系:
(Person)-[:DIRECTED]->(Movie)
(Person)-[:ACTED_IN]->(Movie)
(Movie)-[:HAS_GENRE]->(Genre)
(Character)-[:PORTRAYED_BY]->(Person)
很好,现在我们有了所需的一切:一个将电影剧本的文本块和元数据与IMDb的附加信息和关系整合在一起的知识图谱。你可以在"create-graph.ipynb"notebook中找到构建该知识图谱的完整代码。
现在让我们看看如何在RAG中使用这个图。
在查询时使用知识图谱
一旦知识图谱填充了节点和关系,我们就可以使用以下常见的使用模式之一将其集成到RAG查询流中:文本块增强(chunk enrichment)或图混合检索(graph-hybrid retrieval)。
文本块增强
在这种方法中,检索过程从标准的向量搜索开始,找到与用户查询语义最相关的文本块。然而,原始的文本块文本通常包含"单薄"的引用——拼写错误的名字或"他"之类的代词——缺乏LLM提供事实性回答所需的完整上下文。
我们使用知识图谱来动态增强这些文本块,对文本中找到的实体执行图查找。例如,考虑以下查询:"哪个演员说了'他们管它叫皇家芝士堡(Royale with Cheese)',这是哪部电影?"
首先,我们使用标准向量搜索找到包含"Royale with Cheese"文本的文本块。例如,它可能检索到以下文本块作为最佳匹配:
for this to search you. Searching you is a right that the cops in Amsterdam... [原文示例文本块]
向量搜索成功了——它找到了确切的台词。然而,查看原始文本,这不足以回答用户的问题——它不包含电影名称,也没有指出演员名字,只有角色名(Vincent)。
注意 上面检索到的文本块看起来很杂乱,角色名称与文本混在一起,有一些拼写错误如"do n't"(多余的空格),但请注意这正是使用示例notebook中的代码从MovieSum和IMDb数据集中提取的确切文本块。
仅接收此文本的LLM将很难回答这个问题,因为缺少信息(电影名称和演员名称)。
图增强步骤可以识别文本块中的实体Character: Vincent,并使用知识图谱获取文本中没有的额外上下文:
Character: Vincent -> IS_REAL_NAME: Vincent Vega
Character: Vincent -> PLAYED_BY Actor: John Travolta
Character: Vincent -> APPEARS_IN Movie: Pulp Fiction
我们不是只将原始文本块文本发送给LLM,而是发送文本块加上一个包含这些额外信息的知识上下文包,使LLM能够100%确定地回答,将一个模糊的片段转化为数据丰富的事实。这个流程如图9-2所示。
图9-2. 文本块增强工作流:从向量数据库检索的初始文本块使用图数据库进行增强,然后发送到生成式LLM步骤
文本块增强凸显了知识图谱作为高保真"上下文提供者"的优势,它为基于向量的RAG检索系统的结果添加注释并增加结构或元数据。
图混合检索
在这种方法中,我们首先请求LLM将用户的自然语言问题直接转换为正式的图查询语言(如Cypher或SPARQL),供图数据库执行,目的是从图中提取相关文本块,并将它们与基于向量检索的文本块合并。
为了使这一过程成功,必须首先向LLM提供图的模式——可用节点标签(如Person、Movie、Chunk)、关系类型(如:DIRECTED、:ACTED_IN)和属性的蓝图。该模式为LLM提供了编写有效图查询所需的"词汇"和"语法"。
例如,考虑这个问题:"《黄金眼》中的所有角色是谁?其中哪些与Bond有互动?"
借助模式,LLM可以将其翻译为Cypher查询:
// 步骤1:查找GoldenEye中的所有角色
MATCH (m:Movie)
WHERE toLower(m.title) CONTAINS 'goldeneye'
WITH m
MATCH (c:Character)-[:APPEARS_IN]->(m)
WITH m, collect(DISTINCT c.name) AS all_characters, m.title AS movie_title
// 步骤2:查找与Bond互动的角色(即在同一文本块中被共同提及)
MATCH (m2:Movie)
WHERE toLower(m2.title) CONTAINS 'goldeneye'
MATCH (ch:Chunk)-[:BELONGS_TO]->(m2)
MATCH (ch)-[:MENTIONS]->(bond_char:Character)
WHERE toLower(bond_char.name) CONTAINS 'bond'
MATCH (ch)-[:MENTIONS]->(other_char:Character)
WHERE other_char <> bond_char
WITH movie_title, all_characters, collect(DISTINCT other_char.name) AS
interacted_with_bond, collect(DISTINCT ch.text)[0..10] AS chunks
RETURN movie_title, all_characters, interacted_with_bond, chunks
对图数据库执行此Cypher查询,我们检索到相关文本块,可以直接将它们发送到RAG管道中的生成式LLM。
如果我们仅使用向量搜索的文本块,我们没有足够的信息,RAG会回答"我无法回答这个问题。"然而,通过将向量搜索的文本块与图数据库的文本块合并,并将两者发送到RAG管道中的生成式LLM(如图9-3所示),我们可以得到更好的回答。
Based on the provided context, the following characters appear in GoldenEye:
**Characters in GoldenEye:**
- James Bond
- Marina
- Trevelyan
- Savatier
- Morley
- Kolkhazna (Kolkhazna's dead assistant is mentioned)
- Romaly
- Valentin
- Elliot Harmsway
- Technicians (in the control center)
- Guards
- Militiamen
- Bartender
- Gunner (on the helicopter)
- Jordan (killed by Xenia)
- Xenia
**Characters who interacted with Bond:**
- Marina (multiple scenes, including romantic and action sequences)
- Trevelyan (direct confrontation and dialogue)
- Savatier (physical fight with Bond)
- Morley (present in action scenes with Bond)
- Romaly (Bond gives instructions to Romaly)
- Valentin (dialogue at the bar)
- Elliot Harmsway (introduction and dialogue)
- Bartender (serves Bond a drink)
- Militiamen (chase Bond)
- Guards (involved in action sequences with Bond)
- Gunner (shoots at Bond and Marina)
- Xenia (antagonist, interacts through conflict)
- Technicians (indirectly, as Bond's actions affect them)
**Characters mentioned but with unclear or no direct interaction with Bond:**
- Kolkhazna's dead assistant
- Jordan (killed by Xenia, no direct interaction with Bond in the provided
context)
**Summary:**
The main characters who interacted with Bond in GoldenEye, according to the
context, are: Marina, Trevelyan, Savatier, Morley, Romaly, Valentin, Elliot
Harmsway, Bartender, Militiamen, Guards, Gunner, and Xenia.
图9-3. RAG管道中的图查询生成
通过将语义(向量)搜索的概念理解能力与知识图谱的事实精确性相结合,你使RAG应用能够以比任何单一方法更高的准确性回答更广泛的问题。例如,HippoRAG是一个将LLM与知识图谱结合的图增强RAG框架,在多跳问答基准测试中,与标准RAG基线相比,准确率提高了约20%。
你可以在GitHub仓库中找到这种组合方法的完整代码,其中我们使用LangChain构建了一个本地RAG系统(使用Chroma作为向量数据库),将向量搜索的文本块与图查询识别的文本块(经过自动转换为Cypher)相结合。
在增强和混合检索之间选择
虽然文本块增强和图混合检索都利用了知识图谱为RAG赋能,但它们解决的问题不同,承担的运营成本也不同。
文本块增强是一种"元数据优先"策略。它假设你的向量搜索在查找相关文本方面已经有效,但文本本身缺少更广泛的上下文。当查询是语义性的(如询问电影中的特定台词),但答案需要片段中不存在的外部事实(如演员名字)时,这是理想的选择。因为这涉及对检索到的文本块ID进行简单的索引查找,它增加的延迟可以忽略不计,并且在生产中高度可靠。
图混合检索相比之下是一种"发现优先"策略。当用户的查询是结构性的或关系性的,需要系统遍历向量搜索会遗漏的连接时(例如,"查找在三个以上场景中与Bond互动的所有角色"),它表现出色。然而,这种能力伴随着非平凡的生产复杂性。你必须管理一个"文本到Cypher"的管道,其中LLM将自然语言翻译为数据库查询。这也引入了额外的风险,例如LLM产生无效语法的幻觉,为了安全运行,你需要考虑查询超时并实施重试策略来处理失败。
主要区别列于表9-1中。
表9-1. 在生产中比较RAG的文本块增强与图混合检索
| 特征 | 文本块增强 | 图混合检索 |
|---|---|---|
| 主要目标 | 为特定文本片段添加上下文 | 发现关系/聚合 |
| 理想场景 | 事实性锚定(日期、名称、ID) | 多跳推理(谁见过谁?) |
| 运行时风险 | 低:简单的索引查找 | 较高:查询幻觉或慢速连接 |
| 延迟 | 极小(亚毫秒级查找) | 可变(取决于LLM和查询复杂度) |
| 实现 | 直接;适合最小可行产品 | 复杂;需要"文本到Cypher"或"文本到SPARQL"调优 |
无论你使用哪种模式将知识图谱与RAG集成,知识图谱的成功取决于你的数据工程成熟度。在生产中,你将面临实体爆炸的问题,即单个实体可能被映射到多个节点。例如,你的提取管道可能会为"007"、"James Bond"和"Bond"创建三个不同的节点,而不是将它们合并为单个节点。
正如我们稍后在"构建知识图谱"中讨论的,构建和维护高保真度的知识图谱是一项重大的"离线"工程工作,必须与使用知识图谱提高查询准确性的收益进行权衡。最常见的是,你的评估(参见第6章)可以为做出这一决定提供很好的输入:通过分析查询回答的质量,你可以看到哪些类型的查询失败了,以及知识图谱是否能帮助它们成功。
如果你刚刚起步,文本块增强通常提供最佳的"投入产出比",以低风险提供即时的事实锚定。随着你的用例向复杂推理和跨文档聚合演进,对图混合管道的投资可能成为突破基于相似性检索局限性的必要之举。
在生产中实现上述模式时,另一个重要决策是你的向量嵌入将存储在哪里,这一选择会影响系统的一致性、延迟和运维开销。由于现代图数据库支持原生向量索引,你可以直接在每个文本块节点中存储向量嵌入,属性为chunk.embedding。通过这种方法,你的检索流程可以在单个数据库事务中同时执行语义搜索和图遍历。这提供了原子一致性和嵌入的单一真实来源。然而,你现在依赖于图数据库处理嵌入的能力,这可能与复杂的图遍历竞争RAM,在非常大的数据集中可能导致性能瓶颈。
另一种选择是维护标准的RAG检索流程,将嵌入存储在向量数据库中。一旦检索到文本块,系统使用其chunk_id在图数据库中执行查找,用于增强或进一步遍历。这种方法允许你独立于图遍历(支持高深度逻辑)来维护你的高性能检索管道(包括向量搜索,但也可能包含混合搜索和/或重排序)。然而,你现在需要负责确保向量数据库和图数据库完全同步,避免出现RAG流程从向量存储中检索到一个图中不再存在的文本块的情况,从而导致应用程序错误。
我们已经了解了为什么知识图谱对某些复杂查询有帮助,以及将它们集成到RAG中的两种常见模式。然而事实证明,使用知识图谱与RAG的主要挑战之一是构建和维护这些知识图谱的任务,这是我们接下来要介绍的内容。
构建知识图谱
我们已经在"为电影构建知识图谱"中看到了如何从IMDb和MovieSum数据集构建知识图谱。提醒一下,一般方法如下:
- 设计图模式:我们决定包含Person、Movie、Character、Genre和Chunk等节点,以及ACTED_IN、PORTRAYED_BY和DIRECTED等关系。
- 然后我们使用了IMDb和MovieSum数据集的一些自定义预处理来填充图本身。
对于电影剧本,我们能够自动化部分过程,通过识别剧本中的角色名称,因为电影剧本中的角色名称相对容易识别。但即使有了这种简化,我们仍然必须进行一些手动处理,以移除被误识别为角色名称的词(如"her"或"his")。IMDb数据集已经为我们创建并清理好了,因此从该数据集创建图相对容易——该数据集的创建者为我们完成了所有的艰苦工作。
虽然我们在电影剧本上的经验需要手动干预,但它仍然代表了数据提取的最佳情况。从内部企业数据构建知识图谱意味着要穿越非结构化"暗数据"、不一致的模式和孤立的遗留系统的迷宫。如果清理几个电影剧本就已经感觉繁琐,想象一下在数百万个碎片化的PDF文件、电子表格、电子邮件和私有数据上执行相同的过程,其中领域专业知识是绝对必要的。
自动化知识图谱构建
虽然手动策展知识图谱可以产生干净、准确的结果,但这种专家驱动的方法是劳动密集型的,很快就会成为重大瓶颈。事实上,构建知识图谱很少能扩展到满足现代企业应用的需求,特别是对于必须处理持续不断的新的非结构化信息的动态RAG和智能体系统。
相反,越来越常见的做法是使用自动化方法从文本构建图,遵循以下三个步骤:
- 发现关键"事物"(实体识别) :扫描文本以查找和分类重要名词。例如,将"Apple"识别为"组织",将"Steve Jobs"识别为"人物"。这些事物成为图中的节点。
- 发现连接(关系提取) :分析句子以找出这些事物之间的关系。处理过程可能看到句子"Apple was founded by Steve Jobs"并创建一个连接或链接,表示为(Apple, FOUNDED_BY, Steve Jobs)。
- 清理重复项(实体链接) :最后,系统通过确保同一事物的不同名称都指向一个单一条目或节点来清理数据。例如,它学习到"Apple"、"Apple Inc."和"生产iPhone的公司"都是同一个实体。这确保了图是准确的,没有充满重复。
整个过程有效地将杂乱的文本海洋转化为一个干净、有组织的互联事实网络。
使用LLM,这些步骤可以被显著简化。不是为每个任务使用单独的、专门的、老式NLP模型,而是可以提示一个强大的LLM来阅读文档并直接输出一组结构化的实体-关系三元组。这种方法简化了工程复杂性,并且由于LLM广泛的世界知识和对上下文的细致理解,通常能改善结果。
但虽然LLM可以显著简化这一步骤,重要的是要调适预期:纯LLM驱动的三元组提取仍然是有噪声的且依赖领域。在生产环境中,仅使用LLM的管道通常只是引导图构建的起点,为了达到业务结果所需的高保真度,大多数团队实施混合提取策略。这涉及使用LLM来提议实体和关系,然后通过一层确定性启发式规则(例如,用于ID或日期的正则表达式)、经典NLP模型进行验证,以及对关键实体进行人工审核的人机协作界面。
此外,当我们使用LLM时,一个关键挑战仍然存在:实体链接。
现实世界的企业数据是杂乱和不一致的,一个真实世界的"事物"可能被许多不同的名称或标识符引用。同样的"一个事物多个名称"问题几乎出现在企业知识图谱中的任何实体中。以下是更多例子:
- 金融服务中的公司实体:单个公司实体可能在新闻文章、监管文件和内部报告中出现为"IBM Inc."、"International Business Machines Corp."、"I.B.M."甚至只是"IBM"。
- 制药中的药物成分:单个药物经常被称为其品牌名(例如"Tylenol")、其通用/有效成分名(例如"acetaminophen")和其正式化学名(例如"N-acetyl-para-aminophenol")。
- 供应链和电商中的产品:单个产品,如"iPhone 15 Pro 256GB",可能被不同的供应商或在不同的系统中列为"Apple iPhone 15 Pro (256)"或"IP15PRO-256-BLK"。
要有效解决实体链接,我们需要从定义清晰的本体开始,本体定义了你领域中存在的"事物"(类或实体类型,如"人物"、"公司"或"药物"),以及它们可以具有的属性和关系。
在实体链接的上下文中,本体提供了解决"一个事物多个名称"问题所需的基本结构。例如,它可能定义一个公司实体有一个规范名称(例如"International Business Machines Corp."),但也有一个别名列表(例如"IBM"、"I.B.M.")。当系统后来遇到"IBM Inc."时,它知道自己的任务不是创建新节点,而是识别它为别名并将其链接到现有的规范公司节点,填写模式定义的适当属性。
有了本体作为目标结构,实体链接过程需要主动匹配、链接和合并实体。这很少是单一的算法或方法,而是一个多阶段的管道,通常包括以下两个步骤:
- 归一化:原始文本被清理和标准化(例如,"Corp."和"Corporation"都变成"corp";所有文本转为小写)。
- 候选生成:寻找代表同一"事物"的实体时,你通常会以某种方式缩小搜索空间,这样就不必将每个实体与每个其他实体进行比较。例如,它可能只比较在某种方式上相似的人物实体,使用从简单字符串比较(例如,Jaro-Winkler距离用于"Chris"与"Christopher")到复杂的上下文和领域特定相似度指标的技术。
完整的实体链接过程包括一个初始引导阶段,系统在现有数据上运行大规模任务以创建初始的规范实体集。之后,通常使用增量模式,随着新的非结构化数据到达,实体链接模型的任务是将新的表面形式(如"Tylenol")与图中现有的规范实体(Drug节点"acetaminophen")进行匹配。
你还可以通过人机协作来增强此过程:当系统对匹配的置信度较低时(例如,在"Christian"是否与"Christopher"相同上50/50),它会标记模糊之处供专家审查。这将稀缺的人力精力集中在最困难的案例上,使系统能够扩展,同时不断从专家反馈中学习和提高准确性。
实体链接(在计算机科学文献中也称为记录链接)在大规模和混乱数据中尤其具有挑战性,这凸显了从文本自动生成知识图谱的固有难度,即使我们利用LLM的巨大能力也是如此。
利用标准本体和知识图谱
我们已经看到,从头构建知识图谱可能是一项高风险的事业。事实上,据估计³,超过50%的此类项目会失败。技术原因通常是低估了所涉及的复杂性,特别是围绕实体链接,但另一个常见原因是试图对领域中的"一切"进行建模,而不是采用以用例为驱动的聚焦方法。
标准本体提供了一个起步优势,可以帮助你避免这种不必要的陷阱。它们提供了一个正式的、标准化的结构,为特定领域(如金融或医疗保健)定义了关键概念和关系。通过使用现成的本体,你不仅可以节省开发时间,还可以确保你的数据模型正确、一致且可互操作,防止构建过于宽泛和不可用的图的常见陷阱。
有几个强大的开源本体是公开可用的。例如,在金融领域,我们有金融行业业务本体(FIBO),由企业数据管理(EDM)委员会开发,为Corporation(公司)、Security(证券)和Loan(贷款)等金融概念提供精确的词汇。其价值在于其详细的、标准化的属性,这对准确的实体解析至关重要。
使用本体是有帮助的,因为它为你提供了知识图谱的蓝图,但你仍然需要用数据来填充它。Dun & Bradstreet、Refinitiv(现为LSEG)和S&P Global等公司在实体链接的困难工作中投入了数百万小时,最近他们一直在致力于通过策展的数据源来授权许可这类数据,这些数据源分配规范标识符,如邓白氏编号(D-U-N-S)或永久标识符(PermID),以唯一标识实体并映射其复杂的公司层级结构。
类似地,在医疗保健领域,像DrugBank这样的数据集充当了一个综合性的知识图谱,映射了药物以及化学成分之间的关系。例如,单个药物实体如阿托伐他汀(atorvastatin)通过特定关系连接到其已知的蛋白质靶标(例如HMG-CoA还原酶)、代谢它的酶(例如CYP3A4)以及与之相互作用的其他药物。
许可这类数据的主要价值在于,它提供了一个高质量的、预先解析的核心知识图谱,使你免于自行解析一切的巨大工作量。你的任务被缩减为一个更小、更易管理的问题:将你新的、混乱的内部数据链接到提供商已建立的规范实体。这使你能够将系统中的"IBM"或"I.B.M."连接到"International Business Machines Corp."的唯一黄金记录。
虽然有价值,但这种可授权许可的知识图谱也有其缺点:除了许可费用外,你还需要考虑你对使用这种特定形式的知识图谱所做的承诺,以及所有其他数据系统都必须符合它。
鉴于构建和维护知识图谱的巨大复杂性,研究人员一直在寻找将知识图谱集成到RAG中的其他方法。其中一种方法是微软的GraphRAG,这是一种创新的方法,使用LLM不仅提取原子事实,还生成一个在多个抽象层次上捕获信息的层次化图。
GraphRAG
在深入GraphRAG之前,重要的是要澄清一点:一些AI工程师使用"GraphRAG"一词来描述任何形式的图辅助RAG,例如"在RAG中使用知识图谱"部分的技术。然而在本章中,我们使用GraphRAG一词时,指的是微软研究院引入的将知识图谱用于RAG的特定方法,旨在支持回答意义建构查询(sensemaking queries)——这是一种需要从整个数据集中综合信息的广泛的、探索性的查询,例如"所有James Bond电影中的主要主题是什么?"
用技术术语来说,这个过程被称为面向查询的摘要生成(QFS),目标是基于数据的全局视图生成全面的答案,而不是检索几个特定的片段或文本块(这些可能捕获也可能未捕获那个全局视图)。
GraphRAG使用LLM从源文档自动构建图。有了这个图,它然后识别聚类(社区),生成摘要,并重复这个过程直到图的顶层,以实现对全局上下文的理解。它的工作原理如下:
- 构建知识图谱:使用LLM从非结构化文本语料库中自动提取关键实体(如人物、地点和概念)及其之间的关系,并动态构建知识图谱。这个图不是基于预定义的模式,而是源文档中包含的知识的直接结构化表示,捕获了不同想法和实体在整个文本中的相互联系方式。
- 社区检测:GraphRAG的主要创新在于它如何利用新创建的图。与仅将其视为普通知识图谱不同,在GraphRAG中,你应用社区检测算法来识别密集连接的实体聚类。这些"社区"代表了数据中的核心主题和语义话题,GraphRAG然后利用LLM在多个层次结构级别上为每个社区生成摘要,从非常具体的子主题到广泛的总体主题。
- 查询:在响应用户查询(意义建构查询)时,GraphRAG查询引擎不是像普通RAG管道那样搜索原始文本并用LLM进行摘要。相反,它找到回答你查询的最相关的社区摘要,并使用LLM基于每个相关社区摘要生成部分答案。然后,另一个LLM调用使用所有这些部分答案来制定对查询的最终全面回答。
微软的graphrag包是开源的,让我们看看如何使用它。应用于MovieSum数据集,我们首先加载数据:
import pandas as pd
import numpy as np
from datasets import load_dataset
moviesum_dataset = load_dataset("rohitsaxena/MovieSum")
moviesum_df = pd.DataFrame(moviesum_dataset['train'])
由于GraphRAG相当昂贵且耗时(GraphRAG在索引时会进行大量的LLM调用以处理所有文档),我们随机选择20部电影,使本示例的成本保持合理:
np.random.seed(42)
SAMPLE_SIZE = 20
indices = np.linspace(0, len(moviesum_df) - 1, SAMPLE_SIZE, dtype=int)
filtered_df = moviesum_df.iloc[indices].copy()
在完整的notebook中,你可以找到一个估算在这20部电影上运行GraphRAG成本的函数,结果为6.32美元。对于完整的MovieSum数据集的1800部电影,成本将超过560美元。而这仅仅是1800部电影;想象一下你整个Google Drive或Microsoft SharePoint账户的成本会是多少?我们将在本章稍后讨论这个成本方面。
下一步是定义一个settings.yaml文件,定义GraphRAG的工作方式,包括使用的LLM、文本块大小、图实体和额外的配置参数。
一旦定义了设置,运行GraphRAG归结为对GraphRAG库函数的简单调用。首先我们将文档准备为GraphRAG期望的格式:
from datetime import datetime
input_docs = []
current_date = datetime.now()
for idx, row in filtered_df.iterrows():
input_docs.append({
'id': row['imdb_id'],
'title': row['movie_name'],
'text': row['script'],
'creation_date': current_date
})
input_df = pd.DataFrame(input_docs)
然后,我们运行build_index过程:
from graphrag.api import build_index
from graphrag.config.load_config import load_config
GRAPHRAG_DIR = Path("./graphrag_workspace")
config = load_config(root_dir=GRAPHRAG_DIR)
results = await build_index(
config=config,
input_documents=input_df,
verbose=True
)
这可能需要一段时间。我们是说真的需要一段时间——在一台性能不错的M4 Mac笔记本上,仅仅20部电影就花了大约45分钟。这是因为GraphRAG的索引过程不是简单的单遍处理。系统必须为每个文本块进行数十次顺序LLM调用:首先提取实体和主张,然后解析和合并这些实体,最后生成多层层次化社区摘要。这些步骤中的每一步都计算密集,并依赖于LLM的推理速度,即使对于适度的数据集(在我们的案例中是20部电影),也会产生巨大的累积延迟。
GraphRAG生成一个输出文件夹,其中生成了各种Parquet文件,包含build_index过程的输出。
要在GraphRAG中运行查询,我们首先将这些数据集加载到pandas DataFrame中:
from graphrag.config.load_config import load_config
config = load_config(root_dir=GRAPHRAG_DIR)
entities_df = pd.read_parquet(OUTPUT_DIR / "entities.parquet")
relationships_df = pd.read_parquet(OUTPUT_DIR / "relationships.parquet")
communities_df = pd.read_parquet(OUTPUT_DIR / "communities.parquet")
reports_df = pd.read_parquet(OUTPUT_DIR / "community_reports.parquet")
text_units_df = pd.read_parquet(OUTPUT_DIR / "text_units.parquet")
GraphRAG定义了两种类型的查询函数:
- local_search:可以用作探索性的"自下而上"方法:它首先识别图中与查询密切匹配的几个种子节点,然后沿着它们的边"向外走"以发现附近的、上下文相关的节点和关系(例如1跳或2跳邻居)。这种方法非常适合使用GraphRAG回答特定的、详细的问题,其中必要的上下文可能包含在图的局部"邻域"中。
- global_search:采用全面的"自上而下"策略。它不是仅从种子节点扩展,而是在整个图中搜索,以识别所有与查询概念语义相关的节点、关系,甚至整个子社区,即使它们不是直接连接的。这种方法更适合广泛的、高级别的查询,这些查询需要从图的多个可能不相连的部分综合信息。
The movie scripts analyzed reveal a rich tapestry of recurring themes and
narrative patterns that span a wide range of genres, character types, and
settings. These themes often intertwine, creating complex stories that explore
human emotions, supernatural elements, social dynamics, and conflict. Below is a
comprehensive synthesis of the main themes and narrative patterns identified
across the dataset.
---
## 1. **Conflict and Struggle**
Conflict is a pervasive and driving force in many narratives, manifesting in
various forms:
- **Physical and Military Conflict:** Stories often depict intense battles and
warfare, such as Conan’s confrontations with hostile tribes and empires, Vlad’s
defense against Mehmed’s army, and the violent raids by the Turanian Horsemen.
These conflicts emphasize themes of survival, leadership, rebellion, and the
cost of violence [Data: Reports (177, 665, 684, 659, 554, 547, 6, 668, 699,
+more)].
- **Personal and Social Confrontations:** Beyond warfare, narratives explore
interpersonal conflicts including domestic violence, legal disputes, and social
tensions. For example, the tragic relationship between Denise and Tommy
escalates from care to violence, while Barbara and Jonathan’s turbulent marriage
involves emotional and legal struggles [Data: Reports (239, 442, 118, 379, 943,
980)].
- **Supernatural Battles:** Many scripts incorporate supernatural conflict, such
as possession, hauntings, and battles with demons or fiends. The Lambert and
Renai families face malevolent entities, blending everyday family life with
extraordinary threats, highlighting emotional resilience amid trauma [Data:
Reports (878, 856, 237, 235, 13, 79, 242, 881, +more)].
---
## 2. **Family and Interpersonal Relationships**
Family dynamics and close personal relationships are central to many narratives,
often serving as emotional cores:
- **Parent-Child Bonds:** The father-son relationship between Sam and Jonah
Baldwin exemplifies themes of grief, support, and complex family dynamics.
Similarly, Eve’s growth within her family and community highlights nurturing and
social bonding [Data: Reports (1, 44, 468, 374, 136)].
- **Complex Family Struggles:** Several stories explore emotional tension, love,
conflict, and vulnerability within families, such as Jonathan Rose’s
multifaceted household challenges and the Transylvanian family’s struggles amid
supernatural and political threats [Data: Reports (532, 5, 566, 234, 546)].
- **Interpersonal Networks:** Friendships, mentorships, and romantic
relationships also play significant roles, shaping character development and
social cohesion. Examples include the artistic collaboration of Bob Wallace and
Phil Davis, the mentorship between Rocky Balboa and Apollo Creed, and the social
tensions in adolescent networks [Data: Reports (224, 460, 469, 934, 740, 16)].
---
## 3. **Supernatural and Paranormal Elements**
A strong narrative pattern involves supernatural phenomena, often intertwined
with family and psychological themes:
- **Possession and Hauntings:** Families like the Lamberts and Renais confront
possession and hauntings, with narratives exploring the psychological toll and
protective instincts within these crises. The use of alternate realms such as
The Further and the Black Void adds metaphysical depth [Data: Reports (878, 856,
237, 235, 79, 242, 881, 879, 159, +more)].
- **Psychological Horror and Trauma:** Characters such as Billy embody trauma
and psychological distress, with symbolic motifs like the dark Santa Claus
figure representing the blurring of innocence and menace. These stories delve
into internal conflict and emotional turmoil [Data: Reports (17, 268, 950,
270)].
- **Mystical and Magical Conflicts:** Some narratives incorporate dark magic,
blood rituals, and supernatural warfare, as seen in the Acheron Empire and
Vlad’s transformation, blending fantasy with horror [Data: Reports (665, 614,
575)].
…
[truncated]
完整回答相当大,因此我们在此截断。请在notebook中查看完整回答以及其他一些示例。
尽管GraphRAG在回答困难的意义建构问题(使用QFS)方面具有优势和能力,但GraphRAG的主要缺点(如我们上面所见)是其预处理的大量成本(和时间)。
虽然标准RAG系统只需要分割文本和生成向量嵌入——这是一个相对快速且便宜的过程(尽管使用现代嵌入模型会变得更昂贵,这些模型的维度可能高达4K)——GraphRAG需要进行多阶段、计算密集的预处理管道。它需要一个强大的LLM首先阅读整个语料库以提取实体和关系,然后构建大规模的知识图谱,在该图上运行复杂的社区检测算法,最后再次使用LLM为每个识别的主题生成层次化摘要。
由于这种开销,GraphRAG在几种常见的生产场景中往往是错误的工具:
- 快速变化的语料库:对于频繁更新的数据,如新闻流、支持工单或活跃的代码仓库,持续重新计算社区摘要在财务和运营上往往不切实际。
- 延迟敏感或个性化的查询:综合多个社区摘要的过程本质上比标准向量查找慢。它不适合需要亚秒级响应或针对特定用户私有数据定制的查询的应用。
- 逐字引用的需求:GraphRAG擅长高级别的抽象。如果你的用例要求LLM提供文档中的确切(原始)句子以用于审计或法律合规,社区报告的摘要性质可能过于"有损"。
最终,如果你的查询主要是简单的事实检索(例如,"X的价格是多少?"),GraphRAG的大量投资相比标准语义搜索几乎没有投资回报。
图数据库基础设施
将知识图谱集成到你的RAG应用中不仅仅是一个架构决策;它是一项长期的运维和系统级承诺。虽然获得高精度、可解释答案的潜力很高,但构建、扩展以及最重要的是维护图数据库的复杂性也很高。
首先,让我们看看如何选择图数据库,因为这个选择将决定你整个运维方案。有几种类型的图数据库系统:
传统服务器/集群(如Neo4j、TigerGraph)
你可以将Neo4j或TigerGraph等系统作为有状态的独立服务运行在专用虚拟机(VM)或Kubernetes集群中,在许多方面它们像传统的SQL数据库。这里,你的DevOps团队负责一切:安装、配置、集群、分片、资源管理和网络安全。容量规划至关重要,因为属性图通常是内存受限的,性能取决于将"热"图装入RAM。
当你有严格的本地部署/合规约束或需要托管服务不允许的深度低级别数据库引擎自定义时,这是一个好的选择。
托管云服务(如Neo4j Aura、Amazon Neptune)
使用平台即服务(Neo4j AuraDB、Amazon Neptune)方法,你用精细控制权换取运维简单性。云提供商处理补丁、备份和高可用性,负担从服务器管理转移到成本管理和身份访问管理(IAM)集成。
当你需要多租户访问、高可用性和自动备份,但缺乏内部图数据库专业知识或专门的DevOps资源来管理集群时,选择这个。
嵌入式库(如Kuzu、DuckDB)
在更近期的"无服务器"模型中,如Kuzu或DuckDB提供的,数据库是在你的应用进程内运行的库。"数据库"只是磁盘上的一个文件。这里,传统的服务器管理员角色消失了,挑战变成了数据生命周期和构建管理。如何在正在运行的应用容器中更新静态图文件?这需要一个健壮的CI/CD管道,能够构建新的数据文件,将其打包到新的容器镜像中,并滚动部署。
当你的知识图谱相对较小(低于10-20 GB)、大部分为只读,并且可以通过CI/CD管道刷新时,这是一个很好的选择。这里的挑战是数据生命周期——将新的图文件打包到容器镜像中进行部署。
一旦你选择了技术栈,日常运维工作就开始了,有几个主要挑战需要考虑:
ETL
这是迄今为止被低估最多的成本。一个陈旧的图是一个无用的图。你的源数据可能不断变化,你需要构建可靠的ETL管道来确保你的知识图谱是最新的。关键是,在生产中,该管道必须解决数据完整性问题,由于从多个来源构建图涉及一系列操作,如果导入在中途失败(例如,你的电影剧本文本块已导入,但IMDb元数据同步崩溃),你有可能得到一个"损坏"的图。
虽然传统SQL数据库依赖事务来确保原子性("全有或全无"方法),但将大型图"构建"包装在单个事务中通常是不可行的;它可能锁定数据库数小时并耗尽内存。
相反,使用知识图谱的生产RAG系统可以设计为幂等性,以便如果你的摄取代码失败并重新启动,结果与第一次成功时相同。在Cypher中,例如,这通过使用MERGE而不是CREATE来实现——数据库在添加实体之前检查其是否存在。
通过将幂等性与批处理(每1000个节点提交一次而不是整个图)相结合,你朝着最终一致性模型迈进,这种模型对于生产环境中企业数据的混乱现实足够有弹性。
模式刚性与演化
虽然图数据库通常被宣传为"无模式"的,但RAG系统需要可预测的结构来生成有效的Cypher或SPARQL查询。与SQL不同,大多数图数据库缺乏简单的ALTER TABLE命令,因此当你的领域演化时(例如,添加新的关系类型或拆分实体),你必须管理在线迁移。这涉及运行后台脚本来重构数百万个节点和边,同时不停机。你可能需要考虑模式版本控制,以确保LLM的查询生成逻辑与数据的当前状态保持同步。
性能
多跳图遍历(例如,查询如"查找所有评论了与住在同一城市的CEO相同产品的用户")可能具有可变延迟。所花费的时间取决于查询的深度和图的结构(例如,命中"超级节点")。由于大多数图是内存密集型的,提供正确的硬件(具有足够的RAM)并确保它可以垂直和水平扩展是关键。这往往是一项相对专业的技能:团队需要学习分析Cypher/SPARQL查询、识别瓶颈、管理索引(标准索引和向量索引),并可能重构图的部分以避免"超级节点"热点。
安全性、备份和高可用性
与任何有状态数据库一样,图数据库也需要一个健壮的灾难恢复计划,具有自动化的、经过测试的备份和恢复流程。然而,图驱动的RAG系统中的安全性增加了超越标准静态加密的复杂层。因为图通常综合了来自不同来源的数据,你的基础设施必须支持RBAC(基于角色的访问控制),这可能需要在节点或关系级别实现——例如,确保LLM可以遍历Company节点但被限制查看连接的Employee节点上的Salary属性。
需要再次强调的是,维护开销是图数据库中一项持续的、经常被低估的运维成本。核心挑战是确保数据的新鲜度和一致性:随着源数据的变化,图必须更新以反映新的现实。
知识图谱功能强大,可以显著提高RAG应用中回答的质量,但实施知识图谱的决定取决于一个清醒的成本效益分析。让我们回顾一下做出该决定所涉及的内容。
图更新模式与演化
在生产中,你的源数据很少是静态的。保持知识图谱与活跃数据同步,需要超越"完全重建"方法,走向增量维护。这通常涉及两种主要模式:
摄取策略:CDC与事件驱动
要捕获源系统(如CRM或SQL数据库)中的变化,你需要一个自动触发图更新的管道:
- 变更数据捕获(CDC) :如果你的源数据存在于传统数据库中(如Postgres),你可以使用CDC工具(如Debezium)监听数据库的事务日志,每次创建、更新或删除行时发出事件。然后将这些事件映射为知识图谱中的Cypher MERGE或DELETE命令。
- 事件驱动架构:对于非结构化数据(如新的PDF文件或聊天日志),事件驱动模式更为适合。当新文档进入你的存储(如S3)时,它触发一个无服务器函数(如AWS Lambda),仅对该特定文件运行LLM提取管道,将新节点和边追加到现有图中。
处理实体合并
长期运行的知识图谱中一个常见的边界情况是,两个之前被认为是不同的实体被发现是相同的(例如,"Twitter"和"X")。要处理这种情况,你必须实现"合并"逻辑,其中一个节点的关系被重新映射到"存活"节点(另一个节点被删除)。
另一个挑战是当事实"过期"时。例如,如果一个人离开了公司,WORKS_AT关系不应该被删除(以保留历史上下文),而应该用status: "inactive"标签进行"墓碑化"。你的RAG查询然后必须更新为过滤:WORKS_AT {status: "active"}。
维护一个活跃的知识图谱需要实施自动化的摄取管道(以捕获实时数据变化),同时应用内部生命周期逻辑来解决身份冲突和管理老化事实的相关性。
准确性/成本权衡
在构建RAG应用时,你面临一个基本的架构选择:坚持使用"普通"RAG设置,还是投资集成知识图谱。这个决定是在普通RAG的相对低成本和简单性与可能(但不保证)的准确性提升之间的经典工程权衡。在承诺采用基于图的方法之前,重要的是要了解你在知识图谱上的特定投资回报率,以及你实际看到的准确性提升是否能证明成本和复杂性的增加是合理的。
不要低估普通RAG;它可能已经满足你的需求而无需任何额外的复杂性,实现起来相对直接,运营成本效益高。对于许多应用,如通用问答或摘要大型文档集,找到"方向正确"或"语义相关"的上下文就是LLM提供高质量回答所需要的全部。
实施GraphRAG或我们介绍的任何其他将知识图谱集成到RAG应用中的方法不是一个小的增补;它是一项重大承诺。成本不仅仅是财务上的;它是对开发和运维资源的沉重负担。你需要大量投资于图数据建模,建立和维护新的图数据库基础设施,并构建和维护复杂的数据管道来创建和保持图与不断变化的源数据保持同步。
事实上,这种持续的维护负担经常被低估,可能成为重大的资源消耗。重要的是诚实评估你的系统是否需要这种级别的精确性,只有在你看到潜在的投资回报率时才这样做。
为了使这一决策可操作化,这里有一个快速检查清单可供使用。如果你无法对至少四个问题回答"是",知识图谱的运维"税"可能超过其对你当前阶段的收益。
- 事实性失败:我们是否有反复出现的多跳、时间约束或高度受限的查询,在我们的评估中普通或混合RAG持续失败?
- 锚定必要性:用例是否要求对特定实体(如法律合规或药物剂量)进行100%确定性的事实锚定,其中"概率性"的相似匹配风险太大?
- 可用资产:是否有现有的本体资产(如DrugBank或LSEG等授权许可的知识图谱,或如FIBO等标准本体)可以利用,以避免从头构建?
- 数据连通性:我们的数据是否天然适合图结构?(即,价值是否在于文档之间的关系,如公司层级或供应链依赖,而不是文档本身的内容?)
- 长期所有权:我们是否有一个团队具有长期拥有图建模、模式演化和复杂ETL管道的能力?
- 业务投资回报率:预期的准确性提升是否与清晰的业务成果相关,如降低风险、确保合规或解锁新的创收功能?
结论
在本章中,我们介绍了在RAG中使用知识图谱的概念,目标是对知识图谱最能帮助回答的查询类型实现更高质量的回答。
虽然向量搜索或混合搜索在理解概念性查询方面表现出色,但它们在处理涉及时间约束型事实、多跳逻辑或重叠约束的问题时可能效果不佳。
另一方面,知识图谱擅长回答这类问题。通过将知识图谱集成到RAG中——无论是通过文本块增强还是图混合检索——你可以使RAG应用以更高的准确性回答更复杂的问题。
然而,这一进步并非免费;它需要在数据建模、实体链接、摄取管道和基础设施方面的大量投资,迫使在检索准确性与运维复杂性和成本之间做出关键权衡。
在RAG中使用知识图谱是一个不断发展的领域,其未来在于自动化使其如此具有挑战性的那些瓶颈。手工繁琐的图构建过程正在让位于LLM驱动的管道,这些管道以高效率提取实体和关系,前提是它们有健壮的验证层和人工监督作为锚定。知识增强RAG的未来在于自动化这些瓶颈,同时维护一个"活"的图,该图可以随着业务需求的变化而演化其模式和逻辑。一个突出的例子是微软的GraphRAG,它使用大型语言模型直接从源文档构建图。然而,微软的具体实现可能引入显著的成本和延迟,可能不适合每种企业工作负载。更广泛地说,当图架构围绕应用的数据模型、查询模式和生产约束进行设计时,知识图谱增强的RAG可以非常实用。
在实践中,大多数团队从标准RAG开始,使用评估技术(第6章)来识别回答准确性不足的问题性查询,对于这些查询,他们试点知识增强RAG或GraphRAG。
表9-2. 跨检索方法、图增强和智能体编排的RAG架构比较
| 方法 | 最适合 | 关键局限 | 成本与复杂度 |
|---|---|---|---|
| 标准RAG(向量搜索) | 通用问答、基于相似性的检索和非结构化文本 | 可能在多跳逻辑、时间约束事实或硬约束方面表现不佳。可能遗漏在语义搜索中不匹配的特定SKU或名称。 | 低。构建和维护简单。 |
| 关键词混合(向量 + BM25) | 在语义含义与精确匹配之间取得平衡 | 仍然在多跳逻辑和深层关系方面表现不佳。 | 低-中。需要在向量和BM25之间调整权重。 |
| KG混合RAG | 具有多个约束的精确、事实性查询(如"查找同时拥有电动车的CEO") | 需要构建和维护最新的知识图谱。 | 高。需要大量数据工程。 |
| 微软GraphRAG | 广泛的"意义建构"查询(如"这1000份文档中的主要主题是什么?") | 非常高的前期处理成本。不适合实时数据。缺乏逐字粒度。 | 非常高。摄取计算密集。 |
| 智能体RAG | 多跳逻辑和迭代研究任务 | 高延迟。智能体可能陷入循环或产生工具路径幻觉。 | 中-高。需要健壮的编排(LangGraph等)。 |
知识图谱研究社区持续创新,提供更好、更简单、更具成本效益的方法来将知识图谱集成到RAG和智能体工作流中,我们期望这项技术随着时间的推移提供更多价值和更好的投资回报率。
¹ 我们注意到,最近的高级语义搜索实现(如过滤ANN)有时可以处理这些问题,例如通过按日期过滤。
² 为了说明互联数据的力量,我们鼓励你查看Wikidata查询服务,它展示了知识图谱如何工作。Wikidata是一个大规模的协作知识图谱,作为Wikipedia的结构化骨干,将数百万个实体存储为"节点",将它们的关系存储为"边"。
³ 这个数据点来自与一位在该领域拥有数十年深厚经验的知识图谱构建专家的对话。