乐于分享
好东西不私藏

给 AI Agent 接上文生图:本地 OpenAI-compatible 图片网关 + 自动选模型 + 提示词增强

给 AI Agent 接上文生图:本地 OpenAI-compatible 图片网关 + 自动选模型 + 提示词增强

我一开始只是想让自己的 Agent 能画图。后来发现,真正难的不是“调用一个生图 API”,而是:怎么让 Agent 知道该用哪个模型、怎么把一句很随意的人话补成高质量提示词、以及某个平台挂了之后还能不能自动换下一个。

先说最吸引人的:这套网关能接哪些免费/低成本渠道?

先把结论放前面。

我这次做的不是一个单模型调用脚本,而是一个本地图片生成网关。Agent 只需要调用一个 OpenAI-compatible 接口:

POST /v1/images/generations

后面的模型平台由网关自己处理。

当前我接了三层:

渠道
注册/入口
免费/额度口径怎么理解
我在网关里的定位
硅基流动 SiliconFlow
siliconflow.cn[1] / cloud.siliconflow.cn[2]
官方价格说明里写了新用户注册有 14 元免费额度;官方限流页里,图片生成模型有 IPD(每天可生成图片数)指标,当前从 400 张/天 起。注意:这里的 400 是图片生成限流指标,不等于“永久免费 400 张”。实际能免费生成多少张,要看你账号赠送额度、模型是否免费、模型价格和后台规则。
第一优先级,主力出图
魔搭 ModelScope
modelscope.cn[3]
官方 API-Inference 注册用户每天总调用数是 2000 次/天,但这个是 API-Inference 总额度,包含 LLM 等模型;我们实测图片生成通道是所有图片模型共享约 50 张/天,所以网关默认用 MODELSCOPE_DAILY_LIMIT=50 做本地保护。
第二层,接 Qwen / FLUX / Z-Image / Z-Turbo
Pollinations
pollinations.ai[4] / enter.pollinations.ai[5]
适合轻量测试和最后兜底。新版 OpenAI-compatible 接口建议配置 API Key;老的 public endpoint 也能做保底,但稳定性和限流不承诺。
最后一层兜底

这里先说清楚:这些额度不是我能承诺的永久额度。平台会调模型、调价格、调认证规则。文章里把次数写出来,是为了让你判断“值不值得折腾”;真正长期使用,还是要以各自后台显示为准。

更准确地说,这套方案的吸引点不是“某个平台永远免费多少张”,而是:

  • 硅基流动适合作为主力低成本通道;
  • 魔搭的图片模型池可以做第二层补充,但我按 50 张/天保护它;
  • Pollinations 放在最后兜底,避免整条链路直接断掉。

从个人 Agent、NAS、New-API 接图像能力的角度看,这个组合已经很实用:

硅基流动 Kolors  ↓ 失败/限流魔搭 Qwen / FLUX / Z-Image / Z-Turbo  ↓ 失败/限流Pollinations 兜底

也就是说,Agent 不用知道每个平台的 API 怎么写。它只要知道:

我要画图,就请求本地网关。


我为什么要折腾这个网关?

因为我发现,Agent “会画图”和“能稳定画出好图”是两回事。

最开始我想得很简单:给 Agent 加一个文生图接口就行。用户说一句“帮我画张赛博朋克城市夜景”,Agent 调 API,返回图片,完事。

结果真接起来之后,问题一个接一个:

  • 有的平台是同步接口,有的平台是异步任务,要提交后轮询;
  • 有的平台返回的是临时 URL,过一会儿就打不开;
  • 免费额度不稳定,今天能用,明天可能 401、429、模型维护;
  • 不同模型擅长的东西不一样,不能什么都丢给同一个模型;
  • 用户通常不会写详细提示词,只会说“现实风格美女”“二次元头像”“公众号封面”。

所以我最后没有把它做成一个简单的 API 转发脚本,而是做成了一个本地网关:

用户自然语言   ↓Agent 理解需求、扩写提示词、选择模型   ↓本地 OpenAI-compatible 图片网关   ↓多平台自动调用 / 自动降级 / 本地缓存   ↓返回图片 URL 或 b64_json

这个思路一旦跑通,后面不管你接 New-API、Hermes、OpenClaw、自己的 NAS 工具,都会简单很多。


真正影响出图质量的,不是 API,而是 Agent 前面这一步

直接调用图片模型当然可以,但效果经常不稳定。

比如用户说:

帮我画一张现实风格的美女,站在雨夜街头,霓虹灯背景

