Qwen-Image-2.1 es el modelo de imagen de pesos abiertos que Alibaba lanzó el 20 de septiembre de 2026: un generador de 7B parámetros que maneja texto a imagen, edición con hasta 10 imágenes de referencia y salida nativa transparente (RGBA). Esta guía te lleva desde `pip install` hasta un punto final HTTP funcional. Cubre los cuatro caminos de código de referencia del README de GitHub, las configuraciones importantes, un pequeño envoltorio FastAPI para que el modelo sea invocable como cualquier otra API de imagen, y cómo probar ese punto final en Apidog para que los cambios de prompt y las actualizaciones del modelo no rompan tu aplicación.
Si primero quieres el contexto, ¿Qué es Qwen-Image-2.1? cubre la arquitectura y la licencia. La versión corta de la licencia: solo para uso de investigación y no comercial a menos que obtengas un acuerdo comercial separado de Qwen. Todo lo siguiente es válido para evaluación.
Antes de empezar
| Requisito | Detalle |
|---|---|
| Paquetes de Python | torch>=2.4.0, transformers>=5.17, diffusers del `main` de GitHub, accelerate, pillow |
| Clase de pipeline | QwenImage21Pipeline (una clase para generación y edición) |
| Pesos | Qwen/Qwen-Image-2.1, safetensors bf16 |
| GPU | No especificado por Qwen; el código de referencia apunta a un dispositivo CUDA en bfloat16, con enable_model_cpu_offload() como alternativa |
| Salida predeterminada | 2048 x 2048; 40 pasos de inferencia |
| Opcional | Modelos de reescritura de prompts Qwen-Image-2.1-PE-T2I / PE-I2I |
Instalación:
pip install "torch>=2.4.0" "transformers>=5.17" accelerate pillow
pip install git+https://github.com/huggingface/diffusers
La integración de diffusers llegó en un PR dedicado el día del lanzamiento, por lo que una versión de PyPI anterior al 20 de septiembre no tendrá la clase de pipeline.
Paso 1: texto a imagen
import torch
from diffusers import QwenImage21Pipeline
pipe = QwenImage21Pipeline.from_pretrained(
"Qwen/Qwen-Image-2.1", torch_dtype=torch.bfloat16
).to("cuda")
image = pipe(
prompt='A neon shop sign that reads "QWEN IMAGE 2.1", rainy night, reflections on wet pavement',
num_inference_steps=40,
generator=torch.Generator("cuda").manual_seed(42),
).images[0]
image.save("t2i_example.png")
Dos cosas a tener en cuenta. El prompt pone el texto del cartel entre comillas; la renderización de texto de Qwen es la razón por la que la gente elige esta línea de modelos, y citar la cadena literal es la convención de versiones anteriores. Y la semilla es explícita. Mantenla así en cada solicitud que intentes probar, porque una semilla fija es lo que hace que un punto final de imagen sea lo suficientemente reproducible como para hacerle aserciones.
Pasa `width` y `height` de la tabla de tamaños soportados cuando necesites una salida no cuadrada:
| Relación | Tamaño |
|---|---|
| 1:1 | 2048 x 2048 |
| 4:3 / 3:4 | 2400 x 1792 / 1792 x 2400 |
| 3:2 / 2:3 | 2528 x 1696 / 1696 x 2528 |
| 16:9 / 9:16 | 2752 x 1536 / 1536 x 2752 |
Paso 2: salida transparente
La transparencia se basa en el prompt. La frase recomendada en el README es literal, así que úsala:
image = pipe(
prompt=(
"This is an RGBA image with transparency. A cute cartoon dragon sticker. "
"The image has alpha channel and the background is transparent."
),
num_inference_steps=40,
generator=torch.Generator("cuda").manual_seed(42),
).images[0]
image.save("transparent_example.png")
Verifica el resultado en lugar de confiar en él:
assert image.mode == "RGBA", image.mode
alpha = image.getchannel("A")
print("transparent pixels:", sum(1 for p in alpha.getdata() if p == 0))
Esa aserción es la primera prueba que llevarás a Apidog más tarde. Un modelo que devuelve RGB silenciosamente cuando pediste RGBA es un error que tus usuarios encontrarán antes que tú.
Paso 3: edición, con una imagen o hasta diez
El mismo pipeline edita cuando pasas `image`:
from PIL import Image
input_image = Image.open("input.png")
edited = pipe(
prompt="Change the background to a sunset beach",
image=input_image,
num_inference_steps=40,
generator=torch.Generator("cuda").manual_seed(42),
).images[0]
edited.save("edit_example.png")
Para múltiples referencias, pasa una lista (el límite del post de lanzamiento es 10):
refs = [Image.open(f"ref_{i}.png") for i in range(3)]
result = pipe(
prompt="These three characters are sitting around a campfire in a forest",
image=refs,
num_inference_steps=40,
generator=torch.Generator("cuda").manual_seed(42),
).images[0]
result.save("multi_ref_example.png")
La edición local funciona de tres maneras en el post de lanzamiento: círculos de colores que referencias por color en el prompt, anotaciones pintadas, o la imagen original intacta más una imagen de máscara separada pasada como dos entradas. El README no incluye un ejemplo de máscara dedicado, por lo que la forma de dos entradas es la primera que hay que probar: `image=[original, mask]` con un prompt que describa lo que va en la región enmascarada [VERIFICAR contra el README una vez que haya un ejemplo de máscara].
La edición es también donde se muestra el trabajo de velocidad de la versión 2.1. Las imágenes de referencia y la instrucción son estáticas a través de los pasos de eliminación de ruido, por lo que el modelo calcula su caché de clave-valor una vez y la reutiliza. Diez referencias cuestan notablemente menos que diez veces una.
Paso 4: ajústalo a tu GPU
Qwen no ha publicado números de VRAM. Si el pipeline bf16 no cabe, el README ofrece:
pipe = QwenImage21Pipeline.from_pretrained("Qwen/Qwen-Image-2.1", torch_dtype=torch.bfloat16)
pipe.enable_model_cpu_offload()
Para el servicio, el README apunta a vLLM-Omni (con FP8), SGLang y LightX2V. ComfyUI tiene soporte nativo con un flujo de trabajo de plantilla si prefieres no escribir nada de Python. Y si no tienes GPU, las opciones gratuitas cubren la demo alojada y Qwen Chat.
Paso 5: encapsúlalo como una API HTTP
El código de la aplicación no debería importar diffusers. Coloca el pipeline detrás de un pequeño servicio para que tenga un contrato que puedas versionar, simular y probar. Este envoltorio de FastAPI tiene unas 40 líneas y devuelve bytes PNG:
# server.py
import io, torch
from fastapi import FastAPI, UploadFile, File, Form
from fastapi.responses import Response
from PIL import Image
from diffusers import QwenImage21Pipeline
app = FastAPI()
pipe = QwenImage21Pipeline.from_pretrained(
"Qwen/Qwen-Image-2.1", torch_dtype=torch.bfloat16
).to("cuda")
SIZES = {"1:1": (2048, 2048), "16:9": (2752, 1536), "9:16": (1536, 2752)}
@app.post("/v1/images")
async def generate(
prompt: str = Form(...),
aspect: str = Form("1:1"),
transparent: bool = Form(False),
seed: int = Form(42),
steps: int = Form(40),
references: list[UploadFile] = File(default=[]),
):
if transparent and not prompt.startswith("This is an RGBA image"):
prompt = ("This is an RGBA image with transparency. " + prompt +
" The image has alpha channel and the background is transparent.")
refs = [Image.open(io.BytesIO(await f.read())) for f in references[:10]]
w, h = SIZES.get(aspect, SIZES["1:1"])
kwargs = dict(prompt=prompt, num_inference_steps=steps,
generator=torch.Generator("cuda").manual_seed(seed))
if refs:
kwargs["image"] = refs if len(refs) > 1 else refs[0]
else:
kwargs.update(width=w, height=h)
image = pipe(**kwargs).images[0]
buf = io.BytesIO()
image.save(buf, format="PNG")
return Response(buf.getvalue(), media_type="image/png",
headers={"X-Image-Mode": image.mode, "X-Seed": str(seed)})
Ejecútalo con `uvicorn server:app --port 8000`. Los dos encabezados de respuesta, `X-Image-Mode` y `X-Seed`, existen para que una prueba pueda verificar la transparencia y la reproducibilidad sin decodificar el PNG. Esa es la única elección específica del producto en el envoltorio; el resto es un punto final multipart simple.
Paso 6: prueba el punto final en Apidog
Ahora es una API, y la misma disciplina que aplicarías a la API de gpt-image-2.5 o la API de Nano Banana 2 se aplica aquí. En Apidog:
- **Crea el punto final** como
POST {{base_url}}/v1/imagescon un cuerpo multipart:prompt,aspect,transparent,seed,steps, y un campo de archivoreferencesrepetible. Colocabase_urlen un entorno para que la misma colección apunte a tu portátil, a la caja de la GPU o a un simulacro. - **Envía una solicitud de texto a imagen** con
seed=42y el prompt del letrero de neón. Confirma200,Content-Type: image/png, yX-Image-Mode: RGB. - **Añade aserciones** en el post-procesador: el estado es 200,
X-Image-Modees igual aRGBAcuandotransparent=true, el tamaño del cuerpo de la respuesta está por encima de un mínimo (un PNG de 2K que devuelve 2 KB es una imagen en blanco), yX-Seedrefleja lo que enviaste. - **Envía el caso de transparencia y una edición de tres referencias** de la misma manera, adjuntando las imágenes en el campo de archivo. Guarda cada uno como un caso de prueba.
- **Ejecútalos como un escenario de prueba** en un horario o en CI. Cuando cambies a una compilación cuantificada o a una futura 2.2, el conjunto te dirá en minutos si la transparencia sigue funcionando y si la semilla aún se reproduce.
- **Simúlalo** mientras la GPU está ocupada. La simulación inteligente de Apidog devuelve un PNG predefinido para el mismo contrato, por lo que el frontend sigue construyendo.
Dado que Apidog también genera la especificación OpenAPI y la documentación a partir del punto final que definiste, el contrato del envoltorio se vuelve compartible en el momento en que funciona. Descarga Apidog e importa el punto final anterior para empezar.
Opcional: reescritura de prompts con PE-T2I
El espacio de demostración convierte solicitudes de una línea en prompts estructurados largos usando Qwen-Image-2.1-PE-T2I, un Qwen3.5-VL 9B ajustado que devuelve JSON con un prompt en inglés expandido y una relación de aspecto recomendada. Ejecútalo como un segundo servicio delante de `/v1/images`, o sáltatelo y escribe tus propios prompts completos. Si lo añades, pruébalo por separado: es una API de texto con un contrato JSON, y un reescritor roto produce imágenes deficientes que parecen un error del generador.
Preguntas frecuentes
¿Un solo pipeline realiza tanto la generación como la edición? Sí. QwenImage21Pipeline genera cuando se llama solo con un prompt y edita cuando pasas image (una sola imagen PIL o una lista de hasta 10).
¿Cómo obtengo un PNG transparente? Comienza el prompt con "Esta es una imagen RGBA con transparencia" y di que el fondo es transparente. Verifica image.mode == "RGBA" en el resultado.
¿Cuáles son las configuraciones recomendadas? 40 pasos de inferencia y bfloat16, según el README. Los valores de guía no se enumeran para 2.1; las versiones anteriores de Qwen-Image usaban true_cfg_scale=4.0, así que pruébalo si las salidas parecen insuficientemente guiadas [VERIFICAR].
¿Puedo usar esto en un producto comercial? No bajo la licencia predeterminada. Qwen-Image-2.1 se distribuye bajo la Licencia de Investigación de Qwen; el uso comercial requiere una licencia separada de Qwen. Detalles en ¿Qué es Qwen-Image-2.1?.
¿Hay una API alojada en su lugar? Qwen Image 3.0 y 3.0 Pro son los modelos de imagen alojados de Alibaba con precios por imagen. La comparación 2.1 vs 3.0 cubre cuándo autoalojar y cuándo alquilar.
A dónde ir después
Ahora tienes cuatro llamadas funcionando, un envoltorio con un contrato estable y un conjunto de pruebas que verifica las dos propiedades más importantes para este modelo: transparencia y reproducibilidad. A continuación, decide si la licencia de investigación se ajusta a tu uso, o si la API alojada 3.0 es la opción más adecuada, y mantén ambas detrás de la misma colección de Apidog para que el cambio sea solo un cambio de URL base, no una reescritura.
