Skip to content

FLUX.2 图生图编辑

网关地址: https://ai.ospreyai.cn(公网) 模型: flux-2-klein-9b-kv-fp8 无需后端 Bearer Token

概述

使用 FLUX.2-klein-9b-kv-fp8 模型,通过 Reference Conditioning 技术实现图片编辑,支持换装、换背景、局部修改。仅需 4 步生成,速度极快。任务异步执行:提交工作流 → 轮询状态 → 下载结果。任务状态查询、结果下载等通用接口见 任务管理

前置条件: 需先通过 /api/v1/upload 上传输入图片。

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

接口清单

用途方法路径
上传输入图片POST/api/v1/upload
提交编辑任务POST/api/v1/ai/image/generate
查询任务状态GET/api/v1/ai/tasks/{prompt_id}
下载结果文件GET/api/v1/ai/image/view/
查询队列GET/api/v1/ai/queue

提交图片编辑任务

POST /api/v1/ai/image/generate
Content-Type: application/json
Authorization: Bearer sk-xxx

1. 上传图片

图1=主体,图2=服装参考(自我编辑时图1图2用同一张)。

bash
# 上传图1(主体)
curl -H "Authorization: Bearer $API_KEY" -X POST "$GW/api/v1/upload" \
  -F "image=@/path/to/man.png" \
  -F "type=input"
# 返回: {"name": "man.png", "subfolder": "", "type": "input"}

# 上传图2(服装参考)
curl -H "Authorization: Bearer $API_KEY" -X POST "$GW/api/v1/upload" \
  -F "image=@/path/to/outfit.png" \
  -F "type=input"
# 返回: {"name": "outfit.png", "subfolder": "", "type": "input"}

2. 提交编辑工作流

bash
curl -H "Authorization: Bearer $API_KEY" -X POST "$GW/api/v1/ai/image/generate" \
  -H "Content-Type: application/json" \
  -d '{
    "prompt": {
      "122": {"class_type": "KSamplerSelect", "inputs": {"sampler_name": "euler"}},
      "126": {"class_type": "UNETLoader", "inputs": {"unet_name": "flux-2-klein-9b-kv-fp8.safetensors", "weight_dtype": "default"}},
      "133": {"class_type": "CLIPLoader", "inputs": {"clip_name": "qwen_3_8b_fp8mixed.safetensors", "type": "flux2", "device": "default"}},
      "138": {"class_type": "CFGGuider", "inputs": {"model": ["139", 0], "positive": ["132_121", 0], "negative": ["132_119", 0], "cfg": 1.0}},
      "127": {"class_type": "VAELoader", "inputs": {"vae_name": "flux2-vae.safetensors"}},
      "135": {"class_type": "CLIPTextEncode", "inputs": {"clip": ["133", 0], "text": "Have the man put on the clothes from Figure 2, keep same posture"}},
      "139": {"class_type": "FluxKVCache", "inputs": {"model": ["126", 0]}},
      "123": {"class_type": "SamplerCustomAdvanced", "inputs": {"noise": ["125", 0], "guider": ["138", 0], "sampler": ["122", 0], "sigmas": ["137", 0], "latent_image": ["129", 0]}},
      "125": {"class_type": "RandomNoise", "inputs": {"noise_seed": 720512742793301}},
      "124": {"class_type": "VAEDecode", "inputs": {"samples": ["123", 0], "vae": ["127", 0]}},
      "94":  {"class_type": "SaveImage", "inputs": {"images": ["124", 0], "filename_prefix": "Result"}},
      "685": {"class_type": "ConditioningZeroOut", "inputs": {"conditioning": ["135", 0]}},
      "137": {"class_type": "Flux2Scheduler", "inputs": {"width": ["128", 0], "height": ["128", 1], "steps": 4}},
      "129": {"class_type": "EmptyFlux2LatentImage", "inputs": {"width": ["128", 0], "height": ["128", 1], "batch_size": 1}},
      "128": {"class_type": "GetImageSize", "inputs": {"image": ["130", 0]}},
      "130": {"class_type": "ImageScaleToTotalPixels", "inputs": {"image": ["76", 0], "upscale_method": "lanczos", "megapixels": 1.0, "resolution_steps": 1}},
      "131": {"class_type": "ImageScaleToTotalPixels", "inputs": {"image": ["81", 0], "upscale_method": "lanczos", "megapixels": 1.0, "resolution_steps": 1}},
      "76": {"class_type": "LoadImage", "inputs": {"image": "man.png"}},
      "81": {"class_type": "LoadImage", "inputs": {"image": "outfit.png"}},
      "134_116": {"class_type": "ReferenceLatent", "inputs": {"conditioning": ["685", 0], "latent": ["134_117", 0]}},
      "134_117": {"class_type": "VAEEncode", "inputs": {"pixels": ["130", 0], "vae": ["127", 0]}},
      "134_118": {"class_type": "ReferenceLatent", "inputs": {"conditioning": ["135", 0], "latent": ["134_117", 0]}},
      "132_119": {"class_type": "ReferenceLatent", "inputs": {"conditioning": ["134_116", 0], "latent": ["132_120", 0]}},
      "132_120": {"class_type": "VAEEncode", "inputs": {"pixels": ["131", 0], "vae": ["127", 0]}},
      "132_121": {"class_type": "ReferenceLatent", "inputs": {"conditioning": ["134_118", 0], "latent": ["132_120", 0]}}
    }
  }'

