Skip to main content

金融语音 Agent 后训练实战:从 SFT 到 GRPO 的踩坑全记录

原文:金融行业实时语音聊天机器人后训练经验贴

这篇文章是基于知乎原文的深度扩写。我以第一视角重新梳理了一个金融实时语音 Agent 从架构设计、模型选型、SFT 到 GRPO 微调、上线部署的完整后训练过程——把每一个踩过的坑和最终有效的解法摊开来拆解清楚。


这篇文章说了什么

我为一个金融客户构建了一套实时语音聊天机器人,从架构搭建、模型选型,到 SFT 与 GRPO 微调、上线验证,完整走过了 LLM 后训练的全过程。技术栈是 ASR → LLM Agent → TTS 的端到端语音对话,最终做到了 p99 延迟 1.5s。

这篇文章围绕三个核心挑战展开:如何在延迟和智能之间平衡(不得不分层)、如何构造高质量训练数据(真实录音的噪声处理)、如何让模型真的"能落地"(不要做脱离实际生产的调参)。重点是 Orchestrator 的 GRPO 微调——路由准确率从 87.1% 拉到 98.4%。


两个回合下来,有效的实验就这几招

方法做了什么效果
双层 Agent 架构Orchestrator(Qwen2.5-7B)做调度 + 复杂 Sub-Agent(Mixtral-8x22B)做推理,"先响应后执行"用户感知延迟压缩到 1.3s 内,复杂任务不卡交互
跨语言分层处理小模型负责 Hindi/Hinglish 的语言理解与生成,大模型只处理英文推理大模型专注推理不背多语言负担,系统又快又好
ASR 噪声注入训练构建 ASR 错误模拟器,分析 Whisper 典型错误后注入 10% 噪声到训练数据路由 micro-F1 从 81.2% 提升到 90.9%
复合 reward 函数路由准确性(0.3) + 响应自然度(0.4) + 延迟惩罚(0.3) 三项加权GRPO 后路由准确率 87.1%→98.4%
实体识别预训练5,000 条 NER 数据先训练日期/金额/账号提取,再训练工具调用API 参数准确率 85%→96%
模型选型全面对比Llama3-8B vs Gemma2-9B vs Qwen2.5-7B vs Mistral-7B 逐个测试Qwen2.5-7B 综合最优(格式错误率低至 3%,多语言稳定)

试了但翻车的方法:学习率 5e-6(Hindi 能力退化)、LoRA rank=16(容量不够路由 88%)、单一大模型方案(延迟+成本双高)。


一、先搞懂这些概念

1.1 Agent 架构是什么

这是一个 ASR → LLM Agent → TTS 的端到端语音对话系统。五个环节:

用户说话 → WebRTC → ASR(Whisper) → Agent(LLM) → TTS(Polly) → WebRTC → 用户听到

看起来简单,但最大的挑战是延迟与准确率的 trade-off——用户不能等,但大模型推理本身就慢。最终 VAD 后 p99 延迟 1.5s:ASR 0.25s + LLM 0.35s + TTS 0.8s。

1.2 双层 Agent 架构是什么

一开始考虑过用单一大模型处理所有问题,很快发现不行:

问题具体表现后果
响应速度大模型推理慢用户等待时间 >2s,体验差
成本所有请求都走大模型token 成本不可持续
灵活性简单查询和复杂诊断用同一模型资源浪费

所以我设计了一个双层 Agent 架构——Orchestrator + Sub-Agent。打个比方你就明白了:

Orchestrator 是银行大堂经理。 你进门说「我要取钱」,他立刻回复「请跟我来」然后带你到 ATM——响应快,不需要行长出面。你说「我昨天的转账出问题了」,他先说「我让后台查一下,大概需要半分钟」然后走到后台找风控专员——先给你安心,再去做重活。

用一段实际对话走一遍,你就能看懂这套架构怎么运转:

用户:「I didn't receive my withdrawal yesterday, what happened?」(我昨天取的钱没到账)

VAD 后 0~1.3s:
Orchestrator 立刻回复:
"I understand you haven't received your withdrawal yesterday.
Let me run a quick check; it may take up to half a minute, please hold on."

VAD 后 1.3s~15s:
Orchestrator 调用 investigate_payment_issue(复杂 Sub-Agent)
→ Sub-Agent 多步推理:
Step 1: 查交易历史 → 找到未到账记录
Step 2: 查交易详情 → 付款已发出
Step 3: 查支付网关 → 网关正常
Step 4: 查银行状态 → 银行 API 挂了
Step 5: 输出根因:银行端故障

VAD 后 15s:
Orchestrator 组织语言回复:
"我查到您的转账已从我们这边成功发出,但收款银行目前系统
在处理延迟,预计 2 小时内恢复,您的钱会自动到账。"

关键设计点:Orchestrator 永远先给即时反馈,再执行任务。用户不会觉得系统在发呆。

