进阶Provider阅读约 6 分钟最后核对 2026-09-20

图片生成 Provider

Spark Work 图片生成 Provider:图片 API 源与 imageApiType 字段、9 个内置图片预设、spark_image MCP 工具与 spark_media 统一栈的双链路判定、产物输出目录与 7 类渠道的参数归一规则。

图片生成有两条链路:旧的spark_image(单 Provider、单工具、只生图)与统一的 spark_media(多 Provider 路由、覆盖生图 / 编辑 / 语音 / 视频)。二者的取舍规则 是确定的:只要能解析出统一媒体配置,就只注入spark_media;spark_image 是兜底,不是主力。这篇讲清楚两条链路各管什么、字段怎么落、参数怎么被 归一。

1. 配置步骤与真实选项

  1. 打开设置 → Provider,新建或编辑一条 Provider。
  2. 模型类型选生图模型(存储字面量image)。 图片专属字段只有modelType=image时才会写入。
  3. 选图片 API 源。表单里是下面 9 个选项,括号内是真实枚举值、默认端点与默认调用方式:
    界面标签imageProvider默认端点默认 imageApiType
    OpenAI Imagesopenaihttps://api.openai.com/v1sync
    APIMartapimarthttps://api.apimart.ai/v1async
    OpenRouteropenrouterhttps://openrouter.ai/api/v1sync
    Gemini / Imagengeminihttps://generativelanguage.googleapis.com/v1betasync
    火山方舟 Seedream / Seedanceseeddancehttps://ark.cn-beijing.volces.com/api/v3sync
    阿里百炼bailianhttps://dashscope.aliyuncs.com/api/v1/services/aigcasync
    智谱 GLM Imagezhipuhttps://open.bigmodel.cn/api/paas/v4sync
    xAI Imaginexaihttps://api.x.ai/v1sync
    自定义兼容接口custom(空,自己填)sync
  4. 填 Model ID 与 API Key,保存。

注意枚举拼写:是seeddance而不是seedance。保存时 Spark 会做兼容归一,seedance/volcengine也会被映射成volcengine-ark, 但表单与预设写的是seeddance。

内置的生图预设共 9 条:openai-images(OpenAI,gpt-image-2)、apimart-images(APIMart,gpt-image-2)、xai-imagine-image(xAI, grok-imagine-image-quality)、bailian-images(阿里云百炼,wan2.7-image-pro)、volcengine-seedream-image(火山方舟,doubao-seedream-5-0-pro-260628)、google-gemini-images(Google Gemini,gemini-3.1-flash-image)、midjourney-gateway(Midjourney 网关,需改自建网关地址)、minimax-image(MiniMax 图片,image-01)、tencent-tokenhub-image(腾讯云,hy-image-v3.0)。

2. 运行时链路:spark_image 与 spark_media 的分界

每一轮对话开始时,Spark 按固定顺序解析:

1. resolveMediaGenerationContext()
     聚合所有 enabled 且凭据可用的图片 / 语音 / 视频 Provider
     → 有结果:注入 spark_media(14 个工具),不再注入 spark_image
2. 只有当上一步返回 null 时,才调用 resolveImageGenerationContext()
     找第一条 modelType=image 且凭据可用的 Provider
     → 注入 spark_image,只暴露 mcp__spark_image__generate_image

也就是说:一个 Provider 同时能生图、语音、视频时,图片请求也走 spark_media。 只有「配了图片 Provider 但统一媒体栈解析不出任何可用配置」这种旧环境,才会落到 spark_image。

两条链路的差异:

spark_mediaspark_image
工具14 个(生图 / 编辑 / 语音 / 视频 / 文件 / 任务)1 个(generate_image)
Provider 范围所有 enabled 的 image / voice / video Provider,可混用第一条可用的 image Provider
模型选择靠model(selectionKey / manifest id / 模型 id)路由固定用该 Provider 的默认模型
产物目录.spark-artifacts/media/{images,audio,videos,text}.spark-artifacts/images
能力11 个统一能力仅文生图

图片编辑 / 变体 / 语音 / 视频不在spark_image的能力范围里,请看 多媒体 Provider。

