跳到主要内容

5 篇博文 含有标签「reproducibility」

查看所有标签

离职工程师带走的微调产物

· 阅读需 12 分钟
Tian Pan
Software Engineer

一个微调(fine-tune)不仅是一个文件。它是训练集上流水线的闭包(closure),如果一个团队在交付文件时没有提供这种闭包,那么他们就构建了一个生产依赖,其源代码其实只存在于某个人的脑子里。当那个人带着两周的离职通知和一份整洁的交接文档离开的那天,你某个收入相关特性的巴士系数(bus factor)就降到了零,而且没人会察觉,因为权重依然在注册表中,注册表标签依然稳定,模型也依然在处理流量。清算会在以后出现,比如在一次常规的基座模型迁移中,原本应该只需要一个 sprint 的工作却耗费了一个季度。

在我观察到陷入此困境的团队中,这种模式是一致的。一名 ML 工程师花了六个月时间迭代一个微调模型——包括数据策展(data curation)、超参数搜索、以及根据感觉在留存集上评估的行为补丁(behavioral patches)。最终的适配器(adapter)权重被推送到模型注册表并打上标签。而产出这些权重的训练流水线,只是该工程师笔记本电脑里的一个 Notebook,里面充斥着硬编码路径和浮动依赖,这些依赖指向的是每个单元格最后一次执行当天的最新版本。团队理所当然地接受了交接,因为权重有效、评估分数不错,且注册表标签很稳定。18 个月后,该工程师离职了。又过了 6 个月,一次基座模型迁移需要针对更新后的基座重新生成适配器。此时 Notebook 运行后生成的权重分数降低了 3 分,并且在最困难的客户细分领域出现了明显的性能退化,团队花了 4 个月时间尝试复现原始产物,但最终以失败告终。

客户无法复现的隐形个性化层

· 阅读需 12 分钟
Tian Pan
Software Engineer

一个平台团队发布了一项质量改进。推理阶段的一个图层会读取用户的近期交互记录,并悄无声息地调整响应风格:这里更正式一些,那里更简洁一些,或者当历史记录显示是一个工程师在提问时,响应会更具技术性。A/B 测试显示,整体满意度提升了几个百分点。发布公告的标题是“更智能的响应,无需更改 API”。没有人修改 API 中的标志位。没有人更新文档。响应内容中也没有任何迹象表明模型刚刚采用了哪种人格。

六周后,一位企业客户提交了一个支持工单,称“你们的模型比宣传的要差”。他们的内部评估套件——运行的是你们团队发布基准测试时所用的相同提示词——得分低了 8 分。你团队的第一步是核实提示词的一致性。提示词完全匹配。解码参数匹配。模型版本字符串也匹配。差异最终追溯到了个性化层,它为客户新开设的测试账号推断出一个“历史记录贫乏的默认人格”,而为你衡量基准测试的长效用户账号推断出了一个更丰富的人格。关于个性化究竟是功能还是缺陷的讨论,不再仅仅是一个产品决策,而演变成了一场合同谈判。

你的评估套件设置了确定性种子,但供应商却悄悄忽略了它

· 阅读需 13 分钟
Tian Pan
Software Engineer

你设置了 seed=42。你设置了 temperature=0。你记录了运行情况,发布了仪表板,并在模型更换上签了字。第二天早上,重新运行相同的提示词却返回了不同的数字,你给出的解释——“肯定是采样噪声”——错得离谱:根本没有采样,而且噪声是结构性的。Seed 离开了你的客户端,网关将其丢弃,内核将你的请求与 17 个不相关的请求打包在一起,浮点归约(floating-point reduction)顺序在你眼皮底下发生了变化。你所谓的“可复现”基准测试,距离变成另一个基准测试其实只差一个批次(batch)。

这种失败模式是悄无声息的,因为技术栈中的每一层在技术上都是正确的。SDK 接受了 seed。供应商记录了 seed。模型返回了 system_fingerprint。评估工具记录了这三者。没有 5xx 错误,没有警告,没有抗议。仪表板上的数字只是发生了偏移,而团队将这种偏移合理化为一直存在的某种抖动——因为他们没有工具能告诉他们,他们看到的究竟是随机解码(stochastic decoding),还是导致三周的对比实验全部失效的后端轮换(backend rotation)。

没有复现步骤的故障工单:可复现性是工程化的结果

· 阅读需 11 分钟
Tian Pan
Software Engineer

这张故障工单具有只有真实事故才具备的典型特征。在 02:14,支持代理关闭了一个本应进入 30 天宽限期的客户账户。客户发现了。工单落到你的桌面上,“复现步骤”一栏下面只有一行字:未知

你打开追踪记录。你看到代理调用了 close_account 而不是 set_grace_period。你看到工具执行成功了。你看不出的是模型为什么选择了那个分支 —— 而且当你通过同一个代理重新运行同一条客户消息时,它做出了正确的选择。做了两次。现在的事故复盘报告中,原本该写根本原因的地方出现了一个段落大小的空洞,而你唯一能诚实写下的只有“无法复现”。

确定性重放:如何调试永远不会以相同方式运行两次的 AI Agent

· 阅读需 12 分钟
Tian Pan
Software Engineer

你的 Agent 上周二在生产环境出了故障。一个客户报告了错误的回答。你调出日志,看到最终输出,也许还有几条中间的 print 语句——然后你就卡住了。你无法重新运行 Agent 来重现同样的故障,因为模型不会产生相同的 token,你的工具调用的 API 现在返回了不同的数据,嵌入在提示词中的时间戳也已经变了。Bug 消失了,你只能盯着间接证据发呆。

这就是 AI Agent 的根本调试问题:传统软件是确定性的,所以你可以通过重建输入来复现 bug。Agent 系统不是。每次运行都是模型采样、实时 API 响应和时间依赖状态的独特组合。没有专门的工具,事后调试就变成了取证猜测。

确定性重放通过在执行过程中记录每个非确定性来源,并在重放时替换这些记录来解决这个问题——把你无法复现的 Agent 运行变成你可以像调试器一样逐步跟踪的东西。