Quick index of devices, technical articles, and resources Support Us 中文 EN
VKEFUN

TECHNOLOGY ARCHIVE · EST. 2026

Running Qwen-Image-2.1 on Mac: MPS Deployment, Directory Management, and Common Errors

Based on a deployment record on Apple Silicon, this guide organizes three routes—Diffusers + MPS, ComfyUI, and GGUF—provides isolated environment setup, model download, text-to-image and editing examples, and records issues such as missing torchvision, download progress, and memory pressure.

When trying Qwen-Image-2.1 on an Apple Silicon Mac, you can start with Diffusers + PyTorch MPS, then choose ComfyUI or GGUF depending on whether you need a graphical workflow or are constrained by memory. This article organizes a Mac deployment conversation into a standalone guide, preserving directory management, download, and troubleshooting experience, and corrects examples according to project documentation consulted on October 9, 2026.

The approach in the original conversation targeted an M4 Max with 64GB unified memory, and the last run log stopped at processor loading missing torchvision. Therefore, this provides deployment paths and troubleshooting records, and does not claim to have completed end-to-end generation, measured minimum configuration, or generation speed. The following examples were also not re-executed with large model inference when organizing the article.

1. How to choose among the three run routes

RouteSuitable scenariosTrade-offs to understand
Diffusers + MPSDebugging in Python, maintaining scripts, integrating into your own programsDirect interface; environment and dependencies need to be managed by yourself
ComfyUI + MPSUsing node workflows, combining reference images and editing stepsGraphical interface is convenient; model file layout and node versions need to match
stable-diffusion.cpp + GGUF + MetalResearching quantization, command-line deployment, and lower memory usageNeed to prepare the generation model, text encoder, and VAE simultaneously, and verify backend support

Qwen project provides entry points for Diffusers and ComfyUI; QwenImage21Pipeline handles text-to-image and reference image editing in the same pipeline. Qwen official project, Diffusers pipeline documentation.

ComfyUI's macOS desktop version targets Apple Silicon. The GGUF route can refer to the project maintainer's dedicated documentation, but smaller files do not necessarily mean faster generation; you still need to compare on your own machine. ComfyUI macOS installation, stable-diffusion.cpp Qwen-Image-2.1 documentation.

MLX is another route for runtime and model implementation; you cannot simply replace mps with mlx in Python examples to migrate. If considering it, first confirm the specific implementation supports Qwen-Image-2.1, the weight formats used, and the editing features needed.

2. Why you can't estimate configuration based on "7B" alone

The official 7B refers to the visual generation component; the entire pipeline also includes the Qwen3-VL condition encoder and VAE. Official model card.

This local download directory contains seven Safetensors weight files totaling approximately 33.12GB, about 30.84GiB:

ComponentLocal weight files total, decimal approximation
Transformer14.23GB
Text/visual condition encoder17.53GB
VAE1.35GB

File size only indicates the weight size on disk. Inference must also accommodate intermediate tensors, attention computation, output dimensions, and memory usage by the system and other applications; it does not equal peak unified memory requirements.

For the 64GB machine discussed here, BF16, single output, 1024×1024 is a reasonable starting point, not the official minimum configuration. For 32GB or less, you should first evaluate quantization or component offloading; do not treat a Q4 generation model of only a few GB as the entire system's footprint.

On first run, observe memory pressure and swap space in Activity Monitor. If there is heavy swap usage, first reduce resolution, close other high-memory applications, keep single-image generation, then evaluate optimizations supported by the current backend. Diffusers' MPS guide discusses memory pressure and slowdowns caused by swap; its attention slicing example mainly centers on Stable Diffusion, cannot treat "64GB" as a stable boundary for Qwen, and cannot guarantee the same switch works across all pipelines. MPS optimization notes.

3. Keep environment, models, and outputs in one directory

A valuable point in the original conversation is to keep all files centralized in one root directory. This not only eases maintenance but also preserves the large models when rebuilding the Python environment.

The minimal example in this article uses the following structure; .venv, models, cache, and outputs are created in subsequent steps:

qwen-image-2.1-mac/
├── .venv/
├── cache/
│   ├── huggingface/
│   ├── torch/
│   └── xdg/
├── inputs/
├── models/Qwen-Image-2.1/
├── outputs/
└── src/
    ├── common.py
    ├── download_model.py
    └── run.py

In the terminal, create directories and set up an isolated environment. The example chooses Python 3.12 to specify the interpreter version; it does not mean other versions are unusable. If you already have a usable native arm64 Python 3.12, you can skip the Homebrew installation.

brew install python@3.12
mkdir -p "$HOME/models/qwen-image-2.1-mac"
cd "$HOME/models/qwen-image-2.1-mac"
mkdir -p src inputs outputs models cache