3. spark_image 工具

注入时通过环境变量把配置传进本地 stdio 子进程:

SPARK_IMAGE_API_KEY      Provider 的 API Key(只在子进程里)
SPARK_IMAGE_MODEL        默认模型 id
SPARK_IMAGE_PROVIDER     imageProvider 值,缺省 openai
SPARK_IMAGE_API_TYPE     sync | async | auto,缺省 sync
SPARK_IMAGE_BASE_URL     仅当 Provider 配了 apiEndpoint 时传
SPARK_IMAGE_OUTPUT_DIR   固定为 <workspace>/.spark-artifacts/images

工具mcp__spark_image__generate_image的参数:

参数类型说明
promptstring(必填)详细提示词
sizestring像素尺寸或宽高比,如1024x1024、1:1、16:9,也接受语义值portrait/landscape/square
ninteger 1~4生成数量,默认 1,超出会被夹到 4
filenamestring输出文件名,不要带路径
extraJsonobject渠道私有参数

执行细节:

  • 默认尺寸1024x1024;同步请求超时 10 分钟;异步轮询间隔 5 秒,轮询 GET{baseUrl}/tasks/{taskId}。
  • 结果解析会遍历整个响应体,抓url/image_url/ imageUrl、data:image/*;base64,以及长度大于 64 的 b64_json/base64, 按内容去重后下载落盘。
  • 默认文件名形如img_&lt;时间戳&gt;_&lt;随机串&gt;;一次生成多张时会在基础名后追加_001这类三位序号,再拼扩展名。
  • 返回结构:{ success, provider, mode, files, urls },其中 provider形如apimart/gpt-image-2。只有配置了 URL 前缀时 urls才会是外链,否则与files 相同(都是本地路径)——应用当前不注入该 前缀变量,所以默认拿到本地路径。
  • Agent 侧 system prompt 要求:成功后必须调用mcp__spark_files__present_files 把本地 图片文件交给应用渲染预览;返回纯 URL 不算完成;失败时不要自动重试,要报错并建议 调整模型 / 提示词 / 尺寸 / Provider 配置。

4. 各渠道参数归一

size会按渠道被改写成该渠道真正接受的字段,这是最容易踩坑的地方:

imageProvider提交路径size / 比例处理
openai/images/generations比例映射成像素尺寸:1:1→1024x1024、3:2/16:9→1536x1024、2:3/3:4/9:16→1024x1536
xai/images/generations删除size(xAI 会报 Argument not supported: size),比例改写成aspect_ratio
apimart/images/generations,异步比例或尺寸原样传递
bailian同步/multimodal-generation/generation;异步 /image-generation/generation(带X-DashScope-Async: enable)用星号尺寸(1:1→12801280、3:4→11041472、4:3→14721104、9:16→9601696、16:9→1696*960);body 改写成input.messages+parameters
openrouter/chat/completions比例写进image_config.aspect_ratio;body 是 chat 格式并带 modalities(默认["image","text"])
gemini/seeddance/zhipu/images/generations把aspect_ratio与aspectRatio同时写进extraJson
custom/images/generations比例或尺寸原样传递,其余靠extraJson

5. Provider 选择规则

spark_image自动挑选 Provider 的条件,四条缺一不可:

  1. enabled = 1;
  2. config_json.modelType === "image";
  3. 有keystore_ref,且能真的从密钥库里解出非空 API Key;
  4. 默认模型(defaultModel,回退model)非空。

命中条件时取「第一条」。查询语句是SELECT * FROM provider_profiles LIMIT 1000,没有ORDER BY, 实际就是数据库自然顺序(通常是创建顺序)。所以想固定用哪条,最简单的做法是只保留一条可用的 图片 Provider。

选择过程不检查健康状态:不会去 ping 渠道。只要字段齐全就会注入,真实失败会在第一次 调用时暴露。

6. 与统一媒体栈的字段同步

保存modelType=image的 Provider 时,Spark 会同步三个统一字段:

imageProvider写回的 mediaProvider
openai/openai-compatibleopenai-compatible
apimart/xai/bailian/custom原值
seeddance/seedance/volcenginevolcengine-ark
gemini/googlegoogle-generative-ai
其它(如zhipu、openrouter)custom兜底

mediaApiType取imageApiType的归一值;mediaCapabilities保证至少包含image.generate。运行时解析统一媒体配置时,遇到未知mediaProvider也会兜底成 openai-compatible。

7. 常见问题排查

现象排查
会话里没有图片生成工具先确认是否已有可用的统一媒体 Provider(有的话只会出现spark_media,这是预期行为)。若两套都没有,逐条对照第 5 节的四个条件。
「测试连接」失败,但图片能生成正常。测试连接发的是文本 ping(OpenAI 兼容/chat/completions),纯生图渠道通常没有 chat 端点。
xAI 报Argument not supported: size说明size被透传了。走spark_image时会自动改写为 aspect_ratio;如果你自己拼 HTTP 请求,请只传aspect_ratio+ resolution。
异步渠道报「没有图片也没有 task id」渠道返回体结构与预期不符。代码按task_id/taskId/ job_id/jobId/request_id/ requestId/id顺序找任务号;都没有就只能报错。
图片生成成功但界面没有预览Agent 需要在成功后调用mcp__spark_files__present_files把本地文件交给应用。
想要图片编辑 / 变体 / 多图合成spark_image只做文生图,配置统一媒体 Provider 后用spark_media 的generate_image/edit_image。

速查表

项目内容
图片 API 源openai / apimart / openrouter / gemini / seeddance / bailian / zhipu / xai / custom(注意是 seeddance)
调用方式sync / async / auto(缺省 sync)
内建生图预设9 条:openai-images、apimart-images、xai-imagine-image、bailian-images、volcengine-seedream-image、google-gemini-images、midjourney-gateway、minimax-image、tencent-tokenhub-image
spark_image 工具mcp__spark_image__generate_image(参数:prompt、size、n 1-4、filename、extraJson)
spark_image 产物目录<workspace>/.spark-artifacts/images
超时同步 10 分钟;异步轮询间隔 5 秒
imageProvider → mediaProvideropenai→openai-compatible · seeddance/seedance/volcengine→volcengine-ark · gemini/google→google-generative-ai · 其它→custom

上手清单:在 Spark Work 中接入 OpenAI 图片生成

从创建 Provider 到让 Agent 生成第一张图

  1. 打开「设置 → Provider」,点「新建」
  2. 「模型类型」选「生图模型」,图片 API 源选 OpenAI Images,preset 选 OpenAI
  3. 填入 Model ID(如 gpt-image-2)与 API Key
  4. 保存后不需要依赖「测试连接」——它只 ping 文本端点
  5. 新会话里让 Agent 画图;若同时配了统一媒体 Provider,它会改用 mcp__spark_media__generate_image
  6. 产物文件在 <workspace>/.spark-artifacts/images(或 media/images)下

常见问题

图片生成到底走 spark_image 还是 spark_media?

只要能解析出可用的统一媒体配置,就只注入 spark_media(图片也走它);spark_image 仅在统一媒体栈解析为空时作为兜底注入,避免两个工具争抢模型选择。

图片模型和文本模型有什么区别?

modelType=image 时会多写 imageProvider 与 imageApiType 两个字段,并把它们同步到 mediaProvider / mediaApiType / mediaCapabilities(至少含 image.generate)。非图片模型会清掉图片专属字段。

生成的图存在哪里?

spark_image 是 <workspace>/.spark-artifacts/images;spark_media 是 <workspace>/.spark-artifacts/media/images。落盘目录会被写进仓库本地忽略。

可以同时挂多个图片 Provider 吗?

可以。spark_media 会把所有可用 Provider 聚合起来,用 model 参数路由;但走旧的 spark_image 时只会取第一条满足条件的 Provider(数据库自然顺序,通常是创建顺序),且不检查健康状态。

为什么「测试连接」通不过?

测试连接发的是文本协议 ping(/chat/completions 或 Anthropic messages),不校验图片端点。纯生图渠道没有 chat 端点会失败,这不代表图片功能不可用。