Como montar um pipeline de imagem no Gradio Workflow sem escrever nó customizado

Diagrama de pipeline de imagem montado no Gradio Workflow com nós de fn, model e dataset
Resposta rápida

O Gradio Workflow é um construtor visual de pipelines por nós já embutido no Gradio, sem pacote separado pra instalar. Todo grafo tem references (entradas), operators (o trabalho) e subjects (saídas), e os operadores vêm em quatro tipos: fn, model, space e dataset. Com isso dá pra montar texto-para-imagem mais pós-processamento sem escrever nó customizado: suas funções Python entram por bind=, as ligações por edges=, e o deploy sai com gradio deploy. Nós na mesma profundidade de dependência rodam em paralelo, e boa parte do canvas funciona sem chamada de rede

Fala aí, beleza? A Hugging Face publicou o Workflow1111, uma remontagem da maior parte do AUTOMATIC1111 em um único canvas de nós, e a parte insana é que dá pra fazer isso sem escrever nenhum nó customizado 🙂

A promessa deste guia é bem direta: montar um pipeline de texto-para-imagem com pós-processamento usando só os operadores nativos do gr.Workflow, testar local e publicar num Space no mesmo dia

Antes de tudo, o mais importante: o gr.Workflow é built-in no Gradio, não é pacote separado. Ele é um construtor visual de pipelines de IA baseado em nós, que encadeia Spaces, modelos, datasets e funções Python num canvas de arrastar e soltar

A referência que vou usar o post inteiro é o Workflow1111, publicado no blog da Hugging Face em 10 de setembro de 2026: onze pipelines de mídia construídos com setenta e três nós

Completão, né? Bora entender a mecânica

O que você precisa antes de abrir o canvas

A lista é curta, e é de propósito:

  • Gradio instalado, e só isso do lado da lib: o gr.Workflow vem embutido
  • Conta Hugging Face gratuita pra publicar o app em Spaces
  • Login HF ou access token pra rodar os nós model: depois do login, as chamadas de modelo consomem a quota do próprio usuário
  • requirements.txt na raiz do repositório do Space pras dependências Python (e packages.txt se você precisar de dependência Debian)
  • Atenção ao sdk_version no README.md: num Space o pacote gradio já vem pré-instalado, e é esse campo que define a versão dele
Formação Claude Code
Formação Recomendada

Formação Claude Code

Domine Claude Code do absoluto zero até o avançado

  • 120 aulas
  • 4 projetos
  • 9h 45min

E tem um detalhe que derruba muita gente no primeiro arquivo: o gr.Workflow já é um app Gradio completo

Ou seja, ele precisa ser criado no nível superior do arquivo

Não dá pra aninhar dentro de um contexto gr.Blocks como se fosse um componente qualquer. Tome cuidado com isso, é o tipo de erro que só aparece na hora de subir

Passo a passo: montando o grafo no gr.Workflow

  1. Entenda a anatomia do grafo antes de arrastar qualquer coisa

Todo workflow é um grafo com três tipos de nó: references (as entradas), operators (as etapas que executam trabalho) e subjects (as saídas)

O arquivo de workflow é um JSON com essas três coleções. Um nó operator traz campos como id, label, role ("operator"), kind, model_id, endpoint, pipeline_tag e as especificações de entrada e saída

E o kind é o que define o comportamento do operador:

kind O que é Quando usar
fn Uma função Python Preparar prompt, tratar imagem, montar contact sheet
model Um modelo chamado via InferenceClient (Inference Providers) Texto-para-imagem, LLM, VLM, classificador
space Outro Gradio Space Reaproveitar um app que já existe no Hub
dataset Uma linha de um dataset do Hub Puxar exemplos e dados prontos

O erro comum deste passo: tratar entrada e saída como se fossem a mesma coisa. O label do subject não é enfeite, ele vira o nome do endpoint lá na frente

  1. Escreva as funções Python e passe em bind=

Aqui entram os dois fn do nosso pipeline mínimo: um prompt-builder na entrada e um pós-processamento na saída. É exatamente o desenho do txt2img do Workflow1111, que vai de um nó fn de prompt-builder pro nó model do checkpoint e termina num nó fn de pós-processamento que grava os parâmetros de geração nos metadados do PNG

