数字人平台要听懂一句口语,然后把它变成结构化的工具调用——比如「去 A 栋 3 楼」要变成一段带 actionCode 与参数的 JSON。
先问:真的需要大模型吗
最初的方案参考了一个 27B 的 ReAct 智能体:让大模型自己挑工具、填参数、多轮推理。问题是它要占掉四张显卡,而且部署到现场机器上根本跑不起来。
拆开来看,这个任务只有两件事:判断用户想干什么,以及把参数填对。前者是意图分类,后者是槽位抽取,都在小模型的舒适区里。真正需要"知道"的那部分——目标在哪、参数意味着什么——本来就该由工具层回答,而不是让模型去背。
把一个 1.7B 的模型微调成「口语 → 结构化指令」的转换器,比让 27B 去做它不擅长的事更划算:显存从四张卡降到一张,单次训练 80 秒。
最关键的一个决定:坐标不进模型
直觉上会把经纬度、建筑坐标直接写进训练数据,让模型学会输出。试过之后有两个问题:模型背不准长浮点数(差一位小数就是几百米),而且这些值在运行时是会变的。
最后的做法是让模型只说人能说出口的话——「A 栋」「三楼」「左边那栋」;坐标、运行时 ID、真实资源路径这些机器知识,交给飞渡平台的工具层在调用时解析。
这条边界一划,训练数据规模、模型体积,以及最要紧的——出错概率,全都降下来了。
数据:少而准,还要有反例
几百条样本,按意图分布配比,并刻意加入两类反例:闲聊(不该触发任何动作)与问句(早期版本见到「楼里有 wifi 吗」就去导航,因为训练集里问句太少)。楼层归一化也是数据问题:"三楼""3 层""负一层"要统一成同一种表示。
怎么判断它真的学会了
不看训练损失,看三组互不重叠的评测:分布内(与训练集同分布)、泛化(换一种说法,含多槽位复杂句)、反例(不该触发的输入)。三组全绿才算过。
这套评测后来变成了一个循环:飞渡的动作目录新增一条 → 加几十条样本 → 重训 80 秒 → 重跑三组评测。迭代成本低到可以在一个下午里试好几个想法。
两个工程结论
第一,存适配器而不是合并模型:训练产物是 82MB 的 LoRA 适配器,而合并后的完整模型是 3.3G——在带宽受限的链路上一来一回差了四十倍,而且适配器可以版本化、可以对比。
第二,把训练做成幂等脚本:显存检查、环境变量、启动参数全部固化,避免"这次能跑、上次不能"的玄学。
微调的价值往往不在模型本身,而在你敢不敢把边界划清楚——哪些交给模型,哪些交给它身后的系统。