Skip to content

下载原始 Skill 文件

bash
curl https://ai.ospreyai.cn/docs/raw/skills/comfyui-image-generation.md -o comfyui-image-generation.md

对话式接入

本 Skill 文件可被 AI 助手(Claude Code、Cursor、ChatGPT 等)学习,通过自然语言对话完成图片生成。

在 AI 对话中发送以下指令即可:

学习:https://ai.ospreyai.cn/docs/raw/skills/comfyui-image-generation.md,保存为本地的技能 skills

更多接入方式和使用示例详见 API 文档 — AI 助手对话式接入


ComfyUI 图片生成

Overview

通过公网网关 https://ai.ospreyai.cn 使用 ComfyUI 进行文生图,覆盖工作流提交、状态查询和 PNG 图片下载。

使用 z_image_bf16(百度文生图) 模型,支持 1024×1024 高分辨率图片生成,30 步采样约 30 秒完成。

所有 API 均需 Bearer Token 鉴权(Authorization: Bearer sk-xxx)。

Quick Start

bash
export GW="https://ai.ospreyai.cn"
export API_KEY="sk-your-api-key"

# 1. 提交图片生成工作流
curl -s -H "Authorization: Bearer $API_KEY" -X POST "$GW/api/v1/ai/image/generate" \
  -H "Content-Type: application/json" \
  -d '{"prompt":{...}}'

# 2. 查询任务状态
curl -s -H "Authorization: Bearer $API_KEY" "$GW/api/v1/ai/tasks/{prompt_id}"

# 3. 下载生成的图片
curl -s -H "Authorization: Bearer $API_KEY" \
  "$GW/api/v1/ai/image/view/?filename=output_00001_.png&type=output&subfolder=" \
  -o output.png

Task Routing

场景动作
首次生成图片→ Route A: Submit & Generate
需要查看任务是否完成→ Route B: Check Status
需要获取或下载 PNG→ Route C: Download
需要调优提示词、尺寸或参数→ Route D: Tune Parameters
需要排查服务、节点、模型或文件问题→ Route E: Troubleshoot

Route A: Submit & Generate

服务信息

  • 网关地址: https://ai.ospreyai.cn
  • 提交接口: POST /api/v1/ai/image/generate
  • 鉴权方式: Authorization: Bearer sk-xxx
  • 无需后端 Bearer Token,网关 Bearer Token 即可

基本流程

  1. 直接提交文生图工作流(无需上传图片)
  2. 工作流包含 10 个节点:
    • CLIPLoader — 加载 Lumina2 的 CLIP 文本编码器
    • VAELoader — 加载 VAE 解码器
    • UNETLoader — 加载 UNet 去噪主模型
    • CLIPTextEncode × 2 — 正向/负向提示词编码
    • EmptySD3LatentImage — 生成空 latent
    • KSampler — 采样去噪(核心节点)
    • ModelSamplingAuraFlow — 采样偏移调整
    • VAEDecode — VAE 解码 latent → 像素图
    • SaveImage — 保存图片为 PNG

提交工作流

bash
curl -s -H "Authorization: Bearer $API_KEY" -X POST "$GW/api/v1/ai/image/generate" \
  -H "Content-Type: application/json" \
  -d '{
    "prompt": {
      "62": {"inputs": {"clip_name": "qwen_3_4b.safetensors", "type": "lumina2", "device": "default"}, "class_type": "CLIPLoader"},
      "63": {"inputs": {"vae_name": "ae.safetensors"}, "class_type": "VAELoader"},
      "66": {"inputs": {"unet_name": "z_image_bf16.safetensors", "weight_dtype": "default"}, "class_type": "UNETLoader"},
      "67": {"inputs": {"text": "A cute puppy sitting on grass, sunny day, photorealistic", "clip": ["62", 0]}, "class_type": "CLIPTextEncode"},
      "68": {"inputs": {"width": 1024, "height": 1024, "batch_size": 1}, "class_type": "EmptySD3LatentImage"},
      "69": {"inputs": {"seed": 12345, "steps": 30, "cfg": 4.5, "sampler_name": "res_multistep", "scheduler": "simple", "denoise": 1, "model": ["70", 0], "positive": ["67", 0], "negative": ["71", 0], "latent_image": ["68", 0]}, "class_type": "KSampler"},
      "70": {"inputs": {"shift": 3, "model": ["66", 0]}, "class_type": "ModelSamplingAuraFlow"},
      "71": {"inputs": {"text": "blurry, low quality, distorted, deformed, ugly", "clip": ["62", 0]}, "class_type": "CLIPTextEncode"},
      "65": {"inputs": {"samples": ["69", 0], "vae": ["63", 0]}, "class_type": "VAEDecode"},
      "9": {"inputs": {"filename_prefix": "output", "images": ["65", 0]}, "class_type": "SaveImage"}
    }
  }'

