在 Mac 上运行 Qwen-Image-2.1:MPS 部署、目录管理与常见报错
基于 Apple Silicon 上的部署记录,梳理 Diffusers + MPS、ComfyUI 与 GGUF 三条路线,给出独立环境、模型下载、文生图与编辑示例,并记录 torchvision 缺失、下载进度和内存压力等问题。
登录后可收藏这条档案。
在 Apple Silicon Mac 上尝试 Qwen-Image-2.1,可以先从 Diffusers + PyTorch MPS 开始,再根据是否需要图形工作流、是否受内存限制,选择 ComfyUI 或 GGUF 路线。本文把一次 Mac 部署对话整理为独立指南,保留目录管理、下载与排错经验,并按 2026 年 10 月 9 日查阅的项目文档修正示例。
原始对话中的方案面向 M4 Max、64GB 统一内存,最后一份运行日志停在处理器加载时缺少 torchvision。因此,这里提供的是部署路径与排错记录,没有据此宣称已经完成端到端生成、测出最低配置或生成速度。以下示例也没有在整理文章时重新执行大模型推理。
1. 三条运行路线怎么选
| 路线 | 适合的场景 | 需要了解的取舍 |
|---|---|---|
| Diffusers + MPS | 用 Python 调试、维护脚本、接入自己的程序 | 接口直接,环境和依赖需要自己管理 |
| ComfyUI + MPS | 使用节点工作流、组合参考图与编辑步骤 | 图形界面方便,模型文件布局和节点版本需要匹配 |
| stable-diffusion.cpp + GGUF + Metal | 研究量化、命令行部署与较低内存占用 | 要同时准备生成模型、文本编码器和 VAE,并核对后端支持 |
Qwen 项目提供 Diffusers 与 ComfyUI 的入口;QwenImage21Pipeline 在同一管线中处理文生图和参考图编辑。Qwen 官方项目、Diffusers 管线文档。
ComfyUI 的 macOS 桌面版面向 Apple Silicon。GGUF 路线可参考项目维护者的专用文档,但文件更小不等于必然生成更快,仍需在自己的机器上比较。ComfyUI macOS 安装、stable-diffusion.cpp 的 Qwen-Image-2.1 文档。
MLX 属于另一套运行与模型实现路线,不能把 Python 示例里的 mps 换成 mlx 就完成迁移。若考虑它,应先确认具体实现支持 Qwen-Image-2.1、所用权重格式以及需要的编辑功能。
2. 为什么不能只看“7B”来估算配置
官方所说的 7B 指视觉生成组件,整套管线还包括 Qwen3-VL 条件编码器与 VAE。官方模型卡。
这次本地下载目录中的七个 Safetensors 权重文件合计约 33.12GB,约 30.84GiB:
| 组件 | 本地权重文件合计,十进制近似值 |
|---|---|
| Transformer | 14.23GB |
| 文本/视觉条件编码器 | 17.53GB |
| VAE | 1.35GB |
文件体积只说明磁盘上的权重大小。推理还要容纳中间张量、注意力计算、输出尺寸及系统和其他应用的内存占用;它不等于峰值统一内存需求。
对这次讨论的 64GB 机器,BF16、单张输出、1024×1024 是一个值得尝试的起点,不是官方最低配置。32GB 及以下机器应先评估量化或组件卸载方案,不能因为某个 Q4 生成模型只有几 GB,就把它当作整套系统的占用。
第一次运行时观察“活动监视器”的内存压力和交换空间。如果大量使用 Swap,先降低分辨率、关闭其他高内存应用、保持单张生成,再评估当前后端支持的优化。Diffusers 的 MPS 指南讨论了内存压力与交换造成的变慢;其中 attention slicing 的示例主要围绕 Stable Diffusion,不能把“64GB”直接当成 Qwen 的稳定运行分界线,也不能保证同一个开关在所有管线上有效。MPS 优化说明。
3. 把环境、模型和输出收在一个目录里
原对话中很有价值的一点,是让所有文件集中在一个根目录内。这不仅方便维护,也能在重建 Python 环境时保留大体积模型。
本文的最小示例采用下面的结构;.venv、模型、缓存和输出在后续步骤中创建:
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
在终端创建目录并建立独立环境。示例选择 Python 3.12,是为了明确解释器版本;不表示其他版本一定不能用。已有可用的原生 arm64 Python 3.12 时可跳过 Homebrew 安装。
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 的安装示例给出上述 Torch/Transformers 下限及从源码安装 Diffusers 的方式;本文补上了后续报错暴露的 torchvision。版本下限只表示安装约束,不是一组已经验证成功的完整锁定版本。Qwen 安装说明。
torch 与 torchvision 要使用相互匹配的版本,安装失败时应核对官方对应表。长期维护时,成功生成后保存 python -m pip freeze 的结果,并记录 Diffusers Git 提交与模型 revision,避免一次升级同时改变所有依赖。Torchvision 版本对应表。
先检查解释器与后端:
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
目标是原生 arm64 环境,且 MPS available 为 True。这一步验证的是依赖导入和 GPU 后端可用性,仍需实际加载、生成、保存图片才能完成端到端验证。
4. 下载与生成分开,避免反复拉取模型
将下面的代码保存为 src/common.py。它在导入 Hugging Face、Torch 等库之前设置项目内的缓存位置:
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)
再保存 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)
运行:
source .venv/bin/activate
python src/download_model.py
snapshot_download 支持复用已下载的内容。指定 local_dir 时,Hub 还会在模型目录下建立 .cache/huggingface 元数据,用于后续检查;它和根目录下的 cache/ 不是同一个目录。同一 revision、同一目录重复执行通常复用已有文件;如果上游 revision 改变,也可能下载更新的文件。Hub 下载与本地目录说明。
如果终端留下一个较低百分比的进度行,不应只凭那一行判断下载失败。先看命令是否正常结束、是否还有最终错误;不确定时重新运行相同下载命令。仅有 model_index.json 或检查脚本显示“Model downloaded: YES”,也不能单独证明所有分片完整。
5. 最小文生图与图像编辑示例
保存为 src/run.py。它只读取下载好的本地模型,默认以 1024×1024、单张输出开始;CPU 随机数生成器用于提供固定种子,再由管线把所需张量放到 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)
文生图:
python src/run.py \
--prompt '一张复古电脑放在木桌上的照片,窗边自然光,清晰细节' \
--size 1024 --steps 40 --seed 42
用参考图编辑:
python src/run.py \
--image inputs/photo.png \
--prompt '保留主体的外观,把背景改成柔和的日落海边' \
--size 1024 --steps 40
编辑路径使用 image 与 output_resolution,让管线按输入比例计算尺寸;这里的 size 是目标面积尺度,不承诺输出就是原图像素尺寸。保存 PNG 并保留输入 RGBA,避免示例在读取时直接丢掉透明通道。固定种子方便在同一环境中比较,不保证跨版本、跨后端逐像素一致。管线参数与图像预处理。
确认能保存正常图片后,再尝试 --size 2048。官方模型示例采用 2048×2048、40 步;1024 是这里为排错选择的起点,和模型的原生 2K 使用目标要分开理解。官方生成示例。
上面的脚本只覆盖最小流程,没有加入批处理、GUI、图像质量校验或自动内存优化。若沿用原对话中的 .command 脚本包,可以保持“安装 → 下载 → 检查 → 生成/编辑”的入口划分,把 Finder 双击入口做成调用同一组 Python 文件的薄包装。
6. 这次部署最有用的报错经验
处理器加载到 80% 后缺少 torchvision
原始记录中,权重分片已进入加载流程,随后出现:
Qwen3VLVideoProcessor requires the Torchvision library
这说明首先要解决的是处理器依赖导入。即使当前任务只生成静态图片,组合处理器初始化也可能需要视频处理相关的依赖。
在同一个虚拟环境中安装匹配版本,再退出原进程重新启动:
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__)'
不要为了这个 ImportError 先删除 33GB 模型。修复依赖能处理当前错误,后面是否还有其他问题,仍要以新日志为准。
torch_dtype 的弃用提醒
对话中同时出现了 torch_dtype 的弃用警告,它不是那次 ImportError 的直接原因。本文按照当前 Diffusers 管线文档使用 dtype=torch.bfloat16;维护旧脚本时,可在确认所用版本支持后更新参数名。
python3 自动选到了 3.14
原脚本优先寻找若干明确版本,最后退回 python3,实际选到了 Python 3.14。排查时先打印 sys.executable、Python 版本和架构,不要假设命令名代表固定版本。
如果需要改用 Python 3.12,可退出虚拟环境,将旧 .venv 改名保留后重新创建;保留 models/、inputs/ 和 outputs/。没有必要因为解释器变更重新下载整套模型。
MPS 可用,但图像编辑结果异常
文生图成功不能替代编辑验收:参考图编辑还会经过 VAE 编码。在 ComfyUI 的 问题报告 #16433 中,报告者的特定 MPS 环境出现了 Qwen-Image-2.1 VAE 编码异常,并报告 CPU VAE 可绕过该问题;后续已有补丁讨论。
若在类似环境中遇到参考图变成噪声、偏色或结构损坏,可用 python main.py --cpu-vae 做 ComfyUI 的对照排查,再核对实际版本是否包含相关修复。这是针对报告的排错方法,不代表所有 Mac 必现,也不是可直接套到 Diffusers 的启动参数。
7. 维护时保留哪些东西
- 修依赖时保留模型目录;重建环境时把
.venv单独处理。 - 清缓存时确认目标目录,模型目录内的下载元数据也有自己的用途,不要把整个根目录当缓存。
- 验收分开进行:依赖导入、MPS 可用、完整加载、文生图保存、参考图编辑与结果观感。
- 记录实际 Python、Torch、Torchvision、Transformers、Diffusers 与模型 revision,保留完整错误日志。
- 避免只凭下载百分比、
MPS=True或一张输出文件,就声称完成全部验证或给出速度结论。
8. 模型许可与适用范围
Qwen-Image-2.1 当前使用 Qwen Research License Agreement,并非 Apache 2.0。协议将非商业用途限定为研究或评估,商业使用需要另行获得许可;接入收费应用或服务前应阅读具体条款。模型许可原文。
本文整理的是本地研究与环境维护方法,未分发模型权重、原对话附件或推理服务。接口、依赖与兼容问题会继续变化,实际安装时应核对对应版本的项目文档。
读者交流
评论 (0)
登录后可发表评论和回复;提交内容通过审核后显示。
登录后可以发表评论和回复。
还没有评论。