一句话版:别人让 agent"更会说话",我想让 agent"更会做事"——而且这种能力长在你自己的电脑上。
但下面这篇不是软文:前半段是我怎么用自己产品的编排层,把自己"拆成小模型会更强"的想法打掉的过程,含负结果;后半段才是我最后敢留下的、能被验证的东西。
0. 先说结论(不想看过程的看这 5 条)
- “拆成几个小模型就会更强”——我自己的 4 次实验全部没通过(判据跑之前冻结)。最差的拆法 −6.43pp,25 次里 24 次输。
- 但"拆"不是负资产:换对拆法,从 −6.4pp 变成 ≈0;当拆法与数据的真实结构对齐时还能小赚(最高 +7.0pp)。
- 决定生死的不是"拆不拆",是"怎么拆 + 怎么合":按真实信息源拆 > 按真实子任务拆 ≫ 按特征随意切块。
- 于是我删掉了所有"精度承诺",只留结构性、可验证的东西:本地训练 + 本地推理、判定层把关、导出即带走、数据不出门。
- 现状我也写清楚了:拆解与编排已跑通、有测试;界面接线与推理运行时在做;还没有真实用户跑过完整闭环。
1. 起因:判断这件事,到底该"租"还是"造"
我手上有一类需求:同一类判断要反复做。比如一条产线上"这张图有没有缺陷"、一份表格里"这行是不是异常"。
用云上大模型做,第一天很爽:写个提示词就能跑。但跑到第 N 天,问题全来了:
- 按 token 计费,用得越多越贵;
- 断网 / 限流 / 涨价,你只能等;
- 数据得传出去;
- 你的判断标准(什么叫"缺陷")沉淀在别人的服务里,不在你手里。
那能不能"造"?你其实已经有原料了:你的数据、你的判断、一台(哪怕是旧)电脑。
我在做的东西就是这条路:把一个任务拆成几小块,每块在本地训一个小模型,让它们在本机协作干完;训完怎么用都不再按调用付费。付费方式也简单——买的是训练器,训练按轮次低额计量,推理不再收费。
听着很顺,对吧?问题就出在这句"拆成几个小模型"——它太顺了,顺到我自己都没验证过。
2. 我原来的想法,以及它为什么"听起来很对"
想法很朴素:
一个真实任务 ├─ 感知专模 画面/信号 → 有没有 ├─ 判断专模 状态 → 该不该 ├─ 决策专模 打分 → 选哪个 └─ 执行专模 动作 → 怎么做 ↓ 串联(前级输出 = 后级输入) ↓ 并联(多路投票) 一个结论背书看起来很足:ensemble、stacking、cascade、MoE、蒸馏,全是成熟做法,AutoGluon 之类甚至自带 stacking。"拆了再合"不是天然更强吗?
为了不靠感觉,我给自己的编排层写了实验。编排层本身就支持:串联(前级输出接后级)、并联投票、以及OOF(out-of-fold,折外预测)防泄漏——每条样本的预测都来自"没见过它"的那一折,而不是拿训练时见过的数据算分。
3. 判据先冻结,再跑
判据(跑之前定死,跑完不许改)
- 通过= Δ 的 95% CI 下界 ≥+2pp,且≥4/5 任务族同向,且每个成员单打都过平凡基线;
- 不成立= CI 下界 ≤ 0(“没输"不等于"赢了”);或同向族 ≤3/5。
设置
| 项 | 取值 |
|---|---|
| 任务族 | 5 个:linear / xor / radial3 / 20% 标签噪声 / sparse |
| 规模 | 5 个种子 × n=2000 ——每个"任务族 × 种子"组合各自独立生成 2000 条样本,共 25 组;表里的池化 Δ 是这 25 组的合并统计 |
| 划分 | 按生成簇划分(训练 3 簇 / 验证 1 簇 / 测试 1 簇),避免行随机划分带来的近邻泄漏 |
| 成员 | 同一任务的 4 个特征视图(左半 / 右半 / 混合 / 全量) |
| 后端 | 零依赖兜底后端(朴素贝叶斯,速度优先 preset) |
| 对照 | 同特征、同预算的单个模型("最强单模"在验证集上择优) |
25 组全报,包括负的。
4. 结果:四种拆法,全部没过门槛
| 拆法 | 池化 Δ | 95% CI(配对 bootstrap 10k) | 同向族 | 判定 |
|---|---|---|---|---|
| 同任务特征视图 +投票 | −6.43pp | [−8.13, −4.75] | 0/5 | 不成立 |
| 同任务特征视图 +OOF 串联 | −0.59pp | [−1.30, −0.10] | — | 不成立 |
| 层级串联(gate → expert) | −1.58pp | [−4.62,+0.96] | 3/5 | 不成立(CI 跨 0) |
| 多源互补+ 投票 | +0.01pp | [−1.35, +1.26] | 3/5 | 不成立(精确中性) |
数字怎么来的:这四行是我在本机跑脚本得到的输出(合成数据、5 族 × 5 种子、配对 bootstrap 10k 次算 CI),不是我随手写的估计值;也不是第三方评测。四个臂的 CI 都列在表里,你可以自己看哪几个跨 0。
族平均 Δ:linear −6.9pp · xor −1.8pp · radial3 −9.6pp · noisy −2.7pp · sparse −11.3pp(第一臂)。
门槛再说一遍,免得误读:通过要求CI 下界 ≥ +2pp 且 ≥4/5 族同向。
所以第 4 行的+0.01pp 虽然是正数,但它的 CI 是 [−1.35, +1.26](跨 0),是纯噪声级别,属于"没输",不是"赢了"——这就是判据里写的"不成立 = CI 下界 ≤ 0(没输不等于赢了)"。四臂里没有一个是"显著为正"的。
三个关键读数:
- 最差的拆法非常差:把同一份特征切两半、各训一个、再投票 → −6.4pp,25 次里 24 次输。机制清楚:每个成员看到的信息变少了,信息损失盖过了集成增益。
- ρ̄ ≈ 0.26(ρ̄ = 成员之间预测结果的相关系数均值):成员已经足够"不一样"了(相关性很低)。所以问题不在多样性,在准确率——"多来几个不一样的模型就能救"这条路是错的。
- oracle 上界比任何单模高 5–27pp(xor 0.52→0.79、noisy 0.85→0.93):说明**“有东西可拿,但卡在’怎么合’上”**,不是没收益,是我没拿到。
但也不能一棍子打死(局部是有效的):
hier3(门控条件 = |x₀|>0.7,分支内规则与门控同源):5 个种子里4 个为正,最高 +7.0pp;multi1+2.7pp、hier0+2.6pp。
→ 当拆法与数据结构的"真实层级 / 真实来源"对齐时,能小赚;对不上时,就是白拆甚至倒亏。
5. 顺手记两个我自己踩的坑
坑 1:选择泄漏。第一版实验里"最强单模"是我用测试集挑出来的——也就是"先看答案再选选手",这本身就偏向了"反对投票"。改成只在验证集上择优(验证集挑出分数最高的那个单模,选完只跑一次测试集)后重跑:结论不变(−6.4pp)。判据没动。
坑 2:我差点冤枉了自己的代码。实验日志里 25 次都走"手工两步",我一度判定产品的run_chain不成立。单独验证时它其实输出:
链路 'x' 成立:2 步全部跑通且都过兜底下限(执行序:gate → expert); 注入为 out-of-fold(5 折交叉预测)真正的原因是我读返回结构读错了(ChainStepOutcome不直接暴露模型目录,它在outcome.plan里),读到空串就以为失败。是我的 bug,不是链路的。
教训:做自我证伪的实验,最容易骗过的其实是自己。所以判据必须跑之前冻结,负结果必须原样留在表里。
6. 那到底什么时候"拆"才值当?
我把条件写进话术,不再无条件说"拆就更强":
- 信息源本身不同(多模态 / 多传感器互补)——不是把同一份特征切块;
- 子任务本身不同(流水线各段目标不同,前级解决子问题、后级在它输出上工作);
- 单模训不动(数据不够 / 算力不够,只能分而治之);
- 你要的是可维护 / 可替换 / 零边际成本,而不是精度。
外加一条证明义务:链级验收门——整条链必须在 hold-out 上打败"最强单模 + 平凡基线",否则不通过。
单模各自过线只是必要条件,没人负责的"合起来更好"就是耍流氓。
还有一条不性感但更致命的:拆 N 块 ≈ N 份采集/清洗/验收。效果差只是"不好用",标注重是"第一天就走"。所以我下一步要量的不是准确率,而是自动打标可用率和每个任务的抽检分钟数——而且打标的"老师"必须是真模型(我现在台账里还有注入的假教师,这是个待还的债)。
7. 删掉精度承诺后,我留下什么
下面每条都是我自己代码里的实物(读者拿不到这个仓库,所以我把它写成"它落在哪、长什么样",而不是"第三方已验证"):
| 我留下的 | 在代码里落在哪 / 长什么样 |
|---|---|
| 本地训练 + 本地推理 | 训完断网照样跑;之后每多做一次判断都不再按调用付费(电费和机器仍是你自己的) |
| 判定层 | 先算平凡基线并给同一套指标(多数类占比 / 随机排序 AP / 分位数阈值基线,按后端不同);拿不出基线的数不算数——"全报警"也能有 100% 检出率。评分类任务严格大于基线才算过(相等不算)。过了 → 归档进versions/(旧版保留);没过 → 落进rejected/ |
| 导出即带走 | 导出包 =report.md+manifest.json+KVX-EXPORT.json+WATERMARK.txt,同一个watermark_id互相交叉引用 + 签名;verify_zip()可只读校验,返回ok / tampered / no_mark |
| 编排 | 串联 / 并联投票 / OOF 防泄漏,有测试 |
| 裸机上也能真训 | 零依赖兜底后端:我自己在本机量到的可跑组合从 18 提到 41/51(这张表是自测,不是第三方评测) |
| 边界要如实说 | 仍有10 个(模态 × 任务)组合没有兜底:audio 3 条、graph 3 条、video 的 binary/multiclass、table/text 的异常检测。所以对外应该给一张"你这台机器能训什么"的表,而不是笼统说"什么都能训" |
模态 11 个、后端 14 个(audio / graph / video / table / text / timeseries / sensor / event_log / operation / preference / decision),按算力档位(cpu_only/gpu_small/gpu_large)决定训什么、训多大——不是所有机器都硬上同一套。
8. 算一笔账(假设我写清楚,你自己换成你的单价)
以下数字全部是示例假设,不构成任何成本承诺或对比结论——只是把账摊开给你看怎么算。
场景:一条产线,每天 2000 次外观判断。
走云 API(假设每次 1.5k 输入 token + 0.2k 输出 token,单价按 ¥2/百万输入、¥8/百万输出):
- 每次 ≈ ¥0.0046 → 每天 ≈ ¥9.2 →一年 ≈ ¥3,360
走本地(一次性标注 + 在本机训练;推理电费按 150W × 1 小时/天 × ¥0.6/kWh):
- 电费 ≈ ¥0.09/天 →一年 ≈ ¥33(机器是你本来就有的)
差的不是那 3,300 块。真正的差别是三件事:断网时你还能不能判断、数据要不要出门、对方涨价时你能不能说不。
我不拿这张表当"更省"的承诺——单价请换成你自己账单上的数字再算。成本是结果,不是主张。
9. 现状
- 已跑通:任务拆解、编排(串联/并联/OOF)、判定层、模型版本化与落位、导出与水印校验、零依赖兜底后端——都有代码和测试。
- 在做:界面接线与本地推理运行时(也就是"训完点一下就在你机器上跑起来"这最后一米)。
- 没做的:真实数据上的多源实验。上面 5 个任务族全是合成数据——所以第 4 节的结论只对"同任务同特征拆分"这种最弱形态成立,不能推广到真实多传感器场景。这是我下一步唯一能把话说到位的实验(UCI-HAR:加速度计 + 陀螺仪两路真实传感器,天然多源)。
- 内测阶段:还没有真实用户跑过完整闭环,本文所有数据都是我自己在本机测的。安装包目前到
0.4.9(约 202 MB,每版一行 sha256 / 载荷 md5 / commit 台账)。
10. 护城河不是 skill
这几年最容易被抄的就是 skill:工具封装 + 提示词,一天就能复制一份。我的判断是,壁垒在下面四层:
- 数据飞轮:他的产线照片、他的表格、他的录屏,只在他的机器上变成他的模型。不是因为他不愿意给,而是因为数据不出本机——这让"愿意给"变成了可能。
- 判定层:敢说"不达标不许上线"。这是工程与配方积累,抄走一个函数也抄不走配套的基准与验证流程。
- 配方:11 模态零权重后端 + 训练配方(多教师集成 → TTA/WBF → 属性校验 → cleanlab 剔错标 → 软权重/蒸馏/Noisy Student 这一类做法)+ 按算力档位调度。写得出来,但跑得通要靠一次次真跑验证。
- 模型流通:模型归你,可导出、可分享、可出售。这像 skill 市场,但交易的是权重而不是提示词。
但 skill 我也必须做(它是入口,不是护城河):train_detector(训检测)、collect_screen(采屏)、track_objects(跟踪)、run_overlay(跑悬浮框/接管)。
一句话:别人的护城河是"教会 agent 用工具";我想做的是"让 agent 在你这台机器上、用你的数据,造出只属于你、且经过验证的能力"。
11. 接下来三件事
- 打通闭环:“一句话 → 拆解 → 自动训练 → 判定门 → 点一下启动”(现在只到一半);
- 给每个模态定最小达标线(判定基准库),让"过没过"有统一口径;
- 拿真实数据做一个能传播的端到端案例(给 300 张真实图 → 半小时出模型 → 悬浮框实时识别)。
12. 最后
我把"更强"从自己的卖点里删掉了。留下的是一句可以被验证的话:
同一类判断要反复做的时候,把它拆成几个本地小模型、各带一条验收线,串成链路在你自己的机器上跑完——不联网,训完不再按调用付费。
如果你也在做"反复判断"的活儿(质检、表格异常、屏幕理解、传感器告警),你会把它交给云 API,还是在自己机器上训一个?评论区聊聊,你的场景我大概率没想过。