diff --git a/.changeset/shaggy-rules-reply.md b/.changeset/shaggy-rules-reply.md new file mode 100644 index 00000000000..f3a8aefba09 --- /dev/null +++ b/.changeset/shaggy-rules-reply.md @@ -0,0 +1,6 @@ +--- +"@gradio/workflowcanvas": minor +"gradio": minor +--- + +feat:workflow: add getting started templates diff --git a/gradio/_workflow_curated_snapshot.json b/gradio/_workflow_curated_snapshot.json index 858b2e11b08..fb3bcc2ca40 100644 --- a/gradio/_workflow_curated_snapshot.json +++ b/gradio/_workflow_curated_snapshot.json @@ -1,6 +1,6 @@ { - "snapshot_version": 1, - "fetched_at": "2026-06-09T00:00:00Z", + "snapshot_version": 2, + "fetched_at": "2026-07-20T13:23:24.328983Z", "items": [ { "kind": "space", @@ -8,17 +8,31 @@ "task": "text-to-image", "space_category": "image-generation", "modality": "image", - "title": "FLUX.1 schnell", - "description": "Fast, high-quality text-to-image", + "title": "FLUX.1 [Schnell]", + "description": "", "added_at": "2026-04-01T00:00:00Z", "featured": true, "zero_gpu": true, - "smoke_inputs": { "prompt": "a small red square" }, + "smoke_inputs": { + "prompt": "a small red square" + }, + "validation": { + "status": "ok", + "last_checked": null + } + }, + { + "kind": "model", + "id": "black-forest-labs/FLUX.1-schnell", + "task": "text-to-image", + "modality": "image", + "title": "FLUX.1 schnell", + "description": "", + "added_at": "2026-04-01T00:00:00Z", + "featured": true, "validation": { - "last_checked": "2026-06-08T03:14:00Z", "status": "ok", - "latency_ms": 1800, - "error": null + "last_checked": null } }, { @@ -28,16 +42,154 @@ "space_category": "image-generation", "modality": "image", "title": "Stable Diffusion 3.5 Large", - "description": "High-fidelity text-to-image", + "description": "Generate images with SD3.5", "added_at": "2026-04-01T00:00:00Z", "featured": true, "zero_gpu": true, - "smoke_inputs": { "prompt": "a small red square" }, + "smoke_inputs": { + "prompt": "a small red square", + "negative_prompt": "" + }, + "validation": { + "status": "ok", + "last_checked": null + } + }, + { + "kind": "space", + "id": "krea/Krea-2", + "task": "text-to-image", + "space_category": "image-generation", + "modality": "image", + "title": "Krea 2", + "description": "Krea 2 text-to-image (Raw + Turbo)", + "added_at": "2026-07-03T00:00:00Z", + "featured": true, + "zero_gpu": true, + "smoke_inputs": { + "prompt": "a small red square" + }, + "validation": { + "status": "ok", + "last_checked": null + } + }, + { + "kind": "model", + "id": "krea/Krea-2-Turbo", + "task": "text-to-image", + "modality": "image", + "title": "Krea 2 Turbo", + "description": "", + "added_at": "2026-07-03T00:00:00Z", + "featured": true, + "validation": { + "status": "ok", + "last_checked": null + } + }, + { + "kind": "model", + "id": "krea/Krea-2-Raw", + "task": "text-to-image", + "modality": "image", + "title": "Krea 2 Raw", + "description": "", + "added_at": "2026-07-03T00:00:00Z", + "featured": false, + "validation": { + "status": "ok", + "last_checked": null + } + }, + { + "kind": "space", + "id": "krea/krea-lora-the-explorer", + "task": "text-to-image", + "space_category": "image-generation", + "modality": "image", + "title": "Krea 2 LoRA the Explorer", + "description": "Explore Krea 2 style LoRAs on Turbo", + "added_at": "2026-07-03T00:00:00Z", + "featured": false, + "zero_gpu": true, + "smoke_inputs": { + "prompt": "a small red square" + }, + "validation": { + "status": "ok", + "last_checked": null + } + }, + { + "kind": "space", + "id": "stabilityai/sdxl-turbo", + "task": "text-to-image", + "space_category": "image-generation", + "modality": "image", + "title": "Sdxl Turbo", + "description": "", + "added_at": "2026-07-03T00:00:00Z", + "featured": false, + "zero_gpu": false, + "smoke_inputs": { + "prompt": "a small red square" + }, + "validation": { + "status": "ok", + "last_checked": null + } + }, + { + "kind": "space", + "id": "black-forest-labs/FLUX.1-dev", + "task": "text-to-image", + "space_category": "image-generation", + "modality": "image", + "title": "FLUX.1 [dev]", + "description": "", + "added_at": "2026-07-03T00:00:00Z", + "featured": true, + "zero_gpu": true, + "smoke_inputs": { + "prompt": "a small red square" + }, "validation": { - "last_checked": "2026-06-08T03:14:00Z", "status": "ok", - "latency_ms": 3200, - "error": null + "last_checked": null + } + }, + { + "kind": "model", + "id": "black-forest-labs/FLUX.1-dev", + "task": "text-to-image", + "modality": "image", + "title": "FLUX.1 dev", + "description": "", + "added_at": "2026-07-03T00:00:00Z", + "featured": true, + "validation": { + "status": "ok", + "last_checked": null + } + }, + { + "kind": "space", + "id": "mrfakename/Z-Image-Turbo", + "task": "text-to-image", + "space_category": "image-generation", + "modality": "image", + "title": "Z Image Turbo", + "description": "", + "added_at": "2026-07-03T00:00:00Z", + "featured": true, + "zero_gpu": true, + "smoke_inputs": { + "prompt": "a small red square" + }, + "validation": { + "status": "ok", + "last_checked": null } }, { @@ -46,16 +198,14 @@ "task": "image-to-image", "space_category": "image-editing", "modality": "image", - "title": "BRIA Background Removal", - "description": "Remove image backgrounds", + "title": "BRIA RMBG 2.0", + "description": "remove background from any image", "added_at": "2026-04-01T00:00:00Z", "featured": true, "zero_gpu": true, "validation": { - "last_checked": "2026-06-08T03:14:00Z", "status": "ok", - "latency_ms": 1100, - "error": null + "last_checked": null } }, { @@ -65,30 +215,45 @@ "space_category": "image-editing", "modality": "image", "title": "Face to All", - "description": "Stylize a face photo into many art styles", + "description": "AI filter for your portraits", "added_at": "2026-04-02T00:00:00Z", "featured": false, - "zero_gpu": true, + "zero_gpu": false, "validation": { - "last_checked": "2026-06-08T03:14:00Z", "status": "ok", - "latency_ms": 2400, - "error": null + "last_checked": null } }, { - "kind": "model", - "id": "Salesforce/blip-image-captioning-large", - "task": "image-to-text", + "kind": "space", + "id": "Kwai-Kolors/Kolors-Virtual-Try-On", + "task": "image-to-image", + "space_category": "image-editing", "modality": "image", - "title": "BLIP Image Captioning", - "description": "Generate captions from images", - "added_at": "2026-04-02T00:00:00Z", - "featured": false, + "title": "Kolors Virtual Try-On", + "description": "", + "added_at": "2026-07-03T00:00:00Z", + "featured": true, + "zero_gpu": false, "validation": { - "last_checked": "2026-06-08T03:14:00Z", "status": "ok", - "error": null + "last_checked": null + } + }, + { + "kind": "space", + "id": "InstantX/InstantID", + "task": "image-to-image", + "space_category": "image-editing", + "modality": "image", + "title": "InstantID", + "description": "", + "added_at": "2026-07-03T00:00:00Z", + "featured": true, + "zero_gpu": true, + "validation": { + "status": "ok", + "last_checked": null } }, { @@ -96,29 +261,28 @@ "id": "facebook/detr-resnet-50", "task": "object-detection", "modality": "image", - "title": "DETR ResNet-50", - "description": "Open-vocabulary object detection", + "title": "Detr resnet 50", + "description": "", "added_at": "2026-04-02T00:00:00Z", "featured": true, "validation": { - "last_checked": "2026-06-08T03:14:00Z", "status": "ok", - "error": null + "last_checked": null } }, { - "kind": "model", - "id": "facebook/sam-vit-base", - "task": "image-segmentation", + "kind": "space", + "id": "nvidia/LocateAnything", + "task": "object-detection", "modality": "image", - "title": "Segment Anything (SAM)", - "description": "Segment any region of an image", - "added_at": "2026-04-02T00:00:00Z", + "title": "LocateAnything", + "description": "", + "added_at": "2026-07-03T00:00:00Z", "featured": true, + "zero_gpu": true, "validation": { - "last_checked": "2026-06-08T03:14:00Z", "status": "ok", - "error": null + "last_checked": null } }, { @@ -126,29 +290,155 @@ "id": "google/vit-base-patch16-224", "task": "image-classification", "modality": "image", - "title": "ViT Base", - "description": "Image classification (ImageNet)", + "title": "Vit base patch16 224", + "description": "", "added_at": "2026-04-02T00:00:00Z", "featured": false, "validation": { - "last_checked": "2026-06-08T03:14:00Z", "status": "ok", - "error": null + "last_checked": null } }, { "kind": "model", - "id": "depth-anything/Depth-Anything-V2-Small-hf", - "task": "depth-estimation", + "id": "Salesforce/blip-image-captioning-large", + "task": "image-to-text", "modality": "image", - "title": "Depth Anything V2", - "description": "Monocular depth estimation", - "added_at": "2026-04-02T00:00:00Z", + "title": "Blip image captioning large", + "description": "", + "added_at": "2026-07-03T00:00:00Z", "featured": true, "validation": { - "last_checked": "2026-06-08T03:14:00Z", "status": "ok", - "error": null + "last_checked": null + } + }, + { + "kind": "space", + "id": "facebook/sam2", + "task": "image-segmentation", + "modality": "image", + "title": "Sam2", + "description": "", + "added_at": "2026-07-03T00:00:00Z", + "featured": true, + "zero_gpu": false, + "validation": { + "status": "ok", + "last_checked": null + } + }, + { + "kind": "space", + "id": "tencent/Hunyuan3D-2.1", + "task": "image-to-3d", + "space_category": "3d-modeling", + "modality": "3d", + "title": "Hunyuan3D-2.1", + "description": "Image-to-3D Generation", + "added_at": "2026-07-03T00:00:00Z", + "featured": true, + "zero_gpu": true, + "validation": { + "status": "ok", + "last_checked": null + } + }, + { + "kind": "space", + "id": "trellis-community/TRELLIS", + "task": "image-to-3d", + "space_category": "3d-modeling", + "modality": "3d", + "title": "TRELLIS", + "description": "Scalable and Versatile 3D Generation from images", + "added_at": "2026-07-03T00:00:00Z", + "featured": true, + "zero_gpu": true, + "validation": { + "status": "ok", + "last_checked": null + } + }, + { + "kind": "space", + "id": "THUDM/CogVideoX-5b", + "task": "text-to-video", + "space_category": "video-generation", + "modality": "video", + "title": "CogVideoX-5B", + "description": "Text-to-Video", + "added_at": "2026-07-03T00:00:00Z", + "featured": true, + "zero_gpu": true, + "smoke_inputs": { + "prompt": "a flower opening slowly" + }, + "validation": { + "status": "ok", + "last_checked": null + } + }, + { + "kind": "space", + "id": "ali-vilab/i2vgen-xl", + "task": "image-to-video", + "space_category": "video-generation", + "modality": "video", + "title": "I2Vgen Xl", + "description": "", + "added_at": "2026-07-03T00:00:00Z", + "featured": false, + "zero_gpu": false, + "validation": { + "status": "ok", + "last_checked": null + } + }, + { + "kind": "space", + "id": "Wan-AI/Wan2.2-Animate", + "task": "image-to-video", + "space_category": "video-generation", + "modality": "video", + "title": "Wan2.2 Animate", + "description": "Wan2.2 Animate", + "added_at": "2026-07-03T00:00:00Z", + "featured": true, + "zero_gpu": false, + "validation": { + "status": "ok", + "last_checked": null + } + }, + { + "kind": "space", + "id": "KlingTeam/LivePortrait", + "task": "image-to-video", + "space_category": "video-generation", + "modality": "video", + "title": "Live Portrait", + "description": "Apply the motion of a video on a portrait", + "added_at": "2026-07-03T00:00:00Z", + "featured": true, + "zero_gpu": true, + "validation": { + "status": "ok", + "last_checked": null + } + }, + { + "kind": "model", + "id": "openai/whisper-large-v3-turbo", + "task": "automatic-speech-recognition", + "modality": "audio", + "title": "Whisper large v3 turbo", + "description": "", + "added_at": "2026-04-01T00:00:00Z", + "featured": true, + "validation": { + "status": "ok", + "last_checked": null } }, { @@ -158,16 +448,46 @@ "space_category": "music-generation", "modality": "audio", "title": "MusicGen", - "description": "Generate music from a text prompt", + "description": "", "added_at": "2026-04-02T00:00:00Z", "featured": false, "zero_gpu": true, - "smoke_inputs": { "prompt": "calm piano" }, "validation": { - "last_checked": "2026-06-08T03:14:00Z", "status": "ok", - "latency_ms": 4200, - "error": null + "last_checked": null + } + }, + { + "kind": "space", + "id": "hexgrad/Kokoro-TTS", + "task": "text-to-speech", + "space_category": "speech-synthesis", + "modality": "audio", + "title": "Kokoro TTS", + "description": "Upgraded to v1.0!", + "added_at": "2026-07-03T00:00:00Z", + "featured": true, + "zero_gpu": true, + "smoke_inputs": { + "text": "hello world" + }, + "validation": { + "status": "ok", + "last_checked": null + } + }, + { + "kind": "model", + "id": "microsoft/speecht5_tts", + "task": "text-to-speech", + "modality": "audio", + "title": "Speecht5 tts", + "description": "", + "added_at": "2026-07-03T00:00:00Z", + "featured": false, + "validation": { + "status": "ok", + "last_checked": null } }, { @@ -175,14 +495,13 @@ "id": "facebook/bart-large-cnn", "task": "summarization", "modality": "text", - "title": "BART CNN Summarizer", - "description": "News-style text summarization", + "title": "Bart large cnn", + "description": "", "added_at": "2026-04-02T00:00:00Z", "featured": false, "validation": { - "last_checked": "2026-06-08T03:14:00Z", "status": "ok", - "error": null + "last_checked": null } }, { @@ -190,14 +509,13 @@ "id": "Helsinki-NLP/opus-mt-en-fr", "task": "translation", "modality": "text", - "title": "Opus EN→FR", - "description": "English-to-French translation", + "title": "Opus mt en fr", + "description": "", "added_at": "2026-04-02T00:00:00Z", "featured": false, "validation": { - "last_checked": "2026-06-08T03:14:00Z", "status": "ok", - "error": null + "last_checked": null } }, { @@ -205,178 +523,408 @@ "id": "deepset/roberta-base-squad2", "task": "question-answering", "modality": "text", - "title": "RoBERTa QA", - "description": "Extractive question answering", + "title": "Roberta base squad2", + "description": "", "added_at": "2026-04-02T00:00:00Z", "featured": false, "validation": { - "last_checked": "2026-06-08T03:14:00Z", "status": "ok", - "error": null + "last_checked": null } }, { - "kind": "space", - "id": "tencent/Hunyuan3D-2", - "task": "image-to-3d", - "space_category": "3d-modeling", - "modality": "3d", - "title": "Hunyuan3D 2", - "description": "Generate 3D meshes from a single image", - "added_at": "2026-04-02T00:00:00Z", + "kind": "model", + "id": "distilbert/distilbert-base-uncased-finetuned-sst-2-english", + "task": "text-classification", + "modality": "text", + "title": "Distilbert base uncased finetuned sst 2 english", + "description": "", + "added_at": "2026-07-03T00:00:00Z", + "featured": false, + "validation": { + "status": "ok", + "last_checked": null + } + }, + { + "kind": "model", + "id": "sentence-transformers/all-MiniLM-L6-v2", + "task": "feature-extraction", + "modality": "text", + "title": "All MiniLM L6 v2", + "description": "", + "added_at": "2026-07-03T00:00:00Z", "featured": true, - "zero_gpu": true, "validation": { - "last_checked": "2026-06-08T03:14:00Z", "status": "ok", - "latency_ms": 5200, - "error": null + "last_checked": null } }, { - "kind": "space", - "id": "Wan-AI/Wan2.2-TI2V-5B", + "kind": "model", + "id": "openai-community/gpt2", + "task": "text-generation", + "modality": "text", + "title": "Gpt2", + "description": "", + "added_at": "2026-07-03T00:00:00Z", + "featured": false, + "validation": { + "status": "ok", + "last_checked": null + } + }, + { + "kind": "model", + "id": "google/gemma-4-31B-it", + "task": "image-text-to-text", + "modality": "image", + "title": "Gemma 4 31B it", + "description": "", + "added_at": "2026-07-03T00:00:00Z", + "featured": true, + "validation": { + "status": "ok", + "last_checked": null + } + }, + { + "kind": "model", + "id": "Qwen/Qwen3.6-27B", + "task": "text-generation", + "modality": "text", + "title": "Qwen3.6 27B", + "description": "", + "added_at": "2026-07-03T00:00:00Z", + "featured": true, + "validation": { + "status": "ok", + "last_checked": null + } + }, + { + "kind": "model", + "id": "deepseek-ai/DeepSeek-V4-Flash", + "task": "text-generation", + "modality": "text", + "title": "DeepSeek V4 Flash", + "description": "", + "added_at": "2026-07-03T00:00:00Z", + "featured": true, + "validation": { + "status": "ok", + "last_checked": null + } + }, + { + "kind": "model", + "id": "tencent/HunyuanVideo", "task": "text-to-video", - "space_category": "video-generation", "modality": "video", - "title": "Wan 2.2 TI2V 5B", - "description": "Text-to-video generation", - "added_at": "2026-04-02T00:00:00Z", + "title": "HunyuanVideo", + "description": "", + "added_at": "2026-07-03T00:00:00Z", "featured": true, - "zero_gpu": true, - "smoke_inputs": { "prompt": "a flower opening" }, "validation": { - "last_checked": "2026-06-08T03:14:00Z", "status": "ok", - "latency_ms": 8800, - "error": null + "last_checked": null } }, { "kind": "space", - "id": "hf-audio/whisper-large-v3-turbo", + "id": "openai/whisper", "task": "automatic-speech-recognition", "space_category": "automatic-speech-recognition", "modality": "audio", - "title": "Whisper Large v3 Turbo", - "description": "Fast speech-to-text", - "added_at": "2026-04-01T00:00:00Z", + "title": "Whisper", + "description": "", + "added_at": "2026-07-03T00:00:00Z", "featured": true, "zero_gpu": true, "validation": { - "last_checked": "2026-06-08T03:14:00Z", "status": "ok", - "latency_ms": 900, - "error": null + "last_checked": null } }, { "kind": "space", - "id": "coqui/xtts", + "id": "pharmapsychotic/CLIP-Interrogator", + "task": "image-to-text", + "modality": "image", + "title": "CLIP Interrogator", + "description": "", + "added_at": "2026-07-03T00:00:00Z", + "featured": true, + "zero_gpu": true, + "validation": { + "status": "ok", + "last_checked": null + } + }, + { + "kind": "space", + "id": "mrfakename/E2-F5-TTS", "task": "text-to-speech", "space_category": "speech-synthesis", "modality": "audio", - "title": "Coqui XTTS", - "description": "Multilingual text-to-speech with voice cloning", - "added_at": "2026-04-01T00:00:00Z", + "title": "F5-TTS", + "description": "F5-TTS & E2-TTS: Zero-Shot Voice Cloning (Unofficial Demo)", + "added_at": "2026-07-03T00:00:00Z", "featured": true, "zero_gpu": true, - "smoke_inputs": { "text": "hello" }, + "smoke_inputs": { + "ref_text": "hello", + "gen_text": "hello world" + }, "validation": { - "last_checked": "2026-06-08T03:14:00Z", "status": "ok", - "latency_ms": 2100, - "error": null + "last_checked": null } }, { - "kind": "model", - "id": "black-forest-labs/FLUX.1-schnell", - "task": "text-to-image", + "kind": "space", + "id": "sczhou/CodeFormer", + "task": "image-to-image", + "space_category": "image-editing", "modality": "image", - "title": "FLUX.1 schnell", - "description": "Text-to-image", - "added_at": "2026-04-01T00:00:00Z", + "title": "CodeFormer", + "description": "", + "added_at": "2026-07-03T00:00:00Z", + "featured": false, + "zero_gpu": true, + "validation": { + "status": "ok", + "last_checked": null + } + }, + { + "kind": "space", + "id": "Qwen/Qwen-Image-Edit-2511", + "task": "image-to-image", + "space_category": "image-editing", + "modality": "image", + "title": "Qwen Image Edit 2511", + "description": "", + "added_at": "2026-07-03T00:00:00Z", "featured": true, + "zero_gpu": true, "validation": { - "last_checked": "2026-06-08T03:14:00Z", "status": "ok", - "error": null + "last_checked": null } }, { - "kind": "model", - "id": "stabilityai/stable-diffusion-3.5-large-turbo", - "task": "text-to-image", + "kind": "space", + "id": "Qwen/Qwen3-TTS", + "task": "text-to-speech", + "space_category": "speech-synthesis", + "modality": "audio", + "title": "Qwen3-TTS Demo", + "description": "", + "added_at": "2026-07-03T00:00:00Z", + "featured": true, + "zero_gpu": true, + "smoke_inputs": { + "text": "hello world" + }, + "validation": { + "status": "ok", + "last_checked": null + } + }, + { + "kind": "space", + "id": "Qwen/Qwen3-ASR", + "task": "automatic-speech-recognition", + "space_category": "automatic-speech-recognition", + "modality": "audio", + "title": "Qwen3-ASR Demo", + "description": "", + "added_at": "2026-07-03T00:00:00Z", + "featured": false, + "zero_gpu": true, + "validation": { + "status": "ok", + "last_checked": null + } + }, + { + "kind": "space", + "id": "deepseek-ai/Janus-Pro-7B", + "task": "image-text-to-text", "modality": "image", - "title": "SD 3.5 Large Turbo", - "description": "Fast text-to-image", - "added_at": "2026-04-01T00:00:00Z", + "title": "Chat With Janus-Pro-7B", + "description": "A unified multimodal understanding and generation model.", + "added_at": "2026-07-03T00:00:00Z", "featured": true, + "zero_gpu": true, "validation": { - "last_checked": "2026-06-08T03:14:00Z", "status": "ok", - "error": null + "last_checked": null + } + }, + { + "kind": "space", + "id": "mistralai/voxtral-tts-demo", + "task": "text-to-speech", + "space_category": "speech-synthesis", + "modality": "audio", + "title": "Voxtral TTS Demo", + "description": "", + "added_at": "2026-07-03T00:00:00Z", + "featured": false, + "zero_gpu": false, + "smoke_inputs": { + "text": "hello world" + }, + "validation": { + "status": "ok", + "last_checked": null } }, { "kind": "model", - "id": "Qwen/Qwen2.5-VL-7B-Instruct", - "task": "image-to-text", - "modality": "image", - "title": "Qwen2.5-VL 7B", - "description": "Image understanding & captioning", - "added_at": "2026-04-01T00:00:00Z", + "id": "dslim/bert-base-NER", + "task": "token-classification", + "modality": "text", + "title": "Bert base NER", + "description": "", + "added_at": "2026-07-03T00:00:00Z", "featured": false, "validation": { - "last_checked": "2026-06-08T03:14:00Z", "status": "ok", - "error": null + "last_checked": null } }, { "kind": "model", - "id": "openai/whisper-large-v3-turbo", - "task": "automatic-speech-recognition", - "modality": "audio", - "title": "Whisper Large v3 Turbo", - "description": "Speech-to-text", - "added_at": "2026-04-01T00:00:00Z", + "id": "facebook/bart-large-mnli", + "task": "zero-shot-classification", + "modality": "text", + "title": "Bart large mnli", + "description": "", + "added_at": "2026-07-03T00:00:00Z", "featured": true, "validation": { - "last_checked": "2026-06-08T03:14:00Z", "status": "ok", - "error": null + "last_checked": null } }, { "kind": "model", - "id": "meta-llama/Llama-3.2-3B-Instruct", - "task": "text-generation", - "modality": "text", - "title": "Llama 3.2 3B Instruct", - "description": "Open-weights text generation", - "added_at": "2026-04-01T00:00:00Z", + "id": "MIT/ast-finetuned-audioset-10-10-0.4593", + "task": "audio-classification", + "modality": "audio", + "title": "Ast finetuned audioset 10 10 0.4593", + "description": "", + "added_at": "2026-07-03T00:00:00Z", + "featured": false, + "validation": { + "status": "ok", + "last_checked": null + } + }, + { + "kind": "model", + "id": "ZhengPeng7/BiRefNet", + "task": "image-segmentation", + "modality": "image", + "title": "BiRefNet", + "description": "", + "added_at": "2026-07-03T00:00:00Z", + "featured": true, + "validation": { + "status": "ok", + "last_checked": null + } + }, + { + "kind": "space", + "id": "Lightricks/ltx-video-distilled", + "task": "text-to-video", + "space_category": "video-generation", + "modality": "video", + "title": "LTX Video Fast", + "description": "ultra-fast video model, LTX 0.9.8 13B distilled", + "added_at": "2026-07-03T00:00:00Z", "featured": true, + "zero_gpu": true, + "smoke_inputs": { + "prompt": "a flower opening slowly" + }, "validation": { - "last_checked": "2026-06-08T03:14:00Z", "status": "ok", - "error": null + "last_checked": null } }, { "kind": "model", - "id": "Qwen/Qwen2.5-7B-Instruct", - "task": "text-generation", + "id": "depth-anything/Depth-Anything-V2-Small-hf", + "task": "depth-estimation", + "modality": "image", + "title": "Depth Anything V2 Small hf", + "description": "", + "added_at": "2026-07-03T00:00:00Z", + "featured": false, + "validation": { + "status": "ok", + "last_checked": null + } + }, + { + "kind": "model", + "id": "openai/shap-e", + "task": "text-to-3d", + "modality": "3d", + "title": "Shap e", + "description": "", + "added_at": "2026-07-03T00:00:00Z", + "featured": false, + "validation": { + "status": "ok", + "last_checked": null + } + }, + { + "kind": "model", + "id": "dandelin/vilt-b32-finetuned-vqa", + "task": "visual-question-answering", + "modality": "image", + "title": "Vilt b32 finetuned vqa", + "description": "", + "added_at": "2026-07-03T00:00:00Z", + "featured": false, + "validation": { + "status": "ok", + "last_checked": null + } + }, + { + "kind": "model", + "id": "google-bert/bert-base-uncased", + "task": "fill-mask", "modality": "text", - "title": "Qwen 2.5 7B", - "description": "Multilingual text generation", - "added_at": "2026-04-01T00:00:00Z", + "title": "Bert base uncased", + "description": "", + "added_at": "2026-07-03T00:00:00Z", + "featured": false, + "validation": { + "status": "ok", + "last_checked": null + } + }, + { + "kind": "model", + "id": "FunAudioLLM/SenseVoiceSmall", + "task": "automatic-speech-recognition", + "modality": "audio", + "title": "SenseVoiceSmall", + "description": "", + "added_at": "2026-07-03T00:00:00Z", "featured": false, "validation": { - "last_checked": "2026-06-08T03:14:00Z", "status": "ok", - "error": null + "last_checked": null } } ] diff --git a/js/workflowcanvas/workflow/WorkflowCanvas.svelte b/js/workflowcanvas/workflow/WorkflowCanvas.svelte index ee92faea0c5..041a7ec9c30 100644 --- a/js/workflowcanvas/workflow/WorkflowCanvas.svelte +++ b/js/workflowcanvas/workflow/WorkflowCanvas.svelte @@ -8,7 +8,9 @@ import NodeModelPicker from "./NodeModelPicker.svelte"; import WorkflowEmptyState from "./WorkflowEmptyState.svelte"; import WorkflowApiPanel from "./WorkflowApiPanel.svelte"; + import type { WorkflowTemplate } from "./workflow-templates"; import CheckIcon from "./icons/CheckIcon.svelte"; + import CloseIcon from "./icons/CloseIcon.svelte"; import LayoutIcon from "./icons/LayoutIcon.svelte"; import InfoIcon from "./icons/InfoIcon.svelte"; import CodeIcon from "./icons/CodeIcon.svelte"; @@ -281,6 +283,7 @@ let showShortcuts = $state(false); let showUserMenu = $state(false); let showApiPanel = $state(false); + let showTemplatesOverlay = $state(false); // Popover shown when the "Run only" badge is clicked, explaining why editing // is disabled and how to enable it. let showAccessInfo = $state(false); @@ -1384,6 +1387,16 @@ let clearConfirm = $state(false); + function load_template(t: WorkflowTemplate): void { + if (readOnly) return; + try { + const v2 = migrateToV2(t.workflow); + revokeAllBlobUrls(legacyView.nodes); + workflow.set(v2); + showTemplatesOverlay = false; + } catch {} + } + function clearWorkflow(): void { if (legacyView.nodes.length === 0 || readOnly) return; clearConfirm = true; @@ -2177,6 +2190,12 @@ {/if}
+ {#if !readOnly && nodeCount > 0} + + {/if} {#if auth.status !== "checking"} {#if auth.user}
@@ -2364,7 +2383,29 @@
{#if nodeCount === 0} - + + {/if} + + {#if showTemplatesOverlay} + +
(showTemplatesOverlay = false)} + > +
e.stopPropagation()} + > +
+ Start from a template + +
+ +
+
{/if} {#if running} @@ -2640,6 +2681,7 @@ onClose={() => (showApiPanel = false)} /> {/if} +
diff --git a/js/workflowcanvas/workflow/WorkflowEmptyState.svelte b/js/workflowcanvas/workflow/WorkflowEmptyState.svelte index e3027022078..d85153a21b3 100644 --- a/js/workflowcanvas/workflow/WorkflowEmptyState.svelte +++ b/js/workflowcanvas/workflow/WorkflowEmptyState.svelte @@ -1,7 +1,35 @@ -
-
-
Start building
-
Add a model or space from the toolbar below
+ + +
+
e.stopPropagation()} + onpointerup={(e) => e.stopPropagation()} + > + {#each TEMPLATES as template} + + {/each} +
+ {#if !inline} + + {/if}
diff --git a/js/workflowcanvas/workflow/workflow-templates.ts b/js/workflowcanvas/workflow/workflow-templates.ts new file mode 100644 index 00000000000..3bde0c36b78 --- /dev/null +++ b/js/workflowcanvas/workflow/workflow-templates.ts @@ -0,0 +1,431 @@ +export interface WorkflowTemplate { + id: string; + name: string; + category: string; + description: string; + accent: string; + gradient: string; + workflow: Record; +} + +const TEXT_TO_IMAGE: Record = { + schema_version: "2", + name: "Text to Image", + runtime: { default: "client" }, + references: [ + { + id: "ref-prompt", + label: "Prompt", + role: "reference", + asset_type: "text", + inputs: [{ id: "in", label: "Text", type: "text" }], + outputs: [{ id: "out", label: "Text", type: "text" }], + width: 220, + height: 163, + x: 100, + y: 120, + data: { in: null } + } + ], + operators: [ + { + id: "op-flux", + label: "Generate Image", + role: "operator", + kind: "space", + source: "hf://spaces/multimodalart/FLUX.1-merged", + space_id: "multimodalart/FLUX.1-merged", + runtime: "client", + inputs: [{ id: "in", label: "Prompt", type: "text", required: true }], + outputs: [{ id: "out", label: "Image", type: "image" }], + width: 220, + height: 124, + x: 400, + y: 120, + data: {}, + endpoints: [ + { + name: "/infer", + inputs: [ + { id: "in_0", label: "Prompt", type: "text", required: true }, + { id: "in_1", label: "Seed", type: "number", required: false }, + { + id: "in_2", + label: "Randomize seed", + type: "boolean", + required: false + }, + { id: "in_3", label: "Width", type: "number", required: false }, + { id: "in_4", label: "Height", type: "number", required: false }, + { + id: "in_5", + label: "Guidance Scale", + type: "number", + required: false + }, + { + id: "in_6", + label: "Number of inference steps", + type: "number", + required: false + } + ], + outputs: [ + { id: "out_0", label: "Result", type: "image", output_index: 0 }, + { id: "out_1", label: "Seed", type: "number", output_index: 1 } + ] + } + ] + } + ], + subjects: [ + { + id: "subj-output", + label: "Generated Image", + role: "subject", + asset_type: "image", + inputs: [{ id: "in", label: "Image", type: "image" }], + outputs: [{ id: "out", label: "Image", type: "image" }], + width: 220, + height: 107, + x: 700, + y: 120, + data: { in: null } + } + ], + edges: [ + { + id: "e1", + from_node_id: "ref-prompt", + from_port_id: "out", + to_node_id: "op-flux", + to_port_id: "in", + type: "text" + }, + { + id: "e2", + from_node_id: "op-flux", + from_port_id: "out", + to_node_id: "subj-output", + to_port_id: "in", + type: "image" + } + ] +}; + +const IMAGE_CAPTIONING: Record = { + schema_version: "2", + name: "Image Captioning", + runtime: { default: "client" }, + references: [ + { + id: "ref-image", + label: "Image", + role: "reference", + asset_type: "image", + inputs: [{ id: "in", label: "Image", type: "image" }], + outputs: [{ id: "out", label: "Image", type: "image" }], + width: 220, + height: 124, + x: 100, + y: 120, + data: {} + } + ], + operators: [ + { + id: "op-caption", + label: "Describe Image", + role: "operator", + kind: "space", + source: "hf://spaces/ovi054/image-to-prompt", + space_id: "ovi054/image-to-prompt", + endpoint: "/predict", + runtime: "client", + pipeline_tag: "Image Captioning", + inputs: [ + { id: "in_0", label: "Input Image", type: "image", required: true } + ], + outputs: [ + { + id: "out_0", + label: "Output Prompt", + type: "text", + output_index: 0 + } + ], + width: 280, + height: 124, + x: 400, + y: 120, + data: {}, + endpoints: [ + { + name: "/predict", + inputs: [ + { + id: "in_0", + label: "Input Image", + type: "image", + required: true + } + ], + outputs: [ + { + id: "out_0", + label: "Output Prompt", + type: "text", + output_index: 0 + } + ] + } + ] + } + ], + subjects: [ + { + id: "subj-caption", + label: "Caption", + role: "subject", + asset_type: "text", + inputs: [{ id: "in", label: "Text", type: "text" }], + outputs: [{ id: "out", label: "Text", type: "text" }], + width: 220, + height: 163, + x: 760, + y: 120, + data: { in: null } + } + ], + edges: [ + { + id: "e1", + from_node_id: "ref-image", + from_port_id: "out", + to_node_id: "op-caption", + to_port_id: "in_0", + type: "image" + }, + { + id: "e2", + from_node_id: "op-caption", + from_port_id: "out_0", + to_node_id: "subj-caption", + to_port_id: "in", + type: "text" + } + ] +}; + +const MARKETING_IMAGE: Record = { + schema_version: "2", + name: "Marketing Image Creator", + runtime: { default: "client" }, + references: [ + { + label: "Text", + inputs: [{ id: "in", label: "Text", type: "text" }], + outputs: [{ id: "out", label: "Text", type: "text" }], + width: 220, + height: 163, + asset_type: "text", + role: "reference", + id: "1539a1e9-4906-4008-b345-e6d05bb69b22", + x: 740, + y: 80, + data: { in: null } + }, + { + label: "Image", + inputs: [{ id: "in", label: "Image", type: "image" }], + outputs: [{ id: "out", label: "Image", type: "image" }], + width: 220, + height: 124, + asset_type: "image", + role: "reference", + id: "13e92b22-7173-416c-81c6-1ca097a2a299", + x: 80, + y: 80, + data: {} + } + ], + operators: [ + { + id: "n_flux", + label: "Generate Image", + inputs: [{ id: "in", label: "Prompt", type: "text", required: true }], + outputs: [{ id: "out", label: "Image", type: "image" }], + data: {}, + x: 1040, + y: 80, + width: 220, + height: 124, + role: "operator", + kind: "space", + source: "hf://spaces/multimodalart/FLUX.1-merged", + space_id: "multimodalart/FLUX.1-merged", + runtime: "client", + endpoints: [ + { + name: "/infer", + inputs: [ + { id: "in_0", label: "Prompt", type: "text", required: true }, + { id: "in_1", label: "Seed", type: "number", required: false }, + { + id: "in_2", + label: "Randomize seed", + type: "boolean", + required: false + }, + { id: "in_3", label: "Width", type: "number", required: false }, + { id: "in_4", label: "Height", type: "number", required: false }, + { + id: "in_5", + label: "Guidance Scale", + type: "number", + required: false + }, + { + id: "in_6", + label: "Number of inference steps", + type: "number", + required: false + } + ], + outputs: [ + { id: "out_0", label: "Result", type: "image", output_index: 0 }, + { id: "out_1", label: "Seed", type: "number", output_index: 1 } + ] + } + ] + }, + { + label: "Image To Prompt", + inputs: [ + { id: "in_0", label: "Input Image", type: "image", required: true } + ], + outputs: [ + { + id: "out_0", + label: "Output Prompt", + type: "text", + output_index: 0 + } + ], + width: 280, + height: 124, + kind: "space", + space_id: "ovi054/image-to-prompt", + endpoint: "/predict", + endpoints: [ + { + name: "/predict", + inputs: [ + { + id: "in_0", + label: "Input Image", + type: "image", + required: true + } + ], + outputs: [ + { + id: "out_0", + label: "Output Prompt", + type: "text", + output_index: 0 + } + ] + } + ], + pipeline_tag: "Image Captioning", + role: "operator", + id: "897592dc-17b5-473b-9e89-4ebdae4073d6", + x: 380, + y: 80, + data: {} + } + ], + subjects: [ + { + id: "n_output", + label: "Marketing Image", + inputs: [{ id: "in", label: "Image", type: "image" }], + outputs: [{ id: "out", label: "Image", type: "image" }], + data: { in: null }, + x: 1340, + y: 80, + width: 220, + height: 107, + role: "subject", + asset_type: "image" + } + ], + edges: [ + { + id: "e4", + from_node_id: "n_flux", + from_port_id: "out", + to_node_id: "n_output", + to_port_id: "in", + type: "image" + }, + { + from_node_id: "1539a1e9-4906-4008-b345-e6d05bb69b22", + from_port_id: "out", + to_node_id: "n_flux", + to_port_id: "in", + type: "text", + id: "b44e83fe-23b1-4dcc-83d3-55b3481721bc" + }, + { + from_node_id: "13e92b22-7173-416c-81c6-1ca097a2a299", + from_port_id: "out", + to_node_id: "897592dc-17b5-473b-9e89-4ebdae4073d6", + to_port_id: "in_0", + type: "image", + id: "22796709-ff7d-4250-92c0-2d541f9e6a99" + }, + { + from_node_id: "897592dc-17b5-473b-9e89-4ebdae4073d6", + from_port_id: "out_0", + to_node_id: "1539a1e9-4906-4008-b345-e6d05bb69b22", + to_port_id: "in", + type: "text", + id: "96dab823-0f2c-4356-98c4-aa82feca5e0a" + } + ] +}; + +export const TEMPLATES: WorkflowTemplate[] = [ + { + id: "text-to-image", + name: "Text to Image", + category: "Image Generation", + description: "Generate images from a text prompt using FLUX", + accent: "#4fd1a5", + gradient: + "radial-gradient(ellipse at 15% 85%, #2dd4bf 0%, #0d9488 40%, transparent 70%), radial-gradient(ellipse at 80% 10%, #38bdf8 0%, #0284c7 45%, transparent 70%), radial-gradient(ellipse at 50% 50%, #059669 0%, transparent 60%), #0d766e", + workflow: TEXT_TO_IMAGE + }, + { + id: "image-captioning", + name: "Image Captioning", + category: "Vision", + description: "Describe any image with AI", + accent: "#8b83e8", + gradient: + "radial-gradient(ellipse at 15% 85%, #a78bfa 0%, #7c3aed 40%, transparent 70%), radial-gradient(ellipse at 85% 15%, #818cf8 0%, #4f46e5 45%, transparent 70%), radial-gradient(ellipse at 50% 55%, #6d28d9 0%, transparent 60%), #4c1d95", + workflow: IMAGE_CAPTIONING + }, + { + id: "marketing-image", + name: "Marketing Image Creator", + category: "Creative", + description: "Turn a product photo into marketing copy and a new visual", + accent: "#f97316", + gradient: + "radial-gradient(ellipse at 10% 85%, #fb923c 0%, #ea580c 40%, transparent 70%), radial-gradient(ellipse at 85% 15%, #f43f5e 0%, #be123c 45%, transparent 70%), radial-gradient(ellipse at 50% 50%, #dc2626 0%, transparent 60%), #9a3412", + workflow: MARKETING_IMAGE + } +]; diff --git a/scripts/build_workflow_curated.py b/scripts/build_workflow_curated.py deleted file mode 100644 index 7864743b526..00000000000 --- a/scripts/build_workflow_curated.py +++ /dev/null @@ -1,254 +0,0 @@ -"""Harvest workflow-curated *candidates* from the Hugging Face Hub. - -This does the automatable half of building the curated catalog: for each task in -the taxonomy it pulls the most-liked running Spaces, derives the objective fields -(id, zero_gpu, title, modality, space_category), and emits a candidate pool in the -same envelope `scripts/validate_workflow_curated.py` and `gradio/workflow.py` expect. - -It deliberately does NOT pick the final set. Review the output, drop the junk, set -`featured`, polish `description`, then run: - - python scripts/build_workflow_curated.py --per-task 15 --out curated.candidates.json - # ... hand-trim curated.candidates.json into curated.json ... - python scripts/validate_workflow_curated.py --source curated.json --dry-run - -Selection: top-N Spaces per task (coverage), not global popularity. -""" - -from __future__ import annotations - -import argparse -import json -import logging -import sys -from datetime import datetime, timezone -from typing import Any, Optional - -logging.basicConfig(level=logging.INFO, format="%(asctime)s %(levelname)s %(message)s") -logger = logging.getLogger("build_workflow_curated") - -# task -> (modality, space_category). Keys define which tasks we query. -# space_category is None for tasks that aren't a distinct generative node category. -TASK_META: dict[str, tuple[str, Optional[str]]] = { - "text-to-image": ("image", "image-generation"), - "image-to-image": ("image", "image-editing"), - "image-to-text": ("text", None), - "image-to-3d": ("3d", "3d-modeling"), - "text-to-3d": ("3d", "3d-modeling"), - "text-to-video": ("video", "video-generation"), - "image-to-video": ("video", "video-generation"), - "text-to-speech": ("audio", "speech-synthesis"), - "text-to-audio": ("audio", "music-generation"), - "automatic-speech-recognition": ("audio", "automatic-speech-recognition"), - "audio-to-audio": ("audio", None), - "image-classification": ("image", None), - "image-segmentation": ("image", None), - "object-detection": ("image", None), - "depth-estimation": ("image", None), - "text-generation": ("text", None), - "summarization": ("text", None), - "translation": ("text", None), - "question-answering": ("text", None), -} - -# Hub runtime stages we treat as "usable enough to keep as a candidate". -LIVE_STAGES = {"RUNNING", "SLEEPING", "RUNNING_BUILDING", "RUNNING_APP_STARTING"} - - -def now_iso() -> str: - return datetime.now(timezone.utc).isoformat().replace("+00:00", "Z") - - -def _attr(obj: Any, name: str, default: Any = None) -> Any: - """Read `name` from an object attr or a dict key, whichever exists.""" - if obj is None: - return default - if isinstance(obj, dict): - return obj.get(name, default) - return getattr(obj, name, default) - - -def _card_dict(space: Any) -> dict: - cd = _attr(space, "card_data") or _attr(space, "cardData") - if cd is None: - return {} - if isinstance(cd, dict): - return cd - if hasattr(cd, "to_dict"): - try: - return cd.to_dict() - except Exception: - pass - return {} - - -def _detect_zero_gpu(space: Any) -> bool: - runtime = _attr(space, "runtime") or {} - hw = _attr(runtime, "hardware") or {} - # hardware can be {"current": "zero-a10g", "requested": "zero-a10g"} or a bare str - vals = [] - if isinstance(hw, dict): - vals = [hw.get("current"), hw.get("requested")] - else: - vals = [hw] - return any(isinstance(v, str) and "zero" in v.lower() for v in vals) - - -def _stage(space: Any) -> Optional[str]: - runtime = _attr(space, "runtime") or {} - return _attr(runtime, "stage") - - -def _title(space: Any, repo_id: str) -> str: - card = _card_dict(space) - title = (card.get("title") or "").strip() - if title: - return title - name = repo_id.split("/")[-1].replace("-", " ").replace("_", " ").strip() - return name[:1].upper() + name[1:] if name else repo_id - - -def _description(space: Any) -> str: - card = _card_dict(space) - return (card.get("short_description") or "").strip() - - -def harvest_task( - api: Any, - task: str, - per_task: int, - min_likes: int, - allowed_sdks: set[str], - running_only: bool, -) -> list[dict]: - modality, category = TASK_META[task] - try: - spaces = api.list_spaces( - filter=task, - sort="likes", - direction=-1, - limit=max(per_task * 4, 40), # over-fetch; filtering drops many - expand=["cardData", "likes", "trendingScore", "sdk", "runtime"], - ) - except Exception as e: - logger.warning("list_spaces(%s) failed: %s", task, e) - return [] - - out: list[dict] = [] - for space in spaces: - repo_id = _attr(space, "id") - if not repo_id: - continue - sdk = (_attr(space, "sdk") or "").lower() - if allowed_sdks and sdk and sdk not in allowed_sdks: - continue - likes = _attr(space, "likes") or 0 - if likes < min_likes: - continue - stage = _stage(space) - if running_only and stage is not None and stage not in LIVE_STAGES: - continue - - out.append( - { - "kind": "space", - "id": repo_id, - "task": task, - "space_category": category, - "modality": modality, - "title": _title(space, repo_id), - "description": _description(space), - "added_at": now_iso(), - "featured": False, - "zero_gpu": _detect_zero_gpu(space), - "_likes": likes, # kept only for sorting/trimming; strip before upload - } - ) - if len(out) >= per_task: - break - logger.info("task %-28s -> %d candidates", task, len(out)) - return out - - -def main() -> int: - ap = argparse.ArgumentParser(description=__doc__) - ap.add_argument("--per-task", type=int, default=12, help="Max Spaces kept per task.") - ap.add_argument("--min-likes", type=int, default=5, help="Drop Spaces below this many likes.") - ap.add_argument( - "--tasks", - default=None, - help="Comma-separated subset of tasks to query (default: all in TASK_META).", - ) - ap.add_argument( - "--sdk", - default="gradio,docker", - help="Allowed Space SDKs, comma-separated. Empty string = any.", - ) - ap.add_argument( - "--all-stages", - action="store_true", - help="Keep Spaces regardless of runtime stage (default keeps only live-ish ones).", - ) - ap.add_argument("--out", default="curated.candidates.json", help="Output path.") - args = ap.parse_args() - - try: - from huggingface_hub import HfApi - except Exception as e: - logger.error("huggingface_hub is required: %s", e) - return 2 - - api = HfApi() - tasks = ( - [t.strip() for t in args.tasks.split(",") if t.strip()] - if args.tasks - else list(TASK_META) - ) - unknown = [t for t in tasks if t not in TASK_META] - if unknown: - logger.error("unknown tasks (add them to TASK_META first): %s", unknown) - return 2 - - allowed_sdks = {s.strip().lower() for s in args.sdk.split(",") if s.strip()} - - by_id: dict[str, dict] = {} - for task in tasks: - for cand in harvest_task( - api, task, args.per_task, args.min_likes, allowed_sdks, not args.all_stages - ): - # First task that surfaces a Space wins; record the dupe for review. - if cand["id"] in by_id: - by_id[cand["id"]].setdefault("_also_matched", []).append(task) - continue - by_id[cand["id"]] = cand - - items = sorted(by_id.values(), key=lambda e: e.pop("_likes", 0), reverse=True) - - payload = {"snapshot_version": 2, "fetched_at": now_iso(), "items": items} - with open(args.out, "w", encoding="utf-8") as f: - json.dump(payload, f, indent=2, ensure_ascii=False) - f.write("\n") - - # summary - import collections - - by_modality = collections.Counter(e["modality"] for e in items) - zero = sum(1 for e in items if e["zero_gpu"]) - logger.info( - "wrote %d candidate spaces to %s (%d zero-gpu) modalities=%s", - len(items), - args.out, - zero, - dict(by_modality), - ) - logger.info( - "next: trim %s by hand (drop junk, set `featured`, write `description`, " - "remove any `_also_matched`), rename to curated.json, then run " - "`python scripts/validate_workflow_curated.py --source curated.json --dry-run`", - args.out, - ) - return 0 - - -if __name__ == "__main__": - sys.exit(main())