RAG 系统实战:如何让大模型精准“背书”不胡说八道
前言:GPT 的一本正经胡说八道
大模型 (LLM) 有两个致命弱点:
- 知识截止:GPT-4 的训练数据截止到 2023 年,问它“昨天 QixYuan 博客更新了什么”,它只能瞎编。
- 幻觉 (Hallucination):问它“鲁迅和周树人打过架吗”,它能给你编出一段武侠小说。
为了解决这个问题,RAG (Retrieval-Augmented Generation,检索增强生成) 应运而生。
简单来说,就是在让 LLM 回答问题之前,先去我们的私有知识库里“翻书”,把翻到的相关内容贴给它,让它只根据这些内容回答。
今天,我们不谈 LangChain 的接口怎么调,我们要深挖 RAG 系统落地过程中遇到的真实痛点和优化方案。
1. 朴素 RAG 的架构
最简单的 RAG 流程如下:
- Indexing: 把 PDF/Wiki 切成小块 (Chunks),算出 Embedding 向量,存入向量数据库 (Vector DB)。
- Retrieval: 用户提问 -> 算 Question Embedding -> 去 Vector DB 搜 Top-3 相似的 Chunks。
- Generation: 拼接 Prompt:
"根据以下信息:[Chunks] 回答问题:[Question]"-> 扔给 LLM。
graph LR
User(User Query) --> Embed(Embedding Model)
Embed --> Search(Vector Search)
DB[(Vector DB)] -.-> Search
Search --> Prompt(Context Injection)
Prompt --> LLM(LLM)
LLM --> Answer(Final Answer)
代码实现可能只要 10 行。但当你把它上线后,你会发现效果烂得一塌糊涂。
2. 痛点一:切片 (Chunking) 的艺术
问题:如果切片太小,上下文丢失(比如代词 “它” 指代不明);如果切片太大,包含太多无关噪音,且容易撑爆 LLM 的窗口。
进阶策略:
- Recursive Character Splitter: 优先按
\n\n切,不行再按\n切,再按句号切。保证语义的完整性。 - Window Overlap: 每个切片之间保留 10-20% 的重叠,防止重要的句子不幸被切断在边缘。
- Semantic Chunking: 甚至可以用一个小模型先扫一遍,根据语义突变点来断句,而不是机械地按字符数切。
3. 痛点二:检索不精准 (Retrieval Failure)
问题:用户的提问和文档里的表达不一致。
提问:“Rust 怎么防止内存溢出?”
文档:“Ownership 机制通过编译期检查保证了内存安全性。”
这俩句子的 Embedding 距离可能很远,导致搜不到。
优化方案:
3.1 HyDE (Hypothetical Document Embeddings)
让 LLM 先“脑补”一个答案,然后拿这个“伪答案”去搜。
- 指令:
"请生成一段关于 Rust 内存安全的假想文档" - LLM 生成:
"Rust 使用所有权和借用规则来管理内存..." - 用生成的内容去搜,命中率大大提高。
3.2 Query Expansion / Multi-Query
用户问一句,我们让 LLM 改写成 3 句不同的问法,并行去搜,最后结果去重。
3.3 Hybrid Search (混合检索)
不要只信赖 Vector Search。
Vector 擅长语义模糊匹配,但 BM25 (关键词匹配) 擅长精确匹配(比如专有名词、型号)。
Hybrid Search = 0.7 * Vector_Score + 0.3 * BM25_Score。
再加一个 Re-ranker (重排序模型),用 Cross-Encoder 对 Top-50 进行精细打分,选出 Top-3。
4. 痛点三:Lost in the Middle
斯坦福的研究表明,LLM 对 Prompt 开头和结尾的信息印象最深,放在中间的信息容易被忽略。
如果检索回来的 Top-10 文档里,正确答案不幸夹在第 5 个,LLM 很有可能视而不见。
解决:在 Re-rank 之后,人为打乱顺序,把相关度最高的 chunks 放在 Prompt 的最开头和最末尾(U型分布)。
5. 项目实战:构建企业级 RAG
如果你想自己搭建一套,我推荐的技术栈:
- ETL:
Unstructured(处理 PDF/Excel 表格奇效)。 - Embedding:
BGE-M3(目前中文开源最强,支持多语言、长文本)。 - Vector DB:
Milvus(性能强,Go/Rust 编写) 或Qdrant(Rust 编写,轻量)。 - Orchestration:
LlamaIndex(比 LangChain 更专注于 RAG 的数据结构优化)。 - LLM:
Qwen-Max或DeepSeek-Coder(中文理解能力超越 GPT-3.5)。
6. 总结
RAG 看起来简单,由入门到放弃只需要一天。
但要把它调优到可用状态,需要对 NLP 的每一个环节进行精细的 Engineering。
Chunking strategy is the new Feature Engineering.
不要迷信大模型的能力,更多时候,数据的质量 决定了 RAG 的上限。