Appearance
下载原始 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.pngTask 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 即可
基本流程
- 直接提交文生图工作流(无需上传图片)
- 工作流包含 10 个节点:
CLIPLoader— 加载 Lumina2 的 CLIP 文本编码器VAELoader— 加载 VAE 解码器UNETLoader— 加载 UNet 去噪主模型CLIPTextEncode× 2 — 正向/负向提示词编码EmptySD3LatentImage— 生成空 latentKSampler— 采样去噪(核心节点)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
}使用前需修改:
| 节点 | 字段 | 修改为 |
|---|---|---|
| 67 | text | 你的正向提示词(英文效果更佳) |
| 71 | text | 负向提示词(可保持默认) |
| 69 | seed | 任意整数(不同值生成不同图片) |
| 9 | filename_prefix | 输出文件名前缀 |
节点说明
| 节点 ID | class_type | 功能 |
|---|---|---|
| 62 | CLIPLoader | 加载 Lumina2 的 CLIP 模型(文本编码器) |
| 63 | VAELoader | 加载 VAE 解码器,将 latent 解码为像素图 |
| 66 | UNETLoader | 加载 UNet 去噪主模型 z_image_bf16 |
| 67 | CLIPTextEncode | 正向提示词编码,传递给 KSampler 的 positive |
| 68 | EmptySD3LatentImage | 生成空 latent,设定输出图片宽高和批次 |
| 69 | KSampler | 采样去噪核心节点,控制 seed/steps/cfg 等生成参数 |
| 70 | ModelSamplingAuraFlow | 为 Lumina2 模型调整 shift 采样偏移 |
| 71 | CLIPTextEncode | 负向提示词编码,传递给 KSampler 的 negative |
| 65 | VAEDecode | 将 KSampler 输出的 latent 解码为像素图像 |
| 9 | SaveImage | 保存图片为 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)关键参数
| 节点 | 字段 | 说明 | 示例值 |
|---|---|---|---|
| 67 | text | 正向提示词(英文效果更佳) | "A cute puppy sitting on grass" |
| 71 | text | 负向提示词 | "blurry, low quality, distorted" |
| 68 | width / height | 图片尺寸 | 1024 × 1024 |
| 69 | seed | 随机种子(不同值生成不同图片) | 12345 |
| 69 | steps | 采样步数(越高越精细) | 25-35 |
| 69 | cfg | CFG 强度 | 4-7 |
| 9 | filename_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,注意区别) - 图片输出的
type为output - 下载的是 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 steps | 25-35,30 为推荐值;越高越精细但越慢 |
| CFG 强度 | 69 cfg | 4-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 photographyRoute 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:8188 | ai.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为空字符串) - [ ] 图片可正常查看且分辨率符合配置