1.3 跨语言处理策略

这个项目要支持三种语言:English / Hindi / Hinglish(Hindi + English 混合)。关键设计是大小模型语言分工

  • Orchestrator & 简单 Sub-Agent:需要支持 Hindi/Hinglish,因为直接跟用户对话
  • 复杂 Sub-Agent:只需要 English,因为做的是推理和 API 调用

为什么不让大模型也支持多语言?因为 prompt 里适配多语言会让推理难度更高、速度更慢,而且 post-train 大模型支持多语言通常要更多的训练数据、质量还不稳定。纯英文的大模型在推理上往往更强。

实际运转是:用户说 Hindi → 小模型翻成 English 给大模型 → 大模型用 English 推理 → 小模型翻回 Hindi 回给用户。


二、模型选型:五个候选的全面对比

2.1 Orchestrator 选型:为什么是 Qwen2.5-7B

五个候选全测了:

模型问题为什么不能用
Gemma-2-9B对英文倾向性过高,Hindi 敬语不稳定,经常语言切换金融场景混语是刚需
Mistral-7B语言漂移严重,需要复杂 prompt 压制prompt 越长推理越慢,得不偿失
Llama3-8B指令遵从弱,tool call 格式错误率高格式错误 = 工具调用失败 = 用户体验一票否决
BLOOMZ-7B1混合语言能力最强,但翻译腔严重few-shot 也压不住翻译腔
Qwen2.5-7Btool call 时偶尔把字段名翻成 Hindi用 prompt 就能有效避免

Qwen 的两个关键指标:

  • Valid Tool Call Rate 低至 3%:Orchestrator 调用 MCP tools 时需严格按格式输出,Qwen 的指令遵从在我们测试中最好。以 JSON Schema + 约束解码 + 校验修复链保障,格式类错误自动修复 ≤ 2 次。
  • 微平均 F1 比 Llama3-8B 高 8%:意图识别是 Orchestrator 的核心,这个差距就是上线和不能上线的差距。

2.2 复杂 Sub-Agent 选型:为什么是 Mixtral-8x22B

维度Mixtral-8x22BLlama3-70B
复杂诊断多步推理 Exact Match@K高 10%
未 tune 格式正确率>95%~80%
p95 推理延迟快 20%
总推理成本低 30%

Mixtral 的 MoE 架构在复杂推理里表现出色——不同的 expert 负责不同的推理步骤,不会像 Llama3 那样在多步推理中间步骤"跳步"。而且虽然标称 22B×8 experts,但实际激活参数只有 44B+shard,成本比 70B 模型低 30%。


三、SFT 阶段:数据构建和两个清洗 trick

3.1 数据构建流程

数据来源:400+ 小时脱敏客户客服录音 → Whisper 转写 → AI+人工标注

标注步骤做什么
Step 1Whisper 转写录音为文本
Step 2标注意图类别
Step 3标注应该调用的 MCP tool / Sub-Agent
Step 4插入 Orchestrator 初始响应文本

额外用闭源大模型生成了 2,000+ 条 Hinglish code-switching 样本做数据增强。最终数据集:训练 6,000 / 验证 700 / 测试 300。

3.2 Trick 1:ASR 错误噪声注入

:Whisper 在 Hindi/Hinglish 上准确率约 90%,典型错误如 withdrawal 常被识别成 wish。如果直接用含错数据训练,模型会学到错误模式。

解法:构建了一个"ASR 错误模拟器",分析 Whisper 典型错误类型(口音/同音/混语各 2,000),构建噪声仿真集。在训练数据的用户输入部分注入 10% 的错误。

Trick 的逻辑是:不是去修 ASR,而是让 LLM 见过这些错误。 模型训练时就见过 wish 代表 withdrawal,推理时再遇到就不会被带偏。

效果:Orchestrator 路由 micro-F1 从 81.2% → 90.9%。

3.3 Trick 2:意图标注一致性

:同一个 prompt「我的 withdrawal 怎么还没到」可能被标为 withdrawal_status_query(简单查询)或 withdrawal_issue_diagnosis(复杂诊断)。标注不一致让模型困惑。

解法

  • 建立决策树规则库:问"状态"= 简单查询,问"出什么问题/为什么"= 复杂诊断
  • 多轮专家审核不一致样本
  • 主动学习:用已训练模型预测新数据,找出概率低于 0.7 的样本优先标注

四、GRPO 微调:Orchestrator 的路由准确率 87.1%→98.4%

4.1 为什么需要 GRPO 而不是只做 SFT

SFT 只能教模型「给你一个输入,输出应该是什么」,但 Orchestrator 的任务不是简单的输入→输出。同一个 prompt,可能多个 MCP tool 都合理,需要模型选最优的那个。SFT 教不了「在这些选项中选最好的」。

GRPO 恰好适合:不需要昂贵的人工偏好标注,只需要定义 reward 函数,让模型自己试、自己比较、自己优化。

