一、量化的本质是什么?
大模型量化的本质,不是简单地把 FP16、FP32 直接转换成 INT8 或 INT4,而是要在"模型压缩"和"能力保持"之间做工程平衡。
模型原本的权重和激活值通常使用高精度浮点数表示,比如 FP16 或 FP32。量化之后,部分数值会被映射成低精度整数,比如 INT8、INT4,甚至更低 bit 的表示。
这样做的直接好处是:
text
模型参数更小;
显存占用更低;
内存带宽压力更小;
推理速度可能更快;
部署成本更低。
但它也会带来代价:
text
数值精度下降;
量化误差增加;
模型输出可能变差;
极端情况下会出现精度崩塌。
所以量化真正要解决的问题不是"能不能压缩",而是:
text
如何在压缩模型的同时,尽量不破坏模型原有能力。
1. 量化最底层的数学映射
量化的核心公式可以写成:
text
Real = Scale × (Quantized - ZeroPoint)
也就是:
text
真实浮点值 = 缩放因子 ×(量化整数值 - 零点)
这里有几个关键概念:
| 概念 | 含义 |
|---|---|
| Real | 原始浮点值,比如 FP16 / FP32 |
| Quantized | 量化后的整数值,比如 INT8 / INT4 |
| Scale | 缩放因子,用来控制整数和浮点数之间的比例 |
| ZeroPoint | 零点,用来表示浮点数里的 0 对应哪个整数值 |
可以简单理解为:
text
浮点数范围更大、更细;
整数范围更小、更粗;
Scale 和 ZeroPoint 负责建立两者之间的映射关系。
比如 INT8 只有 256 个可能值,如果要用它表示一段连续的浮点数区间,就必须把浮点数压缩到这个整数范围里。压缩过程越粗,信息损失就越明显。
因此,量化不是简单的数据类型转换,而是一种带有误差的近似表示。
2. 对称量化和非对称量化
量化方式通常可以分成对称量化和非对称量化。
对称量化一般可以理解为:
text
ZeroPoint = 0
它的整数范围围绕 0 对称,比如:
text
[-127, 127]
这种方式计算简单,硬件执行效率也比较高。但如果原始数据分布本身不是对称的,就可能浪费一部分表示空间。
非对称量化允许:
text
ZeroPoint ≠ 0
它更适合表示偏移明显的数据分布,比如某些激活值大部分都在正数区间。非对称量化对数据分布的适应性更强,但计算逻辑会更复杂一些。
可以简单理解为:
text
对称量化:以 0 为中心,计算简单;
非对称量化:允许整体偏移,更适合非对称分布。
在实际工程中,到底选择哪一种方式,要看模型权重和激活值的分布,也要看推理框架和硬件是否支持。
3. 量化粒度:Per-Tensor、Per-Channel、Per-Group
量化不只是决定用 INT8 还是 INT4,还要决定 Scale 和 ZeroPoint 按什么粒度分配。
常见粒度有三类:
text
Per-Tensor
Per-Channel
Per-Group
Per-Tensor 是整个张量共用一组 Scale 和 ZeroPoint。
它的优点是实现简单、计算高效、额外参数少。缺点是精度损失可能比较大,因为一个大矩阵里不同区域的数据分布可能差异很大,强行共用一套缩放参数,会导致某些区域表示得不够精细。
Per-Channel 是每一行或每一列单独分配一组 Scale 和 ZeroPoint。
它比 Per-Tensor 更细,能更好适应不同通道的数据分布。很多模型量化都会采用这种折中方式,因为它在精度和成本之间比较平衡。
Per-Group 是把一行或一列再切成多个小组,比如每 128 个元素一组、每 64 个元素一组,或者每 32 个元素一组,然后每一组单独使用一套量化参数。
它比 Per-Channel 更细,也比逐元素量化更高效,所以在大模型 INT4 量化里非常常见。
可以这样理解:
text
Per-Tensor:整张表用一把尺子;
Per-Channel:每一行或每一列用一把尺子;
Per-Group:每一小段用一把尺子。
粒度越细,精度通常越好,但额外存储和计算管理成本也会更高。大模型量化里常见的 group size,比如 128、64、32,本质上就是在精度和成本之间做平衡。
4. 大模型量化最难处理的是离群值
大模型量化比普通神经网络量化更难,一个重要原因是权重和激活值里经常存在离群值。
也就是某些数值远远大于其他普通值。
量化需要确定一个表示范围。如果为了覆盖这些极大的离群值,就会导致大部分普通值被压缩到很小的整数区间里。
结果可能变成:
text
少数极大值被保住了;
大量正常值被挤压到 0、1、-1 附近;
模型信息大量丢失。
这就是常说的 Activation Outliers,也就是激活值离群点问题。
它可能导致:
text
量化误差变大;
模型输出不稳定;
模型能力下降;
严重时精度崩塌。
所以大模型量化的难点,不只是把参数变小,而是如何处理不同张量分布和激活离群点。
如果忽略离群值,直接用一个统一范围去量化,结果可能是少数异常大值决定了整个量化范围,而绝大多数正常值反而被压得很粗。模型中很多细微信息就会在这个过程中丢失。
5. 两条主流路线:Weight-Only 和 Weight + Activation
前沿量化方案大体可以分成两条路线。
第一条是 Weight-Only Quantization,也就是仅权重量化。
典型形式比如:
text
W4A16
意思是:
text
权重用 4 bit;
激活值仍然用 16 bit。
这种方式主要解决的是模型权重太大、显存占用太高、内存带宽压力太大的问题。
它的优点是精度更容易保持,实现相对更稳,也更适合大模型部署。缺点是激活值没有被量化,所以计算过程未必完全变成低精度整数计算,加速效果可能不如全量化彻底。
第二条是 Weight + Activation Quantization,也就是权重和激活都量化。
典型形式比如:
text
W8A8
意思是:
text
权重用 8 bit;
激活值也用 8 bit。
这种方式不仅压缩权重,还能让计算过程更适合低精度整数运算。它更容易获得真实推理加速,也更适合硬件上的 INT8 计算。
但它的难点也更明显:
text
激活值更难量化;
离群点问题更严重;
精度保持更困难。
所以 W8A8 的关键不是简单地"把激活值转成 INT8",而是要先处理激活值分布,让它更适合低精度表示。
可以这样简单区分:
text
W4A16:主要压缩模型权重,部署更稳;
W8A8:权重和激活都压缩,更利于硬件加速,但处理难度更高。
6. 常见解决思路:GPTQ、AWQ、SmoothQuant
大模型量化里有几类代表性思路。
GPTQ 这类方法可以理解为"二阶信息补偿"。它不是简单粗暴地四舍五入,而是会考虑某个权重量化错误一点,对最终损失影响大不大。它会利用损失函数的二阶信息来判断哪些权重更重要,并在量化过程中尽量补偿误差。
AWQ 这类方法可以理解为"激活感知权重保护"。它认为不是所有权重都一样重要,和高激活值相关的权重更值得保护。于是它会观察激活值分布,找出少量重要通道,在量化前对这些关键权重做缩放保护。
SmoothQuant 的思路是"平滑激活分布"。激活值往往比权重更难量化,所以它通过数学上的等价变换,把一部分激活量化难度转移到权重上。
直观理解就是:
text
激活值太尖、太不平滑;
通过缩放把激活值变得更平滑;
同时对权重做反向补偿;
让整体计算结果尽量保持不变。
这样就能让激活值更适合 INT8 量化。
这些方法虽然具体实现不同,但目标是一致的:
text
减少量化误差;
保护关键通道;
处理激活离群值;
尽量保持模型原有能力。
7. 量化问题可以怎么总结?
大模型量化的核心,是用低精度整数近似表示原来的高精度浮点权重或激活值。它通过 Scale 和 ZeroPoint 建立浮点数与整数之间的映射关系,从而减少模型存储、显存占用和内存带宽压力,并在合适硬件上提升推理速度。
但大模型量化的难点不只是数值映射,而是如何在压缩模型的同时保持精度。因为大模型的权重和激活值分布并不均匀,尤其是激活值中经常存在离群点。如果直接全局量化,少数极大值会拉大量化范围,导致大量正常值被压缩,最终造成精度损失。
所以工程上通常会从三个层面优化:
text
选择合适的量化粒度,比如 Per-Tensor、Per-Channel、Per-Group;
选择合适的量化对象,比如 W4A16 或 W8A8;
通过 GPTQ、AWQ、SmoothQuant 等方法处理误差、关键通道和激活离群值。
因此,量化本质上是一个"低精度近似 + 误差控制 + 硬件友好"的综合工程问题,而不是简单地把 FP16 直接转换成 INT8 或 INT4。
二、在大模型应用里,Workflow 和 Agent 到底有什么区别?什么时候该用固定流程,什么时候该让大模型自主决策?
在大模型应用里,Workflow 和 Agent 的区别,本质上是控制流归属不同。
text
Workflow:流程由开发者提前设计;
Agent:流程由大模型根据目标和环境动态决定。
更简单地说:
text
Workflow 是人控制流程;
Agent 是模型控制流程。
Workflow 更像铁轨列车,路线提前铺好;Agent 更像自动驾驶,目标明确,但路线会根据环境动态调整。
1. Workflow 是什么?
Workflow 可以理解为开发者提前设计好的固定流程。
它的每一步怎么走、先做什么、后做什么、遇到什么情况走哪个分支,基本都由工程代码提前定义好。
比如:
text
收到用户请求
↓
识别用户意图
↓
进入固定分支
↓
调用指定工具
↓
返回结果
在 Workflow 中,大模型通常只是其中一个执行节点。
它可能负责:
text
意图识别;
文本分类;
信息抽取;
格式化输出;
简单判断。
但整个控制流不是大模型自己决定的,而是开发者写死或半写死的。
Workflow 最大的优点是确定性强。
它适合流程清楚、规则明确、容错率低的业务,比如:
text
退款流程;
合同审核;
财务审批;
合规检查;
订单状态查询;
客服工单流转。
这些场景里,系统最重要的不是"聪明",而是:
text
稳定;
可控;
可审计;
可回滚;
可测试。
所以 Workflow 的优势很明显:
| 特点 | 说明 |
|---|---|
| 确定性强 | 每一步都是提前设计好的 |
| 易于调试 | 出问题可以定位到具体节点 |
| 容易测试 | 每个节点输入输出都可以做测试 |
| 适合合规业务 | 关键流程不依赖模型临场发挥 |
| 可观测性好 | 日志、状态、异常都容易追踪 |
但 Workflow 也有明显缺点:灵活性不足。
只要用户的问题超出了预设分支,Workflow 就容易处理不了。
比如用户不是简单问"我要退款",而是问:
text
我之前买了一个会员,但是后来又升级了套餐,现在想取消其中一个订单,
不过我不确定会不会影响另一个订阅,你帮我看一下怎么处理?
这种问题可能涉及订单、订阅、退款规则、用户历史、产品策略和客服话术。如果只靠固定 Workflow,就很容易出现分支爆炸。
所以 Workflow 适合稳定流程,但不适合处理所有开放式问题。
2. Agent 是什么?
Agent 可以理解为由大模型根据目标,自主决定下一步做什么。
开发者给 Agent 的不是完整流程,而是:
text
目标;
工具;
约束;
环境信息;
可执行动作。
然后 Agent 自己决定:
text
先查什么;
调用哪个工具;
是否需要继续检索;
是否需要写代码;
是否需要调用数据库;
是否需要重新规划;
什么时候结束。
一个典型 Agent 流程可能是:
text
用户提出复杂任务
↓
LLM 理解目标
↓
拆解步骤
↓
选择工具
↓
执行工具
↓
观察结果
↓
重新判断下一步
↓
循环直到完成任务
这就是很多 ReAct Agent 的基本思路:
text
Reasoning + Acting
也就是一边推理,一边行动。
Agent 最大的优点是灵活性强。
它适合路径不固定、任务模糊、需要探索的问题,比如:
text
帮我分析这个项目为什么构建失败;
帮我查一下这个用户投诉背后的真实原因;
帮我根据日志定位线上问题;
帮我研究一下竞品的功能设计;
帮我写一个数据分析脚本并解释结果。
这些任务有一个共同特点:
text
目标是明确的,但解决路径不一定提前知道。
Agent 的优势是:
| 特点 | 说明 |
|---|---|
| 灵活性强 | 可以根据中间结果调整下一步 |
| 适合复杂任务 | 可以拆解、检索、调用工具、反复修正 |
| 有探索能力 | 不局限于预设分支 |
| 能处理模糊需求 | 可以边做边观察,边观察边判断 |
| 更接近人类工作方式 | 像一个会使用工具的助手 |
但 Agent 的问题也很明显:可控性弱。
常见风险包括:
text
死循环;
工具选错;
参数生成错误;
调用顺序错误;
目标跑偏;
幻觉;
Token 消耗过大;
高风险动作误执行;
调试困难。
所以,纯 Prompt 驱动的 Agent 在真实工程里通常不够可靠。
3. Workflow 和 Agent 的核心区别
可以用一张表来区分:
| 对比项 | Workflow | Agent |
|---|---|---|
| 控制流 | 开发者预先定义 | 大模型动态决定 |
| 任务路径 | 固定或半固定 | 不固定,可探索 |
| 适合场景 | 规则明确、流程稳定 | 目标明确、路径复杂 |
| 可靠性 | 高 | 相对较低 |
| 灵活性 | 低 | 高 |
| 可测试性 | 强 | 较弱 |
| 可观测性 | 强 | 需要额外设计 |
| 典型类比 | 铁轨列车 | 自动驾驶 |
| 工程重点 | 流程编排、节点校验 | 状态管理、工具治理、边界控制 |
最简单的判断方式是:
text
能画成稳定流程图的,用 Workflow;
画不清楚流程,但目标明确的,用 Agent;
流程主干清楚,局部节点复杂的,用 Agentic Workflow。
也可以从风险角度判断:
text
容错率低、规则明确、高风险动作多 → 优先 Workflow;
路径不确定、探索性强、多轮工具调用多 → 可以引入 Agent;
主流程稳定但局部复杂 → 使用 Agentic Workflow。
4. 为什么真实项目里不能只用 Agent?
很多人刚开始做大模型应用时,会觉得 Agent 更智能,所以所有任务都可以交给 Agent。实际并不是这样。
Agent 一旦进入生产环境,就会遇到很多问题。
第一类问题是死循环。
在 ReAct 模式下,Agent 会反复执行:
text
思考 → 调工具 → 观察结果 → 再思考 → 再调工具
如果目标不清楚,或者工具返回结果不符合预期,Agent 可能会反复调用同一个工具,或者一直尝试无效路径。
最后可能导致:
text
Token 爆炸;
接口反复调用;
任务超时;
成本飙升。
所以工程上必须加:
text
最大迭代次数;
超时机制;
状态机;
失败退出条件;
人工确认节点。
第二类问题是工具调用失败。
Agent 一旦挂了很多工具,比如超过 5 到 10 个,模型就容易出现:
text
选错工具;
漏填参数;
参数类型错误;
JSON 格式错误;
调用顺序错误;
把 A 工具的参数传给 B 工具。
所以工程上需要做:
text
工具分层;
工具路由;
Schema 严格校验;
参数强制解析;
错误重试;
工具调用日志;
反例约束。
不要把所有工具都塞给一个"超级大脑"。
第三类问题是业务风险。
财务、合规、权限、订单、支付这类高风险场景,通常应该优先使用 Workflow。Agent 可以给建议,但不应该随意直接执行最终动作。
比如:
text
退款;
删除数据;
发送邮件;
修改订单;
执行数据库写操作;
提交审批。
这些动作最好由固定 Workflow 执行,并在关键节点加入人工确认。
5. 什么是 Agentic Workflow?
真实项目里更稳的方案,通常不是 Workflow 和 Agent 二选一,而是 Agentic Workflow。
Agentic Workflow 可以理解为:
text
外层用 Workflow 管住流程边界;
内层在复杂节点中引入 Agent 的自主能力。
也就是:
text
Workflow 保证系统稳定下限;
Agent 提升复杂任务处理上限。
比如一个企业客服系统,可以这样设计:
text
节点 1:解析用户邮件
↓
节点 2:Agent 查询知识库、判断问题类型、生成处理建议
↓
节点 3:合规审核
↓
节点 4:固定流程发送回复
这里面:
text
节点 1、3、4 是 Workflow;
节点 2 是 Agent。
这样既保留了 Workflow 的稳定性,又利用了 Agent 的灵活性。
一个典型 Agentic Workflow 架构可以写成:
text
用户请求
↓
入口分类器
↓
任务路由
↓
固定 Workflow 主流程
↓
复杂节点调用 Agent
↓
Agent 使用工具 / RAG / 数据库 / 代码执行
↓
结构化结果返回 Workflow
↓
业务校验
↓
人工确认 / 自动执行
↓
最终输出
核心原则是:
text
Agent 不直接接管整个系统,只在需要智能判断的局部节点中工作。
这样可以避免纯 Agent 失控,也可以避免纯 Workflow 过于死板。
6. 工程落地时要加哪些控制机制?
如果要把 Agent 做成生产级系统,不能只靠 Prompt。
至少需要这些机制:
text
状态管理;
最大迭代次数;
工具分层;
Schema 校验;
Human-in-the-loop;
全链路观测。
状态管理是为了让 Agent 每一步都有明确状态,比如:
text
任务开始;
正在检索;
正在调用工具;
工具调用失败;
等待用户确认;
任务完成;
任务失败。
最大迭代次数是为了防止 Agent 无限循环,比如最多思考 5 次、最多调用工具 8 次、单个任务最多运行 60 秒。
工具分层是为了避免所有工具都暴露给模型。更合理的做法是:
text
先判断任务类型;
再选择工具集合;
再让 Agent 在小范围工具里选择。
Schema 校验是为了保证工具输入输出结构化,避免自然语言传参导致格式漂移。
Human-in-the-loop 是为了控制高风险动作,比如退款、删除数据、发送邮件、修改订单、执行数据库写操作等。
全链路观测是为了让系统能够回答这些问题:
text
为什么选这个工具?
传了什么参数?
工具返回了什么?
下一步为什么这么做?
最终结论来自哪些依据?
否则 Agent 出了问题很难排查。
7. Workflow 和 Agent 可以怎么总结?
Workflow 和 Agent 的核心区别在于控制流归属不同。
Workflow 的控制流由开发者提前定义,大模型只是流程中的一个执行节点;Agent 的控制流则由大模型根据目标、上下文和工具返回结果动态决定。
Workflow 更像铁轨列车,路径固定、确定性强、容易测试和审计,适合退款、审批、合规、财务、订单处理等规则明确、容错率低的场景。
Agent 更像自动驾驶,开发者给它目标、工具和边界,它自己拆解任务、选择工具、观察结果并调整下一步,因此更适合代码分析、日志排查、复杂问答、研究调研等路径不确定的场景。
但工程上不能简单认为 Agent 一定比 Workflow 高级。纯 Agent 容易出现死循环、工具误调用、参数错误、目标漂移和不可观测等问题;纯 Workflow 又缺少处理复杂模糊任务的灵活性。
所以真实的大模型架构通常会演进为 Agentic Workflow,也就是外层用 Workflow 控制主流程和安全边界,内层在复杂节点中引入 Agent 的推理、检索和工具调用能力。
三、在多轮对话中,用户经常不会把问题说完整,只说一句"那它还有什么优势?",系统应该如何准确检索?
在多轮对话 RAG 中,用户经常不会把问题说完整,而是会沿着前面的上下文继续追问。比如前面刚讨论完两个方案的差异,用户接着问一句:
text
那它还有什么优势?
这句话对人来说很好理解,因为人可以结合前面的对话判断"它"指的是谁。但对检索系统来说,这句话本身信息非常少。如果直接拿它去做向量检索或关键词检索,很容易召回一堆泛化内容,最后导致回答偏离用户真正想问的问题。
所以,多轮对话 RAG 的关键不是直接搜索用户原话,而是先结合上下文补全用户真实意图,再生成一个可以独立检索的问题,最后进入检索、重排和生成流程。
简单来说,就是:
text
上下文省略问题
↓
上下文补全
↓
Query Rewrite
↓
Standalone Query
↓
混合检索
↓
Rerank 重排
↓
基于证据生成回答
1. 为什么省略问题不能直接检索?
"那它还有什么优势?"这句话最大的问题是语义不完整。
它至少缺少两个核心信息:
text
"它"指的是谁?
"优势"是相对于谁的优势?
假设前面的对话是在比较传统 RAG 和 GraphRAG:
text
用户:传统 RAG 和 GraphRAG 有什么区别?
系统:传统 RAG 更偏向基于文本片段召回,GraphRAG 更强调实体、关系和全局结构。
用户:那它还有什么优势?
这里的"它"大概率指的是 GraphRAG,"优势"也不是泛泛而谈,而是指 GraphRAG 相比传统 RAG 的优势。
如果系统直接把下面这句话送进检索层:
text
那它还有什么优势?
向量数据库并不知道"它"是谁,BM25 也只能看到"优势"这种非常宽泛的词。结果很可能召回一些和当前话题关系不大的内容,比如某个产品优势、某个方案优势,甚至完全不是 GraphRAG 相关的内容。
这类问题可以称为 Contextual Query,也就是依赖上下文才能理解的问题。
像下面这些表达,都属于典型的 Contextual Query:
text
那它呢?
这个还有什么问题?
上面那个方案适合什么场景?
还有别的吗?
为什么会这样?
这些表达在真实对话里非常自然,但对检索系统不友好。检索系统需要的是语义完整、实体清楚、范围明确的查询语句,而不是一句依赖上下文的省略表达。
所以,多轮 RAG 的第一步不应该是直接检索,而是先判断用户这句话是否可以独立表达完整语义。
如果省略问题不做补全,RAG 后面的流程都会被影响:
text
Query 表达不完整
↓
检索召回不稳定
↓
Rerank 排序依据偏移
↓
上下文组装质量下降
↓
最终回答容易答非所问
也就是说,多轮对话 RAG 的召回质量,很多时候不是从向量数据库开始决定的,而是从用户问题是否被正确改写开始决定的。
2. 如何把省略问题改写成独立检索语句?
解决这类问题的核心思路是:
text
先补全意图,再做检索。
也就是把用户的原始问题:
text
那它还有什么优势?
改写成一个可以脱离上下文独立理解的问题,例如:
text
GraphRAG 相比传统 RAG 还有哪些优势?
这个改写后的问题通常叫 Standalone Query,也就是独立查询语句。
Standalone Query 的判断标准很简单:
text
把这句话单独拿出来看,也能知道用户到底想查什么。
一个好的 Standalone Query 通常要包含四类信息:
text
核心实体;
比较对象;
问题意图;
必要限定条件。
比如:
text
GraphRAG 相比传统 RAG,在复杂知识关联和多跳推理方面有哪些优势?
这句话就比"那它还有什么优势?"更适合检索,因为它明确了:
text
要查的对象:GraphRAG
比较对象:传统 RAG
关注方向:复杂知识关联、多跳推理
问题类型:优势分析
在系统设计上,可以把这一步拆成两个模块:Query Router 和 Standalone Engine。
Query Router 的作用,是判断当前问题是否需要改写。它主要判断三件事:
text
当前问题语义是否完整;
当前问题是否依赖历史上下文;
当前问题是否需要进入检索流程。
如果问题语义完整,就直接进入检索。
如果问题语义缺失,就进入 Query Rewrite。
整体流程可以写成:
text
用户原始问题
↓
读取最近几轮对话上下文
↓
Query Router 判断语义是否完整
↓
语义完整:直接检索
↓
语义缺失:进入 Query Rewrite
↓
生成 Standalone Query
↓
进入检索流程
Standalone Engine 的作用,是真正把上下文依赖问题改写成独立问题。
它一般会读取这些信息:
text
用户当前问题;
最近几轮对话;
当前话题中的核心实体;
业务领域信息;
历史摘要;
Prompt 约束。
例如上下文是:
text
用户:方案 A 和方案 B 有什么区别?
系统:方案 A 成本更低,方案 B 在计算效率方面更好。
用户:那它还有什么优势?
系统应该识别出:
text
它 = 方案 B
优势 = 相对于方案 A 的优势
关注点 = 计算效率以及其他可能优势
然后改写成:
text
方案 B 相比方案 A 还有哪些优势?
这里有一个关键原则:Query Rewrite 不是回答问题,而是改写问题。
改写模块只能补全上下文中已经存在的信息,不能凭空扩展新事实。
为了让改写稳定,Prompt 需要做明确约束:
text
只负责改写查询,不负责回答问题;
只能使用当前问题和历史上下文中的信息;
不能引入上下文中不存在的实体;
不能扩展用户没有表达的需求;
输出必须是一个可以独立检索的问题;
必要时返回结构化 JSON。
在实际工程中,最好让模型输出结构化结果,例如:
json
{
"need_rewrite": true,
"standalone_query": "GraphRAG 相比传统 RAG 还有哪些优势?",
"core_entities": ["GraphRAG", "传统 RAG"],
"reason": "用户问题中的"它"依赖上一轮上下文"
}
这样后续系统可以继续做校验,比如:
text
need_rewrite 是否为 true;
standalone_query 是否为空;
core_entities 是否能在上下文中找到;
confidence 是否低于阈值;
是否需要追问用户。
为了进一步提升改写稳定性,还可以给模型提供 Few-shot 示例,让模型知道什么样的改写才是正确的。
例如:
text
上下文:A 方案成本低,B 方案速度快。
用户:那它适合什么场景?
改写:B 方案适合什么场景?
text
上下文:GraphRAG 更擅长处理实体关系和全局结构。
用户:那它还有什么优势?
改写:GraphRAG 相比传统 RAG 还有哪些优势?
text
上下文:W4A16 主要压缩权重,W8A8 同时量化权重和激活值。
用户:这个有什么缺点?
改写:W8A8 量化方案有哪些缺点?
同时,负向约束也很重要。因为模型很容易把"改写问题"误解成"回答问题",所以要明确禁止这些行为:
text
不要回答用户问题;
不要总结知识库内容;
不要生成最终结论;
不要引入上下文中没有的实体;
不要把一个简单问题扩展成多个无关问题;
不要改变用户原始意图;
不要丢失核心比较对象。
如果上下文中同时出现多个对象,比如方案 A、方案 B 和方案 C,用户又问:
text
那它有什么问题?
这时"它"可能指任意一个方案。如果系统无法高置信度判断,就不应该强行改写,而应该追问:
text
你这里说的"它"是指方案 A、方案 B,还是方案 C?
多轮 RAG 不应该为了保持对话流畅而胡乱补全上下文。低置信度时主动追问,反而能提升系统整体可靠性。
3. 如何在工程上保证检索准确和系统稳定?
生成 Standalone Query 之后,才真正进入检索流程。
但这里也不能只依赖一种检索方式。更稳的方案是混合检索:
text
Vector Search + BM25 / Keyword Search
向量检索适合处理语义相似问题,比如:
text
优势;
好处;
价值;
收益;
改进点。
这些表达字面不同,但语义接近,向量检索更容易召回相关内容。
关键词检索适合精确命中实体和术语,比如:
text
GraphRAG;
BM25;
Query Rewrite;
Standalone Query;
HyDE。
这些专有名词如果只靠向量相似度,有时不如关键词命中稳定。
所以,混合检索可以同时兼顾:
text
语义召回能力;
关键词精确命中;
专有名词稳定匹配;
复杂问题覆盖率。
召回之后,还需要 Rerank 对候选结果重新排序。因为初次召回追求的是"尽量别漏",而 Rerank 追求的是"把最相关的内容排到前面"。这一步可以明显降低无关内容进入上下文的概率。
完整链路可以写成:
text
Standalone Query
↓
向量检索召回语义相关内容
↓
关键词检索命中核心实体和术语
↓
合并候选结果
↓
Rerank 重排
↓
Context Packing 组装上下文
↓
大模型基于检索结果生成回答
除了检索层本身,多轮对话 RAG 还要做好上下文窗口管理。
不能把所有历史对话都塞给改写模型,因为上下文越长,延迟越高,噪声越多,旧话题也越容易干扰当前问题。
更合理的做法是只取最近几轮对话,比如:
text
最近 3 轮对话;
最近 5 轮对话;
最近 N 条与当前问题相关的历史。
如果对话很长,可以先做历史摘要,把核心话题和实体压缩出来:
json
{
"current_topic": "GraphRAG 与传统 RAG 对比",
"entities": ["GraphRAG", "传统 RAG", "多跳推理", "实体关系"],
"last_focus": "GraphRAG 的优势"
}
这样改写模型不需要阅读全部历史,也能知道当前问题处在哪个上下文里。
系统还需要判断用户是否切换了话题。
比如前面一直在聊 GraphRAG,用户突然问:
text
那北京明天天气怎么样?
这时候不能强行把"那"理解成 GraphRAG 的上下文延续。系统应该识别出这是一个新话题,不要继续沿用旧上下文。
可以通过这些信号判断是否发生了话题切换:
text
当前问题是否出现新的实体;
当前问题是否和历史主题语义距离很远;
当前问题是否属于新的业务分类;
当前问题是否不需要历史上下文也能理解;
当前问题是否包含明显的新场景词。
在高并发场景下,Query Rewrite 也不一定要交给最强的大模型。它本质上更像上下文理解和格式化任务,主要能力包括:
text
指代消解;
实体提取;
意图补全;
问题改写;
结构化输出。
这些任务可以交给 7B 级别的小模型,甚至可以用量化后的小模型本地部署。
这样做的好处是:
text
延迟更低;
成本更低;
吞吐量更高;
更适合高并发场景;
可以减少对主大模型的调用压力。
一种比较合理的企业级分工是:
text
小模型:负责意图分类、Query Rewrite、路由判断;
Embedding 模型:负责向量化;
Rerank 模型:负责结果重排;
大模型:负责复杂推理和最终回答。
如果用户问题太短、关键词不充分,还可以用 HyDE 辅助召回。
HyDE 的全称是 Hypothetical Document Embeddings,可以理解为"假设性文档嵌入"。它的思路是:
text
先根据用户问题生成一个假想答案或假想文档;
再用这个假想内容去做向量检索。
例如用户问:
text
GraphRAG 相比传统 RAG 还有哪些优势?
系统可以先生成一段假想内容:
text
GraphRAG 的优势可能包括实体关系建模、全局知识组织、多跳推理、社区结构分析和复杂问题理解能力。
然后用这段假想内容去做向量检索,从而增强召回。
但 HyDE 也有风险:
text
可能生成错误假设;
可能引入上下文中不存在的信息;
可能导致检索方向偏移。
所以 HyDE 更适合作为召回增强手段,不能直接当作最终答案依据。最终答案仍然应该基于真实检索到的知识库内容生成。
综合来看,一个稳定的多轮对话 RAG 系统,不只是"用户问一句,系统搜一下"。它应该具备完整的上下文理解、指代消解、查询改写、混合召回、结果重排、低置信度追问和话题切换识别能力。
可以把整个系统理解成下面这条链路:
text
用户省略问题
↓
判断是否依赖上下文
↓
提取最近几轮核心实体
↓
生成 Standalone Query
↓
低置信度时追问用户
↓
高置信度时进入混合检索
↓
Rerank 重排
↓
组装可靠上下文
↓
大模型基于证据生成回答
最后总结一下:
text
多轮 RAG 的关键不是直接搜索用户原话,
而是先结合上下文补全用户真实意图,
再生成一个可以独立检索的问题,
最后通过混合检索和重排找到可靠依据。
也就是说,多轮对话 RAG 的本质不是"更复杂的搜索",而是让系统先理解用户在上下文里真正想问什么,再把这个问题转换成检索系统能够准确处理的表达。
总结:三个问题背后的共同工程思想
这三个问题表面上分别属于模型部署、应用架构和检索系统,但它们背后的工程逻辑是一致的:
text
量化解决的是如何让模型更轻、更快,同时控制精度损失;
Workflow 与 Agent 解决的是如何让大模型应用既灵活又可控;
多轮 RAG 解决的是如何把用户不完整的自然表达转成可检索、可验证的问题。
最终可以归纳成一句话:
text
大模型应用真正难的地方,不只是让模型"会回答",
而是让模型能力在工程系统中稳定、可控、可观测、可优化地发挥作用。



