Hugging Face Diffusers 入门指南
介绍如何配置 Hugging Face Diffusers 和 SDXL、生成图像、调整参数、节省 GPU 内存,并通过 FastAPI 为 JavaScript 应用提供接口。
Hugging Face Diffusers 是一个 Python 库,用于在本地硬件上运行图像、视频和音频扩散模型。它将文本编码器(text encoder)、调度器(scheduler)、去噪网络和 VAE 封装为一个 pipeline 对象,你只需传入提示词(prompt)即可调用。
托管式图像 API 上手很容易,但随之而来的是按张计费的账单、拖慢原型开发的速率限制,以及对模型内部运作的好奇。在本地运行模型可以同时解决这三个问题,但大多数教程都默认你已经熟悉 PyTorch。
本指南面向 JavaScript 开发者。它将带你从安装开始生成第一张图像,讲解关键参数设置,介绍如何在显存较小的 GPU 上运行模型,最后搭建一个可由前端通过 fetch() 调用的 FastAPI 接口。文中示例基于 Diffusers v0.42.1。
核心要点
- 使用
DiffusionPipeline.from_pretrained(..., dtype=torch.float16)加载stabilityai/stable-diffusion-xl-base-1.0,在 NVIDIA GPU 上将其移至"cuda",在 Apple Silicon 上移至"mps"。 - SDXL base 1.0 采用 CreativeML Open RAIL++-M 许可证发布。在将生成的图像用于产品之前,请先仔细阅读该许可证。
- 使用设置了种子的
torch.Generator可以让输出结果可复现,这样你就能每次只调整一个参数并观察其效果。 - 如果模型无法装入 GPU 显存,请优先调用
enable_model_cpu_offload()。Diffusers 文档指出,顺序 CPU 卸载(sequential CPU offload)速度极慢。 - 在服务器启动时只加载一次 pipeline,并在所有请求中复用。切勿在请求处理函数中加载 pipeline。
什么是 Hugging Face Diffusers?
Diffusers 是 Hugging Face 推出的扩散模型库。其核心抽象是 DiffusionPipeline,它将模型所需的各个组件打包在一起:
- 一个或多个文本编码器,用于将提示词转换为嵌入向量(embedding)
- 一个调度器,用于控制去噪算法
- 一个 UNet 或扩散 Transformer,用于在每一步预测噪声
- 一个 VAE,用于将结果解码为像素
如果你还不熟悉 Hub、Inference Providers 或 Spaces,请先阅读 A Quick Guide to Hugging Face for Developers。如果你希望完全不依赖 Python 后端进行推理,可以了解 Transformers.js 直接在浏览器中运行模型,不过它支持的模型范围有所不同。
Diffusers 需要什么样的硬件?
Diffusers 可以在三类设备上运行。NVIDIA GPU 的速度遥遥领先;Apple Silicon Mac 可通过 PyTorch 的 "mps" 后端运行;纯 CPU 也能运行,但速度非常慢。
| 硬件 | 设备字符串 | dtype | 预期表现 |
|---|---|---|---|
| NVIDIA GPU | "cuda" | torch.float16 | 快 |
| Apple Silicon Mac | "mps" | torch.float16 | 可用,比独立 NVIDIA GPU 慢 |
| 仅 CPU | "cpu" | torch.float32 | 可用,非常慢 |
Quickstart 中列出的设备目标包括 "cuda"、"mps"、"xpu" 和 "cpu"。Diffusers 还提供了专门的 Apple Silicon (MPS) 指南。下面这段辅助代码会为当前机器选择合适的设备和 dtype:
import torch
if torch.cuda.is_available():
device, dtype = "cuda", torch.float16
elif torch.backends.mps.is_available():
device, dtype = "mps", torch.float16
else:
device, dtype = "cpu", torch.float32
安装 Diffusers 并生成第一张图像
使用 Hugging Face Diffusers 生成第一张图像只需三步:安装 Diffusers 和 PyTorch,加载 SDXL,然后传入提示词调用 pipeline 并保存 .images[0]。
自 v0.42.0 起,Diffusers 要求 Python 3.11 或更高版本,并基于 PyTorch 2.6 或更高版本进行测试。请按照安装指南创建虚拟环境,然后安装相关依赖包。SDXL 的文本编码器是来自 Transformers 的 CLIP 模型,因此还需要安装该库:
uv pip install "diffusers[torch]>=0.42.1" transformers
# or: pip install "diffusers[torch]>=0.42.1" transformers
使用上面辅助代码中得到的 device 和 dtype 生成图像:
import torch
from diffusers import DiffusionPipeline
pipeline = DiffusionPipeline.from_pretrained(
"stabilityai/stable-diffusion-xl-base-1.0",
dtype=dtype,
).to(device)
prompt = "isometric pixel-art coffee shop at dusk, warm window light, rain on the street"
image = pipeline(prompt).images[0]
image.save("first.png")
image 是一个 PIL 图像对象,因此调用 .save() 即可将 PNG 文件写入磁盘。模型 id 是该 checkpoint 在 Hub 上的完整名称,包括 stabilityai/ 组织前缀。
许可证: SDXL base 1.0 采用 CreativeML Open RAIL++-M 许可证发布。在产品中使用生成的图像之前,请务必阅读该许可证;如果更换为其他模型,也请检查相应模型的许可证。
哪些 SDXL 参数最关键?
SDXL pipeline 中有四个参数对输出结果影响最大:num_inference_steps、guidance_scale、generator 以及 height / width。建议先固定种子,再每次只调整一个参数。
generator = torch.Generator().manual_seed(42)
image = pipeline(
prompt,
num_inference_steps=30,
guidance_scale=7.0,
height=1024,
width=1024,
generator=generator,
).images[0]
num_inference_steps设置去噪的迭代次数。步数越多,耗时越长,通常细节也越丰富,但达到一定程度后收益会趋于平缓。guidance_scale设置模型遵循提示词的程度。值越高,结果越贴近文本描述;但值过高可能导致画面过度处理、显得”过火”。generator固定初始噪声。在模型、参数和硬件都相同的情况下,设置了种子的 generator 能再次生成相同的图像。height/width以像素为单位设置输出尺寸。图像越大,所需显存和时间就越多。
SDXL pipeline 参考文档列出了所有参数及其默认值。
更换调度器
调度器决定了每一步如何去除噪声,不同的调度器在速度与质量之间各有取舍。你可以通过 from_config() 替换已加载 pipeline 的调度器,并传入现有配置,以确保与该 checkpoint 匹配的设置保持一致:
from diffusers import DPMSolverMultistepScheduler
pipeline.scheduler = DPMSolverMultistepScheduler.from_config(pipeline.scheduler.config)
generator = torch.Generator().manual_seed(42)
image = pipeline(prompt, num_inference_steps=20, generator=generator).images[0]
Schedulers 指南中正是使用这种方式配合 SDXL。DPMSolverMultistepScheduler 参考文档指出,它在约 20 步内即可生成高质量的样本。比较不同调度器时,请保持种子不变,这样两张图像之间唯一的变量就是调度器。
如何在显存较小的 GPU 上运行 SDXL?
如果运行 SDXL 时出现显存不足(OOM)错误,可以按以下顺序依次尝试 Diffusers 提供的四种显存优化方法:模型 CPU 卸载、VAE 分块(tiling)、VAE 切片(slicing)以及 4-bit 量化。越往后,节省的显存越多,速度损失也越大。
- 模型 CPU 卸载。 不调用
.to(device),改为调用pipeline.enable_model_cpu_offload()。每个完整的模型仅在运行时才驻留在 GPU 上。 - VAE 分块。
pipeline.vae.enable_tiling()会将大尺寸图像分块解码。显存优化指南指出,这可能导致各分块之间出现轻微的色调差异。 - VAE 切片。
pipeline.vae.enable_slicing()会将一个批次中的图像逐张解码。只有在单次调用中生成多张图像时,它才会起作用。 - 4-bit 量化。 安装
bitsandbytes并添加一段简短的配置:
from diffusers.quantizers import PipelineQuantizationConfig
quant_config = PipelineQuantizationConfig(
quant_backend="bitsandbytes_4bit",
quant_kwargs={"load_in_4bit": True, "bnb_4bit_quant_type": "nf4", "bnb_4bit_compute_dtype": torch.float16},
components_to_quantize=["unet"],
)
pipeline = DiffusionPipeline.from_pretrained(
"stabilityai/stable-diffusion-xl-base-1.0",
dtype=torch.float16,
quantization_config=quant_config,
)
pipeline.enable_model_cpu_offload()
量化概述文档介绍了 PipelineQuantizationConfig 及其支持的后端。Diffusers 在 v0.39.0 中新增了对 MPS 上 bitsandbytes 量化的支持,因此该方法并不局限于 CUDA。在 Apple Silicon 上,bitsandbytes 需要 PyTorch 2.9 或更高版本,高于前文提到的 PyTorch 2.6 基线要求。
除非别无他法,否则请避免使用 enable_sequential_cpu_offload()。它虽然最省显存,但显存优化指南称其速度极慢。此外,使用 device_map 加载的 pipeline,在调用 .to() 或任一卸载方法之前,必须先调用 reset_device_map()。
在 Web 应用中调用 Hugging Face Diffusers
要在前端使用 Diffusers,可以将 pipeline 封装在一个小型 HTTP 服务器中。服务器应在启动时只加载一次模型,并返回 PNG 字节数据。安装 fastapi 和 uvicorn,然后将以下代码保存为 main.py:
import io, threading
from contextlib import asynccontextmanager
import torch
from diffusers import DiffusionPipeline
from fastapi import FastAPI, Response
from fastapi.middleware.cors import CORSMiddleware
from pydantic import BaseModel
state = {}
lock = threading.Lock()
@asynccontextmanager
async def lifespan(app: FastAPI):
state["pipe"] = DiffusionPipeline.from_pretrained(
"stabilityai/stable-diffusion-xl-base-1.0", dtype=torch.float16
).to("cuda") # or "mps"
yield
state.clear()
app = FastAPI(lifespan=lifespan)
app.add_middleware(CORSMiddleware, allow_origins=["http://localhost:5173"],
allow_methods=["POST"], allow_headers=["*"])
class GenerateRequest(BaseModel):
prompt: str
seed: int | None = None
@app.post("/generate")
def generate(req: GenerateRequest):
gen = torch.Generator().manual_seed(req.seed) if req.seed is not None else None
with lock:
image = state["pipe"](req.prompt, generator=gen).images[0]
buf = io.BytesIO()
image.save(buf, format="PNG")
return Response(content=buf.getvalue(), media_type="image/png")
使用 uvicorn main:app 运行服务。这段代码基于 FastAPI 的三项特性构建:
- lifespan 处理函数会在服务器接受任何请求之前加载一次模型。
from_pretrained()速度太慢,绝不能在每个请求中调用。 - 由于
generate是普通的def函数,FastAPI 会在线程池中运行它,而不会阻塞事件循环。 - 锁(lock)确保各请求依次使用 GPU。
CORSMiddleware 允许你的开发环境前端所在的源(origin)调用该接口。
在前端,使用 fetch() 请求图像,将响应体读取为 Blob,并通过 URL.createObjectURL() 显示图像:
async function generate(prompt, seed, img) {
const res = await fetch("http://localhost:8000/generate", {
method: "POST",
headers: { "Content-Type": "application/json" },
body: JSON.stringify({ prompt, seed }),
});
if (!res.ok) throw new Error(`Generation failed: ${res.status}`);
if (img.src.startsWith("blob:")) URL.revokeObjectURL(img.src);
img.src = URL.createObjectURL(await res.blob());
}
图像生成需要数秒而非数毫秒。请显示加载状态,在请求进行期间禁用提交按钮;如果允许用户取消操作,还应传入 AbortController 的 signal。在将生成的 PNG 图像提供给真实访客之前,可以使用 OpenReplay 图像压缩工具对其进行压缩。
后续步骤
只要在正确的设备上加载好 pipeline,使用 Diffusers 所需的代码就非常少:一个模型 id、一个 dtype、一个提示词和一个种子。先用 SDXL 生成第一张图像,固定种子后每次只调整一个参数。如果显存不足,就按顺序逐步尝试卸载和量化方案。然后将 FastAPI 接口接入你的前端。在此基础上,显存优化指南和 Schedulers 指南涵盖了面向生产环境调优时会遇到的各种权衡。
常见问题
Diffusers 将下载的模型权重存储在哪里?
from_pretrained() 会将模型文件保存在 Hugging Face Hub 缓存中,并在后续运行时复用,不会重复下载。缓存默认位于 ~/.cache/huggingface/hub。设置 HF_HUB_CACHE 环境变量可以仅迁移模型缓存;设置 HF_HOME 则会迁移所有 Hugging Face 数据,此时缓存位于 HF_HOME/hub。你也可以传入 cache_dir 参数,为单次加载指定存储位置。
为什么相同的种子在另一台机器上会生成不同的图像?
只有在相同硬件和相同 PyTorch 版本下,种子才能完全复现同一张图像。CUDA GPU 使用的随机数生成器与 CPU 不同,而且 GPU 矩阵乘法的确定性较低。Diffusers 可复现性指南建议在需要结果一致时传入 CPU generator,而 torch.Generator() 默认创建的正是 CPU generator。即便如此,它也无法保证在不同 GPU 型号或不同 PyTorch 版本之间输出完全相同。
4-bit bitsandbytes 量化能在 Apple Silicon Mac 上使用吗?
可以,前提是使用较新的版本。Diffusers 在 v0.39.0 中新增了对 MPS 上 bitsandbytes 量化的支持,而 bitsandbytes 0.50.0 使其所有 4-bit 和 LLM.int8() 配置都能在 MPS 上运行。bitsandbytes 的 MPS 路径需要 PyTorch 2.9 或更高版本,高于 Diffusers 所要求的 PyTorch 2.6 最低版本。在 macOS 26 及更高版本上,安装 kernels 包即可启用更快的 Metal 内核。
Gain Debugging Superpowers
Unleash the power of session replay to reproduce bugs, track slowdowns and uncover frustrations in your app. Get complete visibility into your frontend with OpenReplay — the most advanced open-source session replay tool for developers.
Star on GitHub12k