import gradio as gr

def prompt_builder(prompt: str, estilo: str, steps: int, hires: bool):
    texto = f"{prompt.strip()}, {estilo}"
    return texto, steps, hires

def pos_processo(imagem, prompt: str, steps: int):
    # aqui você grava metadados, redimensiona, o que for
    return imagem

Você passa essas funções pelo parâmetro bind= e elas viram nós chamáveis no canvas. O Gradio inspeciona a assinatura da função e gera as portas de entrada e saída automaticamente

E presta atenção na inferência de tipo, porque é ela que decide o campo que aparece no canvas:

  • int ou float viram porta number
  • bool vira boolean
  • string, parâmetro sem anotação e outras anotações caem em text

O erro comum deste passo: deixar o parâmetro sem anotação e depois estranhar que o seu "steps" virou campo de texto. Anota o tipo, é de graça 😀

  1. Adicione o nó model do checkpoint

Esse é o miolo: o nó model chama o checkpoint via Inference Providers, e o checkpoint é escolhido pelo campo model_id

No Workflow1111 os controles desse pipeline espelham a aba txt2img do A1111: negative prompt, steps, CFG, seed, width, height e o tal campo model_id

Uma mudança recente do canvas ajuda bastante aqui: a partir de @gradio/[email protected], o gr.Workflow passou a criar automaticamente os nós de input e output pros nós model. Na mesma versão, os botões Input e Output viraram um único botão Component, e o antigo "Data" foi renomeado pra "Dataset"

O erro comum deste passo: sair criando nó de entrada e saída na mão pro model e acabar com nó duplicado pendurado no canvas

  1. Ligue as portas declarando edges

As portas são tipadas, e os tipos suportados incluem image, audio, video, text, number, boolean, gallery, file, json, model3d e any

As ligações entre nós são declaradas pelo parâmetro edges, usando os nomes dos nós. O exemplo oficial é esse:

gr.Workflow(bind=[clean, tag], edges=[("clean", "tag")]).launch()

Mesma ideia no nosso grafo, ligando o prompt-builder ao pós-processamento no fim da cadeia:

app = gr.Workflow(
    bind=[prompt_builder, pos_processo],
    edges=[("prompt_builder", "pos_processo")],
)
app.launch()

O erro comum deste passo: errar o nome do nó dentro da tupla ou tentar plugar uma saída image numa porta text. Porta tipada é chata no começo e salva a sua pele depois

  1. Teste as funções fn direto no Python

Como os nós fn são funções Python comuns, dá pra testá-los diretamente, sem canvas, sem servidor e sem GPU

print(prompt_builder("um farol na tempestade", "cinematic", 30, False))

O erro comum deste passo: subir o Space pra descobrir que o prompt-builder estava concatenando errado. Roda a função, é um segundo

  1. Publique com gradio deploy

No diretório do app, com conta Hugging Face gratuita, roda:

gradio deploy

A CLI coleta os metadados básicos e envia os arquivos

Se você prefere o caminho manual, dá pra clonar o Space com git clone, criar o app.py e mandar com git add, git commit e git push

O erro comum deste passo: esquecer o requirements.txt na raiz, ou tentar instalar dependência de sistema por lá. Dependência Python vai no requirements.txt, dependência Debian vai no packages.txt

Até onde dá para ir sem nó customizado

Agora a pergunta que interessa: quanta coisa os quatro kinds resolvem sozinhos? O Workflow1111 é a prova

Um nó model servindo dois recursos. O hi-resolution fix e o image-to-image usam o mesmo nó model de FLUX.1-Kontext: no hi-res ele recebe uma instrução de refinamento, no image-to-image ele faz o papel da aba de edição

LLM e difusão no mesmo canvas. Tem um pipeline que manda um prompt cru pra um nó model de Qwen3-4B e um nó fn transforma a resposta numa lista de tags limitada a quarenta. Não tem nó customizado envolvido, diferente do ComfyUI: o LLM e o modelo de difusão são operadores model comuns, lado a lado

Dois modelos olhando a mesma imagem. No pipeline de interrogate, o nó model de Qwen2.5-VL e o classificador ViT recebem a mesma entrada de imagem, e nenhum dos dois é nó customizado: são operadores model normais pendurados na mesma entrada

