1. RAG技术:让大模型学会"查资料再回答"的底层逻辑
第一次接触RAG(Retrieval-Augmented Generation)时,我正为一个医疗问答项目头疼——大模型经常一本正经地胡说八道药品剂量。直到把最新医学指南存入向量数据库,让模型先检索再生成回答,准确率才从60%飙升到92%。这种"先查资料再作答"的机制,正是RAG的核心价值。
传统大模型依赖训练时"死记硬背"的知识,而RAG架构通过三个关键环节实现动态知识更新:
- 文本拆分:将PDF/网页等原始资料按语义切块(如每段300字)
- 向量化存储:使用text-embedding模型将文本转为高维向量存入数据库
- 检索增强:用户提问时,先检索最相关的5-10个文本块,连同问题一起喂给大模型
实测显示,加入检索环节后,模型在专业领域的幻觉率降低47%,尤其适合法律、医疗等容错率低的场景。去年我参与的金融风控项目,仅用3天就通过RAG接入了最新监管政策,而传统微调方案需要两周数据标注和训练。
需要模型API调用? 免费领10W Token,多模型网关一键接入 Claude、DeepSeek 等主流模型。
2. 文本拆分:RAG的第一道质量关卡
2.1 拆分策略的工程权衡
在电商客服知识库项目中,我们对比过三种拆分方式:
- 固定长度拆分:简单但可能切断语义
python复制from langchain.text_splitter import RecursiveCharacterTextSplitter
splitter = RecursiveCharacterTextSplitter(
chunk_size=300,
chunk_overlap=50 # 保留50字重叠避免断句
)
- 语义拆分:使用SentenceTransformers计算相似度分割,更精准但耗时
- 混合拆分:先按标题分大段,再对每段固定长度拆分(最终采用方案)
关键经验:医疗/法律文档建议用语义拆分,技术文档可用固定长度+重叠
2.2 参数调优实战记录
测试10份产品手册后发现:
- chunk_size=300:召回率89%,但部分长概念被切断
- chunk_size=500:召回率92%,但噪声增加
- 最终方案:动态调整(标题段落用500,技术参数用200)
常见踩坑:
- 中文需额外处理标点,特别是书名号《》内的内容
- PDF解析时注意保留表格结构(可用pdfplumber库)
- 代码片段需整体保留,避免拆分行号
3. 向量数据库选型:FAISS vs Milvus
3.1 性能基准测试数据
在8核CPU/32GB内存的测试机上:
| 指标 | FAISS(CPU) | Milvus(单机) | Qdrant |
|---|---|---|---|
| 10万条插入 | 12分钟 | 18分钟 | 15分钟 |
| 100次查询QPS | 83 | 67 | 72 |
| 准确率@10 | 0.91 | 0.89 | 0.93 |
3.2 生产环境选型建议
FAISS适合:
- 快速验证原型(pip install即可用)
- 中小数据集(<100万条)
- 无频繁更新需求(重建索引成本高)
Milvus优势:
- 支持动态增删(电商SKU实时更新场景)
- 分布式扩展(我们某个项目处理过20亿向量)
- 多向量检索(如同时搜索商品图和描述)
Windows开发机安装Milvus的避坑指南:
- 必须用Docker Desktop(直接安装包依赖问题多)
- 修改config/milvus.yaml中的内存限制(默认值太小)
- 首次插入前先创建collection并建立IVF_FLAT索引
4. 相似性搜索的工程细节
4.1 距离度量选型实验
测试三种距离计算方式对医疗问答的影响:
| 距离类型 | 症状匹配准确率 | 药品推荐准确率 |
|---|---|---|
| 余弦相似度 | 88% | 76% |
| 欧式距离 | 82% | 81% |
| 内积 | 85% | 79% |
最终采用加权方案:症状用余弦相似度(重语义),药品用欧式距离(重数值)
4.2 混合检索实战技巧
在金融风控项目中,我们结合:
- 关键词过滤:先筛出含"反洗钱"的文档
- 向量检索:在结果集中做相似度搜索
- 时间加权:给近3个月文档+20%权重
python复制# 使用LangChain实现混合检索
from langchain.retrievers import BM25Retriever, EnsembleRetriever
bm25_retriever = BM25Retriever.from_texts(texts)
faiss_retriever = FAISS.as_retriever()
ensemble_retriever = EnsembleRetriever(
retrievers=[bm25_retriever, faiss_retriever],
weights=[0.3, 0.7]
)
5. 生产级RAG系统避坑实录
5.1 性能优化四板斧
- 分层索引:热数据用HNSW,冷数据存IVF_FLAT(查询速度提升3倍)
- 缓存机制:对高频问题缓存检索结果(Redis存24小时)
- 异步更新:文档变更时先返回旧结果,后台重建索引
- 量化压缩:FP32转INT8后体积减少75%,精度损失<2%
5.2 典型故障排查记录
问题现象:突然返回无关内容
- 检查步骤:
- 确认embedding模型版本一致(曾因升级text2vec导致异常)
- 查看最近插入数据是否包含噪声(有次CSV解析错误混入乱码)
- 验证向量索引是否损坏(重建索引解决)
问题现象:检索超时
- 优化方案:
- 限制返回数量(从100条减到10条)
- 添加超时熔断(FastAPI设置timeout=3s)
- 对大数据集启用GPU加速(Faiss-gpu版)
6. 前沿扩展:Agentic RAG实践
最近在内部测试的增强版架构:
- 动态路由:简单问题直接回答,复杂问题触发检索
- 递归检索:首次结果不理想时自动调整查询词
- 结果验证:用另一个模型判断检索内容是否相关
实测在客服场景中,错误率比传统RAG再降40%。一个典型对话流:
code复制用户:打印机显示"墨盒错误"怎么办?
→ Agent判断需要检索
→ 自动生成查询词"HP 墨盒错误 解决方法"
→ 检索到3个相关文档
→ 验证文档相关性(剔除1条过时信息)
→ 生成最终回答
实现这个流程只需在LangChain上加装Agent:
python复制from langchain.agents import AgentExecutor, create_react_agent
agent = create_react_agent(llm, tools, prompt)
agent_executor = AgentExecutor(agent=agent, tools=tools)
这种架构特别适合处理多步骤问题,比如"对比iPhone15和三星S23的摄像头参数",系统会自动拆解子问题、分别检索、最后综合答案。
