尧图网站设计 尧图网站设计YAOTU DESIGN
ARTICLE DETAIL

资讯详情

深耕网站设计与一线实操的经验洞察。

vLLM-Omni 图生图(Image-to-Image)在线编辑服务部署实战:Qwen-Image-Edit 单图 / 多图 / 分层生成全指南

vLLM-Omni 图生图(Image-to-Image)在线编辑服务部署实战:Qwen-Image-Edit 单图 / 多图 / 分层生成全指南 vLLM-Omni 图生图Image-to-Image在线编辑服务部署实战Qwen-Image-Edit 单图 / 多图 / 分层生成全指南【免费下载链接】vllm-omniA framework for efficient model inference with omni-modality models项目地址: https://gitcode.com/GitHub_Trending/vl/vllm-omnivLLM-Omni 基于 OpenAI 兼容的多模态 Chat Completions 协议提供开箱即用的图生图Image-to-Image在线编辑服务。本指南以 Qwen-Image-Edit 为例完整讲解服务端启动、四种客户端调用方式、请求 / 响应协议、生成参数与分层生成Qwen-Image-Layered、多图编辑Qwen-Image-Edit-2509等实战要点。阅读完成后你将能够独立部署一个可对外提供图像编辑能力的在线服务并熟练使用 curl、OpenAI Python SDK、命令行客户端与 Gradio 界面四种方式完成调用与结果解码。一、功能概览与适用模型该示例位于仓库 examples/online_serving/image_to_image用于演示如何通过 vLLM-Omni 部署 Image-to-Image 模型并提供在线图像编辑服务。除 Qwen-Image-Edit 外还支持 BAGEL 等其他 Image-to-Image 扩散流水线。模型能力说明Qwen/Qwen-Image-Edit单图文本引导编辑基础图生图编辑模型风格迁移、调色、场景转换等Qwen/Qwen-Image-Edit-2509多图输入编辑使用QwenImageEditPlusPipeline支持在同一消息中传入多张图片并组合编辑Qwen/Qwen-Image-Layered分层图像生成从参考图 文本提示分解出多层图像ByteDance-Seed/BAGEL-7B-MoT图像编辑BAGEL 流水线通过extra_body透传cfg_text_scale、cfg_img_scale等模型专属参数从源码结构看vLLM-Omni 将每种扩散模型封装为独立的 pipeline例如 pipeline_qwen_image_edit.py 对应单图编辑、pipeline_qwen_image_edit_plus.py 对应多图编辑QwenImageEditPlusPipeline其注释明确Edit prompt template - different from generation template, supports multiple images。不同模型由服务启动时指定的--omni模式自动注册与调度。二、服务端部署2.1 基础启动单图编辑vllm serve Qwen/Qwen-Image-Edit --omni --port 8092--omni为 vLLM-Omni 的多模态统一入口开关--port 8092指定 OpenAI 兼容 API 端口。显存不足OOM提示若遇到显存溢出或 GPU 显存有限可开启 VAE slicing 与 tiling 降低显存占用vllm serve Qwen/Qwen-Image-Edit --omni --port 8092 --vae-use-slicing --vae-use-tiling2.2 多图编辑启动Qwen-Image-Edit-2509vllm serve Qwen/Qwen-Image-Edit-2509 --omni --port 8092多图编辑的核心区别在于请求的 user message content 中可包含多张图片顺序有意义详见下文多图编辑一节。2.3 使用启动脚本带参数仓库提供了现成启动脚本 run_server.shbash run_server.sh脚本内部支持通过环境变量覆盖模型与端口MODELQwen/Qwen-Image-Edit-2509 bash run_server.sh # 换模型 PORT8093 bash run_server.sh # 换端口脚本实现如下默认MODELQwen/Qwen-Image-Edit、PORT8092#!/bin/bash # Qwen-Image-Edit online serving startup script MODEL${MODEL:-Qwen/Qwen-Image-Edit} PORT${PORT:-8092} echo Starting Qwen-Image-Edit server... echo Model: $MODEL echo Port: $PORT vllm serve $MODEL --omni \ --port $PORT服务就绪的标志是日志中出现INFO: Application startup complete.其前为Started server process [PID]与Waiting for application startup.。若需更大并发或更低单请求延迟可参考 Qwen/Qwen-Image-Edit.md 中验证过的--tensor-parallel-size 2TP2配置。2.4 部署其他 Image-to-Image 模型BAGELvllm serve ByteDance-Seed/BAGEL-7B-MoT --omni --port 8091BAGEL 与 Qwen 系列在调用方式上的差异主要体现在模型专属生成参数上如cfg_text_scale、cfg_img_scale完整参数列表见 BAGEL-7B-MoT.md。三、客户端调用四种方式3.1 方法一curl推荐用于快速验证仓库封装了 curl 调用脚本 run_curl_image_edit.sh一行完成读图 → 编码 → 请求 → 解码 → 落盘bash run_curl_image_edit.sh input.png Convert this image to watercolor style # 可指定输出文件默认为 image_edit_时间戳.png bash run_curl_image_edit.sh input.png Convert to cartoon style output.png该脚本的实现要点值得借鉴通过管道把 base64 数据喂给jq -Rs构造 JSON从而避免超大图片突破 shell 的 ARG_MAX 参数长度限制请求体结构为messages[0].content中先放文本指令、再放image_url格式的 data URL生成参数统一放入extra_body。不借助脚本、直接使用 curl 的方式如下IMG_B64$(base64 -w0 input.png) cat EOF request.json { messages: [{ role: user, content: [ {type: text, text: Convert this image to watercolor style}, {type: image_url, image_url: {url: data:image/png;base64,$IMG_B64}} ] }], extra_body: { height: 1024, width: 1024, num_inference_steps: 50, guidance_scale: 1, seed: 42 } } EOF curl -s http://localhost:8092/v1/chat/completions \ -H Content-Type: application/json \ -d request.json \ | jq -r .choices[0].message.content[0].image_url.url \ | cut -d, -f2 | base64 -d output.png注意直接使用 curl 时生成参数必须写在 JSON 顶层的字面量extra_body键内如上所示。3.2 方法二OpenAI Python SDKimport base64 from openai import OpenAI client OpenAI(base_urlhttp://localhost:8092/v1, api_keynone) with open(input.png, rb) as f: img_b64 base64.b64encode(f.read()).decode() response client.chat.completions.create( modelQwen/Qwen-Image-Edit, messages[{ role: user, content: [ {type: text, text: Convert to watercolor style}, {type: image_url, image_url: { url: fdata:image/png;base64,{img_b64} }}, ], }], extra_body{ num_inference_steps: 50, guidance_scale: 1, seed: 42, }, ) img_url response.choices[0].message.content[0].image_url.url _, b64_data img_url.split(,, 1) with open(output.png, wb) as f: f.write(base64.b64decode(b64_data))关键点OpenAI SDK 的extra_body关键字参数会自动将生成参数合并进请求体的顶层无需手工嵌套extra_body键这与 curl 的用法相反详见 chat_completions_api.md 中的参数处理说明。3.3 方法三Python 客户端脚本仓库提供了功能更完整的命令行客户端 openai_chat_client.py# 单图编辑 python openai_chat_client.py --input input.png --prompt Convert to oil painting style --output output.png # 多图编辑需要 Qwen-Image-Edit-2509 服务端 python openai_chat_client.py --input input1.png input2.png --prompt Combine these images into a single scene --output output.png该脚本支持的全部参数如下参数默认值说明--input, -i必填可多个—输入图片路径多图时按顺序传入多个--prompt, -p必填—编辑指令--output, -ooutput.png输出文件--server, -shttp://localhost:8092服务端地址--height1024输出图像高度像素--width1024输出图像宽度像素--steps50去噪步数--guidance7.5CFG 引导强度--seed0随机种子--negative无负向提示词--extra-body无模型专属参数 JSON如{cfg_text_scale: 4.0}模型专属参数可通过--extra-body透传例如针对 BAGELpython openai_chat_client.py \ --input input.png \ --prompt Make the scene look like a watercolor painting \ --server http://localhost:8091 \ --extra-body {cfg_text_scale: 4.0, cfg_img_scale: 1.5}从源码看edit_image()会依次把height、width、num_inference_steps、guidance_scale、seed、negative_prompt写入extra_body并用extra_body.update()合并模型专属参数最终以requests.post提交到/v1/chat/completions再从响应的content[0].image_url.url中截取data:image...;base64,之后的部分解码落盘。3.4 方法四Gradio 交互界面前置依赖Gradio 属于可选依赖需先安装[demo]extraspip install vllm-omni[demo]源码安装则使用pip install -e .[demo]。python gradio_demo.py # 浏览器访问 http://localhost:7861gradio_demo.py 提供可视化编辑界面支持上传主图、附加多张辅助图对应多图编辑、填写编辑指令与负向提示词并提供推理步数10–100默认 50、CFG 强度1.0–20.0默认 7.5、随机种子-1 表示随机三个控件内置水彩、黑白、饱和度增强、卡通、复古滤镜、昼夜转换、油画、梦幻模糊等示例指令一键填充。界面默认连接http://localhost:8092可通过--server、--port、--share参数调整。四、请求格式详解4.1 标准 image_url 格式{ messages: [ { role: user, content: [ {type: text, text: Convert this image to watercolor style}, {type: image_url, image_url: {url: data:image/png;base64,...}} ] } ] }4.2 简化 image 格式不显式指定type直接用text与image两个键{ messages: [ { role: user, content: [ {text: Convert this image to watercolor style}, {image: BASE64_IMAGE_DATA} ] } ] }4.3 带生成参数的请求生成参数统一包裹在请求 JSON 的extra_body中{ messages: [ { role: user, content: [ {type: text, text: Convert to ink wash painting style}, {type: image_url, image_url: {url: data:image/png;base64,...}} ] } ], extra_body: { height: 1024, width: 1024, num_inference_steps: 50, guidance_scale: 7.5, seed: 42 } }OpenAI SDK 用法提示SDK 下通过extra_body关键字参数传入SDK 会自动合并到请求体顶层client.chat.completions.create( modelQwen/Qwen-Image-Edit, messages[...], extra_body{num_inference_steps: 50, guidance_scale: 7.5, seed: 42}, )生成参数在不同客户端中的处理细节参见 Chat Completions API 指南。五、分层图像生成Qwen-Image-LayeredQwen-Image-Layered 从一张参考图 一段文本提示中将图像分解为多层。启动方式vllm serve Qwen/Qwen-Image-Layered --omni --port 80935.1 curl 方式逐层落盘IMG_B64$(base64 -w0 input.png) curl -sS http://localhost:8093/v1/chat/completions \ -H Content-Type: application/json \ -d $(jq -n --arg img $IMG_B64 { messages: [{ role: user, content: [ {type: image_url, image_url: {url: (data:image/png;base64, $img)}}, {type: text, text: a rabbit} ] }], extra_body: { num_inference_steps: 50, cfg_scale: 4.0, seed: 0, layers: 4, resolution: 640 } }) \ | jq -r .choices[0].message.content[] | .image_url.url | split(,)[1] \ | while IFS read -r b64; do ((i)); echo $b64 | base64 -d layer_${i}.png done5.2 OpenAI SDK 方式import base64 from openai import OpenAI client OpenAI(base_urlhttp://localhost:8093/v1, api_keynone) with open(input.png, rb) as f: img_b64 base64.b64encode(f.read()).decode() response client.chat.completions.create( modelQwen/Qwen-Image-Layered, messages[{ role: user, content: [ {type: image_url, image_url: { url: fdata:image/png;base64,{img_b64} }}, {type: text, text: a rabbit}, ], }], extra_body{ num_inference_steps: 50, cfg_scale: 4.0, seed: 0, layers: 4, resolution: 640, }, ) for i, item in enumerate(response.choices[0].message.content): _, b64_data item.image_url.url.split(,, 1) with open(flayer_{i}.png, wb) as f: f.write(base64.b64decode(b64_data))5.3 Python requests 方式import base64 import requests with open(input.png, rb) as f: img_b64 base64.b64encode(f.read()).decode() payload { messages: [{ role: user, content: [ {type: image_url, image_url: { url: fdata:image/png;base64,{img_b64} }}, {type: text, text: a rabbit}, ], }], extra_body: { num_inference_steps: 50, cfg_scale: 4.0, seed: 0, layers: 4, resolution: 640, }, } resp requests.post( http://localhost:8093/v1/chat/completions, jsonpayload, timeout600, ) data resp.json() for i, item in enumerate(data[choices][0][message][content]): _, b64_data item[image_url][url].split(,, 1) with open(flayer_{i}.png, wb) as f: f.write(base64.b64decode(b64_data))响应特点分层生成的响应中choices[0].message.content是一个数组每个元素对应一层生成图像逐个解码即可得到所有图层。5.4 Qwen-Image-Layered 参数表参数类型默认值说明layersint4分解的层数resolutionint640维度计算分辨率640 或 1024cfg_scalefloat4.0无分类器引导强度true_cfg_scale的别名num_inference_stepsint50去噪步数seedintNone随机种子用于结果复现六、多图编辑Qwen-Image-Edit-2509多图编辑需要在content中按顺序提供多张图片顺序有意义模型按传入顺序理解各图角色{ messages: [ { role: user, content: [ {type: text, text: Combine these images into a single scene}, {type: image_url, image_url: {url: data:image/png;base64,...} }, {type: image_url, image_url: {url: data:image/png;base64,...} } ] } ] }对应的多图命令行调用python openai_chat_client.py --input input1.png input2.png --prompt Combine these images into a single scene --output output.png从源码看pipeline_qwen_image_edit_plus.py 中的_get_qwen_prompt_embeds专门实现了Build image prompt template for multiple images即多图编辑的提示词模板拼接逻辑这也是 2509 版与基础版在底层实现上的关键差异。七、生成参数总览使用/v1/chat/completions时这些参数放在extra_body中curl 为 JSON 字面量键SDK 为extra_body关键字参数使用专用的/v1/images/edits端点时支持的生成控制项作为顶层表单字段直接传入。对于图像尺寸与数量应使用size和n而不是height、width或num_outputs_per_prompt。参数类型默认值说明heightintNone输出图像高度像素widthintNone输出图像宽度像素sizestrNone输出图像尺寸如1024x1024num_inference_stepsint50去噪步数guidance_scalefloat1.0CFG 引导强度seedintNone随机种子复现用negative_promptstrNone负向提示词num_outputs_per_promptint1生成的图像数量layersint4层数Qwen-Image-Layeredresolutionint640分辨率640 或 1024Qwen-Image-Layered参数透传机制从 image_edit_api.md 的参数处理说明可知vLLM-Omni 将参数直接透传给扩散流水线不做模型级转换——未指定时使用模型自身默认值API 层仅做基础类型与取值范围校验模型不支持的参数可能被静默忽略不兼容的值会由底层流水线报错。因此最佳实践是先采用模型官方推荐参数再按需微调。模型专属参数示例BAGEL 等模型可通过extra_body接收额外参数如cfg_text_scale、cfg_img_scale、cfg_interval、cfg_renorm_type、cfg_renorm_min、timestep_shift等完整列表参见 BAGEL-7B-MoT.md。八、响应格式编辑请求的响应遵循 OpenAI Chat Completions 结构图像以 data URL 形式内嵌在choices[0].message.content[0].image_url.url{ id: chatcmpl-xxx, created: 1234567890, model: Qwen/Qwen-Image-Edit, choices: [{ index: 0, message: { role: assistant, content: [{ type: image_url, image_url: { url: data:image/png;base64,... } }] }, finish_reason: stop }], usage: {...} }解码方式为取url字符串按,分割后对第二部分做base64 -dcurl 场景或base64.b64decodePython 场景即可得到 PNG 字节流。若希望以 OpenAI DALL-E 兼容的/v1/images/edits端点调用multipart/form-data表单支持image/url输入、size、n、output_format、output_compression、negative_prompt、num_inference_steps、guidance_scale、true_cfg_scale、seed、reference_image、mask_image等参数以及 HunyuanImage3 多阶段流水线的streamtrue流式返回可参考 Image Edit API 文档。九、常见编辑指令示例指令说明Convert this image to watercolor style风格迁移水彩Convert the image to black and white去饱和黑白Enhance the color saturation颜色调整饱和度增强Convert to cartoon style卡通化Add vintage filter effect滤镜效果复古Convert daytime scene to nighttime场景转换昼夜十、配套文件说明与源码索引文件说明路径run_server.sh服务启动脚本支持MODEL/PORT环境变量run_server.shrun_curl_image_edit.shcurl 图生图调用示例支持指定输出文件与SERVER环境变量run_curl_image_edit.shopenai_chat_client.py命令行 Python 客户端支持单图 / 多图 /--extra-bodyopenai_chat_client.pygradio_demo.pyGradio 交互界面需[demo]extrasgradio_demo.py延伸阅读完整请求 / 响应模式与extra_body处理 chat_completions_api.mdDALL-E 兼容的专用编辑端点/v1/images/edits image_edit_api.mdQwen-Image-Edit 在 H200 上的 TP1 / TP2 验证数据冷/热延迟、峰值显存、分阶段耗时剖析 recipes/Qwen/Qwen-Image-Edit.mdBAGEL 模型专属参数完整清单 recipes/Bagel/BAGEL-7B-MoT.md底层扩散流水线实现 pipeline_qwen_image_edit.py、pipeline_qwen_image_edit_plus.py【免费下载链接】vllm-omniA framework for efficient model inference with omni-modality models项目地址: https://gitcode.com/GitHub_Trending/vl/vllm-omni创作声明:本文部分内容由AI辅助生成(AIGC),仅供参考
返回列表