Space como peça de LEGO. O upscale AuraSR x4 é um nó space, e a remoção de fundo com BRIA RMBG-2.0 é outro nó space. O modelo mora no Space dele e o seu canvas só chama

Anotador sem modelo atrás. Canny, line art, sketch, luma-depth e posterize, aquilo que normalmente viria da extensão ControlNet, são nós fn escritos em NumPy puro. Na foto de exemplo pré-carregada, cada anotador leva cerca de meio segundo em CPU

E se você precisar rodar um modelo dentro do próprio Space em GPU, o nó fn aguenta o tranco: ele é Python comum, então dá pra decorar a função ligada com @spaces.GPU

Repara na diferença de escopo, porque isso confunde: o nó model chama o modelo via Inference Providers, ou seja, fora do seu Space, e não exige GPU sua. O @spaces.GPU só entra no caso oposto, quando é você que quer rodar o modelo dentro do seu fn

Paralelismo por profundidade: por que não existe operador de loop

O gr.Workflow não tem operador de loop

Parece limitação, mas é a regra de execução que resolve: operadores na mesma profundidade de dependência rodam em paralelo quando o workflow é executado no canvas interativo

Como montar pensando nisso:

  1. Mapeie quem depende de quem. Profundidade aqui é distância de dependência, não posição na tela
  2. Pendure os irmãos na mesma entrada. É o caso do interrogate que eu citei ali em cima: Qwen2.5-VL e classificador ViT recebem a mesma imagem, então o gr.Workflow roda os dois em paralelo e as duas respostas chegam em aproximadamente o tempo de uma
  3. Troque o loop por nós lado a lado. No prompt matrix do Workflow1111, os quatro nós de texto-para-imagem ficam lado a lado no canvas e, por estarem na mesma profundidade de dependência, geram as quatro imagens ao mesmo tempo

O erro comum deste passo: tentar simular loop encadeando os nós em série, um alimentando o próximo. Aí a profundidade cresce a cada nó e você perde justamente o paralelismo que faria o grafo voar

O que continua funcionando sem chamada de rede

Essa é a parte que eu acho mais massa do desenho

No Workflow1111 são 36 nós operadores no app. Desses, 32 são nós fn, e 22 rodam inteiramente in-process, sem nenhuma chamada de rede

Na prática, cerca de dois terços do canvas continua funcionando se você perder a conexão

Dá pra ver a fronteira nos próprios pipelines:

  • Upscale: o primeiro upscaler é um resample Lanczos local num nó fn, sem chamada de rede. O segundo é o AuraSR x4, primeiro nó space do canvas
  • Detecção para máscara de inpaint: só a chamada de detecção (DETR) sai da máquina. O desenho das caixas e a criação da máscara acontecem localmente com Pillow e NumPy

E volta pro ponto do passo 5: como esses fn são funções Python comuns, você testa cada um direto, sem canvas, servidor ou GPU. Isso muda o jogo do debug

Expondo o pipeline como API REST e ferramenta MCP

Publicou, e agora?

Todo app Workflow expõe seus pipelines conectados pela API REST padrão do Gradio. Cada pipeline desconectado que tenha um ou mais nós de saída ganha um endpoint, e o nome dele deriva do label do primeiro subject

Ou seja, um subject chamado "Output Image" vira o endpoint /output_image. Lembra que eu falei que o label não era enfeite? Pois é 🙂

De referência: o Workflow1111 expõe nove endpoints REST

A execução de subgrafos pela API, cada subgrafo exposto como endpoint nomeado, está presente a partir de @gradio/[email protected]

Com endpoint na mão, o pipeline vira peça de uma automação maior, e aí vale o mesmo cuidado de quem faz monitoramento de workflows no n8n: saber qual etapa quebrou vale mais que saber que "deu erro"

Se você gosta de acompanhar número, o caminho é o mesmo de montar painéis de métricas customizados em cima das execuções, só que consumindo os endpoints do seu Space

E pra expor esses endpoints como ferramentas MCP, são duas coisas: o decorador @app.mcp.tool() e o mcp_server=True no launch

app.launch(mcp_server=True)

Detalhe útil: @app.mcp.tool() e @app.api() são independentes e podem ser empilhados, então o mesmo pipeline serve API e agente