响应:

json
{"prompt_id": "a1b2c3d4-...", "number": 100, "node_errors": {}}

关键节点参数

节点字段说明推荐值
76image主体图片文件名(需先上传)上传返回的 name
81image服装/参考图片文件名可与 76 相同(自我编辑)
135text编辑提示词(英文,Figure 1/2 指代图片)
125noise_seed随机种子任意整数
137steps采样步数4
94filename_prefix输出文件名前缀

提示词技巧

  • 换装:"Have the man in Figure 1 put on the clothes from Figure 2, keep same posture"
  • 改背景:"Change background to African savannah, keep person unchanged"
  • 局部修改:将图1图2设为同一张,写 "Remove the outer jacket, keep inner clothing only"

缓存坑:若提交的工作流与历史完全相同(尤其 seed 相同),ComfyUI 会命中 execution_cached 直接返回,outputs 可能为空。提交时换个随机 noise_seed 可避免。

Python 调用示例

python
import json, time, urllib.request

GW = "https://ai.ospreyai.cn"
API_KEY = "sk-your-api-key"
HEADERS = {"Authorization": f"Bearer {API_KEY}", "Content-Type": "application/json"}

# 1. 上传图片(用 poster.encode/multipart)
# 略 —— 参考「任务管理」页的上传示例

# 2. 提交工作流
nodes = {
    "122": {"class_type": "KSamplerSelect", "inputs": {"sampler_name": "euler"}},
    "126": {"class_type": "UNETLoader", "inputs": {"unet_name": "flux-2-klein-9b-kv-fp8.safetensors", "weight_dtype": "default"}},
    # ...其余节点同上 curl 示例...
}
nodes["135"]["inputs"]["text"] = "Have the man put on the clothes from Figure 2, keep same posture"
nodes["76"]["inputs"]["image"] = "man.png"
nodes["81"]["inputs"]["image"] = "outfit.png"
nodes["125"]["inputs"]["noise_seed"] = 123456  # 避免缓存

req = urllib.request.Request(
    f"{GW}/api/v1/ai/image/generate",
    data=json.dumps({"prompt": nodes}).encode(),
    headers=HEADERS, method="POST",
)
prompt_id = json.loads(urllib.request.urlopen(req, timeout=30).read())["prompt_id"]

# 3. 轮询
while True:
    r = urllib.request.Request(f"{GW}/api/v1/ai/tasks/{prompt_id}", headers=HEADERS)
    task = json.loads(urllib.request.urlopen(r, timeout=15).read())[prompt_id]
    if task["status"].get("completed"):
        break
    time.sleep(5)

# 4. 下载
for out in task["outputs"].values():
    for img in out.get("images", []):
        url = f"{GW}/api/v1/ai/image/view/?filename={img['filename']}&type={img['type']}&subfolder={img.get('subfolder','')}"
        req = urllib.request.Request(url, headers=HEADERS)
        open(img["filename"], "wb").write(urllib.request.urlopen(req, timeout=120).read())

常见问题

问题现象可能原因解决方案
401 UnauthorizedAPI Key 错误/未传检查 Authorization: Bearer sk-xxx
404 / 节点报错输入图片未上传POST /api/v1/upload,文件名填入 LoadImage 节点
任务 success 但 outputs 为空命中 ComfyUI 缓存换随机 noise_seed 重提
编辑后人物姿态变化提示词未强调保持姿态keep same posture / keep person unchanged

详细文档见 ComfyUI FLUX.2 编辑 Skill

AI API Gateway Documentation