最近在做优化的时候涉及到了这块内容,觉得值得写下来,方便以后翻阅。
目录
🍬前言
🍬三、 在线推理第一步:坑是如何被“拆解”的?(Query 拆解)
🍬结语
前言
随着大语言模型(LLM)的爆发式增长,幻觉坑、知识时效性以及数据安全壁垒成为了制约其落地的“三座大山”。检索增强生成(RAG, Retrieval-Augmented Generation)技术因其能外挂知识库、提供可解释的引用而成为目前企业级应用的主流架构。
许多开发者了解 RAG 是“检索 + 生成”,但面对一个复杂的用户提问,系统内部到底经历了怎样的数据流转?大模型在其中究竟是“翻译官”还是“大脑”?本文将绕过浅显的 Demo 级讲解,深入技术底层,详细剖析 RAG 系统的完整生命周期。
一、 RAG 系统全流程总览(宏观视角)
一个标准的 RAG 系统处理流程可以划分为 离线数据预处理 和 在线推理问答 两大阶段。
- 离线阶段(数据工程):原始文档 -> 数据清洗 -> 文档分块(Chunking)-> 向量化(Embedding)-> 构建索引(Vector Index)-> 存入向量数据库。
- 在线阶段(推理问答):用户输入问题 -> 问题分析与拆解 -> 向量检索召回 -> 重排序(Rerank)-> 上下文注入(Prompt Engineering)-> LLM 生成 -> 引用溯源与输出。
二、 离线预处理:决定 RAG 效果的上限
在线检索的质量高度依赖离线处理的数据颗粒度。
1. 数据清洗与分块策略
不能简单地将 PDF 或 Word 直接丢进去。我们需要针对 Markdown、表格、代码块进行结构化解析。分块(Chunking)策略是这里的核心难点:
- 固定大小分块:容易切断语义,导致检索时上下文不完整。
- 基于语义的递归分块:利用
RecursiveCharacterTextSplitter根据段落、句子边界切分,保证每个 Chunk 拥有完整的语义单元。 - 元数据附着:在每个 Chunk 上打上文件名、章节标题、时间戳等标签,便于后续的过滤检索。
三、 在线推理第一步:问题是如何被“拆解”的?(Query 拆解)
这是 RAG 系统中容易被忽视但极具价值的一环。用户的原始问题往往是口语化、模糊甚至包含多重意图的。直接拿原始问题去检索,召回率往往很低。
问题拆解(Query Transformation)的几种主流范式:
拆解策略
适用场景
技术实现示例
HyDE (假设性文档嵌入)
用户问题过于简短
让 LLM 先根据问题生成一段“假想答案”,接着用假想答案去向量库检索。这解决了“查询语句”与“文档语句”语义鸿沟的问题。
多路查询(Multi-Query)
问题涉及多个实体或对比
利用 LLM 将复杂问题扩展为 3-5 个不同视角的相似问题,并行检索,合并结果。例如:用户问“如何优化 MySQL 性能?”扩展为“MySQL 慢查询优化”、“MySQL 索引调优”、“MySQL 缓存策略”。
子问题分解(Decomposition)
多跳推理(Multi-hop)问题
例如问题:“《三体》作者获过的最高文学奖是什么?”拆解为 (1) 《三体》作者是谁? (2) 该作者获过哪些文学奖? (3) 其中最高级别的是?
Step-back Prompting
需要背景知识的问题
将具体问题抽象化。问“为什么特定函数报错”,退回一步问“该编程语言的基础异常处理机制”。
在这个阶段,LLM 扮演的是“问题重构师”的角色,它并不负责提供事实,而是负责理解用户意图,生成更利于检索的关键词或伪代码。
四、 向量检索与重排序:从“大海捞针”到“精准定位”
1. 检索(Retrieval)
系统将拆解后的多个 Query 转化为 Embedding 向量,在向量数据库中进行 ANN(近似最近邻)搜索。这一步通常会设置一个较大的召回值(Top K,例如 50),宁可多召回,也不能漏掉。
2. 重排序(Rerank)
这是 RAG 流程中的“精筛”环节。由于向量相似度有时并不完全等于语义相关性,我们需要一个更强大的交叉编码器(Cross-Encoder)对召回的 50 个 Chunks 进行逐一打分(0-1 相关性分数)。最终只选择得分最高的 Top 3 或 Top 5 送入大模型。
注意:重排序模型的计算开销较大,这样一来通常采用“粗排+精排”的级联架构。
五、 大模型(LLM)在 RAG 中到底负责什么?
许多人误以为大模型在 RAG 里只是负责“把检索到的资料复述一遍”,但实际上,大模型承担了 3 个至关重要的认知职责:
1. 上下文整合与去噪
检索回来的文档可能包含相互矛盾的信息或无关的噪音。大模型需要利用其语义理解能力,自动忽略不相关的检索片段,聚焦于高置信度的信息。
2. 推理与逻辑缝合
大模型不是“搬运工”,而是“逻辑组装师”。它需要将多个碎片化的文本片段,按照逻辑因果、时间顺序或空间结构重新组织成连贯的段落。
3. 未登录知识的拒绝与兜底
这是 RAG 中最体现模型“智能”的地方。如果检索到的文档置信度极低,或者明显与问题无关,优秀的大模型应该能识别这一点并回复:“根据现有资料无法回答该问题。”——这有效缓解了 LLM 的幻觉问题。
六、 最终输出:不仅是“答案”
RAG 系统的最终输出远比一个简单的 result 字符串要丰富。为了提升用户体验和信任度,一个工业级的 RAG 输出应该包含以下结构:
{
"final_answer": "根据2025年Q3财报,该公司营收增长主要得益于AI芯片业务的爆发...",
"references": [
{
"source": "2025_annual_report.pdf",
"page": 42,
"content_snippet": "AI芯片出货量同比增长300%..."
}
],
"thinking_trace": "已检索到 3 篇相关文档,主要依据财务报告章节进行回答。",
"related_questions": ["该公司的毛利率是多少?", "主要竞争对手是谁?"]
}
- 最终答案:生成的自然语言回复。
- 溯源引用:告诉用户这句话出自哪份文档的第几页,实现 RAG 的可解释性(这是企业级应用的刚需)。
- 追问推荐:基于当前上下文,LLM 生成的智能问答引导。
七、 关键痛点与优化方向(总结展望)
1. 上下文丢失:中间部分的检索内容容易被长上下文模型“遗忘”,需采用 Lost in the Middle 的注意力优化策略。
2. 检索延迟:重排序和 LLM 推理是主要耗时点,可通过 流式输出(Streaming) 和 Prefetch(预取) 缓解用户等待焦虑。
3. 评估体系:建议引入 RAGAS 等评估框架,从 Faithfulness(忠实度)和 Answer Relevance(答案相关性)两个维度自动化评估系统效果。
八、面试回答
RAG完整处理流程
第一步:索引阶段(离线)
- 先把你的文档切分成小块(比如500字一段),接着调用Embedding模型把每一块转成向量。
- 把这些向量存到向量数据库里(比如Milvus、Pinecone、Faiss),同时最好把原始文本也存下来。
- 用户问一个问题,比如“我们公司的年假政策是什么?”
- 系统同样用同一个Embedding模型把这个问题转成向量。
- 去向量数据库里做相似度搜索,找回最相关的Top-K个文本块(比如最相似的3段)。
- 把用户的问题 + 检索到的文本块,拼成一个提示词(Prompt)。
- 送给大模型(比如GPT、文心一言、Llama)。
- 大模型基于这些检索到的信息来生成最终答案。
问题如何拆解?
常用的拆解策略:
- 按逻辑步骤拆(因果、时间顺序)
- 按实体关系拆(人名、地名、事件)
- 用Few-shot例子或让大模型自己拆(比如提示:“请把这个问题拆成3个可检索的子问题”)
大模型负责什么?
大模型在RAG里主要做三件事:
1. 理解与改写(入口) 有时先让大模型把用户口语化的问题改写成更适合检索的查询,比如用户说“那个很火的手机是啥来着”,改写成“2024年销量最高的智能手机型号”。
2. 答案生成(核心) 拿到检索的文本块后,大模型要做的事是:基于这些信息生成答案,不能瞎编。它还要做融合——如果多块信息有冲突,它能判断哪个更可信;如果信息缺失,它会说“根据现有资料无法回答”。
3. 可选的后处理 比如总结、翻译、格式化输出(JSON/表格)。另外也可以让大模型检查答案是否确实来自检索内容,避免幻觉。
最终输出什么?
最基础的输出就是一段自然语言的文本答案,但实际工程中通常输出一个结构化的对象。
还可能附带:
- 检索到的原文片段(供用户核验)
- 相关的追问建议(比如“你想了解年假申请流程吗?”)
结语
RAG 系统不仅仅是“向量数据库 + ChatGPT”的简单拼接。从 Query 的拆解改写,到 Rerank 的精准过滤,再到 LLM 的逻辑整合与引用输出,每一个环节都充满了工程与算法的博弈。
希望通过本文的梳理,能帮助你构建一个更稳定、更智能的 RAG 应用。欢迎在评论区留言讨论你在落地过程中遇到的坑!
本次分享就到这里。技术这东西越研究越有意思,后续有新的收获我也会继续更新。
评论 (0)
暂无评论