一、RAG 简介
| 项目 |
内容 |
| 全称 |
Retrieval-Augmented Generation(检索增强生成) |
| 核心思想 |
先从知识库中检索相关内容,再让 LLM 基于检索结果生成回答,避免 LLM 编造信息 |
| 解决的问题 |
LLM 的幻觉问题(编造信息)、知识过时问题、领域知识不足问题 |
基本架构
用户提问
│
▼
[查询处理] → [检索] → [重排] → [上下文组装] → [LLM生成] → 回答
↑
[知识库]
索引 ← 文档处理 ← 数据源
二、架构师要解决的核心问题
2.1 数据处理层——“知识怎么灌进去”
| 问题 |
具体要决策的 |
| 文档怎么切分? |
按固定长度切?按段落切?按语义切?切多大?重叠多少? |
| 切分粒度怎么定? |
太大:检索不精准,混入无关内容;太小:丢失上下文,答案碎片化 |
| 元数据要不要加? |
标题、章节、来源、时间戳——加了能过滤,不加检索更简单 |
| 多模态怎么处理? |
图片、表格、公式要不要单独提取?怎么和文本对齐? |
| 数据更新怎么办? |
增量更新还是全量重建?过期文档怎么标记/删除? |
切分粒度的典型权衡
切分太小(100字):
✅ 检索精准
❌ 上下文断裂,"2023年营收增长30%"不知道是哪家公司
切分太大(1000字):
✅ 上下文完整
❌ 检索噪声多,一段话里只有一句相关
常见选择:256~512 token,重叠 50~100 token
2.2 向量化与索引层——“怎么快速找到相关内容”
| 问题 |
具体要决策的 |
| 用什么 Embedding 模型? |
OpenAI text-embedding-3?BGE?M3E?效果、速度、成本的权衡 |
| 向量维度多少? |
高维度=表达力强但检索慢,低维度=快但可能丢信息 |
| 用什么向量数据库? |
Milvus、Pinecone、Weaviate、Qdrant、Chroma? |
| 索引类型怎么选? |
HNSW(精度高)、IVF(速度快)、Flat(小数据量) |
| 要不要混合检索? |
纯向量检索 vs 向量+关键词(BM25)混合? |
| 多语言怎么处理? |
跨语言 Embedding 还是翻译后统一向量化? |
混合检索的必要性
纯向量检索:
问:"iPhone 15 Pro Max 多少钱"
可能检索到:"这款手机售价9999元" ← 语义相近但没提具体型号
纯关键词检索:
问:"iPhone 15 Pro Max 多少钱"
可能检索到:"iPhone 15 Pro Max 参数配置..." ← 有关键词但不是价格信息
混合检索(向量+关键词):
同时匹配语义相关和关键词命中的内容 ✅
2.3 查询处理层——“用户问的到底是什么”
| 问题 |
具体要决策的 |
| 查询要不要改写? |
用户说"它多少钱","它"指什么?需要结合上下文补全 |
| 要不要拆分子查询? |
“A和B的区别是什么” → 拆成"什么是A"+“什么是B”+“A和B对比” |
| 要不要加查询扩展? |
用户说"手机" → 扩展成"手机 智能手机 mobile phone" |
| 要不要加查询路由? |
不同类型问题走不同检索路径(闲聊/知识库/搜索) |
查询改写的典型场景
用户第1轮:"华为Mate60的电池容量是多少?"
用户第2轮:"那充电速度呢?"
不改写:检索"充电速度" → 找到各种充电速度的信息,不知道是哪个设备的
改写后:检索"华为Mate60充电速度" → 精准定位 ✅
2.4 检索与重排层——“找到的内容哪些真正有用”
| 问题 |
具体要决策的 |
| 检索多少条? |
Top-5?Top-10?Top-20?多了噪声大,少了可能漏 |
| 要不要重排(Rerank)? |
向量检索按相似度排,不一定按相关性排,重排模型能纠正 |
| 用什么重排模型? |
BGE-Reranker、Cohere Rerank、Cross-Encoder? |
| 相似度阈值怎么定? |
低于多少直接丢弃?避免不相关内容混入 |
| 要不要去重? |
不同文档可能包含相同内容,重复输入浪费 token |
为什么需要重排
向量检索(双塔模型):
查询和文档分别编码,算余弦相似度
→ 快,但不够精准
重排模型(交叉编码器):
把查询和文档拼在一起,让模型判断相关性
→ 慢,但精准得多
典型流程:
先用向量检索 Top-50(快速粗筛)
再用重排模型精排 Top-5(慢速精选)
2.5 上下文组装层——“怎么把检索结果喂给 LLM”
| 问题 |
具体要决策的 |
| Prompt 怎么设计? |
检索内容放前面还是后面?要不要加指令约束? |
| 上下文窗口溢出怎么办? |
检索内容+问题超过 LLM 上下文长度怎么截断? |
| 多条检索结果冲突怎么办? |
文档A说价格9999,文档B说价格8999,怎么处理? |
| 要不要压缩检索内容? |
用小模型压缩后再喂给大模型,省 token? |
| 检索结果要不要加引用标注? |
让 LLM 标注答案来自哪个文档? |
Prompt 设计的典型结构
[系统指令]
你是一个问答助手,根据以下参考资料回答用户问题。
如果参考资料中没有相关信息,请回答"我不知道"。
不要编造信息。
[参考资料1] 来源:产品手册.pdf
华为Mate60电池容量为4880mAh...
[参考资料2] 来源:评测文章.md
实测充电速度约40分钟从0充到100%...
[用户问题]
华为Mate60的电池容量和充电速度是多少?
2.6 生成与输出层——“回答怎么保证质量”
| 问题 |
具体要决策的 |
| 用什么 LLM? |
GPT-4、Claude、开源模型?效果、速度、成本怎么平衡? |
| 怎么防止幻觉? |
LLM 编造检索内容中没有的信息怎么办? |
| 要不要加引用? |
回答中标注信息来源,增加可信度 |
| 流式输出还是等完再输出? |
用户体验 vs 实现复杂度 |
| 要不要加安全过滤? |
敏感信息、有害内容的检测和过滤 |
防幻觉的关键手段
1. Prompt 约束:"只能根据参考资料回答,没有就说不知道"
2. 事实校验:生成后用另一个模型检查答案是否和检索内容一致
3. 置信度评估:对答案的每个部分标注置信度
4. 引用溯源:要求标注每句话来自哪个文档哪一段
2.7 工程与运维层——“怎么跑得稳、跑得省”
| 问题 |
具体要决策的 |
| 并发怎么处理? |
向量检索和 LLM 推理都是计算密集型,怎么扩缩容? |
| 延迟怎么控制? |
检索+重排+生成全链路耗时,用户能接受多少? |
| 缓存怎么做? |
相同问题缓存答案?相似问题缓存检索结果? |
| 成本怎么控制? |
Embedding 调用费、向量库存储费、LLM 推理费 |
| 怎么评估效果? |
召回率、准确率、答案质量的评估体系怎么建? |
| 怎么监控? |
检索质量下降、LLM 输出异常、知识库过期怎么发现? |
| 数据安全? |
企业内部知识库,数据不能泄露给外部 API |
三、架构师面临的典型权衡
| 权衡 |
一端 |
另一端 |
| 精度 vs 速度 |
重排+多次检索+大模型 |
简单检索+小模型 |
| 成本 vs 效果 |
GPT-4 + 长上下文 |
开源模型 + 短上下文 |
| 实时性 vs 完整性 |
增量索引,秒级更新 |
全量重建,质量更高 |
| 通用 vs 专用 |
通用 Embedding + 通用 LLM |
领域微调模型 |
| 安全 vs 便捷 |
本地部署,数据不出域 |
云端 API,开发快 |
四、常见架构模式
模式1:基础 RAG
用户提问 → 向量检索 → 拼接Prompt → LLM生成 → 回答
简单,但效果有限
适合:原型验证、简单场景
模式2:进阶 RAG
用户提问 → 查询改写 → 混合检索 → 重排 → 上下文压缩 → LLM生成 → 回答
多了查询优化、混合检索、重排、压缩
适合:生产环境主流方案
模式3:Agent RAG
用户提问 → Agent规划 → 多轮检索/工具调用 → 综合判断 → LLM生成 → 回答
LLM 自主决定要不要检索、检索几次、用什么工具
适合:复杂推理场景
模式4:Graph RAG
用户提问 → 知识图谱检索 + 向量检索 → 融合 → LLM生成 → 回答
用知识图谱补充实体关系,向量检索补充细节
适合:关系密集型场景(如组织架构、产品依赖)
五、意图识别——RAG 的入口路由
5.1 什么是意图识别
意图识别就是判断用户说的话属于哪种类型的需求,本质是一个分类问题。
用户说:"北京今天天气怎么样" → 意图:查天气
用户说:"明天要下雨吗" → 意图:查天气
用户说:"帮我定明天去上海的机票" → 意图:订机票
用户说:"退掉我上周的订单" → 意图:退订单
用户说:"你们客服电话多少" → 意图:查联系方式
用户说:"你好" → 意图:闲聊
同一个意图可以有无数种说法,意图识别就是把不同的说法归到同一个类别。
5.2 意图识别在 RAG 中的作用
| 场景 |
意图识别的结果 |
走什么路径 |
| “华为Mate60电池多大” |
知识查询 |
走 RAG 检索知识库 |
| “你好,你是谁” |
闲聊 |
直接 LLM 回答,不检索 |
| “帮我写一封请假邮件” |
内容生成 |
LLM 直接生成,不需要检索 |
| “计算3的平方根” |
工具调用 |
调计算器,不检索 |
| “总结这篇文档” |
文档处理 |
走文档处理流程 |
没有意图识别:
用户说"你好" → 也去检索知识库 → 检索结果无关 → 回答莫名其妙
用户说"帮我写首诗" → 也去检索知识库 → 浪费资源
有意图识别:
用户说"你好" → 识别为闲聊 → 直接回答 ✅
用户说"帮我写首诗" → 识别为生成 → 直接生成 ✅
用户说"Mate60电池多大" → 识别为知识查询 → 走RAG ✅
RAG 中意图识别的价值:该检索的检索,不该检索的不检索。
5.3 意图识别怎么做
方法1:规则匹配(最简单)
关键词匹配:
if "天气" in query or "下雨" in query:
intent = "查天气"
elif "订票" in query or "机票" in query:
intent = "订机票"
elif "退款" in query or "退货" in query:
intent = "退订单"
else:
intent = "未知"
优点:简单,不需要训练
缺点:覆盖不全,"明天出门要带伞吗"识别不出是查天气
方法2:分类模型(传统做法)
训练一个文本分类器:
训练数据:
"北京今天天气怎么样" → 查天气
"明天要下雨吗" → 查天气
"帮我定机票" → 订机票
"退掉我的订单" → 退订单
...
模型:BERT、FastText、SVM 等
优点:比规则准,能理解语义
缺点:需要标注数据,新意图要重新训练
方法3:LLM 直接判断(当前主流)
Prompt:
你是一个意图识别器,判断用户输入属于以下哪个意图:
- weather:查询天气
- flight:订机票
- refund:退订单
- chat:闲聊
- knowledge:知识查询
- other:其他
用户输入:{query}
请输出意图类别:
LLM 输出:weather
优点:不需要训练数据,零样本就能用,灵活
缺点:每次调用有成本和延迟
方法4:Function Calling(OpenAI 风格)
预先定义一组函数(意图):
functions = [
{"name": "get_weather", "description": "查询天气", "parameters": {"city": "string"}},
{"name": "book_flight", "description": "订机票", "parameters": {...}},
{"name": "refund_order", "description": "退订单", "parameters": {...}},
]
用户说:"北京明天天气怎么样"
LLM 自动选择:get_weather(city="北京")
意图识别 + 参数提取一步完成,这是当前最优雅的方式。
5.4 意图识别的难点
| 难点 |
例子 |
原因 |
| 一句话多个意图 |
“订机票顺便查下那边天气” |
订机票 + 查天气,要拆分处理 |
| 意图模糊 |
“我的订单怎么了” |
是查物流?还是退款?还是投诉? |
| 口语化表达 |
“这破手机又卡了” |
是吐槽?还是求助?还是想退货? |
| 新意图 |
训练时没见过的意图 |
分类模型无法识别,需要兜底策略 |
| 上下文依赖 |
“那充电速度呢” |
上一轮在聊Mate60,这里要继承上下文 |
5.5 多意图怎么处理
用户:"帮我订明天去上海的机票,顺便查下那边天气"
方案1:识别为多意图,并行处理
意图1:订机票 → 走订票流程
意图2:查天气 → 调天气API
→ 两个结果合并返回
方案2:识别为主意图,忽略次要
主意图:订机票 → 只走订票流程
→ 简单但可能遗漏用户需求
方案3:逐个处理
先处理订机票 → 完成后追问"还要查天气吗?"
→ 体验好但交互多
5.6 意图识别在完整系统中的位置
用户输入
│
▼
[意图识别] ──→ 判断意图类别
│
├─ 闲聊 ──────→ LLM 直接回答
├─ 知识查询 ──→ RAG 检索 + LLM 生成
├─ 内容生成 ──→ LLM 直接生成
├─ 工具调用 ──→ 调用对应 API
├─ 多意图 ────→ 拆分后分别处理
└─ 未知意图 ──→ 追问澄清
意图识别是整个系统的入口路由,决定了后续走哪条路。
六、意图识别的常见场景
意图识别不是 RAG 独有的,它出现在几乎所有智能交互系统中。
| 场景 |
例子 |
意图有哪些 |
| RAG / 知识库问答 |
企业知识助手 |
知识查询、闲聊、内容生成、文档处理 |
| 智能客服 |
电商/银行客服 |
查订单、退款、投诉、转人工 |
| 对话系统/聊天机器人 |
小爱同学、Siri |
播音乐、设闹钟、查天气、闲聊 |
| 语音助手 |
车载语音 |
导航、打电话、开空调、听歌 |
| 任务型对话 |
订餐/订票机器人 |
订位、改时间、取消、查菜单 |
| 搜索系统 |
搜索引擎 |
找网页、找图片、找视频、算数学 |
| 工单路由 |
企业IT运维 |
网络问题、账号问题、软件安装、硬件报修 |
哪些场景必须用意图识别?
| 必须 |
原因 |
例子 |
| 智能客服 |
几十种意图,每种走不同业务流程 |
退款和查物流处理完全不同 |
| 语音助手 |
意图决定调哪个设备/API |
设闹钟和开空调调的是不同接口 |
| 任务型对话 |
意图决定执行什么动作 |
订票和改签是不同流程 |
| 多技能 Bot |
意图决定走哪个技能模块 |
RAG、搜索、生成、工具 |
| 不一定需要 |
原因 |
例子 |
| 纯 RAG |
如果系统只做知识问答,所有问题都检索 |
内部文档问答,不涉及闲聊 |
| 纯闲聊 |
只有一种意图 |
聊天机器人,不需要路由 |
| 单任务系统 |
只做一件事 |
只做翻译的 Bot |
七、RAG 中意图识别的典型架构
用户提问
│
▼
[意图识别]
│
├── knowledge(知识查询)──→ [查询改写] → [RAG检索] → [重排] → [LLM生成]
│
├── chat(闲聊)──────────→ [LLM直接回答]
│
├── generate(内容生成)──→ [LLM直接生成]
│
├── tool(工具调用)──────→ [调用API] → [结果返回]
│
└── unknown(未知意图)───→ [追问澄清]
RAG 只是意图识别路由后的一个分支,不是全部。
八、各层核心问题总结
| 层 |
核心问题 |
一句话 |
| 数据处理 |
怎么切、怎么灌、怎么更新 |
知识的质量决定上限 |
| 向量索引 |
怎么编码、怎么存储、怎么检索 |
检索的精度决定下限 |
| 查询处理 |
用户到底在问什么 |
理解问题是正确回答的前提 |
| 检索重排 |
哪些内容真正有用 |
粗筛+精选,宁缺毋滥 |
| 上下文组装 |
怎么喂给 LLM |
垃圾进垃圾出,Prompt 是门手艺 |
| 生成输出 |
怎么保证不编造 |
约束+校验+引用 |
| 工程运维 |
怎么跑得稳、跑得省 |
可用性、成本、安全的平衡 |
| 意图识别 |
用户想干什么 |
该检索的检索,不该检索的不检索 |
九、一句话总结
RAG 的核心难题不是"能不能跑起来",而是"检索准不准、回答对不对、成本控不控得住"。意图识别是系统的入口路由,决定后续走哪条路。架构师的价值在于在精度与速度、成本与效果、安全与便捷之间做出合理权衡。
所有评论(0)