Spaces:
Running
Running
Download app.py from ysharma/Workflow1111: direct link, hf CLI and curl.
- Browser
- Download file 5.54 kB
-
https://huggingface.co/spaces/ysharma/Workflow1111/resolve/main/app.py
- Command line
-
hf download hf://spaces/ysharma/Workflow1111/app.py
-
curl -L -o app.py https://huggingface.co/spaces/ysharma/Workflow1111/resolve/main/app.py
5.54 kB
| """ | |
| Workflow1111 Β· a Diffusion Studio built entirely from `gr.Workflow` | |
| ================================================================== | |
| An Automatic1111-shaped image studio expressed as **one canvas graph** instead | |
| of a tabbed UI β 73 nodes across 11 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 | |
| 11 img2video that same PNG animated into a ~3s clip by Wan 2.2 I2V | |
| A14B on Inference Providers, with a motion/camera prompt | |
| builder and real length/steps/guidance/seed/resolution | |
| 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. | |
| Five design rules came out of probing gradio 6.22 / huggingface_hub 1.26 | |
| directly, and the app depends on all five (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`, `img2video`) 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": <file>, "url": <data: URI>}``. 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. | |
| β’ Video is the exception to that: `_emit_video` returns | |
| ``{"path", "url": "/gradio_api/file=β¦", "is_file": True}`` β gradio's own | |
| `_save_tmp` shape β because an mp4 is megabytes and base64-inlining one | |
| into the graph value would bloat every canvas update carrying it. | |
| β’ 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. | |
| 22 of the 32 `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. 14 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 | |
| # API/MCP callers authenticate per request with an `X-HF-Token` header (see | |
| # `nodes._hf_token`). The four `model`/`space` nodes are run by gradio itself, | |
| # whose `gradio.workflow._resolve_token` only knows OAuth sessions and the local | |
| # write-token β so extend it here to fall back to the caller's header token. | |
| import gradio.workflow as _gw # noqa: E402 | |
| _orig_resolve_token = _gw._resolve_token | |
| def _resolve_token_with_header(data, idx, token, request=None): | |
| return _orig_resolve_token(data, idx, token, request) or nodes._caller_hf_token(request) | |
| _gw._resolve_token = _resolve_token_with_header | |
| 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(mcp_server=True) | |