Skip to content

feat(models): 模型类型系统新增 image 类型,图像生成模型不再兜底为 chat - #1008

Closed
zgpnuaa wants to merge 3 commits into
xerrors:mainfrom
zgpnuaa:feat/model-type-image
Closed

feat(models): 模型类型系统新增 image 类型,图像生成模型不再兜底为 chat#1008
zgpnuaa wants to merge 3 commits into
xerrors:mainfrom
zgpnuaa:feat/model-type-image

Conversation

@zgpnuaa

@zgpnuaa zgpnuaa commented Sep 10, 2026

Copy link
Copy Markdown
Contributor

现象

DashScope 的 qwen-image 系列图像生成模型不支持 OpenAI 兼容 chat 接口(只支持原生 multimodal-generationcontent 必须是数组)。但模型类型系统只有 chat/embedding/rerank 三种,图像模型被兜底登记成 chat,导致:

  1. 模型测试按 chat 接口调用,报 Input should be a valid list: input.messages.0.content
  2. get_all_specs("chat") 把图像模型混进纯文本模型列表,纯对话智能体误选后运行时报同样错误。

机理

VALID_MODEL_TYPES = {"chat", "embedding", "rerank"}image_normalize_remote_model 把不在白名单的类型兜底成 chat。这是类型系统的设计缺陷——图像生成是 DashScope 的原生能力,但类型系统没给它留位置。

改进方法

  1. VALID_MODEL_TYPESimage,归一化保留 image 不再兜底 chat;
  2. DashScope builtin provider 的 capabilitiesimage
  3. 测试分流按 model_type == "image" 走原生 multimodal-generation 接口;
  4. 前端 capabilities/type 下拉/tab 支持「图像生成」。

get_all_specs("chat") 等纯文本分流逻辑不变,image 类型天然不命中,纯文本模型行为零影响。

效果

图像模型正确落位为 image,不再混进 chat 列表;qwen-image 测试走原生接口返回正常;UI 正确显示「图像生成」。附 3 个单测:image 类型可写入、无 image 能力时拒绝、远端归一化保留 image 类型。

@xerrors

xerrors commented Sep 10, 2026

Copy link
Copy Markdown
Owner

Codex Review:

预 review 基于 72ed4d324e65

发现 2 个需修复的问题。

  1. [P2] image 类型被无条件绑定到 DashScope 协议。 service.py:462–463 对所有 image 模型都调用 _test_image_generation_model,但类型/能力配置对自定义 provider 同样开放。用户为其它图像供应商配置 image 后,“测试”会向其 base_url 拼接 DashScope 专用路径并发送 DashScope payload,导致正常模型被判为不可用。请按实际支持的供应商协议分流;暂时仅支持 DashScope 时,应明确限制/报告不支持的测试协议。

  2. [P2] 固定 512×512 不适用于全部 Qwen Image 型号。 service.py:500 给所有 image 模型固定传 size="512*512"。官方 API 文档中 qwen-image-max/plus 系列仅支持列出的分辨率(例如方图 1328×1328),因此测试可因参数不合法而失败,即使凭据与模型正常。建议省略可选 size 使用模型默认值,或按实际型号选择合法值,并测试发出的 HTTP payload。官方分辨率契约

验证:该 head 独立快照执行 PYTHONPATH=package:server python -m pytest test/unit/services/test_model_provider_service.py -q --disable-warnings --tb=short,28 passed;这组测试没有验证新增图像 HTTP 调用。未调用收费图像生成 API、未运行浏览器或该 head 的 Compose/E2E。本次 CI 查询显示 Verify deterministic Agent assembled path 失败,原因尚未归因,不应把它当成本 PR 已获真实链路验证。请补充图像能力的 tracked decision 和实际协议验证。

@xerrors

xerrors commented Sep 10, 2026

Copy link
Copy Markdown
Owner

这个的预期效果是怎么样的?

- 非 DashScope 的 image 模型显式报告暂不支持,不再按 base_url 拼 DashScope 路径
- 测试请求省略 size,避免 qwen-image-max/plus 等型号因非法分辨率误判不可用
- 断言实际 HTTP payload 的 2 个回归测试 + 补 tracked decision
@zgpnuaa

zgpnuaa commented Sep 10, 2026

Copy link
Copy Markdown
Contributor Author

感谢 review,两个问题都成立,已修复(最新 head 03aece06)。

[P2] 图像测试硬绑定 DashScope 协议 → 按供应商协议分流

确认:test_model_status_by_spec所有 model_type == "image" 都调用 _test_image_generation_model,而该函数会把 /api/v1/services/aigc/multimodal-generation/generation 拼到任意 base_url 上——自定义图像供应商会被误判不可用。

修复:原生 multimodal-generation 协议当前只有 DashScope 系供应商提供,因此先做协议判定:

  • base_url 归一化(去掉 compatible-mode 前缀)后若不含 dashscope → 直接返回 status="unavailable"message="当前仅支持 DashScope 图像模型的连接测试"不发任何请求
  • 只有 DashScope 才走原生接口。这样既不会误判其它供应商,也把"暂不支持"如实报告出来,而不是伪装成模型不可用。

[P2] 固定 512×512 → 省略 size 使用模型默认值

确认:parameters.size 对所有 image 型号都固定传 "512*512",而 qwen-image-max/plus 只接受文档列出的分辨率,正常凭据与模型也会因参数非法而测试失败。

修复:不传 size,交给模型默认值(其余 prompt_extend/watermark/n 保留)。这样对任何受支持型号都合法。

证据(断言实际 HTTP payload)

