首頁/人工智慧

在 Mac 上跑 Z-Image:MLX 原生生圖,順便記幾個踩到的雷

2026年08月11日 人工智慧 Z-Image MLX mlx-swift Swift 本機生圖 Apple Silicon

最近在 Mac 上跑通義的文字生圖模型 Z-Image,用的是 Z-Image.swift——一個用原生 Swift 包起來的版本,底層跑 mlx-swift,直接吃 Apple GPU,不用另外裝 Python、PyTorch 或一堆 CUDA 相關套件。

會想試這條路線,理由跟之前在本機跑 LLM 差不多:東西留在自己電腦上、沒有 API 帳單,而且原生 Swift 寫起來跟一般寫 macOS App 沒兩樣,不用切去 Python 的世界。缺點也很直接:踩雷的時候找不到太多中文資料,錯誤訊息大多要自己拆。這篇就是記一下整個過程,包含卡住最久的那個問題。

先準備環境

  • Apple Silicon 的 Mac(M 系列晶片,Metal GPU 加速要靠它)

  • macOS 14 以上

  • 完整的 Xcode,不是只裝 Command Line Tools——這點後面會說明為什麼一定要

  • Swift 6 工具鏈(Xcode 自帶)

第一次在新機器上跑,還可能要多裝一個東西:Metal Toolchain。這是 Xcode 16 之後把 Metal 編譯器獨立拆出來的元件,沒裝過的話會在編譯 shader 時失敗,跳出這行:

error: cannot execute tool 'metal' due to missing Metal Toolchain;
use: xcodebuild -downloadComponent MetalToolchain

照著訊息跑一次就好:

xcodebuild -downloadComponent MetalToolchain

這個元件大概 688MB,下載一次之後就不用再抓了。

寫一個最小範例

先建一個空的 SwiftPM 執行檔專案:

mkdir ZImageDemo && cd ZImageDemo
swift package init --type executable

Package.swift 加上 Z-Image.swift 這個依賴:

// swift-tools-version: 6.0
import PackageDescription

let package = Package(
    name: "ZImageDemo",
    platforms: [.macOS(.v14)],
    dependencies: [
        .package(url: "https://github.com/zhutao100/Z-Image.swift", branch: "main")
    ],
    targets: [
        .executableTarget(
            name: "ZImageDemo",
            dependencies: [
                .product(name: "ZImage", package: "Z-Image.swift")
            ]
        )
    ]
)

Sources/ZImageDemo/main.swift 大概十幾行就能跑通:

import Foundation
import ZImage

let pipeline = ZImagePipeline()

// 先下載(沒下載過的話)+載入模型到記憶體
try await pipeline.loadModel(modelSpec: "Tongyi-MAI/Z-Image-Turbo") { progress in
    print("下載/載入中:\(progress.stage.rawValue) \(progress.percentComplete)%")
}

let request = ZImageGenerationRequest(
    prompt: "A small orange cat sitting on a windowsill, soft morning light, minimalist illustration style",
    negativePrompt: nil,
    width: 1024,
    height: 1024,
    steps: 9,
    seed: nil,
    outputPath: URL(fileURLWithPath: "output.png"),
    model: "Tongyi-MAI/Z-Image-Turbo"
)

_ = try await pipeline.generate(request) { progress in
    print("產生中:\(progress.stage.rawValue) \(progress.percentComplete)%")
}

print("完成,輸出到 output.png")

Tongyi-MAI/Z-Image-Turbo 是加速過的版本,速度快、品質夠用,一般測試用這個就好;Tongyi-MAI/Z-Image 是原版,品質稍微好一點但慢不少。steps 我抓 9,Turbo 版本用低步數本來就是設計上的取捨。

跑起來:不能直接 swift run

到這裡,直覺會下 swift run,但這樣會編過、也能連上,然後在真的要用 GPU 跑推論的那一刻直接 crash,丟出這行:

MLX error: Failed to load the default metallib.

