既然我们的智能体已经拥有了工具和编排能力,它现在完全有能力采取行动来完成实际工作。然而,在大多数情况下,你会希望智能体既能记住发生过的事情,又能知道超出模型权重之外的额外信息。在本章中,我们将通过两个互补但截然不同的方式来丰富智能体的上下文:知识与记忆。
知识(通常通过检索增强生成即 RAG 来实现)是在生成时引入的事实性或领域特定内容——如技术规范、政策文档、产品目录、客户或系统日志。这使得智能体“知道”那些超出即时对话范围的可验证信息,以此补充模型自身(具体存储在其权重和偏置中)的信息。另一方面,记忆捕捉的是智能体自身的历史:之前的用户交流、工具输出和状态更新。它让智能体能够保持跨轮次和跨会话的连续性,使其“记住”过去的互动,并利用这些历史信息来为未来的决策提供依据。
在第五章中,我们介绍了上下文工程(Context Engineering),这是一门关于动态选择、构建和组装所有输入到模型上下文窗口中以产生最佳结果的学科。记忆是上下文工程的基础赋能者:它提供了可以被选择并组装成有效提示词(Prompts)的知识、历史和事实。换句话说,记忆是存储知识的地方,而上下文工程是如何利用这些知识来产生智能行为的方法。
本章将提供使用 LangGraph 的示例,这是第一章介绍的一种用于构建有状态智能体工作流的底层编排框架。LangGraph 将应用程序定义为一个由节点(纯函数,如基础模型调用、记忆更新或工具调用)和边(控制流转换)组成的有向图,使开发人员能够以声明方式对复杂的多步骤流程进行建模。LangGraph 将整个应用程序状态视为一个单一的、强类型的 Python 对象(通常是一个 TypedDict),该对象在运行时流经图结构,从而保持数据管理的显性和类型安全性。与仅支持 DAG(有向无环图)的编排工具不同,它原生支持循环和条件分支,使得无需编写定制代码即可直接实现循环、重试和动态决策路径。它还提供了内置的流式传输(在生成部分结果时即时发出)和检查点功能(Checkpointing),因此长运行的智能体可以持久化并在中断处准确恢复。
通过将记忆机制(滚动上下文窗口、关键词提取、语义检索等)视为一等公民的图节点,LangGraph 保持了记忆逻辑的模块化和可测试性。边(Edges)确保记忆更新相对于 LLM 调用以正确的顺序发生,因此智能体总是在正确的时间注入正确的上下文。而且,由于状态——包括记忆内容——可以被建立检查点并恢复,智能体可以在同一统一的图框架内保持跨会话的连续性并防止故障。
在本章中,我们将首先介绍智能体系统记忆的基础知识,从简单的滚动上下文窗口到语义记忆、检索增强生成(RAG)以及高级知识图谱方法。在整个过程中,我们将强调这些记忆系统如何集成到上下文工程管道中,以构建扎实、能干且符合特定目标和环境的智能体。
本书代码请见:https://github.com/alanhou/ai-agent。
记忆的基础方法
我们首先讨论最简单的记忆方法:依赖基础模型的滚动上下文窗口,以及基于关键词的记忆。尽管它们很简单,但对于广泛的用例来说已经绰绰有余。
管理上下文窗口
我们从最简单的记忆方法开始:依赖上下文窗口。“上下文窗口”是指在单次调用中作为输入传递给基础模型的信息。基础模型在单次调用中可以摄取和关注的最大 Token(词元)数量称为“上下文长度”。这个上下文实际上就是该次请求的工作记忆。一个 Token 平均约为 ¾ 个单词或大约 4 个字符;例如,1,000 个 Token 对应约 750 个英语单词。如今许多流行的模型已经突破了大约 4,000 Token(≈3,000 词,~12 页)和 8,000 Token(≈6,000 词,~24 页)的限制。GPT-5 和 Claude 3.7 Sonnet 现在提供最大 272,000 Token 的输入,而 Gemini 2.5 接受高达一百万 Token 的输入。
上下文窗口是开发人员需要有效利用的关键资源。我们希望为基础模型提供完成任务所需的所有信息,但仅此而已。上下文窗口是调用模型时提供给它的所有信息。在最简单的方法中,上下文窗口包含当前问题和当前会话中的所有先前交互。当窗口填满时,仅保留最近的交互。在某些情况下,我们需要提供的信息比上下文窗口能容纳的更多。发生这种情况时,我们需要谨慎分配有限的 Token 预算。
对于简单的用例,你可以使用滚动上下文窗口。在这种情况下,随着与基础模型交互的进行,完整的交互被传入上下文窗口。在某一点上,上下文窗口填满,最旧部分的上下文被弹出,并以先进先出(FIFO)的方式替换为最近的上下文。这易于实现,复杂度低,适用于许多用例。这种方法的主要缺点是信息会丢失,无论它多么相关或重要,只要发生了足够多的交互将其从当前上下文中挤出。对于大型提示词或冗长的基础模型响应,这种情况会发生得很快。基础模型也可能在大型提示词中遗漏重要信息,因此突出显示最相关的上下文并将其放置在提示词的末尾附近可以增加其被使用的可能性。
这种标准的记忆方法可以按如下方式整合到我们的 LangGraph 智能体中:
|
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 |
from typing import Annotated from typing_extensions import TypedDict from langchain_openai import ChatOpenAI from langgraph.graph import StateGraph, MessagesState, START llm = ChatOpenAI(model="gpt-5") def call_model(state: MessagesState): response = llm.invoke(state["messages"]) return {"messages": response} # 无法在对话中保持状态的示例 input_message = {"type": "user", "content": "hi! I'm bob"} for chunk in graph.stream({"messages": [input_message]}, stream_mode="values"): chunk["messages"][-1].pretty_print() input_message = {"type": "user", "content": "what's my name?"} for chunk in graph.stream({"messages": [input_message]}, stream_mode="values"): chunk["messages"][-1].pretty_print() |
传统全文搜索
传统的全文搜索构成了许多大规模检索系统的支柱,并提供了一种稳健、成熟的方法,将精确的历史上下文注入到基于基础模型的智能体中。其核心是倒排索引(Inverted Index),通过分词(Tokenization)、规一化(小写化、词干提取)和去停止词(Stop-word removal)预处理所有文本,然后将每个术语映射到它出现的消息块或文档列表。这种结构使得查找速度极快——智能体无需扫描每条存储的消息,只需按照术语的发布列表即可准确检索包含查询关键词的段落。
为了按相关性对这些结果进行排名,大多数系统采用 BM25 评分函数。BM25 根据词频(查询词出现的频率)、逆向文档频率(该词在语料库中的稀有程度)和文档长度归一化(惩罚过长或过短的块)对每个段落进行加权。当用户查询到达时,使用与索引相同的文本管道对其进行分析,BM25 生成前 K 个候选段落的排序列表。这些热门结果——通常被截断或摘要——然后被直接注入到基础模型提示词中,确保模型看到最相关的历史上下文,而不会耗尽其上下文长度。幸运的是,在 Python 中实现这一点非常容易,尽管通常人们会将这些存储在数据库中:
|
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 |
# pip install rank_bm25 from rank_bm25 import BM25Okapi from typing import List corpus: List[List[str]] = [ "Agent J is the fresh recruit with attitude".split(), "Agent K has years of MIB experience and a cool neuralyzer".split(), "The galaxy is saved by two Agents in black suits".split(), ] # 2. 构建 BM25 索引 bm25 = BM25Okapi(corpus) # 3. 对一个有趣的查询执行检索 query = "Who is a recruit?".split() top_n = bm25.get_top_n(query, corpus, n=2) print("Query:", " ".join(query)) print("Top matching lines:") for line in top_n: print(" •", " ".join(line)) |
在这个例子中,我们在智能体语料上建立了一个简单的基于 BM25 的全文索引,并获取了给定用户查询的最相关行。通过将这些排名最高的段落直接注入提示词,我们确保模型获得了关键的历史上下文——而无需传递每条过去的消息——并保持在上下文限制内。
虽然这种关键词驱动的方法擅长精确定位准确或高度具体的术语,但它可能会遗漏原始文本中未表达的更广泛的主题、同义转述或概念联系。为了捕捉那种更深层次的、“基于意义”的记忆——以便智能体即使具体措辞不同也能回忆起相关想法——接下来我们将转向语义记忆和向量存储。
语义记忆和向量存储
语义记忆是一种涉及存储和检索一般知识、概念和过去经验的长期记忆,在增强这些系统的认知能力方面起着关键作用。这允许存储信息和过去的经验,并在需要时高效检索,以便后续提高性能。实现的前沿方法是使用向量数据库,它支持大规模的快速索引和检索,使智能体系统能够以更大的深度和相关性理解和响应查询。
语义搜索简介
与传统的基于关键词的搜索不同,语义搜索旨在理解查询背后的上下文和意图,从而产生更准确和有意义的检索结果。其核心在于,语义搜索关注单词和短语的含义,而不是它们的精确匹配。它利用机器学习技术来解析上下文、同义词以及单词之间的关系。这使得检索系统能够理解意图并提供上下文相关的结果,即使它们不包含确切的搜索词。
这些方法的基础是嵌入(Embeddings),即单词的向量表示,它们基于单词在大型文本语料库中的使用来捕捉单词的含义。通过将大量文本投射到密集的数值表示中,我们可以创建已被证明对存储和检索非常有用的丰富表示。像 Word2Vec、GloVe 和 BERT 这样的流行模型通过将语义相似的单词放置到高维空间中彼此靠近的位置,彻底改变了机器理解语言的方式。大型语言模型(LLM)通过增加嵌入模型的大小以及训练数据的数量和多样性,进一步提高了这些嵌入模型在各种文本类型中的性能。事实证明,语义搜索是提高智能体系统内记忆性能的宝贵技术,特别是在检索不共享确切关键词的文档中的语义相关信息方面。
使用向量存储实现语义记忆
我们首先为要存储的概念和知识生成语义嵌入。这些嵌入通常由基础模型或其他自然语言处理(NLP)技术生成,这些技术将文本信息编码为密集的向量表示。这些向量表示,或称嵌入,捕捉了连续向量空间中数据点的语义属性和关系。例如,描述历史事件的句子可以转换为捕捉其语义含义的向量。一旦需要这种向量表示,我们需要一个地方来高效地存储它。这个地方就是向量数据库,它是专门设计用于高效处理数据的高维向量表示的。
向量存储——如 VectorDB、FAISS(Facebook AI Similarity Search)或 Annoy(Approximate Nearest Neighbors Oh Yeah)——针对存储和搜索高维向量进行了优化。这些存储设定为进行快速相似性搜索,能够检索与给定查询在语义上相似的嵌入。
当智能体收到查询或需要检索信息时,可以使用向量存储根据查询的嵌入执行相似性搜索。通过从向量存储中查找并检索最相关的嵌入,智能体可以访问存储的语义记忆并提供有意义、符合上下文的响应。这些查找可以快速执行,提供了一种在大规模信息上快速搜索的有效方式,以提高行动和响应的质量。可以按如下方式实现:
|
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 |
from typing import Annotated from typing_extensions import TypedDict from langchain_openai import ChatOpenAI from langgraph.graph import StateGraph, MessagesState, START llm = ChatOpenAI(model="gpt-5") def call_model(state: MessagesState): response = llm.invoke(state["messages"]) return {"messages": response} from vectordb import Memory # 设置分块策略 memory = Memory(chunking_strategy={'mode':'sliding_window', 'window_size': 128, 'overlap': 16}) text = """Machine learning is a method of data analysis that automates analytical model building. It is a branch of artificial intelligence based on the idea that systems can learn from data, identify patterns and make decisions with minimal human intervention. Machine learning algorithms are trained on datasets that contain examples of the desired output. For example, a machine learning algorithm that is used to classify images might be trained on a dataset that contains images of cats and dogs. Once an algorithm is trained, it can be used to make predictions on new data. For example, the machine learning algorithm that is used to classify images could be used to predict whether a new image contains a cat or a dog.""" metadata = {"title": "Introduction to Machine Learning", "url": "https://learn.microsoft.com/en-us/training/modules/" + "introduction-to-machine-learning"} memory.save(text, metadata) text2 = """Artificial intelligence (AI) is the simulation of human intelligence in machinesthat are programmed to think like humans and mimic their actions.The term may also be applied to any machine that exhibits traits associated witha human mind such as learning and problem-solving.AI research has been highly successful in developing effective techniques for solving a wide range of problems, from game playing to medical diagnosis.""" metadata2 = {"title": "Artificial Intelligence for Beginners", "url": "https://microsoft.github.io/AI-for-Beginners"} memory.save(text2, metadata2) query = "What is the relationship between AI and machine learning?" results = memory.search(query, top_n=3) builder = StateGraph(MessagesState) builder.add_node("call_model", call_model) builder.add_edge(START, "call_model") graph = builder.compile() input_message = {"type": "user", "content": "hi! I'm bob"} for chunk in graph.stream({"messages": [input_message]}, {}, stream_mode="values"): chunk["messages"][-1].pretty_print() print(results) |
测试vectordb时出现了诸多错误,首先应安装的版本是
pip install vector2,其次它依赖于Tensorflow,因此需要安装pip install tensorflow tensorflow-hub,而由于这个包比较老了,在我的Mac上出现了兼容问题,所以在我们的代码仓库中最终使用的是LangChain的InMemoryVectorStore。
检索增强生成 (RAG)
将记忆纳入智能体系统不仅涉及存储和管理知识,还涉及增强系统生成上下文相关且准确的响应的能力。检索增强生成(RAG)是一种强大的技术,结合了基于检索的方法和生成模型的优势来实现这一目标。通过将检索机制与基础模型集成,RAG 使智能体系统能够生成更多信息密集且上下文丰富的响应,从而提高其在各种应用中的性能。
首先,我们从一组可能有助于系统回答问题的文档开始。然后我们将这些文档分解成更小的块(Chunks)。其理念是,模型就像人一样,不需要参考整个长资源——它只需要相关的、小部分内容。然后我们获取这些块,使用编码器模型将它们嵌入,并将它们索引在向量数据库中,如图 6-1 所示。
图 6-1. RAG 的索引管道。 源文档首先被分割成更小的块。每个块由编码器模型转换为密集的嵌入,生成的向量存储在向量数据库中——从而能够在查询时进行快速语义查找。
在检索期间,系统搜索大型文档语料库或嵌入向量存储,以查找与给定查询或上下文相关的信息片段。此阶段依赖于高效的检索机制来快速识别和提取相关信息。
在生成期间,检索到的信息随后被发送到生成式基础模型中,模型使用此上下文来生成连贯且符合上下文的响应。生成模型将检索到的数据与其自身学到的知识合成,增强生成文本的相关性和准确性,如图 6-2 所示。
图 6-2. RAG 运行时工作流。 用户向控制器提交问题,控制器查询向量知识库以检索最相关的信息。然后将检索到的上下文与原始用户问题结合并传递给生成模型,生成模型产生最终的、遵循上下文的响应。
RAG 代表了增强智能体系统能力的一种强大方法。通过利用外部知识并将其集成到生成过程中,RAG 能够创建更多信息丰富、准确且上下文相关的响应。随着技术的不断发展,RAG 将推动 LLM 驱动的应用程序在各个领域的性能和多功能性方面发挥至关重要的作用。这对于整合领域或公司特定的信息或政策以影响输出特别有价值。
语义体验记忆
虽然通过语义存储整合外部知识库是将外部知识纳入我们智能体的有效方式,但我们的智能体将在每次会话开始时都是一张白纸,且长期运行或复杂任务的上下文将逐渐从上下文窗口中溢出。这两个问题都可以通过语义体验记忆(Semantic Experience Memory)来解决。
对于每个用户输入,文本都会使用嵌入模型转换为向量表示。然后,该嵌入被用作查询,在记忆存储中的所有先前交互中进行向量搜索。上下文窗口的一部分被保留给来自语义体验记忆的最佳匹配项,然后剩余空间被分配给系统消息、最新用户输入和最近的交互。语义体验记忆不仅让智能体系统能利用广泛的知识基础,还可以根据积累的经验定制其响应和行动,从而产生更具适应性和个性化的行为。
GraphRAG (图 RAG)
我们现在转向一种更高级的 RAG 版本,将其整合到解决方案中更为复杂,但它能够正确处理更广泛的问题。图检索增强生成(GraphRAG)是 RAG 模型的高级扩展,它结合了基于图的数据结构来增强检索过程。通过利用图,GraphRAG 可以管理和利用信息片段之间复杂的相互关系和依赖关系,显著增强生成内容的丰富性和准确性。
基线 RAG 系统通过对文档进行分块、将这些块嵌入向量空间并在查询时检索语义相似的块来增强 LLM 的提示词。虽然这种方法对于简单的事实查找或直接问答很有效,但在以下情况下会很吃力:
-
答案需要连接分散在多个文档中的信息(“连点成线”)。
-
查询涉及总结数据集中的高级语义主题。
-
数据集很大、混乱,或者是按叙事而非离散事实组织的。
例如,如果没有单个检索到的块全面涵盖 Geoffrey Hinton 的行为,基线 RAG 可能无法回答“Geoffrey Hinton 做了什么?”。GraphRAG 通过从数据集中构建实体和关系的知识图谱来解决这个问题,从而实现多跳推理、关系链和结构化摘要。
使用知识图谱
在几分钟内,GraphRAG CLI 就可以在你的文本上提供全局洞察和局部上下文——无需编写 Python 代码。但如果你想要更多的控制和灵活性,使用 neo4j-graphrag-python 包只需几行代码即可实现生产级管道。使用官方的 neo4j-graphrag 库,设置仅涉及配置 Neo4j 连接、定义嵌入器和创建检索器——却可以立即获得完整的 GraphRAG 能力。对于教育或本地实验,像 nano-graphrag 这样的轻量级工具或社区仓库(例如 example-graphrag)仅需几百行 Python 代码即可解包相同的端到端管道。
该系统利用图数据库或知识图谱的力量来存储和查询互连数据。在 GraphRAG 中,检索阶段不仅拉取相关文档或片段;它分析和检索代表数据中复杂关系和上下文的图中的节点和边。GraphRAG 由以下三个组件组成:
- 知识图谱 (Knowledge Graph)
此组件以图格式存储数据,其中实体(节点)及其关系(边)被明确定义。图数据库在管理连接数据和支持涉及多跳或关系的复杂查询方面非常高效。 - 检索系统 (Retrieval System)
GraphRAG 中的检索系统旨在高效查询图数据库,提取与输入查询或上下文最相关的子图或节点集群。 - 生成模型 (Generative Model)
一旦以图的形式检索到相关数据,生成模型就会合成这些信息以创建连贯且上下文丰富的响应。
GraphRAG 代表了智能体系统能力的重大飞跃,提供了复杂的工具来处理和生成基于复杂互连数据的响应。随着这项技术的发展,它有望开辟 AI 应用的新前沿,使系统更智能、更具上下文感知能力,并能够处理日益复杂的任务。在 GraphRAG 系统中使用知识图谱改变了信息的检索和利用方式,从而在各种应用程序中实现更智能、更具上下文和更准确的响应。我们不会在这里讲解算法的细节,但现在有多种 GraphRAG 的开源实现可用,并且在数据集上配置它们更容易。如果你有大量数据需要推理,而标准分块加向量检索遇到限制,GraphRAG 是一种更昂贵且更复杂的方法,但在实践中通常会产生更好的结果。
构建知识图谱
知识图谱在提供结构化和语义丰富的信息方面至关重要,这些信息增强了包括 GraphRAG 系统在内的智能系统的能力。构建有效的知识图谱涉及一系列步骤,从数据收集和处理到集成和维护。本节将涵盖构建可显著影响 GraphRAG 系统性能的知识图谱的方法论。此过程包括几个步骤:
- 数据收集
构建知识图谱的第一步是收集必要的数据。这些数据可以来自各种来源,包括数据库、文本文档、网站甚至用户生成的内容。确保来源的多样性和质量对于覆盖广泛的知识至关重要。对于一个组织来说,这可能由一组核心政策或包含影响智能体的核心信息的文档组成。 - 数据预处理
一旦收集好数据,就需要对其进行清理和预处理。此步骤涉及删除不相关或冗余的信息、纠正错误以及标准化数据格式。预处理对于减少数据中的噪声和提高后续实体提取过程的准确性至关重要。 - 实体识别和提取
此过程涉及从数据中识别关键元素(实体),这些元素将作为知识图谱中的节点。常见的实体包括人、地点、组织和概念。通常使用命名实体识别(NER)等技术,这可能涉及在大型数据集上训练的机器学习模型,以准确识别和分类实体。 - 关系提取
识别实体后,下一步是确定它们之间的关系。这涉及解析数据以提取连接实体的谓词,形成图的边。关系提取可能具有挑战性,特别是在非结构化数据中,尽管基础模型已显示出随时间推移不断提高的功效。 - 本体设计
本体定义了知识图谱中的类别和关系,作为其骨干。设计本体涉及定义一个模式,该模式封装了实体的类型以及它们之间可能的关系类型。此模式有助于系统地组织知识图谱,并支持更有效的查询和数据检索。 - 图填充
有了本体之后,下一步是用提取的实体及其关系填充图。这涉及根据本体的结构在图数据库中创建节点和边。Neo4j、OrientDB 或 Amazon Neptune 等数据库可用于高效管理这些数据结构。 - 集成和验证
一旦图填充好了,它必须与现有系统集成并进行验证,以确保准确性和实用性。这可能涉及链接来自其他数据库的数据、解决实体重复(实体解析)以及验证图是否准确代表知识领域。验证可能涉及用户测试或自动检查,以确保图的完整性和可用性。 - 维护和更新
知识图谱不是一个静态实体;它需要定期更新和维护以保持相关性。这涉及添加新数据、更新现有信息以及随着新类型的实体或关系的识别而完善本体。自动化和机器学习模型有助于高效地维护和更新知识图谱。
构建知识图谱可以显著改善复杂和多跳检索。通常,这是通过提取基于资源描述框架(RDF)数据模型的语义三元组来进行的。这由主语-谓语-宾语表达式组成。基础模型非常擅长提取这些三元组,因此现在可以大规模构建这些类型的知识图谱。你可以在图 6-3 中看到此过程的可视化。
图 6-3. 知识图谱构建工作流。 文档由模型处理以提取主语-关系-宾语陈述形式的语义三元组(例如,“Jay-Z,配偶,Beyoncé”),然后将其结构化为知识图谱以实现高效的语义查询和推理。
为了更加易用,由于开源工具的存在,今天构建基本的 GraphRAG 管道出奇地简单。微软自己的 GraphRAG 库(可通过 pip install graphrag 获取)提供了一个用于索引和查询文档集的命令行工作流——不需要广泛的设置。例如,在初始化项目并使用其 CLI 建立索引后,你可以运行:
|
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 |
pip install graphrag mkdir -p ./ragtest/input curl https://www.gutenberg.org/ebooks/103.txt.utf-8 -o ./ragtest/input/book.txt # ./ragtest/input/book.txt graphrag init --root ./ragtest graphrag index --root ./ragtest graphrag query \ --root ./ragtest \ --method global \ --query "What are the key themes in this novel?" graphrag query \ --root ./ragtest \ --method local \ --query "Who is Phileas Fogg and what motivates his journey?" |
此处测试如使用的是非官方API需要在settings.yaml中的两处配置api_base。虽然我在代码仓库放置了book.txt,但不太建议用全部内容做测试,有点费token。
这会立即为你提供关于文本的全局洞察和局部上下文——而无需编写一行 Python 代码。如果你更喜欢控制权,Neo4j GraphRAG Python 包允许在代码中设置完整的 GraphRAG 管道。只需几行代码(连接到 Neo4j,定义嵌入器和检索器,然后查询),你就能获得强大的图增强 RAG 功能。对于对轻量级或教育实现感兴趣的开发人员,还有较小的社区项目,如 nano-graphrag 和示例仓库(例如 example-graphrag),它们用几百行 Python 代码解包核心管道。
虽然这对于实验来说很棒,但许多团队希望从原型转向经过强化的、可扩展的系统。这正是 Neo4j 大放异彩的地方:它是最受信任的企业级图数据库。其原生图存储和免索引邻接架构确保了近乎恒定的遍历性能——即使图扩展到数十亿个节点和关系。生产部署通常使用 Neo4j Enterprise 或 AuraDB,提供集群、容错、ACID(原子性、一致性、隔离性和持久性)合规性和多区域支持。一旦你使用了 Neo4j GraphRAG Python 工具或基于 Cypher 的设置来提取实体并定义关系,就有一条通往可扩展部署的平滑路径:
-
通过 Cypher 大规模填充: 使用
CREATE和MERGE语句构建干净、去重的图。 -
增量加载逻辑: 确保你可以在不重复的情况下更新新数据。
-
通过 Neo4j 的读/写集群、缓存分片和优化的查询规划器来扩展性能。
简而言之,Neo4j 使得从笔记本原型过渡到生产级图支持的 RAG 管道变得简单——而不会牺牲性能、可靠性或可维护性。
定义好本体并提取实体和关系后,就该填充知识图谱了。在 Neo4j 中,这是使用 Cypher CREATE 子句完成的,它允许你指定带有标签和属性的节点,然后通过有向关系链接它们。最佳实践是首先加载或匹配现有节点——确保你不重复实体——然后为每个关系发布单独的 CREATE 语句,如下例所示。通过将脚本组织成离散步骤(创建节点 → 匹配节点 → 创建关系),你可以保持清晰度,并随着图的增长更容易地调试或扩展它:
|
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 |
// 创建概念和实体的节点 CREATE (:Concept {name: 'Artificial Intelligence'}); CREATE (:Concept {name: 'Machine Learning'}); CREATE (:Concept {name: 'Deep Learning'}); CREATE (:Concept {name: 'Neural Networks'}); CREATE (:Concept {name: 'Computer Vision'}); CREATE (:Concept {name: 'Natural Language Processing'}); CREATE (:Tool {name: 'TensorFlow', creator: 'Google'}); CREATE (:Tool {name: 'PyTorch', creator: 'Facebook'}); CREATE (:Model {name: 'BERT', year: 2018}); CREATE (:Model {name: 'ResNet', year: 2015}); // 创建概念之间的关系 MATCH (ai:Concept {name:'Artificial Intelligence'}), (ml:Concept {name:'Machine Learning'}) CREATE (ml)-[:SUBSET_OF]->(ai); MATCH (ml:Concept {name:'Machine Learning'}), (dl:Concept {name:'Deep Learning'}) CREATE (dl)-[:SUBSET_OF]->(ml); MATCH (dl:Concept {name:'Deep Learning'}), (nn:Concept {name:'Neural Networks'}) CREATE (nn)-[:USED_IN]->(dl); MATCH (ai:Concept {name:'Artificial Intelligence'}), (cv:Concept {name:'Computer Vision'}) CREATE (cv)-[:APPLICATION_OF]->(ai); MATCH (ai:Concept {name:'Artificial Intelligence'}), (nlp:Concept {name:'Natural Language Processing'}) CREATE (nlp)-[:APPLICATION_OF]->(ai); // 创建与工具和模型的关系 MATCH (tensorflow:Tool {name:'TensorFlow'}), (nn:Concept {name:'Neural Networks'}) CREATE (tensorflow)-[:IMPLEMENTS]->(nn); MATCH (pytorch:Tool {name:'PyTorch'}), (nn:Concept {name:'Neural Networks'}) CREATE (pytorch)-[:IMPLEMENTS]->(nn); MATCH (nlp:Concept {name:'Natural Language Processing'}), (bert:Model {name:'BERT'}) CREATE (bert)-[:BELONGS_TO]->(nlp); MATCH (cv:Concept {name:'Computer Vision'}), (resnet:Model {name:'ResNet'}) CREATE (resnet)-[:BELONGS_TO]->(cv); MATCH (tensorflow:Tool {name:'TensorFlow'}), (bert:Model {name:'BERT'}) CREATE (bert)-[:BUILT_WITH]->(tensorflow); MATCH (pytorch:Tool {name:'PyTorch'}), (resnet:Model {name:'ResNet'}) CREATE (resnet)-[:BUILT_WITH]->(pytorch); // 查询以查找概念之间的关系 MATCH path = shortestPath( (concept1:Concept {name: 'Natural Language Processing'})-[*]-(concept2:Concept {name: 'Deep Learning'}) ) RETURN path; // 查询查找所有使用 TensorFlow 的模型 MATCH (model:Model)-[:BUILT_WITH]->(tool:Tool {name: 'TensorFlow'}) RETURN model.name AS model, model.year AS year; |
一旦加载,你的知识图谱就支持多跳遍历(例如,shortestPath 查询)和丰富关系模式,这远远超过了平面表或向量存储所能表达的内容。这一基础实现了高级 GraphRAG 工作流——智能体可以在运行时遍历图以收集跨越多个分离度的上下文——从而解锁了对结构化知识的真正强大的推理。这些结构使得发现数据中的底层关系变得容易。例如,现在可以在图上搜索元素,然后检索距该节点一个或多个链接的所有元素。正如你在图 6-4 中看到的,在回答复杂查询时,控制器可以遍历图并对结构化数据执行多跳推理,从而扩大了这些类型的系统可以回答的问题的范围和复杂性。
图 6-4. 使用知识图谱回答问题。 用户的提问通过控制器路由,控制器在知识图谱中查询相关的结构化信息,将其与语言模型的推理能力相结合,并返回内容丰富、经过多跳信息验证的答案。
这提供了一种检索解决任务所需相关上下文的有效方法。随着 AI 技术的进步,构建、集成和维护知识图谱的方法论将继续发展,进一步增强其在各个领域的效用。
动态知识图谱的希望与风险
动态知识图谱是实时应用中管理和利用知识的重要一步。这些图谱不断更新新信息,适应知识和上下文的变化,这可以显著增强 GraphRAG 系统。然而,这些图谱的动态性质也引入了需要仔细考虑的特定挑战。本节探讨了与动态知识图谱相关的潜在好处和风险。
作为开发人员,重要的是要仔细考虑以选择最合适的设计,以便高效地检索适当的上下文来处理传入的任务。知识图谱的原型设计相当容易,但让其准备好投入生产是一项重大任务。
模型架构的最新进展正在将上下文窗口推向空前的长度,允许 LLM 在单次传递中“记住”和处理整个文档。例如,Google 的 Gemini 2.5 和 OpenAI 的 GPT-4.1 现在支持高达一百万个 Token——大约 750,000 个单词或超过 2,500 页——从而实现了非常大上下文的无检索生成。同样,免索引 RAG(index-free RAG)系统将它们自己的检索逻辑嵌入到长上下文模型(如 GPT-4.1)中,有效地在内部执行分块和相关性评分,而无需外部向量存储或倒排索引。将知识直接嵌入到这些扩展的上下文中可以简化管道:智能体不必编排单独的检索和排名节点,而是可以将整个知识库(例如,政策文件或技术规范)直接加载到提示词中,并依靠模型的注意力机制来呈现相关段落。
然而,这些无检索方法也有权衡。一次性处理数百万个 Token 需要大量的计算,并可能引入延迟和成本挑战——有时会抵消移除外部检索所带来的简易性收益。此外,无法保证给定的模型能从如此大的上下文窗口中正确识别出那一条相关信息。如果更大的模型、更大的上下文窗口和更多的计算使得对向量数据库的复杂文本搜索和语义搜索变得过时,请不要感到惊讶,但在此期间,社区共识仍然认为混合架构有其价值:即使有了多页上下文窗口,RAG 在寻求事实的查询和企业用例上也可以胜过纯长上下文模型,特别是当记忆的新鲜度或精确排名至关重要时。实际上,许多生产系统结合了扩展的上下文窗口和选择性检索节点——利用两全其美的优势来平衡性能、成本和事实准确性。
动态实时信息处理通过动态知识图谱得到了极大的增强,动态知识图谱可以集成实时数据。这种能力在信息不断变化的环境中特别有用,例如新闻、社交媒体和实时监控系统。通过确保系统的响应始终基于最新和最相关的信息,动态知识图谱提供了显著优势。
自适应学习是动态知识图谱的另一个关键特性。它们不断自我更新,从新数据中学习,而无需定期重新训练或手动更新。这种适应性对于医学、技术和金融等快速发展领域的应用至关重要,在这些领域,保持最新知识至关重要。这有助于组织快速做出明智的决策,这在决策具有重大影响且严重依赖最新信息的场景中非常宝贵。知识图谱还以结构化格式提供关键信息,可以有效地进行操作和推理,可以提供比向量存储更大的灵活性,并且对于理解实体的丰富上下文特别有价值。不幸的是,这些好处伴随着一些重要的缺点:
- 维护的复杂性(Complexity in maintenance)
维护动态知识图谱的准确性和可靠性比管理静态图谱要困难得多。新数据的不断涌入可能会引入错误和不一致,如果不及时识别和纠正,这些错误可能会在整个图谱中传播。 - 资源密集度(Resource intensity)
更新、验证和维护动态知识图谱的过程需要大量的计算资源。随着图谱规模和复杂性的增加,这些过程可能会变得资源密集,从而可能限制可扩展性。 - 安全和隐私问题(Security and privacy concerns)
包含用户数据或敏感信息的动态知识图谱必须在严格遵守安全和隐私标准的情况下进行管理。这些图谱的实时方面可能会使遵守数据保护法规变得复杂,因为任何疏忽都可能导致重大违规。 - 依赖和过度依赖(Dependency and overreliance)
存在过度依赖动态知识图谱进行决策的风险,这可能导致缺乏关键的监督。仅由图谱的自动洞察驱动的决策可能会忽略图谱未捕捉到的外部因素。
为了利用动态知识图谱的好处并减轻其风险,可以采用几种策略。实施带有自动化工具和流程的稳健验证机制对于持续确保图谱中数据的准确性和可靠性至关重要。使用分布式数据库和云计算等技术设计可扩展的架构有助于管理动态图谱的计算需求。强大的安全措施,包括加密、访问控制和匿名化技术,对于确保所有数据输入和集成符合当前的安全和隐私法规至关重要。此外,在关键决策过程中保持人工监督可以减轻错误和过度依赖自动化系统的风险。
动态知识图谱为增强 GraphRAG 系统的智能和响应能力提供了巨大的希望,为各种应用带来了显著的好处。然而,与其动态性质相关的复杂性和风险需要仔细的管理和监督。通过主动应对这些挑战,可以充分实现动态知识图谱的潜力,推动智能系统在不断发展的数字环境中的能力。
笔记 (Note-Taking)
通过这种技术,基础模型被提示专门针对输入上下文注入笔记,而不尝试回答问题[1]。这模仿了我们在页边空白处填写或总结段落或章节的方式。这种记笔记是在提出问题之前进行的,然后在尝试解决当前任务时,将这些笔记与原始上下文交织在一起。实验表明,这种方法在多个推理和评估任务上取得了良好的结果,并有潜力适应更广泛的场景。正如我们在图 6-5 中所见,在传统的“普通(vanilla)”方法中,模型接收上下文和问题,并产生答案。而在思维链(Chain of Thought)中,它有时间推理问题,随后才生成问题的答案。而在自我笔记(Self-note)方法中,模型会对上下文的多个部分生成笔记,然后对问题生成笔记,最后才着手生成最终答案。图 6-5 说明了记笔记如何通过在产生最终答案之前将模型生成的笔记与上下文交织在一起,来增强标准推理工作流。
图 6-5. 笔记工作流。 在标准方法中,模型将上下文和问题一起处理以直接产生答案。在笔记方法中,模型首先生成总结或阐述上下文和问题部分的笔记,然后产生最终答案——从而实现更深层次的推理并提高任务性能。
结论
记忆对于智能体系统的成功运行至关重要,虽然依赖近期交互的上下文窗口的标准方法对于许多用例来说已经足够,但更具挑战性的场景可以从对更稳健方法的投资中获益匪浅。我们在这里探讨了几种方法,包括语义记忆、GraphRAG 和工作记忆。
本章深入探讨了如何构建和利用记忆来增强智能体能力的各个方面。从管理上下文窗口的基本概念,到语义记忆和向量存储的高级应用,再到动态知识图谱和工作记忆的创新实践,我们探索了一系列在智能体系统开发中发挥关键作用的技术和技术。
智能体应用中的记忆系统不仅仅是关于存储数据,更是关于转变智能体与其环境和最终用户互动的方式。通过不断改进这些系统,我们可以创建更智能、更灵敏、更有能力的智能体,从而更有效地执行各种任务。在下一章中,我们将探讨智能体如何从经验中学习,以便随着时间的推移自动改进。
[1] Jack Lanchantin et al., “Learning to Reason and Memorize with Self-Notes”, arXiv, May 1, 2023.
翻译整理自Building Applications with AI Agents一书,仅供学习交流使用









