一、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 的核心难题不是"能不能跑起来",而是"检索准不准、回答对不对、成本控不控得住"。意图识别是系统的入口路由,决定后续走哪条路。架构师的价值在于在精度与速度、成本与效果、安全与便捷之间做出合理权衡。

Logo

Agent 垂直技术社区,欢迎活跃、内容共建。

更多推荐