第14章:知识检索(RAG)
大型语言模型在生成类似人类文本方面展现出显著的能力。然而,它们的知识库通常局限于训练数据,这限制了它们获取实时信息、特定公司数据或高度专业化的细节。知识检索(RAG,或检索增强生成)解决了这一限制。RAG使智能体能够访问和整合外部、当前和上下文特定的信息,从而提高了输出的准确性、相关性和事实基础。
对于智能体来说,这一点至关重要,因为它允许它们将行动和响应建立在实时、可验证的数据之上,这些数据超越了它们静态的训练。这种能力使它们能够准确执行复杂任务,例如,在回答具体问题时访问最新的公司政策,或者在下单前检查当前库存。通过整合外部知识,RAG将智能体从简单的对话者转变为有效、数据驱动的工具,能够执行有意义的工作。
知识检索(RAG)模式概述
知识检索(RAG)模式通过在生成响应之前让智能体访问外部知识库,显著增强了大型语言模型(LLM)的能力。RAG不再让智能体仅依赖其内部、预训练的知识,而是允许智能体“查阅”信息,就像人类可能会查阅书籍或上网搜索一样。这个过程使智能体能够提供更准确、更新、可验证的答案。
当用户使用RAG向AI系统提出问题或给出提示时,查询并不会直接发送给LLM。相反,系统首先在一个庞大的外部知识库中搜索相关信息——这是一个高度组织的文档、数据库或网页库。这种搜索不是简单的关键词匹配,而是一种“语义搜索”,它能理解用户的意图和其话语背后的含义。这次初步搜索提取出最相关的片段或“信息块”。这些提取出的内容随后被“增强”,即添加到原始提示中,从而形成一个更加丰富、信息量更大的查询。最后,这个增强后的提示被发送给LLM。有了这个额外的上下文,LLM可以生成既流畅自然,又基于检索到的数据的回答。
RAG框架提供了多项显著优势。它允许LLM(大型语言模型)访问最新信息,从而克服了它们静态训练数据的限制。这种方法还能通过将回应建立在可验证的数据上,降低“幻觉”——即生成虚假信息——的风险。此外,LLM可以利用公司内部文档或维基中找到的专门知识。这一过程的一个关键优势是能够提供“引文”,这可以精确指出信息的来源,从而增强AI回应的可信度和可验证性。
要充分理解RAG(检索增强生成)的工作原理,关键是要了解几个核心概念(见图1):
嵌入(Embeddings): 在大型语言模型(LLM)的语境中,嵌入是文本(如单词、短语或整个文档)的数值表示。这些表示形式为向量,即一系列数字。关键思想是在数学空间中捕捉不同文本片段的语义意义及其关系。具有相似意义的单词或短语在这个向量空间中的嵌入将彼此更接近。例如,想象一个简单的二维图。单词“猫”可能表示为坐标(2,3),而“小猫”则非常接近,坐标为(2.1,3.1)。相比之下,单词“汽车”将有一个遥远的坐标,如(8,1),反映出其不同的含义。实际上,这些嵌入在一个维度数更高的空间中,拥有数百甚至数千个维度,从而能够对语言有非常细腻的理解。
文本相似度: 文本相似度是指衡量两段文本相似程度的一个指标。这可以在表面层面上进行,查看词语的重叠(词汇相似度),或者在一个更深层次,基于意义层面上进行。在RAG(检索增强生成)的语境中,文本相似度对于在知识库中找到与用户查询最相关的信息至关重要。例如,考虑以下句子:“法国的首都是什么?”和“哪个城市的首都是法国?”。虽然措辞不同,但它们提出的是同一个问题。一个好的文本相似度模型会识别这一点,并将这两个句子的相似度评分设得较高,尽管它们只共享少数几个词语。这通常是通过计算文本的嵌入来实现的。
语义相似性和距离:语义相似性是一种更高级的文本相似性形式,它纯粹关注文本的意义和上下文,而不仅仅是使用的词语。它的目标是理解两段文本是否传达了相同的概念或想法。语义距离是这一概念的逆过程;高语义相似性意味着低语义距离,反之亦然。在RAG中,语义搜索依赖于找到与用户查询具有最小语义距离的文档。例如,短语“a furry feline companion”(一只毛茸茸的猫科动物伴侣)和“a domestic cat”(一只家猫)除了“a”之外没有共同词语。然而,一个理解语义相似性的模型会认识到它们指的是同一事物,并将它们视为高度相似。这是因为它们的嵌入在向量空间中非常接近,表明了小的语义距离。这正是RAG的“智能搜索”功能,它允许RAG在用户的措辞与知识库中的文本不完全匹配的情况下找到相关信息。

