12k
All articles

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.

OpenReplay Team
OpenReplay Team
Primeiros passos com o Hugging Face Diffusers

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.0 com DiffusionPipeline.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.Generator com 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.

HardwareString de dispositivodtypeO que esperar
GPU NVIDIA"cuda"torch.float16Rápido
Mac com Apple Silicon"mps"torch.float16Funciona, mais lento que uma GPU NVIDIA dedicada
Apenas CPU"cpu"torch.float32Funciona, 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_steps define quantas passagens de denoising são executadas. Mais passos levam mais tempo e geralmente acrescentam detalhes, até que os ganhos se estabilizem.
  • guidance_scale define 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.
  • generator fixa 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 / width definem 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.

  1. Model CPU offload. Omita o .to(device) e chame pipeline.enable_model_cpu_offload(). Cada modelo inteiro fica na GPU apenas enquanto está sendo executado.
  2. 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.
  3. 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.
  4. Quantização em 4 bits. Instale o bitsandbytes e 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 é um def comum, 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.

DevTools for the frontend

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

We use cookies to improve your experience. By using our site, you accept cookies.