这句话对人来说很清楚,但对图片模型来说还是太粗了。

更好的做法是让 Agent 先补全成一段更像图片模型能理解的画面描述:

A photorealistic cinematic portrait of an elegant young adult woman standing on a rainy city street at night, neon signs glowing in the background, wet pavement reflections, soft rim light, natural skin texture, realistic facial details, shallow depth of field, 85mm lens, high-end fashion editorial photography, moody atmosphere, clean composition.

同时,Agent 不应该随便选模型。写实人像、二次元头像、中文海报、产品图、风景图,本来就不是同一种任务。

我给 Agent 设计的流程是:

先判断图片类型   ↓再选择模型   ↓再扩写或轻度优化提示词   ↓最后请求图片网关

这个小步骤非常关键。

用户不用学提示词工程。用户只要说人话,Agent 负责把这句话翻译成更适合图片模型的 prompt。


不同模型怎么选?我目前是这么路由的

我在网关里暴露的是一些简单别名,而不是让 Agent 直接记后端真实模型名。

别名
后端/真实模型
我一般让它负责什么
kolors
SiliconFlow Kwai-Kolors/Kolors
默认主力,中文/英文通用文生图、普通封面、普通插画
qwen
ModelScope Qwen/Qwen-Image-2512
中文文字、公众号封面、带字海报、复杂指令、二次元/角色图
flux
ModelScope black-forest-labs/FLUX.1-Krea-dev
高级感写实、自然光、风景、产品氛围图、去 AI 味
z-image
ModelScope Tongyi-MAI/Z-Image
创意艺术、超现实、风格探索、多样构图
z-turbo
ModelScope Tongyi-MAI/Z-Image-Turbo
写实人像、真人摄影、商业感、快速出图
pollinations
Pollinations
保底、临时测试、低成本兜底

这里不要理解成死规则。

比如 qwen 不只是“二次元模型”,它更重要的是中文理解、文字渲染和复杂指令;所以中文海报、公众号封面、角色插画,我会更愿意先交给它。

z-turbo 也不是只能画真人,只是我发现它比较适合“真实摄影感”“人像”“产品图”这类需求,而且速度更适合 Agent 交互。

如果用户没有明显风格要求,那就不指定模型,让网关走默认链:

kolors → qwen → flux → z-image → z-turbo → pollinations

提示词增强:不是越长越好

这个地方我踩过坑。

一开始我以为提示词越详细越好,后来发现不对。真正应该做的是:短提示词补全,长提示词尊重。

用户说得很短,就大胆补全

比如:

画一个赛博朋克城市

Agent 应该补:

  • 是夜景还是白天;
  • 有没有人物;
  • 是广角城市、街头视角,还是空中俯视;
  • 光影是霓虹、雨夜、反射,还是电影感;
  • 用途是封面、壁纸,还是头像。

用户已经说得很完整,就别乱加戏

比如:

生成一张 16:9 的公众号封面,深蓝色科技风背景,中间是一个发光的 AI 芯片,标题文字是“本地图片网关”,副标题是“让 Agent 自动选模型”,整体极简、干净、不要人物

这种 prompt 已经很清楚了。Agent 只需要润色结构,不要擅自加美女、机器人、城市夜景。

我现在给 Agent 的规则很简单:

用户说得少:补画面。用户说得多:保原意。用户给了禁止项:必须遵守。用户要文字:明确写出文字内容、位置、层级和可读性。

这个策略比无脑堆“masterpiece、best quality、ultra detailed”靠谱得多。


这三个平台具体怎么接?

1. 硅基流动:主力通道

硅基流动的图片接口相对直接,POST 到:

https://api.siliconflow.cn/v1/images/generations

Kolors 请求体大概是:

{  "model": "Kwai-Kolors/Kolors",  "prompt": "a cat wearing sunglasses, cyberpunk style",  "image_size": "1024x1024",  "batch_size": 1,  "num_inference_steps": 20,  "guidance_scale": 7.5}

它返回的是图片 URL。这里有个坑:这个 URL 不是永久图床,官方文档里也提醒要及时下载保存。我在网关里会尽量把需要缓存的图片放到本地 /generated/ 目录,再返回一个 NAS/服务器可访问的 URL。

2. 魔搭 ModelScope:异步任务通道

魔搭这边要注意,它的图片生成更像“任务系统”。

你不是直接拿图,而是:

提交任务 → 拿 task_id → 轮询任务 → 拿 output_images

提交任务时要带异步 header,轮询任务时又是另一个 header。这个地方我第一次就踩了坑。