python3.12 -m venv .venv
source .venv/bin/activate
python -m pip install -U pip setuptools wheel
python -m pip install -U 'torch>=2.4.0' torchvision \
  'transformers>=5.17' accelerate pillow huggingface_hub \
  safetensors sentencepiece
python -m pip install -U 'git+https://github.com/huggingface/diffusers.git'
python -m pip check

Qwen's installation example gives the above Torch/Transformers minimum versions and the method to install Diffusers from source; this article adds torchvision, which was exposed by the later error. Version minimums only indicate installation constraints, not a verified set of complete locked versions. Qwen installation instructions.

torch and torchvision must use mutually compatible versions; if installation fails, check the official correspondence table. For long-term maintenance, after successful generation, save the result of python -m pip freeze and record the Diffusers Git commit and model revision to avoid one upgrade changing all dependencies simultaneously. Torchvision version correspondence table.

First check the interpreter and backend:

python - <<'PY'
import platform
import sys
import torch
import torchvision
from diffusers import QwenImage21Pipeline

print("Python:", sys.version.split()[0])
print("Architecture:", platform.machine())
print("Torch:", torch.__version__)
print("Torchvision:", torchvision.__version__)
print("MPS built:", torch.backends.mps.is_built())
print("MPS available:", torch.backends.mps.is_available())
PY

The goal is a native arm64 environment with MPS available as True. This step verifies dependency import and GPU backend availability, but still requires actual loading, generation, and saving of images to complete end-to-end verification.

4. Separate download and generation to avoid repeatedly pulling models

Save the following code as src/common.py. It sets the project's internal cache locations before importing Hugging Face, Torch and other libraries:

import os
from pathlib import Path

ROOT = Path(__file__).resolve().parents[1]
MODEL_DIR = ROOT / "models" / "Qwen-Image-2.1"
OUTPUT_DIR = ROOT / "outputs"

for variable, folder in {
    "HF_HOME": "huggingface",
    "TORCH_HOME": "torch",
    "XDG_CACHE_HOME": "xdg",
}.items():
    location = ROOT / "cache" / folder
    location.mkdir(parents=True, exist_ok=True)
    os.environ[variable] = str(location)

Then save src/download_model.py:

from common import MODEL_DIR
from huggingface_hub import snapshot_download

MODEL_DIR.mkdir(parents=True, exist_ok=True)
snapshot_download(
    repo_id="Qwen/Qwen-Image-2.1",
    local_dir=str(MODEL_DIR),
)
print("Model directory:", MODEL_DIR)

Run:

source .venv/bin/activate
python src/download_model.py

snapshot_download supports reusing already downloaded content. When local_dir is specified, the Hub also creates .cache/huggingface metadata under the model directory for subsequent checks; it is not the same as the cache/ directory at the root. Repeated execution with the same revision and directory usually reuses existing files; if the upstream revision changes, it may also download updated files. Hub download and local directory instructions.

If the terminal leaves a lower percentage progress line, do not judge the download as failed based only on that line. First see whether the command terminated normally and whether there is a final error; if unsure, rerun the same download command. Having only model_index.json or a check script showing "Model downloaded: YES" also cannot alone prove all shards are complete.

5. Minimal text-to-image and image editing examples

Save as src/run.py. It only reads the downloaded local model and starts with 1024×1024, single output by default; the CPU random number generator is used to provide a fixed seed, and the pipeline then places the required tensors on MPS.

import argparse
from datetime import datetime

from common import MODEL_DIR, OUTPUT_DIR
import torch
from PIL import Image
from diffusers import QwenImage21Pipeline

parser = argparse.ArgumentParser()
parser.add_argument("--prompt", required=True)
parser.add_argument("--image")
parser.add_argument("--size", type=int, default=1024)
parser.add_argument("--steps", type=int, default=40)
parser.add_argument("--seed", type=int, default=42)
args = parser.parse_args()

if args.size <= 0 or args.size % 32 or args.steps <= 0:
    parser.error("size must be a positive multiple of 32; steps must be positive")
if not torch.backends.mps.is_available():
    raise RuntimeError("MPS is unavailable; check native Python and PyTorch")

pipeline = QwenImage21Pipeline.from_pretrained(
    str(MODEL_DIR),
    dtype=torch.bfloat16,
    local_files_only=True,
).to("mps")

options = {
    "prompt": args.prompt,
    "num_inference_steps": args.steps,
    "generator": torch.Generator("cpu").manual_seed(args.seed),
}
if args.image:
    with Image.open(args.image) as source:
        options["image"] = source.convert("RGBA")
    options["output_resolution"] = args.size
else:
    options["width"] = args.size
    options["height"] = args.size

