1. RAG技术概述:让大模型学会"查资料再回答"
去年第一次用ChatGPT回答专业问题时,发现它经常一本正经地胡说八道。直到接触RAG(Retrieval-Augmented Generation)技术,才明白让AI"先查资料再回答"有多重要。这就像教实习生工作——不给参考资料直接提问,得到的答案往往似是而非;但提供手册后再问,回答质量立马上个台阶。
RAG的核心流程分三步走:
- 知识库准备:将文档拆分成片段,转化为向量存入数据库
- 实时检索:根据问题查找最相关的文本片段
- 生成回答:将检索结果作为上下文喂给大模型
实测下来,这种方案比直接微调模型成本低得多,且能随时更新知识库。最近帮某医疗客户搭建的问答系统,用RAG后准确率从63%提升到89%,关键是不需要重新训练模型。
2. 文本拆分:RAG的"食材预处理"
2.1 拆分策略比想象中重要
刚开始用RAG时,我简单按固定300字拆分PDF文档,结果效果奇差。后来才明白,文本拆分就像切菜——切太大块不入味,切太碎就成渣了。经过多次实验,总结出这些经验:
- 技术文档:按章节划分,保留完整代码块(用LangChain的RecursiveCharacterTextSplitter)
- 会议纪要:按议题分段,保持话题连贯性
- 研究论文:摘要单独处理,方法/结果/讨论分别拆分
python复制from langchain.text_splitter import RecursiveCharacterTextSplitter
text_splitter = RecursiveCharacterTextSplitter(
chunk_size=500,
chunk_overlap=50,
separators=["\n\n", "\n", "。", "!", "?"]
)
2.2 那些年踩过的坑
- 丢失表格数据:早期方案直接把表格转文本,损失了结构化信息。现在改用Markdown格式保留表格
- 代码片段断裂:没设置
keep_separator=True导致Python函数被腰斩 - 上下文断层:重叠设置(chunk_overlap)太小,使得关键信息被割裂
重要提示:中文建议用句号作为分隔符,英文文档建议增加分号。实际效果要用检索测试验证,我通常会准备20个测试问题来评估不同拆分方案。
3. 向量数据库选型实战
3.1 FAISS vs Milvus深度对比
去年同时测试了三种主流方案,这里分享实测数据:
| 特性 | FAISS | Milvus单机版 | Qdrant |
|---|---|---|---|
| 安装难度 | ⭐️⭐️⭐️⭐️⭐️ (pip安装) | ⭐️⭐️⭐️ (需要Docker) | ⭐️⭐️⭐️⭐️ (Rust编译) |
| 百万向量搜索速度 | 120ms | 90ms | 110ms |
| 内存占用 | 1.2GB | 2.3GB | 1.8GB |
| 支持算法 | 全量算法 | 部分算法需插件 | HNSW优化版 |
| 生产部署 | 需自行封装 | 开箱即用 | 云服务友好 |
个人选择建议:
- 快速验证用FAISS:
pip install faiss-cpu五分钟就能跑起来 - 生产环境用Milvus:自带高可用和RBAC,省去很多运维工作
- 云原生场景选Qdrant:K8s部署特别顺滑
3.2 Milvus本地安装避坑指南
在Windows装Milvus时遇到的坑够写本书:
- Docker Desktop内存分配:默认2GB根本不够,至少调4GB(设置→Resources)
- 端口冲突:19530/9091端口常被占,用
netstat -ano查杀进程 - 镜像拉取慢:换国内源
registry-mirrors配置加速
bash复制# 正确的启动命令(单机版)
docker run -d --name milvus \
-p 19530:19530 \
-p 9091:9091 \
-v ~/milvus/db:/var/lib/milvus/db \
-v ~/milvus/conf:/var/lib/milvus/conf \
milvusdb/milvus:v2.3.3
4. 相似性搜索的玄学调优
4.1 向量化模型选择
测试过6种主流模型后的结论:
- 通用场景:all-MiniLM-L6-v2(平衡速度与质量)
- 中文优先:paraphrase-multilingual-MiniLM-L12-v2
- 专业领域:先用领域数据微调模型(医学/法律等)
python复制# 用SentenceTransformers生成向量
from sentence_transformers import SentenceTransformer
model = SentenceTransformer('all-MiniLM-L6-v2')
embeddings = model.encode(["文本示例"], convert_to_tensor=True)
4.2 搜索参数实战心得
- top_k设置:不是越大越好!通常3-5个结果足够,太多反而引入噪声
- 相似度阈值:建议0.65-0.75区间过滤低质量结果
- 混合搜索:结合关键词过滤(如时间范围)效果提升明显
python复制# FAISS混合搜索示例
D, I = index.search(embedding, k=5)
results = [docstore[i] for i in I[0] if D[0][i] > 0.7]
5. 生产环境落地经验
5.1 性能优化三板斧
- 批量处理:攒够50条查询再批量搜索,吞吐量提升8倍
- 缓存热点:用Redis缓存高频问题的检索结果
- 异步更新:知识库更新走消息队列,避免阻塞查询
5.2 监控指标清单
- 检索延迟P99:<200ms
- 缓存命中率:>60%
- 结果相关性:人工评估每月抽样
最近用Flask+Milvus搭建的客服系统,在8核16G服务器上支撑了日均20万次查询。关键配置:
- 向量维度:384
- 分片数:4
- 索引类型:IVF_FLAT
6. 进阶技巧:Agentic RAG实践
传统RAG只是被动检索,而新型Agentic RAG会:
- 自动改写查询(比如扩展同义词)
- 多步检索验证
- 结果可信度评估
python复制# 查询改写示例
def expand_query(query):
synonyms = {"价格": ["价位", "多少钱", "费用"]}
for k, v in synonyms.items():
query = query.replace(k, f"({k} OR {' OR '.join(v)})")
return query
这种方案在金融领域问答中,使准确率再提升15%,但延迟会增加30-50ms。需要根据场景权衡。
