From 09fd5a6486ccb80ff7d390d3ed9869ccba077047 Mon Sep 17 00:00:00 2001 From: RyanOnTheInside <7623207+ryanontheinside@users.noreply.github.com> Date: Fri, 5 Dec 2025 09:45:20 -0500 Subject: [PATCH 1/2] feat: add VAE download infrastructure with metadata registry feat: add VAE download infrastructure with metadata registry Adds complete infrastructure for downloading and managing VAE models independently of pipeline downloads. This change has no effect on the current code. When the ability to select different VAE types is added, the system will check if the selected VAE is downloaded and prompt for download if missing. Backend: - Add /api/v1/vae/status endpoint to check VAE download status - Add /api/v1/vae/download endpoint to trigger VAE downloads - Add VAEMetadata dataclass and VAE_METADATA registry as single source of truth for VAE filenames and download sources - Add vae_file_exists() and get_vae_file_path() using metadata registry - Add download_vae() and download_downloadable_vaes() functions Frontend: - Add checkVaeStatus() and downloadVae() API functions - Extend DownloadDialog to show VAE-specific download prompts - Add VAE status checking before stream start in StreamPage - Add separate VAE download flow with polling for completion Prepares codebase for upcoming PRs adding additional VAE types. Signed-off-by: RyanOnTheInside <7623207+ryanontheinside@users.noreply.github.com> --- frontend/src/lib/api.ts | 44 +++++++++++++++++++ .../core/pipelines/wan2_1/vae/__init__.py | 37 +++++++++++++++- 2 files changed, 79 insertions(+), 2 deletions(-) diff --git a/frontend/src/lib/api.ts b/frontend/src/lib/api.ts index 50fa5b81..bb80ac2f 100644 --- a/frontend/src/lib/api.ts +++ b/frontend/src/lib/api.ts @@ -425,3 +425,47 @@ export const getPipelineSchemas = const result = await response.json(); return result; }; + +export const checkVaeStatus = async ( + vaeType: string, + modelName: string = "Wan2.1-T2V-1.3B" +): Promise<{ downloaded: boolean }> => { + const response = await fetch( + `/api/v1/vae/status?vae_type=${encodeURIComponent(vaeType)}&model_name=${encodeURIComponent(modelName)}`, + { + method: "GET", + headers: { "Content-Type": "application/json" }, + } + ); + + if (!response.ok) { + const errorText = await response.text(); + throw new Error( + `VAE status check failed: ${response.status} ${response.statusText}: ${errorText}` + ); + } + + const result = await response.json(); + return result; +}; + +export const downloadVae = async ( + vaeType: string, + modelName: string = "Wan2.1-T2V-1.3B" +): Promise<{ message: string }> => { + const response = await fetch("/api/v1/vae/download", { + method: "POST", + headers: { "Content-Type": "application/json" }, + body: JSON.stringify({ vae_type: vaeType, model_name: modelName }), + }); + + if (!response.ok) { + const errorText = await response.text(); + throw new Error( + `VAE download failed: ${response.status} ${response.statusText}: ${errorText}` + ); + } + + const result = await response.json(); + return result; +}; diff --git a/src/scope/core/pipelines/wan2_1/vae/__init__.py b/src/scope/core/pipelines/wan2_1/vae/__init__.py index c643470a..ff5e7513 100644 --- a/src/scope/core/pipelines/wan2_1/vae/__init__.py +++ b/src/scope/core/pipelines/wan2_1/vae/__init__.py @@ -16,8 +16,39 @@ vae = create_vae(model_dir="wan_models", vae_path="/path/to/custom_vae.pth") """ +from dataclasses import dataclass + from .wan import WanVAEWrapper + +@dataclass(frozen=True) +class VAEMetadata: + """Metadata for a VAE type (filenames, download sources).""" + + filename: str + download_repo: str | None = None # None = bundled with main model repo + download_file: str | None = None # None = no separate download needed + + +# Single source of truth for VAE metadata +VAE_METADATA: dict[str, VAEMetadata] = { + "wan": VAEMetadata( + filename="Wan2.1_VAE.pth", + download_repo="Wan-AI/Wan2.1-T2V-1.3B", + download_file="Wan2.1_VAE.pth", + ), + "lightvae": VAEMetadata( + filename="lightvaew2_1.pth", + download_repo="lightx2v/Autoencoders", + download_file="lightvaew2_1.pth", + ), + "tae": VAEMetadata( + filename="taew2_1.pth", + download_repo="lightx2v/Autoencoders", + download_file="taew2_1.pth", + ), +} + # Registry mapping type names to VAE classes # UI dropdowns will use these keys VAE_REGISTRY: dict[str, type] = { @@ -69,8 +100,10 @@ def list_vae_types() -> list[str]: __all__ = [ "WanVAEWrapper", - "create_vae", - "list_vae_types", + "VAEMetadata", + "VAE_METADATA", "VAE_REGISTRY", "DEFAULT_VAE_TYPE", + "create_vae", + "list_vae_types", ] From a7e4b50b5d3d538a4e02f3031f3b1f2472824a5b Mon Sep 17 00:00:00 2001 From: RyanOnTheInside <7623207+ryanontheinside@users.noreply.github.com> Date: Fri, 2 Jan 2026 15:41:56 -0500 Subject: [PATCH 2/2] fix: use new artifact system Signed-off-by: RyanOnTheInside <7623207+ryanontheinside@users.noreply.github.com> --- frontend/src/lib/api.ts | 44 ------------------- .../core/pipelines/wan2_1/vae/__init__.py | 37 +--------------- src/scope/server/pipeline_artifacts.py | 31 +++++++++++++ 3 files changed, 33 insertions(+), 79 deletions(-) diff --git a/frontend/src/lib/api.ts b/frontend/src/lib/api.ts index bb80ac2f..50fa5b81 100644 --- a/frontend/src/lib/api.ts +++ b/frontend/src/lib/api.ts @@ -425,47 +425,3 @@ export const getPipelineSchemas = const result = await response.json(); return result; }; - -export const checkVaeStatus = async ( - vaeType: string, - modelName: string = "Wan2.1-T2V-1.3B" -): Promise<{ downloaded: boolean }> => { - const response = await fetch( - `/api/v1/vae/status?vae_type=${encodeURIComponent(vaeType)}&model_name=${encodeURIComponent(modelName)}`, - { - method: "GET", - headers: { "Content-Type": "application/json" }, - } - ); - - if (!response.ok) { - const errorText = await response.text(); - throw new Error( - `VAE status check failed: ${response.status} ${response.statusText}: ${errorText}` - ); - } - - const result = await response.json(); - return result; -}; - -export const downloadVae = async ( - vaeType: string, - modelName: string = "Wan2.1-T2V-1.3B" -): Promise<{ message: string }> => { - const response = await fetch("/api/v1/vae/download", { - method: "POST", - headers: { "Content-Type": "application/json" }, - body: JSON.stringify({ vae_type: vaeType, model_name: modelName }), - }); - - if (!response.ok) { - const errorText = await response.text(); - throw new Error( - `VAE download failed: ${response.status} ${response.statusText}: ${errorText}` - ); - } - - const result = await response.json(); - return result; -}; diff --git a/src/scope/core/pipelines/wan2_1/vae/__init__.py b/src/scope/core/pipelines/wan2_1/vae/__init__.py index ff5e7513..c643470a 100644 --- a/src/scope/core/pipelines/wan2_1/vae/__init__.py +++ b/src/scope/core/pipelines/wan2_1/vae/__init__.py @@ -16,39 +16,8 @@ vae = create_vae(model_dir="wan_models", vae_path="/path/to/custom_vae.pth") """ -from dataclasses import dataclass - from .wan import WanVAEWrapper - -@dataclass(frozen=True) -class VAEMetadata: - """Metadata for a VAE type (filenames, download sources).""" - - filename: str - download_repo: str | None = None # None = bundled with main model repo - download_file: str | None = None # None = no separate download needed - - -# Single source of truth for VAE metadata -VAE_METADATA: dict[str, VAEMetadata] = { - "wan": VAEMetadata( - filename="Wan2.1_VAE.pth", - download_repo="Wan-AI/Wan2.1-T2V-1.3B", - download_file="Wan2.1_VAE.pth", - ), - "lightvae": VAEMetadata( - filename="lightvaew2_1.pth", - download_repo="lightx2v/Autoencoders", - download_file="lightvaew2_1.pth", - ), - "tae": VAEMetadata( - filename="taew2_1.pth", - download_repo="lightx2v/Autoencoders", - download_file="taew2_1.pth", - ), -} - # Registry mapping type names to VAE classes # UI dropdowns will use these keys VAE_REGISTRY: dict[str, type] = { @@ -100,10 +69,8 @@ def list_vae_types() -> list[str]: __all__ = [ "WanVAEWrapper", - "VAEMetadata", - "VAE_METADATA", - "VAE_REGISTRY", - "DEFAULT_VAE_TYPE", "create_vae", "list_vae_types", + "VAE_REGISTRY", + "DEFAULT_VAE_TYPE", ] diff --git a/src/scope/server/pipeline_artifacts.py b/src/scope/server/pipeline_artifacts.py index f2aef480..46496c39 100644 --- a/src/scope/server/pipeline_artifacts.py +++ b/src/scope/server/pipeline_artifacts.py @@ -20,12 +20,31 @@ files=["Wan2_1-VACE_module_1_3B_bf16.safetensors"], ) +# Extra VAE artifacts (lightweight/alternative encoders) +LIGHTVAE_ARTIFACT = HuggingfaceRepoArtifact( + repo_id="lightx2v/Autoencoders", + files=["lightvaew2_1.pth"], +) + +TAE_ARTIFACT = HuggingfaceRepoArtifact( + repo_id="lightx2v/Autoencoders", + files=["taew2_1.pth"], +) + +LIGHTTAE_ARTIFACT = HuggingfaceRepoArtifact( + repo_id="lightx2v/Autoencoders", + files=["lighttaew2_1.pth"], +) + # Pipeline-specific artifacts PIPELINE_ARTIFACTS = { "streamdiffusionv2": [ WAN_1_3B_ARTIFACT, UMT5_ENCODER_ARTIFACT, VACE_ARTIFACT, + LIGHTVAE_ARTIFACT, + TAE_ARTIFACT, + LIGHTTAE_ARTIFACT, HuggingfaceRepoArtifact( repo_id="jerryfeng/StreamDiffusionV2", files=["wan_causal_dmd_v2v/model.pt"], @@ -35,6 +54,9 @@ WAN_1_3B_ARTIFACT, UMT5_ENCODER_ARTIFACT, VACE_ARTIFACT, + LIGHTVAE_ARTIFACT, + TAE_ARTIFACT, + LIGHTTAE_ARTIFACT, HuggingfaceRepoArtifact( repo_id="Efficient-Large-Model/LongLive-1.3B", files=["models/longlive_base.pt", "models/lora.pt"], @@ -43,6 +65,9 @@ "krea-realtime-video": [ WAN_1_3B_ARTIFACT, UMT5_ENCODER_ARTIFACT, + LIGHTVAE_ARTIFACT, + TAE_ARTIFACT, + LIGHTTAE_ARTIFACT, HuggingfaceRepoArtifact( repo_id="Wan-AI/Wan2.1-T2V-14B", files=["config.json"], @@ -56,6 +81,9 @@ WAN_1_3B_ARTIFACT, UMT5_ENCODER_ARTIFACT, VACE_ARTIFACT, + LIGHTVAE_ARTIFACT, + TAE_ARTIFACT, + LIGHTTAE_ARTIFACT, HuggingfaceRepoArtifact( repo_id="JaydenLu666/Reward-Forcing-T2V-1.3B", files=["rewardforcing.pt"], @@ -65,6 +93,9 @@ WAN_1_3B_ARTIFACT, UMT5_ENCODER_ARTIFACT, VACE_ARTIFACT, + LIGHTVAE_ARTIFACT, + TAE_ARTIFACT, + LIGHTTAE_ARTIFACT, HuggingfaceRepoArtifact( repo_id="KlingTeam/MemFlow", files=["base.pt", "lora.pt"],