一、什么是 RAG?

RAG(检索增强生成),顾名思义,是一种将检索(Retrieval) 与生成(Generation) 两种能力结合的 AI 系统架构。它的核心思想可以类比为“开卷考试”:当一个大型语言模型(LLM)需要回答一个具体、可能超出其训练数据时效或专有领域的问题时,它不再完全依赖自己“死记硬背”的参数知识(即“闭卷考试”),而是先从一个可靠、可更新的知识库中“查阅”相关资料,然后基于这些资料进行回答生成。

这种“先检索,后生成”的模式,让 AI 的回答得以建立在实时、准确的事实基础上,有效缓解了纯生成模型固有的幻觉(Hallucination) 问题。例如,当被问及“昨天发布的某公司最新财报关键数据”时,一个未更新知识的 LLM 可能会编造答案,而 RAG 系统会首先从最新的新闻或财报 PDF 中检索出相关段落,然后生成准确摘要。

二、为什么需要 RAG?解决 LLM 的哪些痛点?

纯粹的 LLM 虽然强大,但存在几个关键缺陷,而 RAG 正是针对这些痛点的良方。

  1. 知识时效性差:LLM 的知识被冻结在其训练数据截止的时间点,无法获取最新信息。RAG 的外部知识库可以随时更新。
  2. 专业领域知识不足:通用 LLM 在特定垂直领域(如医疗、法律、金融)的专业知识深度有限。通过检索该领域的内部文档,RAG 能快速赋予模型专家级知识。
  3. 幻觉问题:LLM 有时会“一本正经地胡说八道”。RAG 要求模型的回答必须基于检索到的真实文档,提供了可追溯的答案来源,大幅提升了可靠性。
  4. 无法访问私有数据:企业或个人的私有数据(如内部文档、聊天记录)不可能作为公开训练数据。RAG 允许模型安全、可控地“接触”这些私有数据,而不必将数据上传或用于微调。
关键提示:RAG 的核心价值在于 “可控性”与“可更新性”。它将模型的知识获取与生成能力解耦,使得知识管理变得独立且灵活。

三、RAG 的核心组件与工作流程

一个典型的 RAG 系统包含三个核心组件,其工作流程也是一个清晰的管道。

基本流程如下:

  1. 索引阶段:离线进行,将文档分块、向量化并存入数据库。
  2. 检索阶段:在线进行,处理用户查询,检索相关上下文。
  3. 生成阶段:在线进行,合成提示词,LLM 生成回答。

四、动手实践:一个简单的 RAG 检索流程

下面我们用 Python 代码片段来演示 RAG 中最关键的一环——检索。这里我们使用 sentence-transformers 进行文本向量化,并用 FAISS 进行高效向量检索。

from sentence_transformers import SentenceTransformer
import faiss
import numpy as np

# 1. 准备知识库(示例为几个句子)
documents = [
    "RAG 代表检索增强生成,是一种结合外部知识的大模型应用范式。",
    "向量数据库能够高效存储和检索文本的向量表示。",
    "提示工程对于引导 LLM 基于给定上下文生成回答至关重要。",
    "气候变化是全球面临的主要环境挑战之一。" # 一个不相关的例子
]

# 2. 加载模型并编码文档
model = SentenceTransformer('paraphrase-multilingual-MiniLM-L12-v2') # 一个多语言嵌入模型
doc_embeddings = model.encode(documents)

# 3. 构建 FAISS 索引
dimension = doc_embeddings.shape[1]
index = faiss.IndexFlatL2(dimension) # 使用 L2 距离(等效于余弦相似度归一化后)
index.add(np.array(doc_embeddings).astype('float32'))

# 4. 处理用户查询
query = "什么是 RAG?"
query_embedding = model.encode([query])

# 5. 检索 Top-K 相关文档
k = 2
distances, indices = index.search(np.array(query_embedding).astype('float32'), k)

print(f"查询: {query}")
print(f"检索到的相关文档(Top {k}):")
for i, idx in enumerate(indices[0]):
    print(f"  [{i+1}] (距离: {distances[0][i]:.4f}) {documents[idx]}")

# 6. 将检索到的上下文交由生成器(此处模拟)
retrieved_context = "\n".join([documents[idx] for idx in indices[0]])
prompt_template = f"基于以下信息:\n{retrieved_context}\n\n请回答:{query}"
print(f"\n组装后的提示词:\n{prompt_template}")

运行上述代码,你会看到系统正确地将关于 RAG 和向量数据库的句子检索出来,而过滤了不相关的“气候变化”句。这个 prompt_template 就是接下来送给 LLM 的“考卷”。

实践提示:在实际项目中,文档需要经过分块(Chunking) 处理。分块策略(如按固定字符数、按语义段落)会显著影响检索效果。块太大,主题不聚焦;块太小,可能丢失上下文。

五、优化方向与个人心得

构建一个生产级的 RAG 系统远不止上述示例那么简单。优化是多维度的:

从我的经验来看,RAG 是一个典型的“垃圾进,垃圾出”的系统。知识库的质量与预处理是成功的基础。清晰、结构化、干净的源数据,配合精心设计的分块策略,其重要性往往超过后期对检索或生成模型的微调。此外,RAG 让 AI 应用具备了可解释性——你可以向用户展示答案是基于哪些具体文档生成的,这在金融、医疗等严肃场景中至关重要。