Repository navigation
v0.8.0 — codearts 图片降级,不再整单 406
修复:codearts 不再因为图片整单失败
CodeArts 的模型都是纯文本,收到任何带图片的请求会整单拒绝:
InferHub.001001020.406: The request model is not multimodal
拒绝的粒度是整条请求,不是最后一条消息。 实测(每形态 12 次):
| 请求形态 | 200 | codearts 406 |
|---|---|---|
| 纯文本 | 12 | 0 |
| 图片在最新一条 | 12 | 6 |
| 图片只在历史里 | 12 | 5 |
第三行是这类报错最难排查的地方:最新一条是纯文本,表面上没有任何东西提示"有图片"。
改成什么
图片 part 在发往上游之前被换成文本占位符,并记一条 warn 日志:
[image omitted: this CodeArts model accepts text only]
为什么是降级而不是拒绝:DeepSeek-V4.1-Flash 是同名池化模型,四个上游发布同一个名字,只有部分能读图(实测同一张纯蓝图片,sensenova-max 答 Blue,codearts 报 406)。拒绝会让整个名字被一张图打挂;降级则让该上游诚实地说"看不到图",同时其它渠道照常给出完整答案。
用 400 拒绝是错的:CPA 会把 400 判为请求方错误并中断跨渠道故障转移,用户什么都拿不到。
实测效果
修复前后各跑一轮 A/B/C(每个形态 12 次):
| 406 次数 | |
|---|---|
| 修复前 | 5–6 / 12 |
| 修复后 | 0 / 12 |
同一次带图请求命中 codearts 时答 Unknown(诚实),命中其它渠道时答 Blue(正确)。
顺带查清了两个 CPA 行为(v8.0.4 源码 + 实测)
- 冷却是按「凭据+模型」,不是按渠道整体。 同一账号下模型 A 被限流不影响模型 B(实测 cline 上 DeepSeek 429 时,同凭据的 Nemotron 仍 200)。
- 冷却时长是固定阶梯
1s → 2s → 4s → … 30min,上游回复里的Try again in 14h 53m到不了 CPA:核心路径不解析 body 文案,且插件 ABI 的错误对象只有code/message/retryable/http_status四个字段,没有时长字段,auth.save写回的next_retry_after也会被宿主覆盖。因此不存在"针对某渠道模型设置冷却时长"的配置项——粒度已经是按渠道模型,缺的是时长而时长不可配。唯一可配的是按凭据整体关闭冷却(disable_cooling: true)。
详见 docs/DEPLOYMENT.md §3.7(同名池化与模态能力)与 §3.8(上游限流与冷却)。
测试
新增 plugins/codearts/vision_test.go,7 个用例覆盖:最新消息带图、仅历史带图、三种图片 part 拼写、工具结果内嵌图片、无图请求逐字不变、占位符是 text part。做了反向验证:停用剥离调用后 5 个用例立刻转红。
go build / go vet / gofmt / 全部包测试均通过。