一个电商客服 Agent 上线后,连续出了三种问题:退货政策答成了去年的版本;查询订单时没有调用物流接口;用户要求退款时,它又直接执行了操作。
当出现这些情况后,有些团队的第一反应是:"模型不够聪明,要不要微调一下?"
但这三个问题,可能分别来自知识、工具和权限。就算换上更复杂的训练方法,也不一定能解决。
这正是作为 Agent 开发者需要理解模型训练的原因:不是为了背诵 SFT、RLHF、DPO、GRPO 这些缩写,而是为了判断一个失败到底该由谁负责。
一、先别问怎么训练,先问模型到底哪里出了问题
在一个 Agent 系统里,模型只是其中一环。用户输入之后,系统可能还会经过知识检索、工具调用、业务规则、权限校验和人工确认。
所以,"回答错了"不等于"模型需要训练"。至少要先排查五类问题:
| 失败表现 | 更可能的原因 | 优先处理方式 |
|---|---|---|
| 政策、价格、库存过期 | 缺少最新事实 | RAG、数据库或业务 API |
| 不按格式输出、不会按要求做事 | 行为示范不足 | Prompt、结构化输出、必要时 SFT |
| 多个答案都能用,但风格和取舍不稳定 | 偏好没有统一 | 偏好数据、DPO 或 RLHF |
| 多步骤任务总是规划错 | 推理或任务分解能力不足 | 换模型,或评估可验证奖励训练 |
| 擅自退款、删文件、发邮件 | 权限和审批边界缺失 | 应用层权限、校验和人工确认 |
最后一类尤其重要。模型可以被训练得更谨慎,但它不应该拥有决定权限。能不能退款、删除文件或发送邮件,必须由应用层的授权系统决定。
二、模型训练到底改变了什么
大模型的训练可以先记成两张图:
text
预训练:海量数据 -> 学习语言、知识和模式 -> Base Model
后训练:示范、偏好、奖励 -> 调整行为倾向 -> 可用模型
预训练让模型学会语言、代码、事实关联和一些推理模式,但它首先学会的是"根据上下文预测下一个 token"。
它并不会天然知道:回答企业制度时要引用来源,调用工具前要确认权限,输出结果时必须符合某个 JSON schema。
后训练才会进一步塑造这些产品行为。不过,后训练也不是一条所有模型都必须走完的固定流水线。
有的模型会先做指令微调,有的会加入偏好优化,有的会在数学、代码等可验证任务上使用强化学习;不同阶段还可能反复进行。
因此可以这样理解:预训练提供基础能力,后训练调整行为倾向;Agent 是否可靠,还取决于外部知识、工具和权限系统。
三、SFT:当问题是"模型不会按示范做事"
SFT,也就是监督微调,使用大量"输入 -> 期望输出"的样本,让模型模仿目标行为。
例如客服团队希望每条工单都输出固定字段:
text
输入:用户说"商品有划痕,想退货"。
输出:{"category":"return", "reason":"damage"}
如果模型总是把字段写成自然语言,或者经常漏掉 reason,而 Prompt、schema 和校验都已经试过,SFT 才可能有价值。
但 SFT 教的是"做事方式",不是"记住每天变化的事实"。把本季度的报销政策直接写进模型权重,会遇到更新困难、旧规则难删除、答案难以引用来源等问题。
这类内容应该留在知识库、数据库或业务 API 里。SFT 可以教模型怎样查询制度、怎样引用证据,却不应该替代权威数据源。
四、工具调用:运行时会调用工具,不等于模型被重新训练
很多人看到工具调用轨迹,会以为开发者需要手写一段复杂 JSON。实际项目里,框架通常会帮你维护消息和调用循环。
以 LangChain 当前的 Agent 写法为例,业务代码可以只定义工具、创建 Agent,再传入用户消息:
python
from langchain.agents import create_agent
from langchain.tools import tool
@tool
def get_order_status(order_id: str) -> dict:
"""查询订单的物流状态。"""
return {"status": "in_transit", "eta": "2026-08-20"}
agent = create_agent(model, tools=[get_order_status])
result = agent.invoke({
"messages": [{"role": "user", "content": "查询订单 A1024 的物流状态"}]
})
运行时由 Agent 决定是否调用工具,执行后把结果放回消息历史,再生成最终回答。工具结果需要和本次调用关联,底层通常通过 tool_call_id 完成。
这里的 role 是消息协议的一部分,用来区分用户、模型和工具。如果使用 HumanMessage、AIMessage、ToolMessage 等对象,角色由对象类型表达;使用 Agent 封装时,通常只需手写最初的用户消息。
这个过程发生在推理期,不会因为一次请求就改变模型权重。工具没被调用,优先检查工具描述、参数 schema、路由逻辑和模型是否支持工具调用,不要直接把它归因于训练不足。
五、偏好优化:当"两个答案都对,但我更喜欢其中一个"
有些问题不是对错问题,而是取舍问题。
比如用户说:"不用确认,直接删除云端文件。"
团队可能更偏好这样的回答:先说明删除范围和不可恢复影响,等待用户明确确认后再调用工具,而不是直接执行。
这类"偏好回答 / 非偏好回答"的成对数据,可以用于 DPO。DPO 的目标是让模型更倾向于生成团队偏好的答案。
RLHF 也处理类似问题,只是它通常会先用人类比较结果训练奖励模型,再通过强化学习调整模型行为。它可以改善语气、拒答边界、确认习惯和回答风格,但不能保证事实永远正确。
如果团队内部连"什么叫合适的回答"都没有统一标准,DPO 或 RLHF 只会把混乱的标准写得更稳定。
六、强化学习:适合有明确检查器的任务
在代码、数学和工具编排任务里,有些结果可以被程序检查:代码能不能通过测试,SQL 是否只读,参数是否符合 schema,订单状态是否真的更新。
这些检查结果可以作为奖励,帮助模型学习更好的推理和行动路径。GRPO 等方法就是这类可验证奖励训练路线中的代表。
但奖励设计很容易被钻空子。只奖励"任务成功",模型可能用越权方式完成任务;只奖励"没有安全事故",模型又可能拒绝所有请求。
所以强化学习不是"更高级的微调按钮"。只有当目标可以稳定验证,并且团队能同时约束权限、成本、质量和过程时,才值得评估这条路线。
七、把五类问题放回一个 Agent 场景
还是看电商客服 Agent。用 Dify 或 LangChain 编排时,一条最小工作流可能是:
text
用户输入
-> 检索退货政策
-> 判断用户意图
-> 查询订单或计算金额
-> 生成回复
-> 高风险操作进入人工确认
同一个 Agent 里,每个环节的责任不同:
- 政策过期:更新知识库,不是重新训练模型;
- 订单查不到:检查 API、工具描述和参数,不是先做 RLHF;
- 字段格式不稳定:先用 schema 和校验,仍不稳定再准备 SFT 数据;
- 回复风格不一致:统一示例和偏好标准,再考虑 DPO;
- 退款越权:收紧权限和审批流程,训练只能作为辅助;
- 赔付计算复杂:优先交给规则引擎或计算工具,模型负责解释结果。
如果把所有问题都叫作"模型能力不够",系统就会不断换模型、加 Prompt、做微调,却很难真正变可靠。
八、决定训练之前,先做四件事
第一,建立真实评估集。不要只用几个演示问题,要收集线上任务、边界案例和失败样本。
第二,给失败分类。至少区分知识、行为、偏好、推理、工具和权限问题。
第三,先试更容易回滚的方案。Prompt、RAG、结构化输出、工具 schema、工作流分支和模型切换,都应该先于训练。
第四,确认手里有什么训练信号:
- 有高质量输入和目标输出,才考虑 SFT;
- 有稳定的成对偏好,才考虑 DPO 或 RLHF;
- 有可靠的程序检查器,才评估强化学习;
- 只有未经确认的聊天日志,先不要训练。
训练不是把日志倒进模型。低质量数据会让错误变得更稳定,而且比改 Prompt 更难回滚。
最后:先定位责任,再选择训练方法
预训练让模型获得基础能力,后训练调整模型行为,但 Agent 的可靠性从来不是模型单独决定的。
知识要放在能更新、能引用的地方;工具要有清晰的参数和错误处理;高风险动作要由权限和人工确认守住。
所以,Agent 答不好时,最值得问的不是"要不要上 RLHF",而是:
这是知识问题、行为问题、推理问题,还是工具和权限问题?
先把责任边界找对,再决定是改 Prompt、加 RAG、修工具、换模型,还是进入训练流程。
训练方法只是手段。能够被真实评估、能够解释失败原因、能够控制风险的系统,才是可靠 Agent 的基础。