Vídeo: pipeline montado na prática

Pra quem está começando do zero na ideia de montar um pipeline com ferramentas de IA, este vídeo do canal mostra o fluxo do desenho até o código, com o Stitch desenhando e o Claude Code construindo

Conclusão: duplique, religue, publique

Recapitulando o caminho: o gr.Workflow é built-in no Gradio, o grafo tem references, operators e subjects, os operadores vêm em quatro kinds (fn, model, space, dataset), suas funções entram por bind=, as ligações por edges= e a publicação sai com gradio deploy

Com isso já dá pra montar o pipeline mínimo: prompt-builder em fn, checkpoint em model, pós-processamento em fn, saída como subject

Se você quiser começar pelo caminho curto, o Workflow1111 pode ser duplicado como Space e reconectado pro seu caso de uso. Lembrando que, pra rodar os pipelines dele, é preciso entrar com a conta Hugging Face ou fornecer um access token, e as chamadas de modelo consomem a quota do próprio usuário

Uma nota de contexto pra fechar: a biblioteca Daggr foi descontinuada em favor do gr.Workflow, e o repositório está arquivado em modo somente leitura

Então o caminho atual é o que a gente montou aqui, direto no Gradio

Bora testar? até o próximo post!

Perguntas frequentes

Dá pra usar o gr.Workflow sem escrever nenhum nó customizado, mesmo em um pipeline de imagem completo?

Dá sim, e é exatamente esse o ponto do Workflow1111: onze pipelines de mídia inteiros montados com setenta e três nós, todos usando só os kinds nativos fn, model, space e dataset. O próprio pipeline de texto-para-imagem segue essa regra, com um fn de prompt-builder, um model pro checkpoint e um fn de pós-processamento no final.

Por que meu campo de steps aparece como texto em vez de número no canvas do gr.Workflow?

Porque a inferência de tipo depende da anotação do parâmetro na função Python ligada com bind=. int ou float viram porta number e bool vira boolean, mas string, parâmetro sem anotação e qualquer outra anotação caem em text. Anotar o tipo na assinatura resolve isso na hora.

É possível rodar dois nós model ao mesmo tempo pra ganhar velocidade no gr.Workflow?

Sim, contanto que os dois estejam na mesma profundidade de dependência do grafo: o gr.Workflow executa em paralelo os operadores desse mesmo nível quando o workflow roda no canvas interativo. Encadear os nós em série faz a profundidade crescer a cada etapa, e aí você perde justamente esse paralelismo.

O gr.Workflow tem operador de loop pra gerar várias imagens de uma vez, tipo um prompt matrix?

Não, o gr.Workflow não tem operador de loop. A saída é deixar os nós de geração lado a lado, pendurados na mesma entrada: como ficam na mesma profundidade de dependência, o gr.Workflow executa todos em paralelo em vez de um depois do outro.

Preciso pagar alguma coisa ou ter GPU própria pra rodar os nós model do Workflow1111?

Não precisa de GPU própria pros nós model, porque eles chamam o modelo via Inference Providers, fora do seu Space. O que é preciso é entrar com conta Hugging Face ou fornecer um access token: depois do login, as chamadas de modelo consomem a quota do próprio usuário.

Dá pra testar os nós fn do gr.Workflow antes de montar o canvas inteiro?

Dá, e é uma das vantagens de usar fn: como são funções Python comuns, testá-las direto no Python funciona sem canvas, sem servidor e sem GPU. Isso ajuda a validar prompt_builder e pos_processo isoladamente antes de plugar tudo com edges.




Escrito por | Matheus Battisti

Matheus Battisti
Fundador da Hora de Codar

Programador apaixonado pelo mundo das tecnologias, sempre buscando em aprender e se aprofundar em linguagens, frameworks e o que mais for necessário para executar um bom trabalho. Agora tem uma nova missão que é de passar seu conhecimento adiante para formar novos programadores e especializar mais os que já são.

Subscribe
Notify of
guest

0 Comentários
Oldest
Newest Most Voted

Formações

Formação Vibe Coding

Formação Vibe Coding

Do Prompt ao Produto: Crie Software Real com IA

  • 474 aulas
  • 20 projetos
  • 39h 27min

Blog | Mais populares