图1:RAG核心概念:分块、嵌入和向量数据库
文档分块: 文档分块是将大型文档分解成更小、更易于管理的部分,或称为“块”的过程。为了使检索增强生成(RAG)系统高效运行,它不能将整个大型文档输入到大型语言模型(LLM)中。相反,它处理这些较小的块。文档分块的方式对于保留信息的上下文和意义至关重要。例如,与其将50页的用户手册视为一个单一的文本块,不如采用分块策略将其分解为章节、段落,甚至句子。例如,“故障排除”部分将作为一个独立的块,与“安装指南”分开。当用户就特定问题提问时,RAG系统可以检索到最相关的故障排除块,而不是整个手册。这使得检索过程更快,提供给LLM的信息更加聚焦和符合用户的即时需求。一旦文档被分块,RAG系统必须采用检索技术来找到针对给定查询的最相关部分。主要方法是向量搜索,它使用嵌入和语义距离来找到与用户问题概念上相似的块。一种较老但仍然有价值的技术是BM25,这是一种基于关键词的算法,它根据词频对块进行排名,而不理解语义意义。为了兼顾两者之长,通常会使用混合搜索方法,结合BM25的关键词精确度和语义搜索的上下文理解。这种融合使得检索更加稳健和准确,能够捕捉到字面匹配和概念相关性。
向量数据库:向量数据库是一种专门设计的数据库,旨在高效地存储和查询嵌入(embeddings)。在将文档分块并转换为嵌入后,这些高维向量被存储在向量数据库中。传统的检索技术,如基于关键词的搜索,在查找包含查询中确切单词的文档方面非常出色,但缺乏对语言的深入理解。它们不会识别“毛茸茸的猫伴侣”意味着“猫”。这正是向量数据库的优势所在。它们专门为语义搜索而构建。通过将文本存储为数值向量,它们可以根据概念意义而非仅仅是关键词重叠来找到结果。当用户的查询也被转换为向量时,数据库使用高度优化的算法(如HNSW - 层次可导航小世界)快速搜索数百万个向量,并找到意义“最接近”的向量。这种方法对于RAG(检索增强生成)来说远优于其他方法,因为它甚至能够在用户的措辞与源文档完全不同的情况下揭示相关上下文。本质上,虽然其他技术搜索的是单词,但向量数据库搜索的是意义。这项技术以各种形式实现,从像Pinecone和Weaviate这样的托管数据库到像Chroma DB、Milvus和Qdrant这样的开源解决方案。甚至现有的数据库也可以通过向量搜索功能进行增强,如Redis、Elasticsearch和Postgres(使用pgvector扩展)所示。核心检索机制通常由像Meta AI的FAISS或Google Research的ScaNN这样的库提供支持,这些库是这些系统效率的基础。
RAG的挑战: 尽管RAG模式功能强大,但它并非没有挑战。一个主要问题出现在需要回答查询的信息不仅限于单个片段,而是分散在文档的多个部分甚至多个文档中时。在这种情况下,检索器可能无法收集所有必要的上下文,导致答案不完整或不准确。系统的有效性也高度依赖于分块和检索过程的质量;如果检索到无关的片段,可能会引入噪声并混淆LLM。此外,有效地从可能存在矛盾的信息源中综合信息仍然是这些系统的一个重大障碍。除此之外,另一个挑战是RAG需要将整个知识库预先处理并存储在专门的数据库中,例如向量或图数据库,这是一项相当大的工作。因此,这些知识需要定期更新以保持最新,当处理如公司维基等不断变化的信息源时,这是一个至关重要的任务。整个过程可能会对性能产生明显影响,增加延迟、运营成本以及最终提示中使用的token数量。
总的来说,检索增强生成(RAG)模式在使人工智能更加知识渊博和可靠方面迈出了重要的一步。通过将外部知识检索步骤无缝集成到生成过程中,RAG解决了独立大型语言模型(LLM)的一些核心局限性。嵌入和语义相似性的基础概念,结合关键词和混合搜索等检索技术,使系统能够智能地找到相关信息,并通过战略性的分块使其变得可管理。整个检索过程由专门设计的向量数据库提供支持,这些数据库旨在以规模存储和高效查询数百万个嵌入。尽管检索碎片化或相互矛盾的信息仍然存在挑战,但RAG使LLM能够生成不仅符合上下文,而且基于可验证事实的答案,从而在人工智能中培养出更大的信任和实用性。
图RAG(Graph RAG): 图RAG是一种高级的检索增强生成(Retrieval-Augmented Generation)形式,它使用知识图谱而不是简单的向量数据库进行信息检索。通过在结构化知识库中导航数据实体(节点)之间的显式关系(边),它能够回答复杂的查询。一个关键优势是它能够从多个文档中分散的信息中综合答案,这是传统RAG常见的不足。通过理解这些联系,图RAG提供了更符合语境和更细腻的回答。
应用场景包括复杂的财务分析、将公司连接到市场事件,以及科学研究以发现基因与疾病之间的关系。然而,主要缺点是构建和维护高质量知识图谱所需的复杂性、成本和专业知识非常显著。与简单的向量搜索系统相比,这种设置也缺乏灵活性,并且可能引入更高的延迟。系统的有效性完全取决于底层图结构的质量和完整性。因此,GraphRAG在提供复杂问题的优越上下文推理方面表现出色,但实施和维护成本也相对较高。总之,它在深度、互联的洞察力比标准RAG的速度和简单性更为关键的地方表现出色。
智能体RAG:这种模式的一种演变,称为智能体RAG(见图2),引入了推理和决策层,以显著提高信息提取的可靠性。不同于仅仅检索和增强,一个“智能体”——一个专门的AI组件——充当了知识的关键守门人和精炼者。这个智能体不会被动地接受最初检索到的数据,而是会主动地对其质量、相关性和完整性进行质疑,以下场景进行了说明。
首先,智能体擅长反思和源验证。如果用户询问:“我们公司关于远程工作的政策是什么?”一个标准的RAG可能会同时检索到一篇2020年的博客文章和一份官方的2025年政策文件。然而,智能体会分析文档的元数据,识别出2025年的政策是最新的、最权威的来源,并在将正确的上下文发送给LLM以获得精确答案之前,丢弃过时的博客文章。

