Appearance
AI API Gateway — API 调用手册
网关地址:
https://ai.ospreyai.cn鉴权方式: Bearer Token(new-apisk-xxx格式)
目录
- 通用说明
- 1. ComfyUI — 图像/视频生成
- 2. bge-m3 — Embedding 向量化
- 3. bge-reranker — 重排序
- 4. SearXNG — 聚合搜索
- 5. RAGFlow — RAG 知识库
- 6. Dify — 工作流编排
- AI 助手对话式接入
- 错误码参考
通用说明
鉴权
所有 API 均需 Bearer Token 鉴权(/health 和 /webui/ 除外):
bash
curl -H "Authorization: Bearer sk-your-api-key" https://ai.ospreyai.cn/api/v1/...网关通过 auth_request 将 Bearer Token 转发给 new-api 验证有效性。有效 key 返回 200,无效 key 返回 401。
Bearer Token 透传(RAGFlow / Dify 专用)
RAGFlow 和 Dify 自身需要 Authorization: Bearer xxx,与网关鉴权共用同一 header。 后端 Bearer token 通过 X-Authorization header 传入,网关自动转为 Authorization 转发给后端。
bash
curl -H "Authorization: Bearer sk-your-api-key" \
-H "X-Authorization: Bearer <你的后端token>" \
https://ai.ospreyai.cn/api/v1/rag/...若未传
X-Authorization,网关会清空转发给后端的Authorizationheader(避免 sk-xxx 泄露给后端服务),后端将返回 401。
限流
| 类型 | 速率 | 适用路径 |
|---|---|---|
| AI 接口 | 10 次/分/IP(突发 5) | /api/v1/ai/* |
| 普通接口 | 60 次/分/IP(突发 10-20) | /api/v1/embed/*, /api/v1/rerank/*, /api/v1/rag/*, /api/v1/search |
超限返回 429 Too Many Requests。
环境变量
以下示例中使用变量:
bash
export GW="https://ai.ospreyai.cn" # 网关地址
export API_KEY="sk-your-api-key" # Bearer Token1. ComfyUI — 图像/视频生成
内部地址:
192.168.1.236:8188模型: z_image_bf16(百度文生图) 无需后端 Bearer Token,网关 Bearer Token 即可
1.1 提交图像生成任务
POST /api/v1/ai/image/generate
Content-Type: application/json
Authorization: Bearer sk-xxx请求体 — ComfyUI 工作流 JSON,prompt 字段内为节点定义:
bash
curl -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", "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 | 负向提示词 | "blurry, low quality, distorted" |
| 68 | width / height | 图片尺寸 | 1024 × 1024 |
| 69 | seed | 随机种子(不同值生成不同图片) | 任意整数 |
| 69 | steps | 采样步数(越高越精细) | 25-35 |
| 69 | cfg | CFG 强度 | 4-7 |
| 9 | filename_prefix | 输出文件名前缀 | — |
1.2 提交视频生成任务(图生视频)
POST /api/v1/ai/video/generate
Content-Type: application/json
Authorization: Bearer sk-xxx使用 Wan2.2 I2V + LightX2V 4步加速 工作流,仅需 4 步采样即可生成约 5 秒视频。
前置条件: 需先通过 /api/v1/upload 上传输入图片。
bash
# 1. 上传图片
curl -H "Authorization: Bearer $API_KEY" -X POST "$GW/api/v1/upload" \
-F "image=@/path/to/input.png" \
-F "overwrite=true"
# 返回: {"name": "input.png", "subfolder": "", "type": "input"}
# 2. 提交视频工作流
curl -H "Authorization: Bearer $API_KEY" -X POST "$GW/api/v1/ai/video/generate" \
-H "Content-Type: application/json" \
-d '{
"prompt": {
"84": {"inputs": {"clip_name": "umt5_xxl_fp8_e4m3fn_scaled.safetensors", "type": "wan", "device": "default"}, "class_type": "CLIPLoader"},
"85": {"inputs": {"add_noise": "disable", "noise_seed": 0, "steps": 4, "cfg": 1, "sampler_name": "euler", "scheduler": "simple", "start_at_step": 2, "end_at_step": 4, "return_with_leftover_noise": "disable", "model": ["103", 0], "positive": ["98", 0], "negative": ["98", 1], "latent_image": ["86", 0]}, "class_type": "KSamplerAdvanced"},
"86": {"inputs": {"add_noise": "enable", "noise_seed": 42, "steps": 4, "cfg": 1, "sampler_name": "euler", "scheduler": "simple", "start_at_step": 0, "end_at_step": 2, "return_with_leftover_noise": "enable", "model": ["104", 0], "positive": ["98", 0], "negative": ["98", 1], "latent_image": ["98", 2]}, "class_type": "KSamplerAdvanced"},
"87": {"inputs": {"samples": ["85", 0], "vae": ["90", 0]}, "class_type": "VAEDecode"},
"89": {"inputs": {"text": "色调艳丽,过曝,静态,细节模糊不清,字幕,风格,作品,画作,画面,静止,整体发灰,最差质量,低质量,JPEG压缩残留,丑陋的,残缺的,多余的手指,画得不好的手部,画得不好的脸部,畸形的,毁容的,形态畸变的肢体,手指融合,静止不动的画面,杂乱的背景,三条腿,背景人很多,倒着走", "clip": ["84", 0]}, "class_type": "CLIPTextEncode"},
"90": {"inputs": {"vae_name": "wan_2.1_vae.safetensors"}, "class_type": "VAELoader"},
"93": {"inputs": {"text": "A bird spreading its wings and flying away", "clip": ["84", 0]}, "class_type": "CLIPTextEncode"},
"94": {"inputs": {"fps": 16, "images": ["87", 0]}, "class_type": "CreateVideo"},
"95": {"inputs": {"unet_name": "wan2.2_i2v_high_noise_14B_fp8_scaled.safetensors", "weight_dtype": "default"}, "class_type": "UNETLoader"},
"96": {"inputs": {"unet_name": "wan2.2_i2v_low_noise_14B_fp8_scaled.safetensors", "weight_dtype": "default"}, "class_type": "UNETLoader"},
"97": {"inputs": {"image": "input.png"}, "class_type": "LoadImage"},
"98": {"inputs": {"width": 640, "height": 640, "length": 81, "batch_size": 1, "positive": ["93", 0], "negative": ["89", 0], "vae": ["90", 0], "start_image": ["97", 0]}, "class_type": "WanImageToVideo"},
"101": {"inputs": {"lora_name": "wan2.2_i2v_lightx2v_4steps_lora_v1_high_noise.safetensors", "strength_model": 1.0, "model": ["95", 0]}, "class_type": "LoraLoaderModelOnly"},
"102": {"inputs": {"lora_name": "wan2.2_i2v_lightx2v_4steps_lora_v1_low_noise.safetensors", "strength_model": 1.0, "model": ["96", 0]}, "class_type": "LoraLoaderModelOnly"},
"103": {"inputs": {"shift": 5.0, "model": ["102", 0]}, "class_type": "ModelSamplingSD3"},
"104": {"inputs": {"shift": 5.0, "model": ["101", 0]}, "class_type": "ModelSamplingSD3"},
"108": {"inputs": {"filename_prefix": "video/my_video", "format": "auto", "codec": "auto", "video-preview": "", "video": ["94", 0]}, "class_type": "SaveVideo"}
}
}'响应:
json
{"prompt_id": "03464627-3b48-43fe-91b9-ca7c779ba618", "number": 130, "node_errors": {}}关键节点参数:
| 节点 | 字段 | 说明 | 推荐值 |
|---|---|---|---|
| 97 | image | 输入图片文件名(需先上传) | 上传返回的 name |
| 93 | text | 正向提示词(英文动作描述) | — |
| 98 | width / height | 视频尺寸 | 640 × 640 |
| 98 | length | 视频帧数(81帧≈5秒@16fps) | 81 |
| 86 | noise_seed | 随机种子 | 任意整数 |
| 108 | filename_prefix | 输出文件名前缀 | "video/xxx" |
输出: MP4 视频,640×640, 81帧, 16fps, 约5秒。下载时需注意 subfolder=video。
详细文档见 ComfyUI 视频生成 Skill。
1.3 提交视频生成任务(LTX-2 文生视频)
POST /api/v1/ai/video/generate
Content-Type: application/json
Authorization: Bearer sk-xxx使用 LTX-2 19B 模型做文生视频。采用两阶段采样管线:低分辨率(输出尺寸的 1/2)20 步打底 → 空间放大 2× → 4 步精修,输出静音 mp4(空音轨占位,非真实音频)。纯文本生成,无需上传图片。
bash
curl -H "Authorization: Bearer $API_KEY" -X POST "$GW/api/v1/ai/video/generate" \
-H "Content-Type: application/json" \
-d '{
"prompt": {
"75": {"inputs": {"filename_prefix": "video/LTX-2", "format": "mp4", "codec": "auto", "video": ["122", 0]}, "class_type": "SaveVideo"},
"98": {"inputs": {"steps": 20, "max_shift": 2.05, "base_shift": 0.95, "stretch": true, "terminal": 0.1, "latent": ["109", 0]}, "class_type": "LTXVScheduler"},
"99": {"inputs": {"text_encoder": "gemma_3_12B_it_fp4_mixed.safetensors", "ckpt_name": "ltx-2-19b-dev-fp8.safetensors", "device": "default"}, "class_type": "LTXAVTextEncoderLoader"},
"100": {"inputs": {"sigmas": "0.909375, 0.725, 0.421875, 0.0"}, "class_type": "ManualSigmas"},
"101": {"inputs": {"model_name": "ltx-2-spatial-upscaler-x2-1.0.safetensors"}, "class_type": "LatentUpscaleModelLoader"},
"102": {"inputs": {"positive": ["107", 0], "negative": ["107", 1], "latent": ["116", 0]}, "class_type": "LTXVCropGuides"},
"103": {"inputs": {"cfg": 1, "model": ["132", 0], "positive": ["102", 0], "negative": ["102", 1]}, "class_type": "CFGGuider"},
"104": {"inputs": {"upscale_method": "lanczos", "scale_by": 0.5, "image": ["111", 0]}, "class_type": "ImageScaleBy"},
"105": {"inputs": {"image": ["104", 0]}, "class_type": "GetImageSize"},
"106": {"inputs": {"frames_number": ["112", 0], "frame_rate": ["130", 0], "batch_size": 1, "audio_vae": ["123", 0]}, "class_type": "LTXVEmptyLatentAudio"},
"107": {"inputs": {"frame_rate": ["129", 0], "positive": ["121", 0], "negative": ["110", 0]}, "class_type": "LTXVConditioning"},
"108": {"inputs": {"width": ["105", 0], "height": ["105", 1], "length": ["112", 0], "batch_size": 1}, "class_type": "EmptyLTXVLatentVideo"},
"109": {"inputs": {"video_latent": ["108", 0], "audio_latent": ["106", 0]}, "class_type": "LTXVConcatAVLatent"},
"110": {"inputs": {"text": "blurry, low quality, still frame, frames, watermark, overlay, titles, has blurbox, has subtitles", "clip": ["99", 0]}, "class_type": "CLIPTextEncode"},
"111": {"inputs": {"width": 1280, "height": 720, "batch_size": 1, "color": 0}, "class_type": "EmptyImage"},
"112": {"inputs": {"value": 121}, "class_type": "PrimitiveInt"},
"113": {"inputs": {"noise": ["115", 0], "guider": ["128", 0], "sampler": ["135", 0], "sigmas": ["98", 0], "latent_image": ["109", 0]}, "class_type": "SamplerCustomAdvanced"},
"114": {"inputs": {"noise_seed": 0}, "class_type": "RandomNoise"},
"115": {"inputs": {"noise_seed": 12345}, "class_type": "RandomNoise"},
"116": {"inputs": {"av_latent": ["113", 0]}, "class_type": "LTXVSeparateAVLatent"},
"117": {"inputs": {"video_latent": ["118", 0], "audio_latent": ["116", 1]}, "class_type": "LTXVConcatAVLatent"},
"118": {"inputs": {"samples": ["102", 2], "upscale_model": ["101", 0], "vae": ["138", 2]}, "class_type": "LTXVLatentUpsampler"},
"119": {"inputs": {"noise": ["114", 0], "guider": ["103", 0], "sampler": ["136", 0], "sigmas": ["100", 0], "latent_image": ["117", 0]}, "class_type": "SamplerCustomAdvanced"},
"121": {"inputs": {"text": "A cheerful girl puppet singing in the rain, close-up, soft lighting, photorealistic", "clip": ["99", 0]}, "class_type": "CLIPTextEncode"},
"122": {"inputs": {"fps": ["129", 0], "images": ["126", 0], "audio": ["127", 0]}, "class_type": "CreateVideo"},
"123": {"inputs": {"ckpt_name": "ltx-2-19b-dev-fp8.safetensors"}, "class_type": "LTXVAudioVAELoader"},
"124": {"inputs": {"av_latent": ["119", 1]}, "class_type": "LTXVSeparateAVLatent"},
"126": {"inputs": {"tile_size": 512, "overlap": 64, "temporal_size": 4096, "temporal_overlap": 8, "samples": ["124", 0], "vae": ["138", 2]}, "class_type": "VAEDecodeTiled"},
"127": {"inputs": {"samples": ["124", 1], "audio_vae": ["123", 0]}, "class_type": "LTXVAudioVAEDecode"},
"128": {"inputs": {"cfg": 4, "model": ["138", 0], "positive": ["107", 0], "negative": ["107", 1]}, "class_type": "CFGGuider"},
"129": {"inputs": {"value": 24}, "class_type": "PrimitiveFloat"},
"130": {"inputs": {"value": 24}, "class_type": "PrimitiveInt"},
"132": {"inputs": {"lora_name": "ltx-2-19b-distilled-lora-384.safetensors", "strength_model": 1, "model": ["138", 0]}, "class_type": "LoraLoaderModelOnly"},
"135": {"inputs": {"sampler_name": "euler_ancestral"}, "class_type": "KSamplerSelect"},
"136": {"inputs": {"sampler_name": "euler_ancestral"}, "class_type": "KSamplerSelect"},
"138": {"inputs": {"ckpt_name": "ltx-2-19b-dev-fp8.safetensors"}, "class_type": "CheckpointLoaderSimple"}
},
"extra_data": {}
}'响应:
json
{"prompt_id": "5af01c46-eeba-4978-9bbd-71d763c770d4", "number": 6, "node_errors": {}}关键节点参数:
| 节点 | 字段 | 说明 | 推荐值 |
|---|---|---|---|
| 121 | text | 正向提示词(英文,动作描述) | — |
| 111 | width / height | 输出分辨率(需被 32 整除) | 1280 × 720 |
| 112 | value | 帧数(121 帧 ≈ 5s @ 24fps) | 121 |
| 129 / 130 | value | 帧率(两处必须同步) | 24 |
| 115 | noise_seed | 随机种子 | 任意整数 |
| 75 | filename_prefix | 输出文件名前缀(可含子目录) | "video/LTX-2" |
两阶段采样:
| 阶段 | 节点 | 步数 | 分辨率 |
|---|---|---|---|
| 低清打底 | 98(LTXVScheduler)+ 113 | 20 步 | 输出 ×0.5 |
| 空间放大 | 118(LTXVLatentUpsampler) | — | ×2 |
| 精修 | 100(ManualSigmas)+ 119 | 4 步 | 输出全尺寸 |
提示词技巧:
- 英文优先(文本编码器基于 Gemma-3)
- 动作 + 镜头 + 光影 + 质感四要素:
A cheerful girl puppet singing in the rain, close-up, soft lighting, photorealistic - 运镜:
camera dolly out/slow pan/close-up
输出: MP4 静音视频,1280×720, 121帧, 24fps, 约5秒。视频在任务状态 outputs 的 images 字段(文件名 .mp4,同节点 animated 标记为视频),下载时需带 subfolder=video。
缓存坑:若提交的工作流与历史完全相同(尤其 seed 相同),ComfyUI 会命中
execution_cached直接返回,outputs可能为空。提交时换个随机noise_seed可避免。
1.4 提交图片编辑任务(FLUX.2 图生图)
POST /api/v1/ai/image/generate
Content-Type: application/json
Authorization: Bearer sk-xxx使用 FLUX.2-klein-9b-kv-fp8 模型,通过 Reference Conditioning 技术实现图片编辑,支持换装、换背景、局部修改。仅需 4 步生成,速度极快。
前置条件: 需先通过 /api/v1/upload 上传输入图片。
bash
# 1. 上传图片(图1=主体,图2=服装参考)
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"}
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. 提交图片编辑工作流
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": {}}关键节点参数:
| 节点 | 字段 | 说明 | 推荐值 |
|---|---|---|---|
| 76 | image | 主体图片文件名(需先上传) | 上传返回的 name |
| 81 | image | 服装/参考图片文件名 | 可与 76 相同(自我编辑) |
| 135 | text | 编辑提示词(英文,Figure 1/2 指代图片) | — |
| 125 | noise_seed | 随机种子 | 任意整数 |
| 137 | steps | 采样步数 | 4 |
| 94 | filename_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"
详细文档见 ComfyUI FLUX.2 编辑 Skill。
1.5 提交图片编辑任务(Qwen-Image-Edit)
POST /api/v1/ai/image/generate
Content-Type: application/json
Authorization: Bearer sk-xxx使用 Qwen-Image-Edit-2511 模型,支持 Turbo 4步(Lightning LoRA)和 Native 40步两种模式,可做高质量图片编辑(换装、改背景、物体替换)。
前置条件: 需先通过 /api/v1/upload 上传输入图片。
bash
# 1. 上传图片
curl -H "Authorization: Bearer $API_KEY" -X POST "$GW/api/v1/upload" \
-F "image=@/path/to/input.png" \
-F "type=input"
# 返回: {"name": "input.png", "subfolder": "", "type": "input"}
# 2. 提交 Turbo 模式编辑(4步,推荐)
curl -H "Authorization: Bearer $API_KEY" -X POST "$GW/api/v1/ai/image/generate" \
-H "Content-Type: application/json" \
-d '{
"prompt": {
"41": {"inputs": {"image": "input.png"}, "class_type": "LoadImage"},
"83": {"inputs": {"image": "input.png"}, "class_type": "LoadImage"},
"170:160": {"inputs": {"image": ["41", 0]}, "class_type": "FluxKontextImageScale"},
"170:161": {"inputs": {"unet_name": "qwen_image_edit_2511_bf16.safetensors", "weight_dtype": "default"}, "class_type": "UNETLoader"},
"170:162": {"inputs": {"clip_name": "qwen_2.5_vl_7b_fp8_scaled.safetensors", "type": "qwen_image", "device": "default"}, "class_type": "CLIPLoader"},
"170:146": {"inputs": {"vae_name": "qwen_image_vae.safetensors"}, "class_type": "VAELoader"},
"170:145": {"inputs": {"shift": 3.1, "model": ["170:161", 0]}, "class_type": "ModelSamplingAuraFlow"},
"170:152": {"inputs": {"strength": 1.0, "model": ["170:145", 0]}, "class_type": "CFGNorm"},
"170:156": {"inputs": {"pixels": ["170:160", 0], "vae": ["170:146", 0]}, "class_type": "VAEEncode"},
"170:168": {"inputs": {"value": false}, "class_type": "PrimitiveBoolean"},
"170:165": {"inputs": {"value": 4}, "class_type": "PrimitiveInt"},
"170:166": {"inputs": {"value": 40}, "class_type": "PrimitiveInt"},
"170:154": {"inputs": {"value": 1.0}, "class_type": "PrimitiveFloat"},
"170:155": {"inputs": {"value": 4.0}, "class_type": "PrimitiveFloat"},
"170:149": {"inputs": {"prompt": "", "clip": ["170:162", 0], "vae": ["170:146", 0], "image1": ["170:160", 0], "image2": ["83", 0]}, "class_type": "TextEncodeQwenImageEditPlus"},
"170:147": {"inputs": {"reference_latents_method": "index_timestep_zero", "conditioning": ["170:149", 0]}, "class_type": "FluxKontextMultiReferenceLatentMethod"},
"170:151": {"inputs": {"prompt": "Remove the jacket, keep the T-shirt underneath", "clip": ["170:162", 0], "vae": ["170:146", 0], "image1": ["170:160", 0], "image2": ["83", 0]}, "class_type": "TextEncodeQwenImageEditPlus"},
"170:148": {"inputs": {"reference_latents_method": "index_timestep_zero", "conditioning": ["170:151", 0]}, "class_type": "FluxKontextMultiReferenceLatentMethod"},
"170:153": {"inputs": {"lora_name": "Qwen-Image-Edit-2511-Lightning-4steps-V1.0-bf16.safetensors", "strength_model": 1.0, "model": ["170:152", 0]}, "class_type": "LoraLoaderModelOnly"},
"170:163": {"inputs": {"switch": ["170:168", 0], "on_false": ["170:152", 0], "on_true": ["170:153", 0]}, "class_type": "ComfySwitchNode"},
"170:164": {"inputs": {"switch": ["170:168", 0], "on_false": ["170:154", 0], "on_true": ["170:155", 0]}, "class_type": "ComfySwitchNode"},
"170:167": {"inputs": {"switch": ["170:168", 0], "on_false": ["170:166", 0], "on_true": ["170:165", 0]}, "class_type": "ComfySwitchNode"},
"170:169": {"inputs": {"seed": 1234567890, "steps": ["170:167", 0], "cfg": ["170:164", 0], "sampler_name": "euler", "scheduler": "simple", "denoise": 1.0, "model": ["170:163", 0], "positive": ["170:148", 0], "negative": ["170:147", 0], "latent_image": ["170:156", 0]}, "class_type": "KSampler"},
"170:158": {"inputs": {"samples": ["170:169", 0], "vae": ["170:146", 0]}, "class_type": "VAEDecode"},
"9": {"inputs": {"filename_prefix": "Qwen_Edit_2511", "images": ["170:158", 0]}, "class_type": "SaveImage"}
},
"extra_data": {}
}'响应:
json
{"prompt_id": "e5f6g7h8-...", "number": 101, "node_errors": {}}关键节点参数:
| 节点 | 字段 | 说明 | 推荐值 |
|---|---|---|---|
| 41 | image | 输入图片文件名(需先上传) | 上传返回的 name |
| 83 | image | 参考图片文件名(可同 41 = 自我编辑) | 上传返回的 name |
| 170:151 | prompt | 编辑提示词(英文) | — |
| 170:168 | value | Turbo 模式开关(false=Native 40步) | false |
| 170:165 | value | Turbo 步数 | 4 |
| 170:169 | seed | 随机种子 | 任意整数 |
| 9 | filename_prefix | 输出文件名前缀 | — |
Turbo vs Native:
| 模式 | 步数 | CFG | 速度 | 质量 |
|---|---|---|---|---|
| Turbo (Lightning LoRA) | 4 | 1.0 | ~2-6s | 好 |
| Native | 40 | 4.0 | ~15-20s | 更好 |
切换方式:将节点
170:168的value改为true(启用 Turbo / Lightning LoRA)。
提示词推荐:
- 换装:
"Have the person in image 1 wear the clothes from image 2" - 改背景:
"Change the background of image 1 to a sunny beach" - 去除物体:
"Remove the jacket, keep the T-shirt underneath" - 物体替换:
"Replace the red wine with flowers"
详细文档见 ComfyUI Qwen 图片编辑 Skill。
1.6 查询任务状态
GET /api/v1/ai/tasks/{prompt_id}
Authorization: Bearer sk-xxxbash
curl -H "Authorization: Bearer $API_KEY" "$GW/api/v1/ai/tasks/0871f625-65f6-4d2f-abd8-0b248dafa58f"响应(进行中):
json
{
"0871f625-...": {
"prompt": [...],
"outputs": {},
"status": { "status_str": "success", "completed": false }
}
}响应(已完成):
json
{
"0871f625-...": {
"status": { "status_str": "success", "completed": true },
"outputs": {
"9": {
"images": [
{ "filename": "output_00001_.png", "subfolder": "", "type": "output" }
]
}
}
}
}1.7 查看生成的图片
GET /api/v1/ai/image/view/?filename={filename}&type={type}&subfolder={subfolder}
Authorization: Bearer sk-xxx参数值来自任务状态响应中的 outputs 字段。
bash
# 命令行下载
curl -H "Authorization: Bearer $API_KEY" "$GW/api/v1/ai/image/view/?filename=output_00001_.png&type=output&subfolder=" -o output.png1.8 上传图片
POST /api/v1/upload
Content-Type: multipart/form-data
Authorization: Bearer sk-xxxbash
curl -H "Authorization: Bearer $API_KEY" -X POST "$GW/api/v1/upload" \
-F "image=@/path/to/image.png" \
-F "overwrite=true"最大文件大小: 50MB。
1.9 查询队列状态
GET /api/v1/ai/queue
Authorization: Bearer sk-xxxbash
curl -H "Authorization: Bearer $API_KEY" "$GW/api/v1/ai/queue"响应:
json
{
"queue_running": [],
"queue_pending": []
}完整示例:生成小狗图片
bash
# 1. 提交任务
RESPONSE=$(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 fluffy golden retriever puppy, big shiny eyes, 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": "puppy", "images": ["65", 0]}, "class_type": "SaveImage"}
}
}')
PROMPT_ID=$(echo $RESPONSE | python3 -c "import sys,json; print(json.load(sys.stdin)['prompt_id'])")
echo "任务 ID: $PROMPT_ID"
# 2. 等待约30秒后查询状态
sleep 30
STATUS=$(curl -s -H "Authorization: Bearer $API_KEY" "$GW/api/v1/ai/tasks/$PROMPT_ID")
# 3. 提取文件名并下载
FILENAME=$(echo $STATUS | python3 -c "
import sys,json
d=json.load(sys.stdin)
for node in d.values():
for out in node.get('outputs',{}).values():
for img in out.get('images',[]):
print(img['filename']); exit()
")
curl -H "Authorization: Bearer $API_KEY" "$GW/api/v1/ai/image/view/?filename=$FILENAME&type=output&subfolder=" -o puppy.png
echo "图片已保存到 puppy.png"2. bge-m3 — Embedding 向量化
内部地址:
192.168.1.236:20083模型:bge_m3维度: 1024 无需后端 Bearer Token
2.1 查看可用模型
GET /api/v1/embed/models
Authorization: Bearer sk-xxxbash
curl -H "Authorization: Bearer $API_KEY" "$GW/api/v1/embed/models"响应:
json
{
"object": "list",
"data": [
{ "id": "bge_m3", "object": "model", "owned_by": "vllm", "max_model_len": 8192 }
]
}2.2 文本向量化
POST /api/v1/embed/embeddings
Content-Type: application/json
Authorization: Bearer sk-xxxbash
curl -H "Authorization: Bearer $API_KEY" -X POST "$GW/api/v1/embed/embeddings" \
-H "Content-Type: application/json" \
-d '{
"model": "bge_m3",
"input": "人工智能改变了世界"
}'批量输入:
bash
curl -H "Authorization: Bearer $API_KEY" -X POST "$GW/api/v1/embed/embeddings" \
-H "Content-Type: application/json" \
-d '{
"model": "bge_m3",
"input": ["第一段文本", "第二段文本", "第三段文本"]
}'响应:
json
{
"object": "list",
"data": [
{
"object": "embedding",
"index": 0,
"embedding": [-0.0641, 0.0111, -0.0142, ...]
}
],
"model": "bge_m3",
"usage": { "prompt_tokens": 7, "total_tokens": 7 }
}兼容性: 接口兼容 OpenAI Embedding API,可直接替换 api.openai.com 基础地址。
3. bge-reranker — 重排序
内部地址:
192.168.1.236:20080模型:bge_reranker_v3无需后端 Bearer Token
3.1 查看可用模型
GET /api/v1/rerank/models
Authorization: Bearer sk-xxxbash
curl -H "Authorization: Bearer $API_KEY" "$GW/api/v1/rerank/models"3.2 文本重排序
POST /api/v1/rerank/rerank
Content-Type: application/json
Authorization: Bearer sk-xxxbash
curl -H "Authorization: Bearer $API_KEY" -X POST "$GW/api/v1/rerank/rerank" \
-H "Content-Type: application/json" \
-d '{
"model": "bge_reranker_v3",
"query": "什么是机器学习",
"documents": [
"机器学习是人工智能的一个子领域",
"今天天气很好",
"深度学习使用神经网络来学习数据表示"
]
}'响应:
json
{
"results": [
{ "index": 0, "relevance_score": 0.9956, "document": { "text": "机器学习是人工智能的一个子领域" } },
{ "index": 2, "relevance_score": 0.0860, "document": { "text": "深度学习使用神经网络来学习数据表示" } },
{ "index": 1, "relevance_score": 0.0000, "document": { "text": "今天天气很好" } }
]
}兼容性: 接口兼容 Cohere/Jina Rerank API。
4. SearXNG — 聚合搜索
内部地址:
192.168.1.236:8888无需后端 Bearer Token
4.1 搜索
GET /api/v1/search?q={query}&format=json
Authorization: Bearer sk-xxx通过公网网关(需 Bearer Token):
bash
curl -H "Authorization: Bearer $API_KEY" \
"https://ai.ospreyai.cn/api/v1/search?q=人工智能&format=json"内网直连(无需鉴权):
bash
curl "http://192.168.1.236:8888/search?q=人工智能&format=json"参数:
| 参数 | 说明 | 示例 |
|---|---|---|
| q | 搜索关键词 | 人工智能 |
| format | 返回格式(必须为 json) | json |
| categories | 搜索类别 | general, images, news |
| language | 语言 | zh, en |
| pageno | 页码 | 1, 2 |
响应(摘要):
json
{
"query": "人工智能",
"number_of_results": 205000,
"results": [
{
"title": "人工智能_百度百科",
"url": "https://baike.baidu.com/item/人工智能",
"content": "人工智能(Artificial Intelligence)...",
"engine": "bing",
"engines": ["bing"],
"score": 100.0
}
],
"unresponsive_engines": [["baidu", "Suspended: CAPTCHA"]]
}Python 调用示例
通过公网网关(需 Bearer Token):
python
import requests
API_KEY = "sk-your-api-key"
response = requests.get(
"https://ai.ospreyai.cn/api/v1/search",
params={"q": "AI agent framework", "format": "json"},
headers={"Authorization": f"Bearer {API_KEY}"}
)
results = response.json()["results"]
for r in results[:5]:
print(f"{r['title']}: {r['url']}")内网直连(无需鉴权):
python
import requests
response = requests.get(
"http://192.168.1.236:8888/search",
params={"q": "AI agent framework", "format": "json"}
)
results = response.json()["results"]
for r in results[:5]:
print(f"{r['title']}: {r['url']}")调用方式对比
| 内网直连 | 公网网关 | |
|---|---|---|
| 地址 | 192.168.1.236:8888 | ai.ospreyai.cn |
| 鉴权 | 无 | Authorization: Bearer sk-xxx |
| 路径 | /search | /api/v1/search |
| 限流 | 无 | 60次/分/IP |
| 适用场景 | 内网服务间调用 | 外部/前端公网调用 |
5. RAGFlow — RAG 知识库
内部地址:
192.168.1.236:1280需要后端 Bearer Token(通过X-Authorization传入)
鉴权方式
RAGFlow API Key 在 RAGFlow Web 界面中生成,格式为 ragflow-xxxxxx。
所有请求必须同时携带:
Authorization: Bearer sk-xxx— 网关层鉴权X-Authorization: Bearer <ragflow-api-key>— 后端鉴权
5.1 列出知识库
GET /api/v1/rag/datasets
Authorization: Bearer sk-xxx
X-Authorization: Bearer ragflow-xxxxxxbash
curl -H "Authorization: Bearer $API_KEY" \
-H "X-Authorization: Bearer ragflow-xxxxxx" \
"$GW/api/v1/rag/datasets"5.2 创建知识库
POST /api/v1/rag/datasets
Content-Type: application/json
Authorization: Bearer sk-xxx
X-Authorization: Bearer ragflow-xxxxxxbash
curl -H "Authorization: Bearer $API_KEY" \
-H "X-Authorization: Bearer ragflow-xxxxxx" \
-H "Content-Type: application/json" \
-X POST "$GW/api/v1/rag/datasets" \
-d '{"name": "我的知识库"}'5.3 对话
POST /api/v1/rag/chats
Authorization: Bearer sk-xxx
X-Authorization: Bearer ragflow-xxxxxx
Content-Type: application/jsonbash
curl -H "Authorization: Bearer $API_KEY" \
-H "X-Authorization: Bearer ragflow-xxxxxx" \
-H "Content-Type: application/json" \
-X POST "$GW/api/v1/rag/chats" \
-d '{
"question": "什么是深度学习?",
"dataset_ids": ["你的知识库ID"]
}'Python 调用示例
python
import requests
session = requests.Session()
session.headers.update({
"Authorization": "Bearer sk-your-api-key",
"X-Authorization": "Bearer ragflow-xxxxxx",
"Content-Type": "application/json"
})
BASE = "https://ai.ospreyai.cn/api/v1/rag"
# 列出知识库
resp = session.get(f"{BASE}/datasets")
print(resp.json())6. Dify — 工作流编排
内部地址:
192.168.1.236:80需要后端 Bearer Token(通过X-Authorization传入)
鉴权方式
Dify API Key 在 Dify Web 界面中生成,格式为 app-xxxxxx。
所有请求必须同时携带:
Authorization: Bearer sk-xxx— 网关层鉴权X-Authorization: Bearer <dify-api-key>— 后端鉴权
6.1 工作流对话(阻塞模式)
POST /api/v1/ai/workflow/chat-messages
Content-Type: application/json
Authorization: Bearer sk-xxx
X-Authorization: Bearer app-xxxxxxbash
curl -H "Authorization: Bearer $API_KEY" \
-H "X-Authorization: Bearer app-xxxxxx" \
-H "Content-Type: application/json" \
-X POST "$GW/api/v1/ai/workflow/chat-messages" \
-d '{
"inputs": {},
"query": "你好,请介绍一下自己",
"response_mode": "blocking",
"conversation_id": "",
"user": "api-user"
}'6.2 工作流对话(流式模式)
POST /api/v1/ai/workflow/chat-messages
Content-Type: application/json
Authorization: Bearer sk-xxx
X-Authorization: Bearer app-xxxxxxbash
curl -H "Authorization: Bearer $API_KEY" \
-H "X-Authorization: Bearer app-xxxxxx" \
-H "Content-Type: application/json" \
-X POST "$GW/api/v1/ai/workflow/chat-messages" \
-d '{
"inputs": {},
"query": "你好",
"response_mode": "streaming",
"conversation_id": "",
"user": "api-user"
}'响应(流式): 返回 SSE 事件流,event: message 包含增量内容。
6.3 获取工作流参数
GET /api/v1/ai/workflow/parameters
Authorization: Bearer sk-xxx
X-Authorization: Bearer app-xxxxxxbash
curl -H "Authorization: Bearer $API_KEY" \
-H "X-Authorization: Bearer app-xxxxxx" \
"$GW/api/v1/ai/workflow/parameters"Python 调用示例
python
import requests
session = requests.Session()
session.headers.update({
"Authorization": "Bearer sk-your-api-key",
"X-Authorization": "Bearer app-xxxxxx",
"Content-Type": "application/json"
})
BASE = "https://ai.ospreyai.cn/api/v1/ai/workflow"
# 阻塞模式对话
resp = session.post(f"{BASE}/chat-messages", json={
"inputs": {},
"query": "你好",
"response_mode": "blocking",
"conversation_id": "",
"user": "api-user"
})
print(resp.json())AI 助手对话式接入
本网关提供 Skill 文件,可被 AI 智能体学习并通过自然语言对话调用 API。主要场景为龙虾(OpenClaw)智能体接入,同时兼容 Claude Code、Cursor 等 AI 助手。
什么是龙虾(OpenClaw)
龙虾(OpenClaw) 是团队内部的 AI 智能体平台,支持通过加载 Skill 文件扩展能力。将网关 Skill 文件导入龙虾智能体后,即可在对话中直接调用 ComfyUI 图片生成、视频生成等 API,无需手动编写 curl 命令。
可用 Skill 列表
| Skill | 下载地址 | 功能 |
|---|---|---|
| ComfyUI 图片生成 | https://ai.ospreyai.cn/docs/raw/skills/comfyui-image-generation.md | 文生图,1024×1024 |
| ComfyUI 视频生成 | https://ai.ospreyai.cn/docs/raw/skills/comfyui-video-generation.md | 图生视频,Wan2.2 I2V |
| ComfyUI 关键帧视频 | https://ai.ospreyai.cn/docs/raw/skills/comfyui-keyframes-video-generation.md | 6 关键帧首尾帧视频,Wan2.2 FLF2V |
方式一:龙虾智能体在线学习(推荐)
在龙虾对话中发送以下指令,智能体会自动下载并学习 Skill 内容:
学习:https://ai.ospreyai.cn/docs/raw/skills/comfyui-image-generation.md,保存为本地的技能 skills学习:https://ai.ospreyai.cn/docs/raw/skills/comfyui-video-generation.md,保存为本地的技能 skills学习:https://ai.ospreyai.cn/docs/raw/skills/comfyui-keyframes-video-generation.md,保存为本地的技能 skills学习完成后,龙虾智能体会:
- 理解 API 调用流程(提交工作流 → 轮询状态 → 下载结果)
- 将 Skill 保存到本地技能目录
- 后续对话中自动匹配触发词,按 Skill 流程调用 API
方式二:手动加载
先下载 Skill 文件到本地,再让智能体读取:
bash
# 创建技能目录并下载
mkdir -p .skills
curl https://ai.ospreyai.cn/docs/raw/skills/comfyui-image-generation.md -o .skills/comfyui-image-generation.md
curl https://ai.ospreyai.cn/docs/raw/skills/comfyui-video-generation.md -o .skills/comfyui-video-generation.md然后在对话中:
请阅读 .skills/comfyui-image-generation.md,学习 ComfyUI 图片生成技能。
之后我说"生成一张 xxx 的图片"时,按此 Skill 的流程调用 API。对话使用示例
学习 Skill 后,可在龙虾中直接用自然语言触发:
| 你说的话 | 智能体执行的动作 |
|---|---|
| "生成一张可爱小狗的图片" | 提交工作流 → 轮询状态 → 下载 PNG |
| "用 50 步采样生成一张风景照" | 修改 steps=50,提交 → 轮询 → 下载 |
| "查看当前队列状态" | 调用 GET /api/v1/ai/queue |
| "换个种子重新生成" | 更换 seed 值,重新提交工作流 |
| "把这张图片生成一段视频" | 提交 I2V 工作流 → 轮询 → 下载 MP4 |
环境变量配置
对话中使用前,需确保智能体知道以下信息:
网关地址: https://ai.ospreyai.cn
API Key: sk-your-api-key(需提前申请)可在项目根目录创建 .env 文件或在对话中直接告知智能体。
错误码参考
| HTTP 状态码 | 含义 | 处理建议 |
|---|---|---|
| 200 | 请求成功 | — |
| 400 | 请求参数错误 | 检查请求体格式 |
| 401 | 鉴权失败 | 检查 Bearer Token 是否有效 |
| 404 | 路径不存在或资源未找到 | 检查 URL 路径和 prompt_id |
| 429 | 请求被限流 | 降低请求频率,稍后重试 |
| 503 | 后端服务不可用 | 检查内网服务是否运行 |
401 常见原因:
| 场景 | 原因 | 解决方案 |
|---|---|---|
| 所有 API 返回 401 | Bearer Token 无效或过期 | 检查 sk-xxx key 是否正确 |
| 所有 API 返回 401 | 缺少 Authorization header | 添加 -H "Authorization: Bearer sk-xxx" |
| RAGFlow/Dify 返回 401 | 未传 X-Authorization | 添加 -H "X-Authorization: Bearer <token>" |
| RAGFlow/Dify 返回 401 | 后端 Bearer Token 无效 | 检查 API Key 是否正确、是否过期 |