""" Workflow1111 · a Diffusion Studio built entirely from `gr.Workflow` ================================================================== An Automatic1111-shaped image studio expressed as **one canvas graph** instead of a tabbed UI — 64 nodes across 10 pipelines, every one of them runnable on its own. python apps/05_workflow1111/app.py What's on the canvas -------------------- 1 txt2img prompt/style builders → FLUX.1-schnell → post-processing with the real control surface: negative prompt, steps, CFG, seed, and size presets 2 Hires fix the txt2img result re-rendered through FLUX.1-Kontext 3 img2img upload an image, edit it by instruction 4 Prompt magic an LLM writes a prompt from a rough idea 5 Interrogate recover a prompt from an image (VLM) + classify it (ViT) 6 Detect & mask DETR boxes → annotated preview → inpainting mask 7 Prompt matrix four variants rendered in parallel into an X/Y grid 8 Extras local upscale, AuraSR ×4, background removal 9 Annotators Canny / line art / sketch / luma-depth previews 10 PNG Info read generation parameters back out of a file Why it is shaped like this -------------------------- `gr.Workflow` raises if constructed inside a `gr.Blocks` context, so an app like this genuinely cannot be tabs — the graph *is* the UI. Each output ("subject") is independently runnable and is also published as an API endpoint, which is the closest analogue to A1111's tabs. Four design rules came out of probing gradio 6.22 / huggingface_hub 1.26 directly, and the app depends on all four (details in `nodes.py` and README): • A `model` node's ports get rewritten to the endpoint's canonical schema the moment a browser loads the graph — and the file is saved back that way. So anything needing a richer control surface than the schema (`txt2img`, `chat_llm`, `interrogate`) is an `fn` node calling `InferenceClient` itself. `build_workflow.py` refuses to build if a `model` node's ports ever diverge from its schema again. • `fn` nodes emit images as ``{"path": , "url": }``. The REST endpoint's `gr.Image` component needs a real file (a bare ``data:`` URI is read as a *filename*); the canvas and a chained `model` node need the URI. Both keys, one value. • A `model` image output is never wired straight into another `model`'s image port; `prep_image` sits between them (gradio would otherwise hand the provider an unresolvable ``/gradio_api/file=`` path). • `space` nodes only ever take an *uploaded* image. 19 of the 26 `fn` nodes are pure local Pillow/numpy — no token, no quota, no network — so most of the app keeps working even when a provider is having a bad day. 13 nodes in total leave the machine. Setup ----- hf auth login # or: set HF_TOKEN=hf_xxx pip install -r apps/05_workflow1111/requirements.txt Tests (no network, ~2s): python apps/05_workflow1111/test_nodes.py Live pipelines (hits HF): python apps/05_workflow1111/test_pipelines.py REST endpoints: python apps/05_workflow1111/test_api.py Regenerate the graph: python apps/05_workflow1111/build_workflow.py Deploy to a Space: python apps/05_workflow1111/deploy_space.py --push """ import os import sys import gradio as gr sys.path.insert(0, os.path.dirname(os.path.abspath(__file__))) import nodes # noqa: E402 HERE = os.path.dirname(os.path.abspath(__file__)) WORKFLOW = os.path.join(HERE, "workflow.json") if not os.path.exists(WORKFLOW): raise SystemExit( f"{WORKFLOW} is missing.\n" "Generate it with: python apps/05_workflow1111/build_workflow.py" ) demo = gr.Workflow(WORKFLOW, bind=nodes.BIND) if __name__ == "__main__": from huggingface_hub import get_token if not (get_token() or os.environ.get("HF_TOKEN")): print( "\n ⚠ No Hugging Face token found.\n" " The 19 local `fn` nodes (post-processing, annotators, masks,\n" " contact sheet, PNG info) work regardless, but every `model`\n" " and `space` node will fail until you run `hf auth login`,\n" " set HF_TOKEN, or sign in from inside the app.\n" ) demo.launch()