test/unit/services/test_model_provider_service.py 新增 2 个用例,用 httpx_mock 断言真正发出的请求:

  • test_image_test_uses_native_endpoint_without_size_parameter:请求路径为 /api/v1/services/aigc/multimodal-generation/generation,payload parameters不含 sizeinput.messages[0].content == [{"text": ...}]
  • test_image_test_reports_unsupported_provider_without_sending_request:非 DashScope base_url 下返回「暂不支持」,且 httpx_mock.get_requests() == [](确认未发出错误请求)。

另外补上了此前遗漏的 tracked decision:docs/develop-guides/decisions/implemented/2026-09-08-model-type-image.md(含协议分流与 size 决策)。

验证:该文件 30 passed;ruff check/format/select-I 与 verify_engineering_contracts.py 通过。未调用真实图像生成 API。

@xerrors

xerrors commented Sep 10, 2026

Copy link
Copy Markdown
Owner

请补充一下使用场景和实际运行截图

@zgpnuaa

zgpnuaa commented Sep 10, 2026

Copy link
Copy Markdown
Contributor Author

补充使用场景与实测截图(对应「这个的预期效果是怎么样的?」「请补充一下使用场景和实际运行截图」)。

使用场景

在「智能体管理 → 模型供应商 → DashScope → 管理模型」中配置 qwen-image-3.0 / qwen-image-3.0-pro,并用行内「测试模型连接」验证凭据与模型可用性;配置完成后由 image-gen 技能在沙盒里实际调用它生成图片。修复前这两个模型被登记为 chat,上述验证会按 OpenAI 兼容 chat 接口去调它。

pr1008-model-list-crop

图中两个 qwen-image 的「类型」列均为 image(provider「能力」也已含 image)。

修复前的报错(实测)

  1. 直接按兼容模式 chat 接口调用(content 传字符串):

    POST https://dashscope.aliyuncs.com/compatible-mode/v1/chat/completions
    {"model":"qwen-image-3.0","messages":[{"role":"user","content":"Say 1"}]}

    返回:

    HTTP 400
    {"error":{"message":"Input should be a valid list: input.messages.0.content",
              "type":"invalid_request_error","code":"invalid_parameter_error"}}
    
  2. 通过应用内「测试模型连接」(把类型临时改回 chat 后实测):

    错误: Error calling model: Error code: 404,
    URL: https://dashscope.aliyuncs.com/compatible-mode/v1, Model: qwen-image-3.0
    

两条都指向同一件事:图像生成模型不在兼容模式 chat 端点的服务范围内,按 chat 路径调用必然失败。(第 2 条是本次实测结果;最初报告里看到的是第 1 条的 400 文案,两者是同一根因在不同请求形态下的表现。)

修复后的预期效果

  • 「测试模型连接」走 DashScope 原生 multimodal-generation 接口,返回
    {"status":"available","message":"连接正常(已生成测试图片)","model_type":"image"}
  • get_all_specs("chat") 不再把图像模型混进纯文本模型列表(误选后不再报错);
  • 图像生成链路实际产出正常:
pr1008-generate-crop

助手回复「已为您生成蓝色圆形图片,保存在 outputs/blue-circle.png」并给出产物卡片,可直接预览/下载。

两张截图均为本 PR head 对应运行实例的界面区域。

@xerrors

xerrors commented Sep 11, 2026

Copy link
Copy Markdown
Owner

这个是在模型选择的时候可以选择图像模型进行对话吗?然后这个模型既能 对话,又能生成图片?为什么我目前看下来,消费入口只有模型管理页的“测试”按钮,没有面向用户的实际生图场景?而且生图的接入场景应该是修改生图的那个工具就可以了。

@zgpnuaa

zgpnuaa commented Sep 11, 2026

Copy link
Copy Markdown
Contributor Author

感谢 review,澄清一下 image 类型与生图消费的关系。

image 类型不是「对话入口」,是类型系统正确性修复

qwen-image纯图像生成模型,不能对话。这个 PR 修的是类型系统缺陷:之前类型系统只有 chat/embedding/rerank 三种,qwen-image 被兜底登记成 chat,导致两个问题:

  1. 「测试连接」按 OpenAI 兼容 chat 接口去调它,报 Input should be a valid list: input.messages.0.content(图像模型不支持 chat 协议);
  2. get_all_specs("chat") 把 qwen-image 混进纯文本模型列表,纯对话智能体误选后运行时同样报错。

所以 image 类型的作用是把它从 chat 列表分离出来(纯对话智能体看不到、不会误选),并让「测试连接」走正确的 DashScope 原生 multimodal-generation 接口。它不做对话、也不直接生图。

实际生图由 image-gen skill 完成(面向用户,与本 PR 正交)

生图由内置 image-gen skill 在沙盒里调用 DashScope 原生接口完成,用户在对话里让智能体生图即可。实际生图场景(在对话里,而非模型管理页的「测试」按钮):

image-gen 生图场景

图中对话为「生成一张蓝色圆形的图片」→ 智能体调用工具(写入文件 · 执行命令)→ 产物 blue-circle.png(交付文件 · PNG)。这条链路走 image-gen skill,读的是沙盒里的 DASHSCOPE_API_KEY,不经过「模型类型系统」。

所以两者正交:

  • image 类型(本 PR):让模型管理页能正确登记/测试图像模型,避免它污染 chat 列表;
  • image-gen skill:面向用户的实际生图入口(在对话里)。

如果你认为「测试按钮」不是有意义的消费入口、这个 PR 的价值只在「防止图像模型污染 chat 列表 + 正确测试」,我可以把 PR 描述收窄到这个定位;如果你觉得生图只由 skill 走原生接口即可、不需要在类型系统里登记 image,也可以讨论是否撤掉这个 PR。

@xerrors xerrors closed this Sep 11, 2026
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

2 participants