我在网关里把它封装成同步体验:Agent 还是只发一个 /v1/images/generations 请求,网关内部自己提交、轮询、拿结果。

当前我接了四个 ModelScope 图片模型:

qwen     -> Qwen/Qwen-Image-2512flux     -> black-forest-labs/FLUX.1-Krea-devz-image  -> Tongyi-MAI/Z-Imagez-turbo  -> Tongyi-MAI/Z-Image-Turbo

注意:qwen、flux、z-image、z-turbo 是我自己给 Agent 用的别名。真正发给后端时,必须换成完整模型名。

3. Pollinations:兜底通道

Pollinations 的好处是接入轻,适合做最后兜底。

我这里做了两层:

  • 如果配置了 POLLINATIONS_API_KEY,优先走 OpenAI-compatible 图片接口;
  • 如果没配置 Key,就尝试 legacy public endpoint,生成后下载到本地缓存,再返回本地 URL。

它不适合作为严肃生产主力,但很适合当“最后一层保险”。


快速部署

仓库地址:

https://github.com/ang77712829/image-proxy-gateway

本地直接跑:

git clone https://github.com/ang77712829/image-proxy-gateway.gitcd image-proxy-gatewaypython3 -m venv .venvsource .venv/bin/activatepip install -r requirements.txtcp .env.example .envpython3 scripts/proxy.py

.env 里常用的是这些:

# 免费 / 低成本通道,至少填一个SILICONFLOW_API_KEY=sk-your-siliconflow-keyMODELSCOPE_API_KEY=ms-your-modelscope-keyPOLLINATIONS_API_KEY=# 可选:OpenAI-compatible 付费图片渠道# 不会进入默认免费降级链,只有显式指定 gpt-image-2 / openai-image 时才会调用OPENAI_IMAGE_API_KEY=OPENAI_IMAGE_BASE_URL=https://api.openai.com/v1OPENAI_IMAGE_MODEL=gpt-image-2# 给局域网 / 公网 / New-API 使用时强烈建议设置GATEWAY_API_KEY=change-mePROXY_HOST=0.0.0.0PROXY_PORT=9890PUBLIC_BASE_URL=http://localhost:9890IMAGE_PROXY_STATE_DIR=/dataMODELSCOPE_DAILY_LIMIT=50POLLINATIONS_MODEL=zimageHTTP_TIMEOUT=60MAX_POLL_TIME=120POLL_INTERVAL=3

启动后检查:

curl http://localhost:9890/health

生成一张图:

curl -X POST http://localhost:9890/v1/images/generations \  -H "Content-Type: application/json" \  -d '{"prompt":"一只戴墨镜的猫,赛博朋克风格"}'

指定模型:

curl -X POST http://localhost:9890/v1/images/generations \  -H "Content-Type: application/json" \  -d '{"model":"qwen","prompt":"一张中文科技风公众号封面,标题是 AI 图片网关"}'

如果设置了 GATEWAY_API_KEY:

curl -X POST http://localhost:9890/v1/images/generations \  -H "Authorization: Bearer $GATEWAY_API_KEY" \  -H "Content-Type: application/json" \  -d '{"model":"z-turbo","prompt":"A realistic portrait photo, cinematic lighting"}'

Docker Compose 部署

如果你放在 NAS 或服务器上,也可以用 Docker Compose:

cp .env.example .env# 编辑 .envdocker compose up -d --build

compose 大概是这样:

services:  image-proxy:    build: .    env_file:      - .env    ports:      - "9890:9890"    environment:      - PROXY_PORT=9890      - IMAGE_PROXY_STATE_DIR=/data      - PUBLIC_BASE_URL=${PUBLIC_BASE_URL:-http://localhost:9890}    volumes:      - image-proxy-data:/data    restart: unless-stoppedvolumes:  image-proxy-data:

NAS 上一定注意 PUBLIC_BASE_URL。

如果 Agent 和网关不在同一台机器,不能写:

http://localhost:9890

而应该写成:

http://你的NAS局域网IP:9890

否则 Agent 拿到本地缓存图片 URL 后,自己打不开。


接入 Agent / New-API

因为网关对外就是 OpenAI-compatible,所以接 New-API 很简单。

新增一个 OpenAI 类型渠道:

Base URL: http://你的服务器IP:9890API Key: 如果设置了 GATEWAY_API_KEY,就填它模型: kolors / qwen / flux / z-image / z-turbo / pollinations / gpt-image-2(可选付费通道)

但重点还是那句话:不要让 Agent 直接裸传用户原话。

我更推荐 Agent 内部按这个流程工作:

1. 判断图片类型:写实、人像、二次元、海报、产品图、风景……2. 提取用户明确要求:主体、场景、文字、比例、禁止项3. 选择模型:qwen / flux / z-turbo / kolors……4. 判断扩写强度:强扩写 / 轻润色 / 原意保留5. 调用本地网关

这样用户只要说:

帮我画一张现实风格美女,雨夜街头,霓虹灯背景

Agent 最终会发出类似:

{  "model": "z-turbo",  "prompt": "A photorealistic cinematic portrait of an elegant young adult woman standing on a rainy city street at night, neon signs glowing in the background, wet pavement reflections, soft rim light, natural skin texture, shallow depth of field, 85mm lens, high-end fashion editorial photography, clean composition.",  "size": "1024x1024"}

这才是我想要的体验。


后续加新渠道也不难

这套代码后来我又整理了一下,把后端做成了 provider registry。

意思是,后续如果要接:

  • 即梦;
  • GPT-Image-2;
  • 其他 OpenAI-compatible 图片服务;
  • 自己的 ComfyUI / 推理服务器;

就不应该在主流程里乱加一堆 if/else,而是按模板加一个 provider adapter。

一个新渠道至少要补齐:

provider_name认证方式真实模型名和别名映射prompt / size / n / response_format 参数映射同步还是异步返回值怎么标准化成 OpenAI Images 格式临时 URL 要不要下载到本地错误码如何分类/health 里怎么展示状态README / SKILL / .env.example 怎么同步更新

这样项目后面才不会越写越乱。

付费模型我也倾向于这么接,但不要放进默认免费降级链。比如 gpt-image-2 这种高质量模型,最好让 Agent 明确判断“这次值得用高质量付费模型”时再调用,避免普通请求无意中烧额度。

这版代码里已经预留了 OPENAI_IMAGE_API_KEY、OPENAI_IMAGE_BASE_URL、OPENAI_IMAGE_MODEL 这组变量。如果你后面真的要接 GPT-Image-2 或其他 OpenAI-compatible 图片服务,只需要配置这几项,再显式传 model: "gpt-image-2" 即可。


我踩过的几个坑

1. 别名不能直接传给后端

Agent 用 qwen 这个名字很方便,但 ModelScope 后端不认识 qwen。

真正传过去必须是:

Qwen/Qwen-Image-2512

所以网关里必须维护一层:

别名 -> provider -> 真实模型名

2. ModelScope 是异步任务,不是同步返回图

这块一定要处理好提交和轮询,否则会出现“任务提交了但拿不到图”的情况。

3. 临时 URL 不等于图床

很多平台返回的图片 URL 都有有效期。硅基流动官方文档里也明确提醒生成图 URL 有效期问题。

所以如果图片要长期保留,最好下载到自己的 NAS、对象存储或媒体库。

4. 不要公网裸奔

本地测试可以不鉴权,但只要给局域网、New-API 或公网使用,就应该设置:

GATEWAY_API_KEY=一个足够长的随机字符串

再加一层 Nginx / Caddy 做 HTTPS 和限流会更稳。

5. 提示词增强不要变成“替用户乱创作”

这点反而最影响体验。

用户说“不要人物”,Agent 就不能补人物。

用户说“极简”,Agent 就别加一堆霓虹城市和机器人。

扩写的本质是补足画面信息,不是改掉用户需求。


写在最后

这个项目做完后,我最大的感受是:

Agent 的生图能力,不应该只是“接一个图片 API”。

真正好用的体验应该是:

用户说自然语言;Agent 理解需求、补全提示词、选择模型;网关负责多平台调用、失败降级、本地缓存;最终返回一张可访问、可保存的图片。

免费额度和限流当然重要,所以我把硅基流动、魔搭和 Pollinations 都接了进来:硅基流动做主力低成本通道,魔搭按图片模型 50 张/天做本地保护,Pollinations 做最后兜底。

但这个项目真正有价值的地方,不只是“省钱”,而是把 Agent 生图这件事抽象成了一个稳定接口。

今天接 SiliconFlow、ModelScope、Pollinations;明天要接即梦、GPT-Image-2、自建 ComfyUI,也不用把 Agent 侧全部推倒重来。

仓库地址:

https://github.com/ang77712829/image-proxy-gateway

如果你也在给 Agent、NAS 或 New-API 接图片生成,可以直接拿这套网关改。欢迎 Star、提 issue,也欢迎继续补新的图片渠道。

相关学习资料