图2:智能体RAG引入了一个推理智能体,该智能体主动评估、调和和细化检索到的信息,以确保最终响应更加准确和可靠。
其次,智能体擅长解决知识冲突。想象一下,一位财务分析师问道:“Alpha项目第一季度的预算是多少?”系统检索到两份文档:一份初始提案中提到预算为50,000欧元,另一份最终财务报告中将其列为65,000欧元。一个Agentic RAG会识别出这种矛盾,将财务报告作为更可靠的来源进行优先处理,并向LLM提供经过验证的数字,确保最终答案基于最准确的数据。
第三,智能体可以执行多步推理以综合复杂答案。如果用户询问:“我们的产品功能和定价与竞争对手X相比如何?”智能体会将这个问题分解成几个独立的子查询。它会分别搜索自身产品的功能、定价、竞争对手X的功能以及竞争对手X的定价。在收集到这些单独的信息片段后,智能体会将它们综合成一个结构化的比较上下文,然后再将其输入到LLM中,从而生成一个全面回答,这是简单检索无法实现的。
第四,智能体可以识别知识空白并使用外部工具。假设用户询问:“昨天我们新推出的产品,市场立即的反应是什么?”智能体搜索每周更新的内部知识库,但没有找到相关信息。识别到这一空白后,它可以激活一个工具——例如实时网络搜索API——来查找最近的新闻文章和社交媒体情绪。然后,智能体利用这些新收集的外部信息提供最新的答案,克服了其静态内部数据库的限制。
智能体RAG的挑战: 虽然功能强大,但智能体层也带来了一系列挑战。主要缺点是复杂性和成本显著增加。设计、实施和维护智能体的决策逻辑和工具集成需要大量的工程努力,并增加了计算成本。这种复杂性也可能导致延迟增加,因为智能体的反思周期、工具使用和多步骤推理所需的时间比标准的直接检索过程更长。此外,智能体本身也可能成为新的错误来源;一个有缺陷的推理过程可能导致它陷入无用的循环,误解任务或错误地丢弃相关信息,最终降低最终响应的质量。
总结: 智能体RAG代表了标准检索模式的复杂进化,将其从被动数据管道转变为主动的问题解决框架。通过嵌入一个能够评估来源、解决冲突、分解复杂问题并使用外部工具的推理层,智能体显著提高了生成答案的可靠性和深度。这一进步使人工智能更加值得信赖和能干,尽管这也带来了系统复杂性、延迟和成本等重要权衡,必须谨慎管理。
实际应用与用例
知识检索(RAG)正在改变大型语言模型(LLM)在各个行业的应用方式,提升了它们提供更准确和与上下文相关的响应的能力。
应用范围包括:
- 企业搜索与问答:组织可以开发内部聊天机器人,通过使用内部文档如人力资源政策、技术手册和产品规格等来回应员工的咨询。RAG系统从这些文档中提取相关部分,以供LLM(大型语言模型)参考并生成回应。
- 客户支持和帮助台: 基于RAG(检索增强生成)的系统可以通过访问产品手册、常见问题(FAQ)和支持工单等信息,为顾客查询提供精确且一致的回答。这可以减少对直接人工干预日常问题的需求。
- 个性化内容推荐: 与基本的关键词匹配不同,RAG可以识别和检索与用户偏好或先前交互语义相关的(文章、产品)内容,从而实现更相关的推荐。
- 新闻和时事摘要: 大型语言模型(LLM)可以与实时新闻源集成。当被询问关于某一时事时,检索增强生成(RAG)系统会检索最近的文章,使LLM能够生成最新的摘要。
通过整合外部知识,RAG扩展了LLM的功能,使其不仅限于简单的通信,还能作为知识处理系统。
动手代码示例(ADK)
为了说明知识检索(RAG)模式,让我们来看三个示例。
首先,是如何使用Google搜索进行RAG(检索增强生成)并将LLM(大型语言模型)与搜索结果关联。由于RAG涉及访问外部信息,Google搜索工具是一个直接示例,它内置的检索机制可以增强LLM的知识。
from google.adk.tools import google_search
from google.adk.agents import Agent
search_agent = Agent(
name="research_assistant",
model="gemini-2.0-flash-exp",
instruction="You help users research topics. When asked, use the Google Search tool",
tools=[google_search]
)
其次,本节解释了如何在Google ADK中利用Vertex AI RAG功能。提供的代码演示了从ADK初始化VertexAiRagMemoryService的过程。这允许建立与Google Cloud Vertex AI RAG语料库的连接。通过指定语料库资源名称和可选参数(如SIMILARITY_TOP_K和VECTOR_DISTANCE_THRESHOLD)来配置服务。这些参数影响检索过程。SIMILARITY_TOP_K定义了要检索的相似结果数量。VECTOR_DISTANCE_THRESHOLD为检索结果设置了语义距离限制。这种设置使智能体能够从指定的RAG语料库中执行可扩展和持久的语义知识检索。该过程有效地将Google Cloud的RAG功能集成到ADK智能体中,从而支持基于事实数据开发响应。
# Import the necessary VertexAiRagMemoryService class from the google.adk.memory module.
from google.adk.memory import VertexAiRagMemoryService
RAG_CORPUS_RESOURCE_NAME = "projects/your-gcp-project-id/locations/us-central1/ragCorpora/your-corpus-id"
# Define an optional parameter for the number of top similar results to retrieve.
# This controls how many relevant document chunks the RAG service will return.
SIMILARITY_TOP_K = 5
# Define an optional parameter for the vector distance threshold.
# This threshold determines the maximum semantic distance allowed for retrieved results;
# results with a distance greater than this value might be filtered out.
VECTOR_DISTANCE_THRESHOLD = 0.7
# Initialize an instance of VertexAiRagMemoryService.
# This sets up the connection to your Vertex AI RAG Corpus.
# - rag_corpus: Specifies the unique identifier for your RAG Corpus.
# - similarity_top_k: Sets the maximum number of similar results to fetch.
# - vector_distance_threshold: Defines the similarity threshold for filtering results.
memory_service = VertexAiRagMemoryService(
rag_corpus=RAG_CORPUS_RESOURCE_NAME,
similarity_top_k=SIMILARITY_TOP_K,
vector_distance_threshold=VECTOR_DISTANCE_THRESHOLD)
动手代码示例(LangChain)
第三,让我们通过一个使用LangChain的完整示例来进行分析。
import os
import requests
from typing import List, Dict, Any, TypedDict
from langchain_community.document_loaders import TextLoader
from langchain_core.documents import Document
from langchain_core.prompts import ChatPromptTemplate
from langchain_core.output_parsers import StrOutputParser
from langchain_community.embeddings import OpenAIEmbeddings
from langchain_community.vectorstores import Weaviate
from langchain_openai import ChatOpenAI
from langchain.text_splitter import CharacterTextSplitter
from langchain.schema.runnable import RunnablePassthrough
from langgraph.graph import StateGraph, END
import weaviate
from weaviate.embedded import EmbeddedOptions
import dotenv
# Load environment variables (e.g., OPENAI_API_KEY)
dotenv.load_dotenv()
# Set your OpenAI API key (ensure it's loaded from .env or set here)
# os.environ["OPENAI_API_KEY"] = "YOUR_OPENAI_API_KEY"
# --- 1. Data Preparation (Preprocessing) ---
# Load data
url = "https://github.com/langchain-ai/langchain/blob/master/docs/docs/how_to/state_of_the_union.txt"
res = requests.get(url)
with open("state_of_the_union.txt", "w") as f:
f.write(res.text)
loader = TextLoader('./state_of_the_union.txt')
documents = loader.load()
# Chunk documents
text_splitter = CharacterTextSplitter(chunk_size=500, chunk_overlap=50)
chunks = text_splitter.split_documents(documents)
# Embed and store chunks in Weaviate
client = weaviate.Client(embedded_options=EmbeddedOptions())
vectorstore = Weaviate.from_documents(
client=client,
documents=chunks,
embedding=OpenAIEmbeddings(),
by_text=False
)
# Define the retriever
retriever = vectorstore.as_retriever()
# Initialize LLM
llm = ChatOpenAI(model_name="gpt-3.5-turbo", temperature=0)
# --- 2. Define the State for LangGraph ---
class RAGGraphState(TypedDict):
question: str
documents: List[Document]
generation: str
# --- 3. Define the Nodes (Functions) ---
def retrieve_documents_node(state: RAGGraphState) -> RAGGraphState:
"""Retrieves documents based on the user's question."""
question = state["question"]
documents = retriever.invoke(question)
return {"documents": documents, "question": question, "generation": ""}
def generate_response_node(state: RAGGraphState) -> RAGGraphState:
"""Generates a response using the LLM based on retrieved documents."""
question = state["question"]
documents = state["documents"]
# Prompt template from the PDF
template = """You are an assistant for question-answering tasks. Use the following pieces of retrieved context to answer the question. If you don't know the answer, just say that you don't know. Use three sentences maximum and keep the answer concise. Question: {question} Context: {context} Answer: """
prompt = ChatPromptTemplate.from_template(template)
# Format the context from the documents
context = "\n\n".join([doc.page_content for doc in documents])
# Create the RAG chain
rag_chain = prompt | llm | StrOutputParser()
# Invoke the chain
generation = rag_chain.invoke({"context": context, "question": question})
return {"question": question, "documents": documents, "generation": generation}
# --- 4. Build the LangGraph Graph ---
workflow = StateGraph(RAGGraphState)
workflow.add_node("retrieve", retrieve_documents_node)
workflow.add_node("generate", generate_response_node)
workflow.set_entry_point("retrieve")
workflow.add_edge("retrieve", "generate")
workflow.add_edge("generate", END)
app = workflow.compile()
# --- 5. Run the RAG Application ---
if __name__ == "__main__":
print("\n--- Running RAG Query ---")
query = "What did the president say about Justice Breyer"
inputs = {"question": query}
for s in app.stream(inputs):
print(s)
print("\n--- Running another RAG Query ---")
query_2 = "What did the president say about the economy?"
inputs_2 = {"question": query_2}
for s in app.stream(inputs_2):
print(s)
这段Python代码展示了使用LangChain和LangGraph实现的检索增强生成(RAG)管道。过程从创建一个由文本文档派生的知识库开始,该文档被分割成块并转换为嵌入表示。然后,这些嵌入表示被存储在Weaviate向量存储中,以促进高效的信息检索。LangGraph中的StateGraph用于管理两个关键函数之间的工作流程:retrieve_documents_node和generate_response_node。retrieve_documents_node函数查询向量存储以根据用户的输入识别相关的文档块。随后,generate_response_node函数利用检索到的信息和预定义的提示模板,使用OpenAI大型语言模型(LLM)生成响应。app.stream方法允许通过RAG管道执行查询,展示了系统生成上下文相关输出的能力。
概览
内容: 大型语言模型(LLM)拥有令人印象深刻的文本生成能力,但其本质上受到训练数据的限制。这种知识是静态的,意味着它不包括实时信息或特定领域的私有数据。因此,它们的回答可能过时、不准确,或者缺乏特定任务所需的特定上下文。这种差距限制了它们在需要当前和事实性答案的应用中的可靠性。
原因:检索增强生成(RAG)模式通过将大型语言模型(LLM)连接到外部知识源,提供了一个标准化的解决方案。当接收到查询时,系统首先从指定的知识库中检索相关信息片段。然后,这些片段被附加到原始提示中,为它增添了及时和具体的内容。这个增强后的提示随后被发送给LLM,使其能够生成准确、可验证且基于外部数据的响应。这个过程有效地将LLM从闭卷推理者转变为开卷推理者,显著提高了其效用和可信度。
经验法则:当您需要LLM回答问题或基于特定、最新或专有信息生成内容,而这些信息并未包含在其原始训练数据中时,请使用此模式。它非常适合构建基于内部文档的问答系统、客户支持机器人以及需要可验证、基于事实并附有引用的应用程序。
视觉摘要