OUTPUT_DIR.mkdir(parents=True, exist_ok=True)
result = pipeline(**options).images[0]
name = datetime.now().strftime("qwen-%Y%m%d-%H%M%S-%f.png")
destination = OUTPUT_DIR / name
result.save(destination)
print("Saved:", destination)

Text-to-image:

python src/run.py \
  --prompt '一张复古电脑放在木桌上的照片,窗边自然光,清晰细节' \
  --size 1024 --steps 40 --seed 42

Edit with reference image:

python src/run.py \
  --image inputs/photo.png \
  --prompt '保留主体的外观,把背景改成柔和的日落海边' \
  --size 1024 --steps 40

The editing path uses image and output_resolution, letting the pipeline calculate dimensions based on the input aspect ratio; here size is the target area scale and does not promise output exactly at the original image pixel size. Save PNG and preserve input RGBA to avoid the example discarding transparency when reading. Fixed seed facilitates comparison in the same environment; it does not guarantee pixel-by-pixel consistency across versions or backends. Pipeline parameters and image preprocessing.

After confirming normal image saves, try --size 2048. The official model example uses 2048×2048, 40 steps; 1024 is the starting point chosen here for troubleshooting, and should be understood separately from the model's native 2K usage goal. Official generation example.

The above script covers only the minimal process and does not include batching, GUI, image quality validation, or automatic memory optimization. If continuing with the .command script package from the original conversation, you can keep the "install → download → check → generate/edit" entry division, making Finder double-click entries thin wrappers that call the same set of Python files.

6. The most useful error experience from this deployment

Missing torchvision after processor loaded to 80%

In the original record, weight shards had entered the loading process, then the following appeared:

Qwen3VLVideoProcessor requires the Torchvision library

This indicates the first thing to solve is the processor dependency import. Even if the current task only generates static images, the combined processor initialization may require video processing-related dependencies.

Install matching versions in the same virtual environment, then exit the original process and restart:

source .venv/bin/activate
python -m pip install -U torch torchvision
python -m pip check
python -c 'import torch, torchvision; print(torch.__version__, torchvision.__version__)'

Do not delete the 33GB model first for this ImportError. Fixing the dependency can resolve the current error; whether other issues follow should be judged from new logs.

Deprecation warning for torch_dtype

The conversation also showed a deprecation warning for torch_dtype, which was not the direct cause of that ImportError. This article uses dtype=torch.bfloat16 according to the current Diffusers pipeline documentation; when maintaining old scripts, update the parameter name after confirming the version in use supports it.

python3 automatically selected 3.14

The original script preferred several explicit versions and finally fell back to python3, actually selecting Python 3.14. When troubleshooting, first print sys.executable, Python version, and architecture; do not assume the command name represents a fixed version.

If you need to use Python 3.12, exit the virtual environment, rename the old .venv to keep it, and recreate; keep models/, inputs/, and outputs/. There is no need to redownload the entire model set because of the interpreter change.

MPS available but image editing results are abnormal

Text-to-image success cannot replace editing acceptance: reference image editing also goes through VAE encoding. In ComfyUI's issue report #16433, the reporter's specific MPS environment had Qwen-Image-2.1 VAE encoding anomalies, and reported that CPU VAE could bypass the issue; patch discussions have since occurred.

If you encounter reference image becoming noise, color cast, or structural damage in a similar environment, you can use python main.py --cpu-vae for a ComfyUI control investigation, then check whether the actual version includes the relevant fix. This is a troubleshooting method for the report, not indicating all Macs necessarily have it, nor a startup parameter that can be directly applied to Diffusers.

7. What to preserve during maintenance

  • When fixing dependencies, keep the model directory; when rebuilding the environment, handle .venv separately.
  • When clearing cache, confirm the target directory; the download metadata inside the model directory serves its own purpose, so do not treat the entire root directory as cache.
  • Acceptance checks should be done separately: dependency import, MPS availability, full loading, text-to-image saving, reference image editing, and result appearance.
  • Record actual Python, Torch, Torchvision, Transformers, Diffusers, and model revision, and keep complete error logs.
  • Avoid claiming full validation or speed conclusions based only on download percentage, MPS=True, or a single output file.

8. Model license and scope of applicability

Qwen-Image-2.1 currently uses the Qwen Research License Agreement, not Apache 2.0. The agreement limits non-commercial use to research or evaluation; commercial use requires separate permission. Before connecting to paid applications or services, read the specific terms. Model license original text.

This article organizes local research and environment maintenance methods, and does not distribute model weights, original conversation attachments, or inference services. Interfaces, dependencies, and compatibility issues will continue to change; when actually installing, verify the corresponding version's project documentation.

READER CORRESPONDENCE

Comments (0)

Sign in to comment or reply. Submissions appear after moderation.

No comments yet.

Click again or press Esc to close