我的 LoRA 更会选路由了,JSON 却更不可靠了

微调之后,我的小型路由模型更擅长返回预期字段,却略微更不擅长输出合法 JSON。

在 576 条留出的合成请求上,严格全字段通过率从 7.6% 升到 47.2%,JSON 合法率却从 98.6% 降到 95.5%。提高总分的同一个适配器,也制造了更多严格解析器读不懂的回答。

我公开了 MLX 适配器和复现包、合成数据集,以及检查冻结输出的 Kaggle Notebook。这次实验值得留下的,是这个取舍,以及可以逐项检查它的证据。

任务:把请求变成一个小型路由决策

实验用 Qwen2.5-0.5B-Instruct 处理英文、中文和中英混合请求。输出契约覆盖笔记、日程、计算、需要澄清的请求和不支持的请求。

一次回答要通过好几层检查:能被严格解析为 JSON,符合允许的 schema,选对路由,并且所有字段值与预期完全一致。通过前一层,不保证通过后一层。解析器能读懂一个编造的路由,schema 校验器也可能放过一个类型正确、值却错误的字段。

基座模型和适配器的提示词都包含 schema,双方都不需要猜一个隐藏接口。

这是一项个人合成实验。不同划分的模板仍共享词汇,各语言版本也由同一个作者编写。它不能衡量开放领域助手的能力或生产路由系统的可靠性。

按模板家族划分,还不够

第一版先划分模板家族,再展开语言变体。这样避免了同一个例子的直接译文同时进入训练集和测试集,却留下了另一个问题:相关家族仍可能描述几乎相同的场景。

完整的日程请求和缺少时间的同类请求,应归为一组。家族编号不同,并不会让它们成为独立场景。

在 v2 中,我把 77 个家族归入 23 个明确的场景簇,纳入改写,以及信息完整和信息缺失的同类请求。先划分场景簇,再展开英文、中文和混合语言版本。最终得到 1,026 条训练数据、291 条验证数据和 576 条测试数据。测试集覆盖七个留出场景簇中的 23 个家族。

这些场景簇是有记录的人工判断,并不是语义独立性的证明。我在 v2 运行前冻结了划分清单,将 v1 保留为单独的历史。v1 和 v2 的测试分数不能直接比较。划分变化及审计见公开复核记录。

有一个结果影响很大:整个 percent_of 场景被分到了测试集,训练集从未教过模型这项运算。因此,计算成绩里包含了训练之外的探测,不能把它当成对熟悉计算任务的普通抽样。

结果取决于到底在算什么

冻结的 v2 测试得到以下四舍五入后的百分比:

检查项 基座模型 LoRA 适配器
严格 JSON 合法 98.6% 95.5%
符合 schema 40.6% 95.0%
路由正确 35.6% 72.2%
严格全字段匹配 7.6% 47.2%
跨语言一致且正确 2.6% 43.1%

基座模型通常能输出可解析的 JSON,却经常使用契约之外的字段或路由。适配器学会了更多接口约束,也更常选对路由;与此同时,可解析性退步了。

严格全字段匹配要求输出符合 schema、通过类型检查,并且值与预期完全相同。评分器拒绝重复键、非有限数值、Markdown 代码围栏和额外文字,也拒绝 Python 中容易混过去的类型关系:true 不算整数 1,3.0 也不能满足只接受整数的字段。

冻结评分器将操作数顺序作为标准答案契约的一部分。另设的 commutative_ok 指标用于诊断,不会悄悄取代主指标。在这次 v2 运行中,它没有挽回任何仅由操作数交换造成的失败。

验证集的严格准确率几乎没有变化:基座为 25.4%,适配器为 25.8%。测试集的大幅提升主要集中在笔记和日程。把 47.2% 的总通过率理解为普遍改善,会掩盖这种不均衡。

失败改变了下一轮实验的方向

适配器的严格计算成绩为零。面对留出的百分比请求,它输出了熟悉的 div 或 add 等运算。它学会了一些有用的路由模式,却没有通过这份训练集获得缺失的运算。

澄清和拒绝也很弱,两者的路由准确率约为 24% 和 47%。信息不足的请求,仍经常被当成可以直接执行的动作。即使总分看起来不错,这种行为在真实系统里也很要紧。

我最初把适配器的全部 26 条非法 JSON 输出归因于未见运算。后来一次追问促使我重新统计原始冻结预测,发现这个解释说过头了。更正后的分类如下:

标准任务 非法 JSON 输出数
使用 percent_of 的计算 13
缺少一个数值、需要澄清的百分比请求 10
信息不足、需要澄清的笔记请求 3

