English interface selected · this article is currently written in Chinese.
模型交付后为什么表现变了:模板、量化与行为回归
English overview →具备清晰骨架、初步数学推导或工程验证,持续补充论据与实测。
数字花园
🌿 什么是数字花园与思想演进?
遵循 Maggie Appleton 与 Andy Matuschak 的常青笔记理念:这里不是按时间沉底的流水账,而是持续修剪打磨的知识生态。文章按成熟度经历:
- 🌱 萌芽 (Seedling): 发散灵感、读书摘录、开放猜想
- 🌿 演进 (Budding): 结构渐明、初步代码推导、积极修正
- 🌳 常青 (Evergreen): 逻辑闭环、持久经得起检验的基石
- 🔬 实验待证 (Speculative): 结合沙盒与仿真探针的理论探索
训练结束后,验证脚本里的模型能够正确调用库存查询工具。换成推理服务,却开始输出普通文字,偶尔还会给出半截 JSON。权重文件明明相同,为什么表现不一样?
先不要急着重新训练。用户消息需要经过模板变成 token,模型输出还要经过采样、停止判断和解析,才成为用户看到的回答。交付改变了其中任何一步,都可能改变结果。
本文沿用库存查询这个任务:用户要 3 件 A17 商品,先查杭州,不足再查深圳,查询不等于预订。实际执行的检查只有自定义 token 协议、十进制舍入和回归计数,没有加载语言模型,没有进行真实量化或服务性能测试。下面的交付流程是待应用到真实模型的实验设计。
先确定要保持哪一种行为
行为回归是拿新版本重新做旧版本已经能做的事,检查是否出现退步。这里的“版本”不只指权重,也包括服务配置。
对于库存任务,至少有三种不同要求:调用内容能否解析、参数是否正确、整个任务是否完成。输出是合法 JSON,不代表商品编号正确;编号正确,也不代表模型遵守了先杭州后深圳的顺序。
因此,交付目标不应该只写“回答和训练时一样”。训练时通常在已有答案前缀上预测下一个 token,部署时则使用自己刚生成的内容继续回答,两者运行方式本来就不同。更合理的目标是:在固定任务、输入协议和预算下,保持已验证的能力与约束。
把原始验证环境保留为参考实现,把待交付版本称为候选实现。后续每次只改变一个环节,才能解释差异来自哪里。
从用户消息一直检查到 token
同一份 messages,在不同模板下不一定是相同输入。角色标记、消息结束标记、工具定义位置,都会进入模型看到的序列。
下面是自定义教学协议,不对应任何真实模型的词表:
BOS=1, USER=2, END=3, ASSISTANT=4“查询 A17 库存”这个完整占位内容=10
参考输入:[1, 2, 10, 3, 4]重复起始:[1, 1, 2, 10, 3, 4]缺少角色:[1, 2, 10, 3]这三组数字的中文内容看起来一样,但模型接收的序列不同。教学检查只能发现序列变了,不能证明真实模型会因此下降多少分。
Transformers 的模板文档提醒:模板通常已经包含所需特殊 token;先渲染为文本再分词时,应避免再次添加特殊 token。是否需要生成用的 assistant 前缀,也由具体模型模板决定。Transformers 4.57.1 对话模板
真实交付时,选几条可以公开保存的固定请求,同时记录原始消息、渲染文本、token ID、attention mask 和截断位置。文本一致而 token 不一致,应先检查分词器与特殊 token 配置;token 一致而输出不同,才继续向模型计算与生成过程排查。
输入一致性还包括服务有没有偷偷加入系统提示、有没有把工具说明改写成另一种格式,以及长请求超出限制时删掉了哪一段。接口字段名相同,不等于这些行为相同。
批量推理也要单独检查:一条请求独立运行,与混在不同长度请求里运行,是否仍正确处理填充、位置和掩码。不要凭经验强行统一所有模型的填充方向,应核对实际后端要求和最终张量。
权重交付要说明基座、适配器与转换关系
如果训练的是 LoRA,交付目录里可能只有适配器,并没有完整基座。PEFT 文档说明,适配器检查点需要配合原始模型与适配器配置加载。PEFT 0.17.0 检查点格式
因此要保存基座版本、适配器版本、目标模块与缩放配置。只写一个可能继续更新的模型名称,不足以锁定当时的计算。分词器或词表如果也改过,同样需要与模型配套;新增 token 的编号和相关参数不能丢失。
对标准加性 LoRA,理想实数运算下,可以把基座与增量写成:
但“分开计算再相加”和“先合并再计算”在有限精度下未必逐位一致。某些适配器方法或量化组合也不支持相同的合并方式,不能把这条式子当作任意格式转换都安全的保证。
保留未经转换的参考版本。依次比较“基座加适配器”“合并后”“量化后”,每次都记录转换工具、版本和配置。否则最终结果变差时,很难判断是哪一次转换造成的。
量化误差小,不代表任务一定不变
量化可以理解为:用更有限的一组数表示原来的数。它能减少某些存储需求,但实际速度还取决于硬件、算子与任务形状,不能仅凭位数宣布加速。
为了看清转换顺序,定义一个非常简单的函数 Q:四舍五入到最近的 0.1,遇到正数正中间时向上取。取权重 w=0.14,增量 d=0.04:
这是实际复算过的十进制反例:先合并再量化,与先量化再合并、再次量化,可以得到不同结果。它不是 NF4、GPTQ 或某种实际量化器的模拟,也不说明哪条路径在真实任务上更好。
还要区分数值偏差和决策变化。假设两个候选 token 的原始分数是 1.001 和 1.000,变换后变成 0.999 和 1.000;每个分数变化都很小,但贪心选择已经翻转。接下来的生成以这个不同 token 为条件,整段文字可能进一步分开。
所以量化验收至少看两层:固定输入下的数值差异,以及实际任务上的变化。平均误差可以帮助定位问题,却不能替代 JSON 完整率、工具参数正确率或任务成功率。也不能从一个教学反例推断所有量化模型都会严重退化。
把生成与停止规则当作交付配置
生成策略决定模型怎样从分数中选下一个 token。贪心选择与随机采样不是同一项测试;官方文档分别描述了这两种机制。Transformers 4.57.1 生成策略
比较参考版本和候选版本时,要显式记录实际生效的采样开关、温度、候选截断设置、最大新增 token 数、停止 token 或停止字符串。不同服务同名参数的默认值与实现语义可能不同,应检查最终配置,而不只保存客户端传过去的字段。
即使使用贪心生成,也不意味着跨设备、跨实现必然逐字一致;数值差异可能改变接近的候选排名。上一文的复现边界同样适用。
对于半截 JSON,先检查停止原因:是模型主动输出结束标记,还是达到长度上限、超时、服务取消,或解析器误截断?这些原因不应都记成模型“不懂格式”。
自定义协议可以把完整回答表示成三个 token:JSON_START, JSON_BODY, JSON_END。如果最大新增数只有 2,输出一定不完整;如果错误地把 JSON_BODY 配成停止 token,也会提前结束。本文脚本实际检查了这两种情况,但没有模拟模型生成概率。
不要为了提高解析率而静默修复答案,再把修复后的成绩算给原始模型。若服务确实使用补全括号、重试或二次解析,应把它们作为系统的一部分,同时报告原始失败率、修复后的成功率和额外成本。
分层回归,比只对比最终字符串更容易定位
推荐按下面顺序比较,每层失败时先停在该层排查:
| 层次 | 固定什么 | 检查什么 |
|---|---|---|
| 输入协议 | 原始消息、工具定义 | 渲染文本、ID、掩码、截断 |
| 模型前向 | 相同输入张量 | 指定位置分数、候选排名、数值容差 |
| 生成过程 | 输入与解码规则 | 输出 token、停止原因、长度 |
| 结果解析 | 同一段原始输出 | 格式、字段、类型、错误处理 |
| 完整任务 | 相同初始环境与预算 | 正确性、约束、调用次数与耗时 |
前向比较最好使用相同的固定前缀。若两个版本已经生成了不同内容,再比较后面位置的分数,会把输入变化和计算变化混在一起。
逐字匹配适合固定格式的回归样例,但不是全部质量标准。例如两个自然语言答案措辞不同,却都明确说明“深圳有货,但尚未预订”,可以都算完成任务。相反,两段文字看起来很像,也可能在 reserved 字段上有关键区别。
做一张能看见退步的配对表
假设有 100 个独立任务,下面是人为构造、已复算的计数,不是模型实测:
| 参考版本 | 候选版本 | 任务数 |
|---|---|---|
| 成功 | 成功 | 70 |
| 失败 | 成功 | 5 |
| 成功 | 失败 | 5 |
| 失败 | 失败 | 20 |
两个版本都是 75% 成功,但候选版本丢掉了原来能完成的 5 个任务。只看总分,会错过这 5 个退步。它们可能集中在工具调用、长输入或某个语言子集,不能只用另外 5 个修复抵消后就宣布等价。
真实验收前,明确哪些错误不可接受、哪些指标允许多大变化,以及用多少任务和重复采样来估计不确定性。阈值应由使用要求决定,不在看到结果后临时放宽。小样本没有发现退步,也不是已经证明两个系统等价。
对采样输出,不要只比较一个随机种子。保留同一组任务、多次运行和配对统计;对于工具任务,沿用环境重置与轨迹重放中的隔离方法,否则任务差异可能来自环境而非模型。
一次最小交付实验应该留下什么
先用少量固定样例排除协议错误,再在预先保留的任务集上比较参考与候选。依次加入合并、量化、服务批处理等变化,记录每一步的输入与输出,不把所有优化一次打开。
最终交付包至少能回答五个问题:权重从哪个不可变版本来;用哪份分词器和模板;服务实际采用什么计算与生成配置;在哪份回归集上接受了哪些差异;发现问题时怎样恢复到参考版本。
可以用文件哈希识别内容,用配置和工具版本解释生成过程,用逐任务结果支持验收结论。哈希只能帮助确认文件身份,不能证明模型正确;一份通过的回归报告也只支持它实际覆盖的条件。
这一步的研究结论应当具体到:“在这份任务集、这个预算和这些约束下,该交付版本满足预设标准。”保留失败样例和未覆盖条件,下一次换后端、改模板或压缩权重时,才有可靠的比较起点。
文章概念网络
从章节进入正文概念。实线表示所属层级,虚线连接跨章节重复出现的概念,不代表因果关系。
55 / 55 个节点 · 正文标记术语与关键词概念
模型交付后为什么表现变了:模板、量化与行为回归
回到原文 ↗最后更新于 2026-10-23
引用本文
@article{2026-10-23-llm-training-eval-05-delivery,
author = {枫语},
title = {模型交付后为什么表现变了:模板、量化与行为回归},
journal = {枫语},
year = {2026},
month = {oct},
url = {https://meiluosi.github.io/posts/2026-10-23-llm-training-eval-05-delivery/}
}