Primeiros passos com o Hugging Face Diffusers
Configure o Hugging Face Diffusers com SDXL, gere imagens, ajuste parâmetros, economize memória da GPU e crie um endpoint FastAPI para seu app JavaScript.
O Hugging Face Diffusers é uma biblioteca Python para executar modelos de difusão de imagem, vídeo e áudio no seu próprio hardware. Ela reúne o text encoder, o scheduler, a rede de denoising e o VAE em um único objeto de pipeline, que você chama passando um prompt.
APIs hospedadas de geração de imagens são fáceis para começar. Depois chegam as cobranças por imagem, os rate limits deixam seu protótipo lento e você passa a querer entender o que o modelo realmente está fazendo. Executar o modelo localmente resolve os três problemas, mas a maioria dos tutoriais pressupõe que você já conhece PyTorch.
Este guia foi escrito para desenvolvedores JavaScript. Ele leva você da instalação até a primeira imagem, explica as configurações que importam, mostra como fazer o modelo caber em GPUs menores e termina com um endpoint FastAPI que o seu frontend chama com fetch(). Os exemplos usam o Diffusers v0.42.1.
Principais pontos
- Carregue o
stabilityai/stable-diffusion-xl-base-1.0comDiffusionPipeline.from_pretrained(..., dtype=torch.float16)e mova-o para"cuda"em GPUs NVIDIA ou para"mps"em Apple Silicon. - O SDXL base 1.0 é distribuído sob a CreativeML Open RAIL++-M License. Leia-a antes de publicar imagens geradas.
- Um
torch.Generatorcom seed fixa torna os resultados reproduzíveis, para que você altere uma configuração por vez e veja o efeito. - Se o modelo não couber na memória da GPU, chame
enable_model_cpu_offload()primeiro. A documentação do Diffusers descreve o CPU offload sequencial como extremamente lento. - Carregue o pipeline uma única vez na inicialização do servidor e reutilize-o em todas as requisições. Nunca o carregue dentro de um handler de requisição.
O que é o Hugging Face Diffusers?
O Diffusers é a biblioteca da Hugging Face para modelos de difusão. Sua abstração central é o DiffusionPipeline, que agrupa os componentes de que um modelo precisa:
- um ou mais text encoders que transformam o prompt em embeddings
- um scheduler que controla o algoritmo de denoising
- uma UNet ou um diffusion transformer que prevê o ruído em cada passo
- um VAE que decodifica o resultado em pixels
Se você ainda não conhece o Hub, os Inference Providers ou os Spaces, leia primeiro A Quick Guide to Hugging Face for Developers. Se você quer inferência sem nenhum backend em Python, o Transformers.js executa modelos diretamente no navegador, embora cubra um conjunto diferente de modelos.
De qual hardware o Diffusers precisa?
O Diffusers roda em três tipos de máquina. Uma GPU NVIDIA é, de longe, a opção mais rápida; um Mac com Apple Silicon funciona por meio do backend "mps" do PyTorch; e uma CPU comum funciona, mas é muito lenta.
| Hardware | String de dispositivo | dtype | O que esperar |
|---|---|---|---|
| GPU NVIDIA | "cuda" | torch.float16 | Rápido |
| Mac com Apple Silicon | "mps" | torch.float16 | Funciona, mais lento que uma GPU NVIDIA dedicada |
| Apenas CPU | "cpu" | torch.float32 | Funciona, muito lento |
O Quickstart lista "cuda", "mps", "xpu" e "cpu" como dispositivos de destino. O Diffusers também tem um guia dedicado para Apple Silicon (MPS). Este helper escolhe o dispositivo e o dtype corretos para a máquina atual:
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
Instale o Diffusers e gere a primeira imagem
Gerar a primeira imagem com o Hugging Face Diffusers leva três passos: instalar o Diffusers com o PyTorch, carregar o SDXL e, em seguida, chamar o pipeline com um prompt e salvar .images[0].
Desde a v0.42.0, o Diffusers exige Python 3.11 ou mais recente e é testado com PyTorch 2.6 ou mais recente. Siga o guia de instalação para configurar um ambiente virtual e depois instale os pacotes. Os text encoders do SDXL são modelos CLIP da biblioteca Transformers, então instale-a também:
uv pip install "diffusers[torch]>=0.42.1" transformers
# or: pip install "diffusers[torch]>=0.42.1" transformers
Usando o device e o dtype do helper acima, gere uma imagem:
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 é uma imagem PIL, então .save() grava um PNG em disco. O id do modelo é o nome completo do checkpoint no Hub, incluindo o prefixo da organização stabilityai/.
Licença: o SDXL base 1.0 é distribuído sob a CreativeML Open RAIL++-M License. Leia-a antes de usar imagens geradas em um produto e verifique a licença de qualquer outro modelo que você venha a usar no lugar dele.
Quais configurações do SDXL importam mais?
Quatro argumentos do pipeline do SDXL controlam a maior parte do que você vê no resultado: num_inference_steps, guidance_scale, generator e height / width. Fixe a seed primeiro e depois altere um argumento por vez.
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_stepsdefine quantas passagens de denoising são executadas. Mais passos levam mais tempo e geralmente acrescentam detalhes, até que os ganhos se estabilizem.guidance_scaledefine o quanto o modelo segue o prompt à risca. Valores mais altos ficam mais fiéis ao texto, e valores altos demais podem deixar a imagem com aspecto exagerado e supersaturado.generatorfixa o ruído inicial. Com o mesmo modelo, as mesmas configurações e o mesmo hardware, um generator com seed fixa produz a mesma imagem novamente.height/widthdefinem o tamanho da saída em pixels. Imagens maiores exigem mais memória e mais tempo.
A referência do pipeline SDXL lista todos os argumentos com seus valores padrão.
Troque o scheduler
O scheduler decide como o ruído é removido a cada passo, e schedulers diferentes oferecem diferentes equilíbrios entre velocidade e qualidade. Substitua-o em um pipeline já carregado com from_config(), passando a configuração existente para que os parâmetros compatíveis com o checkpoint continuem alinhados:
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]
O guia de Schedulers usa exatamente esse padrão com o SDXL. A referência do DPMSolverMultistepScheduler afirma que ele produz amostras de alta qualidade em cerca de 20 passos. Mantenha a seed fixa ao comparar schedulers, para que o scheduler seja a única diferença entre as duas imagens.
Como fazer o SDXL caber em GPUs menores?
Se o SDXL apresentar erros de falta de memória (out-of-memory), experimente estas quatro soluções de memória do Diffusers, nesta ordem: model CPU offload, VAE tiling, VAE slicing e quantização em 4 bits. Cada passo economiza mais memória e custa mais velocidade.
- Model CPU offload. Omita o
.to(device)e chamepipeline.enable_model_cpu_offload(). Cada modelo inteiro fica na GPU apenas enquanto está sendo executado. - VAE tiling.
pipeline.vae.enable_tiling()decodifica imagens grandes em blocos (tiles). O guia de memória observa que isso pode causar uma leve variação de tonalidade entre os blocos. - VAE slicing.
pipeline.vae.enable_slicing()decodifica um lote uma imagem por vez. Só ajuda quando você gera várias imagens em uma única chamada. - Quantização em 4 bits. Instale o
bitsandbytese adicione uma configuração curta:
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()
A visão geral de quantização documenta o PipelineQuantizationConfig e seus backends. O Diffusers adicionou a quantização com bitsandbytes no MPS na v0.39.0, então essa abordagem não se limita ao CUDA. No Apple Silicon, o bitsandbytes exige PyTorch 2.9 ou mais recente, versão superior ao PyTorch 2.6 mencionado acima como base.
Evite enable_sequential_cpu_offload(), a menos que nada mais funcione. Ele é o que mais economiza memória, mas o guia de memória o descreve como extremamente lento. Além disso, um pipeline carregado com device_map precisa chamar reset_device_map() antes de você usar .to() ou qualquer um dos métodos de offload.
Chamando o Hugging Face Diffusers a partir de uma aplicação web
Para usar o Diffusers a partir de um frontend, encapsule o pipeline em um pequeno servidor HTTP. O servidor deve carregar o modelo uma única vez na inicialização e retornar os bytes do PNG. Instale fastapi e uvicorn e salve o código abaixo como 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")
Execute-o com uvicorn main:app. O código se apoia em três recursos do FastAPI:
- O lifespan handler carrega o modelo uma única vez, antes de o servidor aceitar qualquer requisição. O
from_pretrained()é lento demais para ser chamado a cada requisição. - Como
generateé umdefcomum, o FastAPI o executa em um threadpool em vez de bloquear o event loop. - O lock faz com que as requisições usem a GPU uma de cada vez.
O CORSMiddleware permite que a origem do seu frontend de desenvolvimento chame o endpoint.
No frontend, use fetch() para requisitar a imagem, leia o corpo da resposta como um Blob e exiba-o com 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());
}
A geração leva segundos, não milissegundos. Exiba um estado de carregamento, desabilite o botão de envio enquanto uma requisição estiver em andamento e passe o signal de um AbortController se os usuários puderem cancelar. Antes de servir os PNGs gerados para visitantes reais, reduza o tamanho deles com o compressor de imagens do OpenReplay.
Próximos passos
Depois que o pipeline está carregado no dispositivo certo, o Diffusers exige muito pouco código: um id de modelo, um dtype, um prompt e uma seed. Gere uma primeira imagem com o SDXL, fixe a seed e ajuste uma configuração por vez. Se faltar memória, siga os passos de offload e quantização na ordem. Depois, coloque o endpoint FastAPI por trás do seu frontend. A partir daí, o guia de memória e o guia de Schedulers abordam os trade-offs que surgem quando você faz o ajuste fino para produção.
Perguntas frequentes
Onde o Diffusers armazena os pesos dos modelos baixados?
O from_pretrained() salva os arquivos do modelo no cache do Hugging Face Hub e os reutiliza nas execuções seguintes, sem baixá-los novamente. Por padrão, o cache fica em ~/.cache/huggingface/hub. Defina a variável de ambiente HF_HUB_CACHE para mover apenas o cache de modelos. Defina HF_HOME para mover todos os dados da Hugging Face, o que coloca o cache em HF_HOME/hub. Você também pode passar o argumento cache_dir para escolher um local para um carregamento específico.
Por que a mesma seed gera uma imagem diferente em outra máquina?
Uma seed só reproduz uma imagem com total fidelidade no mesmo hardware e com a mesma versão do PyTorch. GPUs CUDA usam um gerador de números aleatórios diferente do das CPUs, e a multiplicação de matrizes na GPU é menos determinística. O guia de reprodutibilidade do Diffusers recomenda passar um generator de CPU quando os resultados precisam ser idênticos, que é o que o torch.Generator() cria por padrão. Mesmo assim, não há garantia de saída idêntica entre modelos de GPU ou versões do PyTorch diferentes.
A quantização em 4 bits com bitsandbytes funciona em um Mac com Apple Silicon?
Sim, com versões recentes. O Diffusers adicionou a quantização com bitsandbytes no MPS na v0.39.0, e o bitsandbytes 0.50.0 fez todas as suas configurações de 4 bits e LLM.int8() funcionarem no MPS. O suporte do bitsandbytes ao MPS exige PyTorch 2.9 ou mais recente, versão superior ao mínimo de PyTorch 2.6 do Diffusers. No macOS 26 e posteriores, instalar o pacote kernels habilita kernels Metal mais rápidos.
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