原因是 mlx-swift 的 Metal shader(.metal 檔)要編成 default.metallib,這一步只有 Xcode 的建置系統做得到,純指令列的 swift buildswift run 編不出來。mlx-swift 自己的 README 也寫得很清楚:command line SwiftPM 沒辦法編 Metal shader,最終一定要靠 Xcode。

好消息是不用真的開 Xcode 視窗,xcodebuild 就能吃單一個 Package.swift,自動生出對應的 scheme:

xcodebuild -list

會看到一個跟你套件同名的 scheme(這裡是 ZImageDemo)。接著直接建置:

xcodebuild build -scheme ZImageDemo -destination 'platform=macOS' \
  -derivedDataPath .build/xcode-dd

第一次跑會連著把 Metal shader 一起編掉,比 swift build 慢一些,但編出來的執行檔放在:

.build/xcode-dd/Build/Products/Debug/ZImageDemo

直接執行這支檔案,才會是真的能跑 GPU 推論的版本:

.build/xcode-dd/Build/Products/Debug/ZImageDemo

幾個踩到的雷

一、下載進度卡在 0%,不代表當掉

第一次抓模型(尤其是沒加速過的 Tongyi-MAI/Z-Image,權重有好幾 GB)的時候,畫面會停在「Loading model 0%」很長一段時間,看起來像卡死。

實際上是背景真的在抓檔案,只是套件目前回報進度的方式是「一個檔案算一單位」,遇到單一個大檔案(例如整包 safetensors)下載到一半,進度就是不會動,要等這個檔案完整下完才會跳。不放心的話可以開活動監視器,或者用 lsof -p <pid> 看那個行程有沒有正在寫某個成長中的暫存檔——只要檔案大小持續在漲,就是還在抓,不是卡住。

二、下載到一半把程式關掉,不會接續

這個雷比較痛:如果模型正在下載時把程式砍掉(或當機),已經下載一部分的那個大檔案不會留著、下次也不會接續下載,會整包重新抓一次。已經完整下載完成的小檔案(設定檔、tokenizer 那些)才會被保留,不用重抓。

所以下載中盡量不要中斷。真的要中斷,有心理準備那個正在下的檔案要重來一次。

三、模型快取位置可以換,記得先想好放哪

模型預設抓到 ~/.cache/huggingface/hub,跟 Python 生態的 huggingface_hub 共用同一套快取目錄——如果你機器上已經用 Python 版工具下載過同樣的模型,Swift 這邊可以直接讀到,不用重抓。

想換位置(例如系統碟空間不夠,想存到外接硬碟),設環境變數就好:

export HF_HUB_CACHE=/Volumes/External/hf-cache

要注意的是換路徑之後,新路徑底下如果沒有對應模型的快取,等於要重新下載一次,不是搬移舊的過去。

小結

整體來說,原生 Swift + MLX 這條路線可用,速度也不差,比想像中好上手。真正卡人的不是 API 或模型本身,而是「純 SwiftPM 編不出 Metal shader」這件事——不知道要用 xcodebuild 的話,可能會一直卡在同一個 crash 訊息上打轉。剩下下載進度顯示不夠即時、中斷不續傳這幾點,比較像是套件現階段的粗糙之處,繞得過去,只是要有心理準備。

相簿:Z-Image 產圖風格試跑

同一顆 Tongyi-MAI/Z-Image-Turbo,9 步、guidance_scale=0,換不同 prompt 風格跑出來的樣子,順手記錄一下:

寫實攝影風格

賽博龐克風格

日系水彩插畫風格

企業簡報等角圖風格

黏土立體插畫風格

水墨寫意風格

復古底片攝影風格

極簡線稿手繪風格

太空科幻插畫風格

扁平商務資訊圖風格

9 步、無 CFG 的 Turbo 版本,對寫實攝影跟等角商務插圖這類「構圖規則、色塊清楚」的風格掌握得比較穩;水墨、線稿這種靠留白跟筆觸節奏的風格,偶爾會需要多抽幾次種子才會滿意。