响应:

json
{
  "prompt_id": "0871f625-65f6-4d2f-abd8-0b248dafa58f",
  "number": 99
}

使用前需修改:

节点字段修改为
67text你的正向提示词(英文效果更佳)
71text负向提示词(可保持默认)
69seed任意整数(不同值生成不同图片)
9filename_prefix输出文件名前缀

节点说明

节点 IDclass_type功能
62CLIPLoader加载 Lumina2 的 CLIP 模型(文本编码器)
63VAELoader加载 VAE 解码器,将 latent 解码为像素图
66UNETLoader加载 UNet 去噪主模型 z_image_bf16
67CLIPTextEncode正向提示词编码,传递给 KSampler 的 positive
68EmptySD3LatentImage生成空 latent,设定输出图片宽高和批次
69KSampler采样去噪核心节点,控制 seed/steps/cfg 等生成参数
70ModelSamplingAuraFlow为 Lumina2 模型调整 shift 采样偏移
71CLIPTextEncode负向提示词编码,传递给 KSampler 的 negative
65VAEDecode将 KSampler 输出的 latent 解码为像素图像
9SaveImage保存图片为 PNG,设置输出文件名前缀

工作流连接图

CLIPLoader (62) ──→ CLIPTextEncode 正向 (67) ──→ KSampler (69)
                 └→ CLIPTextEncode 负向 (71) ──→ KSampler (69)

UNETLoader (66) ──→ ModelSamplingAuraFlow (70) ──→ KSampler (69)

EmptySD3LatentImage (68) ──→ KSampler (69)

KSampler (69) ──→ VAEDecode (65) ──→ SaveImage (9)
VAELoader (63) ──→ VAEDecode (65)

关键参数

节点字段说明示例值
67text正向提示词(英文效果更佳)"A cute puppy sitting on grass"
71text负向提示词"blurry, low quality, distorted"
68width / height图片尺寸1024 × 1024
69seed随机种子(不同值生成不同图片)12345
69steps采样步数(越高越精细)25-35
69cfgCFG 强度4-7
9filename_prefix输出文件名前缀"output"

输出图片参数

  • 分辨率: 默认 1024 × 1024
  • 格式: PNG
  • 输出路径: subfolder=""(空字符串), type=output

Route B: Check Status

查询队列

bash
curl -s -H "Authorization: Bearer $API_KEY" "$GW/api/v1/ai/queue"

响应:

json
{
  "queue_running": [[99, "0871f625-...", {...}]],
  "queue_pending": []
}
  • queue_running 不为空 → 任务正在执行
  • queue_pending 不为空 → 任务排队等待

查询任务状态

bash
curl -s -H "Authorization: Bearer $API_KEY" "$GW/api/v1/ai/tasks/{prompt_id}"

进行中:

json
{
  "0871f625-...": {
    "status": {"status_str": "success", "completed": false},
    "outputs": {}
  }
}

已完成:

json
{
  "0871f625-...": {
    "status": {"status_str": "success", "completed": true},
    "outputs": {
      "9": {
        "images": [
          {"filename": "output_00001_.png", "subfolder": "", "type": "output"}
        ]
      }
    }
  }
}

图片生成通常需要 20-40 秒(取决于 GPU 和队列情况)。

Route C: Download

下载前先从任务状态中获取输出文件信息(filename, subfolder, type),然后通过查看接口下载。

bash
# 下载 PNG 图片(注意 subfolder 为空字符串)
curl -s -H "Authorization: Bearer $API_KEY" \
  "$GW/api/v1/ai/image/view/?filename=output_00001_.png&type=output&subfolder=" \
  -o output.png

关键点:

  • 图片输出的 subfolder 为空字符串(视频是 video,注意区别)
  • 图片输出的 typeoutput
  • 下载的是 PNG 格式,可直接查看

Python 调用示例

python
import requests
import time

GW = "https://ai.ospreyai.cn"
API_KEY = "sk-your-api-key"
headers = {"Authorization": f"Bearer {API_KEY}"}