4.2 Reward 函数设计

这是 GRPO 的灵魂。我设计了一个复合 reward:

R = 0.3 × R_routing + 0.4 × R_fluency + 0.3 × R_latency
维度权重怎么算为什么
路由准确性0.3模型选的 Sub-Agent 跟标注一致 → +1,否则 → -1这是核心目标,但权重太高会过拟合
响应自然度0.4闭源大模型打分 0-1,评估初始响应是否自然、友好金融场景客户体感最重要
延迟惩罚0.3response token 低于 50 → +1,50-100 → 0,超过 100 → -1强制 Orchestrator 简洁,超时扣分

路由权重不高反而让准确率更高——因为过度追求路由正确会牺牲自然度,用户听到的是"生硬但正确"的回复,体验反而差。

4.3 训练超参数和调参教训

学习率:3e-6(不是常见的 5e-6)
Batch size:32
LoRA rank:32(不是 16)
LoRA alpha:64
Epochs:4
优化器:AdamW

三个关键调参决定:

参数初始值现象最终值原因
学习率5e-6微调初期 Hindi 能力退化,只能说 English3e-6训练数据 Hindi 占比不高,高学习率导致灾难性遗忘多语言知识,冻结 embedding 层保持多语言稳定
LoRA rank16路由准确率只有 88%,容量不够32增加到 32 拉升到 94%;试过 64 没进一步提升但训练时间 +50%,没必要
Epochs第 3 个 epoch 后验证 reward 收敛,第 4 个 +1.2%4边际收益递减,不做更多 epoch 防止过拟合

4.4 最终效果

指标Base ModelGRPO 后提升
路由准确率78%94%+16%
响应自然度3.2/54.5/5+1.3
平均响应长度85 tokens42 tokens-50%
线上用户满意度+18%
线上响应速度+32%

五、简单 Sub-Agent 微调:工具调用的两个坑

5.1 坑一:API 参数提取不准确

日期、金额等实体提取频繁出错:

用户:「show me transactions from 1st January to 31st March」
模型应该输出:start_date="2025-01-01", end_date="2025-03-31"
模型经常输出:start_date="January 1", end_date="March 31"(缺少年份+格式错)

解法:在训练工具调用之前,先用 5,000 条 NER 数据做实体识别预训练,让模型先学会提日期、金额、账号。然后结合约束解码 + 参数校验器,参数准确率 85% → 96%。

5.2 坑二:生产日志中的脏数据

生产日志里很多 API 调用缺少必需参数:

{
"api": "get_transaction_history",
"params": {
"start_date": "2025-01-01"
// 缺少 end_date
}
}

不完整的样本会污染训练数据。解法:训练前先跑一遍参数完整性校验,筛掉缺必需参数的样本。额外用闭源大模型补齐 2,000+ 条覆盖边界情况的合成样本(缺失参数、格式错误等)。


六、Insight 提炼

6.1 延迟是语音 Agent 的一票否决项——架构设计优先于模型选择

用户对语音交互的等待容忍度是秒级。不管模型多聪明,超过 2 秒不回应就是失败。所以「先响应后执行」不是锦上添花,是架构必须项。双层 Agent 的核心逻辑不是「大模型做难事小模型做简单事」,而是「用瞬时反馈买推理时间」。

6.2 跨语言策略的核心原则:让模型各司其职

不要妄想一个大模型同时搞定多语言理解和复杂推理。让大模型专注做它最擅长的(英文推理),让经过多语言微调的小模型做语言理解和翻译。这样做的代价很小(小模型翻译开销可忽略),收益很大(大模型不背多语言负担,推理又快又准)。

6.3 训练数据噪声不是坏事——关键是让模型见过噪声

ASR 错误是语音系统的常态。不应该花无限精力去提升 ASR 准确率,而应该在训练数据里注入噪声,让 LLM 学会在噪声下理解意图。效果上,10% 的噪声注入就让路由 micro-F1 从 81.2% 跳到 90.9%,远超继续优化 ASR 的边际收益。

6.4 GRPO reward 设计:复合权重比单一指标更稳

不要只 reward 准确率。对生产系统来说,自然度和延迟跟准确率同等重要。0.3/0.4/0.3 的权重分配是因为:自然度 > 路由准确 > 延迟控制(自然度权重最高,因为语音场景用户感知最直接)。单一维度的 reward 会导致模型在一个指标上过拟合,牺牲用户体验。

6.5 模型选型不要只看 benchmark

五个模型全测的结果是 Qwen2.5-7B 胜出——不是因为它的 benchmark 最高,而是因为它在实际场景的指令遵从和多语言稳定性上最好。Llama3-8B 在通用 benchmark 上分数不低,但在 tool call 格式上频繁出错,这种事情 benchmark 测不出来。

原文链接:https://zhuanlan.zhihu.com/p/1967407474224108408