什么是RAG?
RAG(Retrieval-Augmented Generation,检索增强生成)是一种将外部知识检索与大语言模型生成结合的技术架构。简单说,就是在回答问题之前,先从知识库里找到相关内容,再把它"塞"给模型作为参考,让模型基于事实生成答案。
为什么RAG比直接问模型更靠谱?
直接问大模型存在三大硬伤:
- 知识截止日期:模型的训练数据有时间边界,GPT-4的知识截止于某年,它不知道昨天发生了什么。
- 私有数据无法访问:你公司的内部文档、产品手册、客户合同,模型根本没见过。
- 幻觉问题:模型为了"看起来像在回答",会编造听起来合理但实际错误的内容,危害极大。
RAG通过在回答前注入真实检索内容,从根源上缓解这三个问题——模型只需基于给定的上下文进行归纳,而不是凭记忆"猜"。
RAG完整流程
RAG分为两个阶段:索引阶段(离线)和查询阶段(在线)。
流程图(ASCII版)
【索引阶段(离线)】
原始文档(PDF/Word/网页)
│
▼
文档切分(Chunking)
│
▼
Embedding模型 → 向量表示
│
▼
写入向量数据库(持久化)
【查询阶段(在线)】
用户提问 (Query)
│
▼
Query → Embedding模型 → 查询向量
│
▼
向量数据库相似度检索 → Top-K个相关片段
│
▼
上下文拼接(System Prompt + 检索片段 + 用户问题)
│
▼
大语言模型生成 → 最终答案
最小实现代码(Python)
以下是一个用 openai + chromadb 实现的最小RAG系统:
import chromadb
from openai import OpenAI
client = OpenAI()
chroma = chromadb.Client()
collection = chroma.create_collection("my_docs")
# ===== 索引阶段 =====
documents = [
"Hermes Agent是由Nous Research开发的AI助手框架。",
"RAG技术通过检索外部知识来增强语言模型的回答质量。",
"向量数据库可以高效地进行语义相似度搜索。",
]
def get_embedding(text):
resp = client.embeddings.create(
model="text-embedding-3-small",
input=text
)
return resp.data[0].embedding
# 将文档写入向量库
for i, doc in enumerate(documents):
embedding = get_embedding(doc)
collection.add(
ids=[f"doc_{i}"],
embeddings=[embedding],
documents=[doc]
)
# ===== 查询阶段 =====
query = "什么是RAG技术?"
query_embedding = get_embedding(query)
# 检索最相关的2个片段
results = collection.query(
query_embeddings=[query_embedding],
n_results=2
)
retrieved_chunks = results["documents"][0]
# 拼接上下文
context = "\n".join(retrieved_chunks)
prompt = f"""请根据以下参考内容回答用户问题。
参考内容:
{context}
用户问题:{query}"""
# 调用LLM生成答案
response = client.chat.completions.create(
model="gpt-4o-mini",
messages=[{"role": "user", "content": prompt}]
)
print(response.choices[0].message.content)
RAG的核心挑战
RAG听起来简单,但工程实践中有很多坑:
- 检索质量决定上限:找不到相关内容,再好的模型也没用。检索是RAG的瓶颈。
- 上下文窗口限制:检索到的片段不能无限堆叠,需要权衡数量与质量。
- chunk边界问题:关键信息可能被切分开,导致单个chunk不完整。
- 多跳推理困难:需要综合多个片段才能回答的问题,简单RAG表现差。
小结
RAG是目前最实用的"让AI使用私有数据"方案。它的核心思路是:检索→增强→生成。后续章节将深入讲解每个环节的最佳实践,包括切分策略、Embedding选型、向量库选择、混合检索和Rerank。