# 1. 提交文生图工作流
prompt = {
    "prompt": {
        "62": {"inputs": {"clip_name": "qwen_3_4b.safetensors", "type": "lumina2", "device": "default"}, "class_type": "CLIPLoader"},
        "63": {"inputs": {"vae_name": "ae.safetensors"}, "class_type": "VAELoader"},
        "66": {"inputs": {"unet_name": "z_image_bf16.safetensors", "weight_dtype": "default"}, "class_type": "UNETLoader"},
        "67": {"inputs": {"text": "A cute puppy sitting on grass, sunny day, photorealistic", "clip": ["62", 0]}, "class_type": "CLIPTextEncode"},
        "68": {"inputs": {"width": 1024, "height": 1024, "batch_size": 1}, "class_type": "EmptySD3LatentImage"},
        "69": {"inputs": {"seed": 12345, "steps": 30, "cfg": 4.5, "sampler_name": "res_multistep", "scheduler": "simple", "denoise": 1, "model": ["70", 0], "positive": ["67", 0], "negative": ["71", 0], "latent_image": ["68", 0]}, "class_type": "KSampler"},
        "70": {"inputs": {"shift": 3, "model": ["66", 0]}, "class_type": "ModelSamplingAuraFlow"},
        "71": {"inputs": {"text": "blurry, low quality, distorted", "clip": ["62", 0]}, "class_type": "CLIPTextEncode"},
        "65": {"inputs": {"samples": ["69", 0], "vae": ["63", 0]}, "class_type": "VAEDecode"},
        "9": {"inputs": {"filename_prefix": "output", "images": ["65", 0]}, "class_type": "SaveImage"}
    }
}

resp = requests.post(f"{GW}/api/v1/ai/image/generate", headers=headers, json=prompt)
prompt_id = resp.json()["prompt_id"]
print(f"Task submitted: {prompt_id}")

# 2. 轮询任务状态
while True:
    resp = requests.get(f"{GW}/api/v1/ai/tasks/{prompt_id}", headers=headers)
    data = resp.json()
    task = data.get(prompt_id, {})
    status = task.get("status", {})
    if status.get("completed"):
        print("Task completed!")
        break
    print(f"Status: {status.get('status_str', 'unknown')}...")
    time.sleep(5)

# 3. 下载图片
outputs = task.get("outputs", {}).get("9", {})
image_info = outputs.get("images", [{}])[0]
resp = requests.get(f"{GW}/api/v1/ai/image/view/", headers=headers,
                    params={"filename": image_info["filename"],
                            "subfolder": image_info.get("subfolder", ""),
                            "type": image_info.get("type", "output")})
with open("output.png", "wb") as f:
    f.write(resp.content)
print(f"Downloaded: output.png ({len(resp.content)} bytes)")

Route D: Tune Parameters

参数节点建议
正向提示词67 text英文效果更稳定,描述越具体越好
负向提示词71 text默认可保持;可补充不想出现的元素
图片尺寸68 width/height默认 1024×1024;正方形效果最佳
采样步数69 steps25-35,30 为推荐值;越高越精细但越慢
CFG 强度69 cfg4-7,4.5 为推荐值;过高会导致过饱和
随机种子69 seed不同值生成不同图片;相同种子可复现
采样器69 sampler_name推荐 res_multistep
调度器69 scheduler推荐 simple
采样偏移70 shift默认 3;增大偏移更锐利,减小更平滑

示例提示词

宠物:

text
A cute fluffy golden retriever puppy, big shiny eyes, soft fluffy fur, sitting on green grass, sunny day, photorealistic, high quality

风景:

text
A beautiful sunset over the ocean, golden hour, dramatic clouds, orange and purple sky, professional photography

人物:

text
A portrait of a woman, soft natural lighting, detailed skin, professional photography, 8k

建筑:

text
A modern glass skyscraper, sunlight reflecting on glass, blue sky background, architectural photography

Route E: Troubleshoot

问题排查方法
工作流提交报 value_not_in_list模型文件名不正确,检查 UNet/CLIP/VAE 名称是否与服务器一致
工作流提交报 return_type_mismatch节点间连接类型不匹配,检查节点输出→输入的链接是否正确
任务长时间未完成检查 /api/v1/ai/queue 是否有排队任务;GPU 可能忙碌
下载图片返回空检查 subfolder 是否为空字符串(视频是 video,图片是空)
401 鉴权失败检查 Bearer Token 是否有效:curl -H "Authorization: Bearer sk-xxx" $GW/api/v1/ai/queue
429 请求被限流AI 接口 10次/分/IP,稍后重试
503 后端服务不可用检查内网 ComfyUI 服务是否运行
图片质量不理想优先使用英文提示词;steps 调整到 25-35;cfg 保持在 4-7;更换 seed 生成变体

内网直连 vs 公网网关

内网直连公网网关
地址192.168.1.236:8188ai.ospreyai.cn
鉴权Authorization: Bearer sk-xxx
提交路径/prompt/api/v1/ai/image/generate
任务查询/history/{id}/api/v1/ai/tasks/{id}
队列查询/queue/api/v1/ai/queue
下载路径/view?filename=.../api/v1/ai/image/view/?filename=...&type=output&subfolder=
限流10次/分/IP

Verification Checklist

  • [ ] 工作流提交成功,返回 prompt_id
  • [ ] 任务在 /api/v1/ai/queue 中执行完成
  • [ ] 任务状态 completed: true,outputs 包含 PNG 文件信息
  • [ ] 成功下载 PNG 文件(注意 subfolder 为空字符串)
  • [ ] 图片可正常查看且分辨率符合配置

AI API Gateway Documentation