RAG 检索增强生成入门
为什么需要 RAG
LLM 的知识有限:
- 训练数据截止日期之前的知识
- 不知道你的私有数据(公司文档、代码库)
- 无法实时更新
RAG 解决方案:把相关文档检索出来,放入提示词,让 LLM 基于文档回答。
RAG 工作流程
用户提问
↓
将问题转为向量(Embedding)
↓
在向量数据库中检索相似文档
↓
将检索到的文档 + 问题发给 LLM
↓
LLM 基于文档生成回答
向量数据库选型
| 数据库 | 类型 | 特点 | 适合 |
|---|---|---|---|
| Pinecone | 云服务 | 托管,易用 | 快速上手 |
| Weaviate | 开源 | 功能强大 | 自部署 |
| Chroma | 开源 | 轻量,嵌入式 | 本地开发 |
| pgvector | PostgreSQL 扩展 | 复用现有 DB | 已有 PG |
文档切分策略
文档太长无法全部放入提示词,需要切分成小块(Chunk)。
| 策略 | 适合 | Chunk 大小 |
|---|---|---|
| 固定长度 | 通用文本 | 500-1000 字 |
| 按段落 | 结构化文档 | 变长 |
| 按语义 | 技术文档 | 变长 |
| 重叠切分 | 避免断句 | 重叠 50-100 字 |
Embedding 模型选择
| 模型 | 维度 | 语言 | 成本 |
|---|---|---|---|
| OpenAI text-embedding-3-small | 1536 | 多语言 | $0.02/1M tokens |
| OpenAI text-embedding-3-large | 3072 | 多语言 | $0.13/1M tokens |
| Cohere embed-multilingual-v3 | 1024 | 多语言 | $0.10/1M tokens |
简单 RAG 示例(Python)
import chromadb
from openai import OpenAI
# 初始化
chroma_client = chromadb.Client()
collection = chroma_client.create_collection("docs")
openai_client = OpenAI()
# 1. 索引文档
documents = [
"Inkess 是一个 AI API 代理服务,支持 Claude、GPT 等模型。",
"Inkess 的价格低于官方定价,按量计费。",
"Inkess 支持 Anthropic SDK 和 OpenAI SDK。"
]
collection.add(
documents=documents,
ids=[f"doc{i}" for i in range(len(documents))]
)
# 2. 检索 + 生成
def rag_query(question: str) -> str:
# 检索相关文档
results = collection.query(
query_texts=[question],
n_results=2
)
context = "\n".join(results["documents"][0])
# 生成回答
response = openai_client.chat.completions.create(
model="gpt-4o",
messages=[
{"role": "system", "content": "根据以下文档回答问题。"},
{"role": "user", "content": f"文档:\n{context}\n\n问题:{question}"}
]
)
return response.choices[0].message.content
# 使用
print(rag_query("Inkess 支持哪些 SDK?"))
检索优化
1. Hybrid Search(混合检索)
结合关键词检索(BM25)和向量检索:
最终得分 = 0.7 × 向量相似度 + 0.3 × BM25 得分
2. Reranking(重排序)
检索出 Top 20,用更强的模型重新排序,取 Top 5。
3. Query Expansion(查询扩展)
用 LLM 生成问题的多个变体,分别检索后合并结果。
评估指标
| 指标 | 含义 | 目标 |
|---|---|---|
| Recall@K | 前 K 个结果中包含正确答案的比例 | >0.9 |
| MRR | 正确答案的平均排名倒数 | >0.8 |
| Answer Accuracy | 最终回答的准确性 | >0.85 |