知识检索模式:一个用于查询和从结构化数据库中检索信息的AI智能体

图3:知识检索模式:一个AI智能体根据用户查询从公共互联网中查找和综合信息。
关键要点
知识检索(RAG)通过允许智能体访问外部、最新和特定信息,增强了大型语言模型。 该过程涉及检索(在知识库中搜索相关片段)和增强(将这些片段添加到LLM的提示中)。 RAG帮助LLM克服如过时训练数据等限制,减少“幻觉”,并实现特定领域知识的整合。 RAG允许提供可追溯的答案,因为LLM的响应基于检索到的来源。 GraphRAG利用知识图谱来理解不同信息片段之间的关系,使其能够回答需要从多个来源综合数据的复杂问题。 智能体RAG超越了简单的信息检索,通过使用智能体来主动推理、验证和精炼外部知识,确保提供更准确和可靠的答案。 实际应用范围涵盖企业搜索、客户支持、法律研究和个性化推荐。
结论
总结来说,检索增强生成(RAG)通过将大型语言模型与外部、最新的数据源连接,解决了其静态知识的核心限制。该过程首先检索相关信息片段,然后增强用户的提示,使LLM能够生成更准确和具有情境意识的响应。这得益于诸如嵌入、语义搜索和向量数据库等基础技术,它们通过意义而非仅仅关键词来查找信息。通过将输出建立在可验证的数据之上,RAG显著减少了事实错误,并允许使用专有信息,通过引用增强信任。
一个高级的进化,智能体RAG,引入了一个推理层,该层能够主动验证、调和和综合检索到的知识,从而进一步增强可靠性。同样,像GraphRAG这样的专门方法利用知识图来导航明确的数据关系,使系统能够综合回答高度复杂、相互关联的查询。这个智能体可以解决冲突信息,执行多步查询,并使用外部工具查找缺失数据。虽然这些高级方法增加了复杂性和延迟,但它们极大地提高了最终响应的深度和可信度。这些模式的实际应用正在改变各个行业,从企业搜索和客户支持到个性化内容交付。尽管存在挑战,但RAG是使AI更加知识渊博、可靠和有用的关键模式。最终,它将LLM从闭卷的对话者转变为强大的开卷推理工具。