最后一组包含重复键或截断。测试中的其他家族没有产生非法 JSON。按语言计,英文八条、中文九条、混合语言九条。

这个更正会影响诊断。只给未见运算增加训练样本,不能解释信息不足的笔记请求为何失败。我会单独测试缺失信息的处理,并检查重复键输出,再决定改什么。

上述分类以仓库根目录更正后的复核记录为准。现有 experiment.zip 和 Kaggle 冻结包仍包含较早的复核文字,输出、权重和总体分数没有变化。这是一次重新计数,没有重新训练。

实际运行了什么

训练使用 MLX,在本地 Apple silicon 上完成。公开适配器采用 MLX-LM 格式,既不是独立模型,也不是 PEFT 适配器。

基座为 Qwen/Qwen2.5-0.5B-Instruct,固定修订为 7ae557604adf67be50417f59c2c2f167def9a775。LoRA rank 为 8、scale 为 20、层数为 16,学习率 1e-4,batch size 为 1,迭代 1,500 次,seed 为 42。我按声明使用最终 checkpoint,没有根据测试成绩挑选。

评测在新进程中重新加载保存的适配器。两组使用相同提示词、贪心解码和 96 token 输出上限。相同 seed 的第二次训练得到逐比特一致的适配器,没有重复评测。这验证了该设置下的可重复性,没有验证跨 seed 或跨环境的稳健性。

测试集只有七个场景簇。公开的按家族 bootstrap 估计中,严格准确率区间很宽:基座约为 1--16%,适配器约为 28--67%。576 条数据包含语言三元组和相关例子,不能把它们视为 576 个独立的真实场景。

两种不同的复现方式

如果只想检查评分、不运行模型,可以使用 Kaggle 冻结输出 Notebook。它读取保存的预测,检查冻结产物,并在 CPU 上重新计算分数。成功的云端运行证明了这条评分路径可行,没有证明云端训练或推理性能。

要在兼容的 Apple silicon 上重跑训练,请遵循模型仓库说明。下载仓库后,在仓库根目录解压 experiment.zip:

bash 复制代码
unzip experiment.zip
cd reproduction
bash scripts/run_all.sh

脚本会安装固定版本的依赖、下载固定修订的基座、重新生成数据、检查评分器、训练、重新加载适配器,并评测两组。新运行的输出与公开的冻结输出分开保存。耗时和内存取决于机器。

代码、数据和适配器以 Apache-2.0 发布,附许可和 notice 文件,不重新分发基座权重。理解失败归因时,应同时阅读更正后的根目录复核记录和历史包。

接下来我会改什么

我会保留这份测试不动,另做实验研究它暴露的弱点:缺失信息的请求、不支持的请求,以及训练里没有出现的运算。我也会在同一批请求上比较普通解码和受约束输出,分别报告格式合规和字段正确性。

这些实验尚未运行,它们回答的问题也与这次发布不同。

这次适配器对既定路由契约的整体表现更好,却仍未通过任何严格留出计算测试,而且合法 JSON 更不稳定。在决定是否把它接到 API 后面之前,我希望这三个事实都摆在眼前。


作者:Renchao Wu | 原文:我的 LoRA 更会选路由了,JSON 却更不可靠了

相关推荐
小蒋观天下6 小时前
厂区人员徘徊游荡判别——基于时序轨迹速度的逗留行为分级算法落地
大数据·人工智能·深度学习·算法·机器学习·ai大模型
ITOM运维行者6 小时前
WAN监控怎么做?从链路质量指标到路径级定位的完整方法
数据库·人工智能·机器学习
Rocky Ding*6 小时前
DeepSeek-Bot技术拆解:持久化Agent团队如何管理记忆、上下文与协作成本
论文阅读·人工智能·深度学习·机器学习·aigc·ai-native·智能体
在所不辞兄6 小时前
为什么物理嵌入神经网络要把物理方程残差加入损失函数,而不是直接作为网络结构的硬约束?
人工智能·深度学习·神经网络·机器学习·有限元
嫂子开门我是_我哥7 小时前
敏感性分析
算法·机器学习·论文笔记
有Li7 小时前
EEG脑电图数据处理基础
人工智能·算法·机器学习·语言模型·医学生
明志数科7 小时前
机器人训练数据获取困境:互联网数据为何无法直接复用
人工智能·深度学习·microsoft·机器学习·机器人
I Am a robert girl7 小时前
VideoLoop:用循环工作记忆对抗长视频 Agent 的语义抖动
大数据·人工智能·机器学习·多模态agent·长视频理解·工作记忆·语义抖动