LLMs 在生成类人文本方面展现出强大能力。然而,它们的知识库通常受限于训练所用的数据,无法获取实时信息、特定公司的数据或高度专业化的细节。知识检索(RAG,Retrieval Augmented Generation,检索增强生成)针对这一限制提供了解决方案。RAG 使 LLMs 能够访问并整合外部、最新且与上下文相关的信息,从而提升其输出的准确性、相关性和事实依据。
对于智能体而言,这一点至关重要,因为它使其能够将行动和回复建立在超越静态训练的实时、可验证数据之上。借助这一能力,它们能够准确执行复杂任务,例如访问最新的公司政策以回答特定问题,或在下单前检查当前库存。通过整合外部知识,RAG 将智能体从简单的对话者转变为能够执行有意义工作的高效、数据驱动工具。
概览
知识检索(RAG)模式通过在生成回答之前为 LLMs 提供对外部知识库的访问,显著增强了其能力。RAG 不是仅依赖其内部的预训练知识,而是允许 LLMs “查找”信息,就像人类会查阅书籍或搜索互联网一样。这个过程使 LLMs 能够提供更准确、最新且可验证的答案。
当用户向使用 RAG 的 AI 系统提出问题或给出提示时,查询并不会直接发送给 LLM。相反,系统首先会在庞大的外部知识库——高度组织化的文档库、数据库或网页集合——中搜索相关信息。此搜索并非简单的关键词匹配,而是能理解用户意图和语义的“语义搜索”。这一步会提取最相关的信息片段或“块”。随后,这些提取的内容会被“增强”到原始提示中,形成更丰富、更有信息量的查询。最后,这个增强后的提示被发送给 LLM。借助这些额外上下文,LLM 能够生成不仅流畅自然,而且在检索数据基础上事实扎实的回答。
RAG 框架带来多项重要益处。它使 LLMs 能够访问最新信息,从而克服其静态训练数据的限制。这种方法还通过将回答建立在可验证数据之上,降低了“幻觉”(生成错误信息)的风险。此外,LLMs 还能利用内部公司文档或 wiki 中的专业知识。此过程的一个关键优势是能够提供“引文”,精确定位信息来源,从而提升 AI 回答的可信度和可验证性。
要充分理解 RAG 的工作原理,需要掌握几个核心概念(见图 1):
嵌入(Embeddings): 在 LLMs 的语境下,嵌入是对文本(如单词、短语或整篇文档)的数值表示。这些表示以向量的形式存在,即一个数字列表。其核心思想是在数学空间中捕捉文本的语义含义以及不同文本片段之间的关系。含义相似的单词或短语在该向量空间中的嵌入彼此更接近。举例来说,想象一个简单的二维坐标图。单词“cat”可能用坐标 (2, 3) 表示,而“kitten”会非常接近,比如 (2.1, 3.1)。相反,“car”可能是像 (8, 1) 这样较远的坐标,反映其不同的含义。实际上,这些嵌入位于维度更高的空间中,可能有数百甚至数千个维度,从而能够非常细腻地理解语言。
文本相似度(Text Similarity): 文本相似度是指衡量两段文本相似程度的指标。它可以停留在表层,考察词语重叠(词汇相似度),也可以深入到基于含义的层面。在 RAG 的语境中,文本相似度对于在知识库中找到与用户查询最相关的信息至关重要。比如,句子“What is the capital of France?”和“Which city is the capital of France?”虽然措辞不同,但提出的是同一个问题。一个优秀的文本相似度模型会识别出这一点,即使两者只有少量词语相同,也会为这两个句子分配较高的相似度分数。这通常是通过对文本的嵌入进行计算实现的。
语义相似度与距离(Semantic Similarity and Distance): 语义相似度是一种更高级的文本相似度,纯粹关注文本的含义与上下文,而不仅仅是所用词语。它旨在判断两段文本是否表达了相同的概念或想法。语义距离则与此相反;高语义相似度意味着低语义距离,反之亦然。在 RAG 中,语义搜索依赖于寻找与用户查询语义距离最小的文档。例如,“a furry feline companion”和“a domestic cat”除了“a”之外没有共同词汇。然而,理解语义相似度的模型会识别它们指的是同一事物,并将其视为高度相似。这是因为它们在向量空间中的嵌入彼此非常接近,表明语义距离很小。这种“智能搜索”使 RAG 即使在用户的措辞与知识库中的文本不完全匹配时,也能找到相关信息。
图 1:RAG 核心概念:分块、嵌入与向量数据库
文档分块(Chunking of Documents): 分块是将大型文档拆分为更小、更易管理的片段(“chunks”)的过程。为了让 RAG 系统高效工作,它无法将整篇大型文档直接输入 LLM,而是处理这些更小的块。文档如何分块对于保留信息的上下文和含义非常重要。比如,不把一本 50 页的用户手册视为一个整体文本块,而是根据章节、段落甚至句子进行拆分。例如,“Troubleshooting(故障排除)”部分会作为与“Installation Guide(安装指南)”不同的独立块。当用户询问某个具体问题时,RAG 系统就能检索到最相关的故障排除块,而不是整个手册。这样使检索过程更快,并让提供给 LLM 的信息更聚焦、更贴合用户的即时需求。文档分块完成后,RAG 系统必须采用检索技术来为特定查询找到最相关的片段。主要方法是向量搜索,它使用嵌入与语义距离来寻找与用户问题在概念上相似的块。一个较早但仍有价值的技术是 BM25,这是一种基于关键词的算法,根据词项频率对块进行排序,而不理解语义含义。为了兼顾两者,通常使用混合搜索方法,将 BM25 的关键词精确性与语义搜索的上下文理解相结合。这种融合能够实现更健壮、更准确的检索,同时捕捉到字面匹配与概念相关性。
向量数据库(Vector databases): 向量数据库是一种专门用于高效存储和查询嵌入的数据库。文档在分块并转换为嵌入之后,这些高维向量会存储在向量数据库中。传统的检索技术,如基于关键词的搜索,擅长找到包含查询中精确词汇的文档,但缺乏对语言的深层理解。它们无法识别“furry feline companion”意味着“cat”。这正是向量数据库的优势所在。它们专为语义搜索而构建。通过将文本存储为数值向量,向量数据库可以基于概念含义而不仅仅是关键词重合来找到结果。当用户的查询也被转换为向量后,数据库会使用高度优化的算法(如 HNSW——Hierarchical Navigable Small World)在数百万个向量中快速搜索,找到在含义上“最接近”的那些。对于 RAG 来说,这种方法优越得多,因为它能发现相关上下文,即使用户的表述与源文档完全不同。本质上,其他技术在搜索词语,而向量数据库在搜索含义。该技术以多种形式实现,从托管数据库如 Pinecone 和 Weaviate,到开源解决方案如 Chroma DB、Milvus 和 Qdrant。甚至现有数据库也可以通过添加向量搜索能力来增强,如 Redis、Elasticsearch 和 Postgres(使用 pgvector 扩展)。核心检索机制通常由 Meta AI 的 FAISS 或 Google Research 的 ScaNN 等库驱动,这些库是这些系统高效性的基础。
RAG 的挑战: 尽管强大,RAG 模式并非没有挑战。一个主要问题在于,当回答查询所需的信息并不局限于单一块,而是分散在文档的多个部分甚至多个文档中时,检索器可能无法收集所有必要的上下文,从而导致答案不完整或不准确。系统的有效性还高度依赖于分块和检索过程的质量;如果检索到不相关的块,会引入噪音并干扰 LLM。此外,从潜在相互矛盾的来源中有效综合信息,仍然是此类系统面临的一大难题。除此之外,另一个挑战是 RAG 需要对整个知识库进行预处理,并存储在专用数据库(如向量或图数据库)中,这是一项相当大的工程。因此,这些知识需要定期对齐更新,以保持最新,这在处理公司 wiki 等不断变化的来源时尤为关键。整个过程会对性能产生显著影响,增加延迟、运营成本以及最终提示中使用的 token 数量。
总而言之,检索增强生成(RAG)模式在提升 AI 的知识性和可靠性方面迈出了重要一步。通过将外部知识检索步骤无缝集成到生成过程中,RAG 解决了独立 LLMs 的一些核心局限。以嵌入与语义相似度为基础,结合关键词与混合搜索等检索技术,使系统能够智能地找到相关信息,并通过策略性分块加以管理。整个检索过程由专用的向量数据库驱动,这些数据库被设计用于在大规模下存储并高效查询数以百万计的嵌入。尽管在检索碎片化或相互矛盾的信息方面仍存挑战,RAG 使 LLMs 能够生成不仅在语境上恰当、且以可验证事实为基础的答案,从而提升了 AI 的可信度与实用性。
Graph RAG: GraphRAG 是一种高级的检索增强生成形式,它利用知识图谱而非简单的向量数据库来进行信息检索。它通过在这一结构化知识库中导航数据实体(节点)之间的显式关系(边)来回答复杂查询。一个关键优势是它能够从分散在多个文档中的信息中综合答案,这是传统 RAG 常见的短板。通过理解这些连接关系,GraphRAG 能提供更符合语境且更细腻的响应。
应用场景包括复杂的金融分析、将公司与市场事件关联,以及用于发现基因与疾病关系的科学研究。然而,其主要缺点是构建与维护高质量知识图谱所需的巨大复杂度、成本和专业能力。该方案的灵活性也较低,且相比更简单的向量搜索系统可能引入更高的延迟。系统的有效性完全取决于底层图结构的质量与完整性。因此,GraphRAG 在实现复杂问题的卓越上下文推理方面表现出色,但实施与维护成本也高得多。总之,当对深度、互联的洞见需求高于标准 RAG 的速度与简洁性时,它更能发挥优势。
Agentic RAG: 这一模式的演进版本称为 Agentic RAG(见图 2),引入了一个推理与决策层,以显著提升信息提取的可靠性。与其仅仅检索与增强,一个“agent”(智能体)——一种专门的 AI 组件——充当关键的把关者与知识精炼器。该智能体不会被动接受初始检索到的数据,而是会主动审视其质量、相关性与完整性,正如下述场景所示。
首先,智能体擅长反思与来源验证。如果用户问:“What is our company's policy on remote work?”,标准 RAG 可能会同时检索到 2020 年的一篇博客文章和官方的 2025 年政策文件。而智能体会分析文档的元数据,识别 2025 年的政策是最新且最权威的来源,并在将正确的上下文发送给 LLM 以生成精确答案之前,丢弃过时的博客文章。
图 2:Agentic RAG 引入了一个具备推理能力的智能体,用于主动评估、协调并完善检索到的信息,以确保更准确且更可信的最终回答。
第二,智能体擅长调和知识冲突。设想一位财务分析师问:“Project Alpha 的第一季度预算是多少?”系统检索到两份文档:初步方案写着预算为 €50,000,而最终财务报告则列为 €65,000。Agentic RAG 会识别出这一矛盾,优先将财务报告视为更可靠的来源,并向 LLM 提供经核实的数字,确保最终答案基于最准确的数据。
第三,智能体可以进行多步推理以综合复杂答案。若用户询问:“我们的产品功能和定价与 Competitor X 相比如何?”智能体会将其分解为独立的子查询。它会分别搜索自身产品的功能、自身产品的定价、Competitor X 的功能以及 Competitor X 的定价。在收集到这些独立信息后,智能体会将其综合为结构化的对比性上下文,再提供给 LLM,从而生成简单检索无法产生的全面回答。
第四,智能体可以识别知识空白并使用外部工具。假设用户问:“市场对我们昨天发布的新产品的即时反应如何?”智能体搜索每周更新的内部知识库,未找到相关信息。识别到这一缺口后,它可以调用工具——例如实时网页搜索 API——查找最新的新闻报道和社交媒体情绪。随后,智能体利用这批新获取的外部信息提供分秒不差的回答,从而克服静态内部数据库的局限。
Agentic RAG 的挑战: 尽管强大,智能体层也带来了自身的一系列挑战。主要缺点是复杂性与成本显著增加。设计、实现与维护智能体的决策逻辑及工具集成需要大量工程投入,并增加计算开销。这种复杂性还可能导致更高的延迟,因为智能体的反思、工具使用与多步推理循环比标准的直接检索耗时更多。此外,智能体本身也可能成为新的错误来源;有缺陷的推理过程可能使其陷入无用的循环、误解任务,或不当丢弃相关信息,最终降低最终回答的质量。
总之: Agentic RAG 代表了标准检索模式的复杂进化,将其从被动的数据管道转变为主动的、解决问题的框架。通过嵌入一个能够评估来源、调和冲突、分解复杂问题并使用外部工具的推理层,智能体显著提升了生成答案的可靠性与深度。这一进步让 AI 更加可信与强大,但也带来了系统复杂性、延迟与成本上的重要权衡,需谨慎管理。
实际应用与使用场景
知识检索(RAG)正在改变大型语言模型(LLMs)在各行业中的使用方式,增强其提供更准确且与上下文更相关回答的能力。
- 企业搜索与问答: 组织可以开发内部聊天机器人,基于内部文档(如人力资源政策、技术手册和产品规格)回答员工问题。RAG 系统从这些文档中提取相关段落,以辅助 LLM 的回答。
- 客户支持与服务台: 基于 RAG 的系统可通过访问产品手册、常见问题(FAQ)和支持工单,为客户查询提供精准且一致的回应。这样可以减少在常规问题上对人工干预的需求。
- 个性化内容推荐: RAG 不仅依赖基础的关键词匹配,还能识别并检索与用户偏好或过往互动在语义上相关的内容(文章、产品),从而提供更相关的推荐。
- 新闻与时事摘要: LLMs 可与实时新闻源集成。当被询问当前事件时,RAG 系统会检索最新文章,使 LLM 能够生成最新的摘要。
通过引入外部知识,RAG 将 LLMs 的能力从简单交流扩展为知识处理系统。
实战代码示例(ADK)
为说明知识检索(RAG)模式,我们来看三个示例。
首先,是如何使用 Google Search 来执行 RAG,并将 LLMs 与搜索结果对齐。由于 RAG 涉及访问外部信息,Google Search 工具是内置检索机制的直接示例,可用于增强 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 Corpus 的连接。通过指定语料库资源名称以及可选参数(如 SIMILARITY_TOP_K 和 VECTOR_DISTANCE_THRESHOLD)来配置该服务。这些参数会影响检索过程:SIMILARITY_TOP_K 定义要检索的相似结果数量;VECTOR_DISTANCE_THRESHOLD 为检索结果设定语义距离上限。此设置使智能体能够从指定的 RAG Corpus 执行可扩展且持久的语义知识检索。该过程有效地将 Google Cloud 的 RAG 功能集成进 ADK Agent,从而支持基于事实数据生成响应。
# 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)
# Add nodes
workflow.add_node("retrieve", retrieve_documents_node)
workflow.add_node("generate", generate_response_node)
# Set the entry point
workflow.set_entry_point("retrieve")
# Add edges (transitions)
workflow.add_edge("retrieve", "generate")
workflow.add_edge("generate", END)
# Compile the graph
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 流水线执行查询,展示了系统生成上下文相关输出的能力。
回顾
是什么(What)
LLMs 具有令人印象深刻的文本生成能力,但从根本上受限于其训练数据。这些知识是静态的,不包含实时信息或私有、特定领域的数据。因此,其回答可能过时、不准确,或缺乏专门任务所需的特定上下文。这一缺口限制了其在需要最新且基于事实答案的应用中的可靠性。
为什么(Why)
检索增强生成(RAG)模式通过将 LLMs 连接到外部知识源提供了标准化解决方案。当接收到查询时,系统首先从指定知识库检索相关的信息片段,然后将这些片段附加到原始提示中,以及时且具体的上下文进行丰富。这个增强后的提示被发送给 LLM,使其能够生成准确、可验证并以外部数据为依据的响应。此过程有效地将 LLM 从“闭卷”推理者转变为“开卷”推理者,大幅提升其实用性和可信度。
经验法则(Rule of Thumb)
当你需要 LLM 基于其原始训练数据之外的特定、最新或专有信息来回答问题或生成内容时,使用该模式。它非常适合构建覆盖内部文档的问答系统、客户支持机器人,以及需要带引用的可验证、基于事实的响应的应用。
图示摘要
知识检索模式:由一个智能体从结构化数据库中查询并检索信息
知识检索模式:一个智能体根据用户查询从公共互联网中查找并综合信息。
关键点
- 知识检索(RAG)通过让 LLMs 访问外部、最新且特定的信息来增强其能力。
- 该过程包括检索(在知识库中搜索相关片段)和增强(将这些片段添加到 LLM 的提示中)。
- RAG 帮助 LLMs 克服诸如训练数据过时等限制,减少“幻觉”,并实现领域特定知识的集成。
- RAG 使答案可追溯,因为 LLM 的响应以检索到的来源为依据。
- GraphRAG 利用知识图谱来理解不同信息片段之间的关系,使其能够回答需要综合多个来源数据的复杂问题。
- Agentic RAG 超越了简单的信息检索,通过使用智能体主动推理、验证和完善外部知识,确保答案更加准确和可靠。
- 实际应用涵盖企业搜索、客户支持、法律研究以及个性化推荐等。
总结
总之,检索增强生成(RAG)通过连接外部、最新的数据源,解决了大型语言模型静态知识的核心局限。该过程先检索相关信息片段,再增强用户提示,使 LLM 能生成更准确、具备上下文意识的响应。这依赖于嵌入、语义搜索和向量数据库等基础技术,它们基于语义而非仅仅关键词来发现信息。通过将输出建立在可验证数据之上,RAG 大幅降低事实性错误,并允许使用专有信息,通过引用增强信任。
一种先进演进形式 Agentic RAG,引入了一个推理层,主动验证、调和并综合检索到的知识,以获得更高的可靠性。类似地,GraphRAG 等专门方法利用知识图谱来导航显式的数据关系,使系统能够综合回答高度复杂、相互关联的查询。该智能体可以解决相互冲突的信息,执行多步查询,并使用外部工具查找缺失数据。尽管这些先进方法增加了复杂性和延迟,但它们极大地提升了最终响应的深度与可信度。这些模式的实际应用已在改变各行各业,从企业搜索、客户支持到个性化内容分发。尽管存在挑战,RAG 是让 AI 更加博学、可靠且有用的关键模式。最终,它将 LLMs 从“闭卷”对话者转变为强大的“开卷”推理工具。
参考资料
- Lewis, P., et al. (2020). Retrieval-Augmented Generation for Knowledge-Intensive NLP Tasks. arxiv.org/abs/2005.11…
- Google AI for Developers Documentation. Retrieval Augmented Generation - cloud.google.com/vertex-ai/g…
- Retrieval-Augmented Generation with Graphs (GraphRAG), arxiv.org/abs/2501.00…
- LangChain and LangGraph: Leonie Monigatti, "Retrieval-Augmented Generation (RAG): From Theory to LangChain Implementation," medium.com/data-scienc…
- Google Cloud Vertex AI RAG Corpus cloud.google.com/vertex-ai/g…