"""Validated runtime configuration derived from the user-editable ``space_config``. Only fork-author customization belongs in ``space_config.py``. This module owns normalization, safety fallbacks, derived values, runtime-only constants, and model-download allow patterns so ``app.py`` can focus on Gradio composition. """ from __future__ import annotations import os from space_config import ( AUTO_DURATION_ENABLED, AUTO_DURATION_MAX_SECONDS, AUTO_DURATION_MIN_SECONDS, A2V_ENABLED, DEFAULT_ATTENTION_BACKEND, DEFAULT_DURATION_SECONDS, DEFAULT_LORA_STRENGTH, DEFAULT_RANDOMIZE_SEED, DEFAULT_RESOLUTION, DEFAULT_SEED, DEFAULT_SELECTED_LORAS, DEFAULT_USE_AUTO_DURATION, DEFAULT_USE_DIFFUSION_DECODER, DIFFUSION_DECODER_ENABLED, EXPERIMENTAL_MAX_SECONDS, FRAME_RATE, FULL_SFT_STAGE2_LORA_REPO_ID, FULL_SFT_STAGE2_LORA_REVISION, FULL_SFT_STAGE2_LORA_STRENGTH, FULL_SFT_TRANSFORMER_PATH, FULL_SFT_TRANSFORMER_REPO_ID, FULL_SFT_TRANSFORMER_REVISION, IC_COLORIZER_ENABLED, IC_PIXEL_UPSCALER_ENABLED, IC_INOUTPAINT_ENABLED, MODEL_QUANTIZATION_POLICY, MODEL_REPO_ID, MODEL_REVISION, MODEL_RUNTIME_PROFILE, PROMPT_ENHANCER_ENABLED, PROMPT_ENHANCER_QUANTIZATION_POLICY, RESOLUTIONS, STANDARD_MAX_SECONDS, ZEROGPU_GPU_SIZE, ) from . import app_helpers CANONICAL_MODEL_REPO_ID = "Lightricks/LTX-2.5-Diffusers" CANONICAL_MODEL_REVISION = "549f18015d588ce728aad02aebff9212d94f598e" MAX_FRAMES = int(round(EXPERIMENTAL_MAX_SECONDS * FRAME_RATE)) # LTX temporal grid is 8k+1; canonical 30s/24fps endpoint is 721f. MAX_FRAMES = int(round((MAX_FRAMES - 1) / 8) * 8 + 1) GPU_CONCURRENCY_ID = "ltx25-gpu" FULL_SFT_STAGE2_ADAPTER_NAME = "stage_2_distilled" ZERO_GPU_ENV_KEYS = ("SPACES_ZERO_GPU", "ZEROGPU_V2", "SPACE_ZERO_GPU", "ZERO_GPU") ZERO_GPU_TEXT_ENV_KEYS = ( "SPACE_HARDWARE", "HF_SPACE_HARDWARE", "SPACE_RUNTIME", "SPACES_RUNTIME", "HF_SPACE_RUNTIME" ) TRUE_VALUES = {"1", "true", "t", "yes", "y", "on", "zerogpu", "zero"} IS_ZEROGPU = app_helpers.detect_zerogpu_env( os.environ, bool_keys=ZERO_GPU_ENV_KEYS, text_keys=ZERO_GPU_TEXT_ENV_KEYS, true_values=TRUE_VALUES, ) ATTENTION_BACKEND = os.environ.get("LTX25_ATTENTION_BACKEND", DEFAULT_ATTENTION_BACKEND).strip().lower() CONFIG_WARNINGS: list[str] = [] def _safe_config_float(name: str, value, default: float, minimum: float, maximum: float) -> float: return app_helpers.safe_config_float(name, value, default, minimum, maximum, warnings=CONFIG_WARNINGS) def _safe_config_int(name: str, value, default: int) -> int: return app_helpers.safe_config_int(name, value, default, warnings=CONFIG_WARNINGS) def _safe_config_bool(value, default: bool) -> bool: return app_helpers.safe_config_bool(value, default, warnings=CONFIG_WARNINGS, true_values=TRUE_VALUES) QUANTIZATION_POLICY = str(MODEL_QUANTIZATION_POLICY or "nf4_auto").strip().lower() if QUANTIZATION_POLICY not in {"nf4_auto", "repo_native"}: CONFIG_WARNINGS.append( f"Unsupported MODEL_QUANTIZATION_POLICY={MODEL_QUANTIZATION_POLICY!r}; using safe default 'nf4_auto'." ) QUANTIZATION_POLICY = "nf4_auto" RUNTIME_PROFILE = str(MODEL_RUNTIME_PROFILE or "distilled_nf4").strip().lower() if RUNTIME_PROFILE not in {"distilled_nf4", "full_sft_nf4"}: CONFIG_WARNINGS.append( f"Unsupported MODEL_RUNTIME_PROFILE={MODEL_RUNTIME_PROFILE!r}; using safe default 'distilled_nf4'." ) RUNTIME_PROFILE = "distilled_nf4" IS_FULL_SFT_PROFILE = RUNTIME_PROFILE == "full_sft_nf4" EFFECTIVE_ZEROGPU_GPU_SIZE = str(ZEROGPU_GPU_SIZE or "large").strip().lower() if EFFECTIVE_ZEROGPU_GPU_SIZE not in {"large", "xlarge"}: CONFIG_WARNINGS.append(f"Unsupported ZEROGPU_GPU_SIZE={ZEROGPU_GPU_SIZE!r}; using canonical 'large'.") EFFECTIVE_ZEROGPU_GPU_SIZE = "large" EFFECTIVE_A2V_ENABLED = bool(A2V_ENABLED) EFFECTIVE_IC_COLORIZER_ENABLED = bool(IC_COLORIZER_ENABLED) IC_COLORIZER_AVAILABLE = EFFECTIVE_IC_COLORIZER_ENABLED EFFECTIVE_IC_PIXEL_UPSCALER_ENABLED = bool(IC_PIXEL_UPSCALER_ENABLED) IC_PIXEL_UPSCALER_AVAILABLE = EFFECTIVE_IC_PIXEL_UPSCALER_ENABLED and not IS_FULL_SFT_PROFILE EFFECTIVE_IC_INOUTPAINT_ENABLED = bool(IC_INOUTPAINT_ENABLED) IC_INOUTPAINT_AVAILABLE = EFFECTIVE_IC_INOUTPAINT_ENABLED and not IS_FULL_SFT_PROFILE FULL_SFT_TRANSFORMER_REPO_EFFECTIVE = str(FULL_SFT_TRANSFORMER_REPO_ID or MODEL_REPO_ID).strip() FULL_SFT_TRANSFORMER_REVISION_EFFECTIVE = str(FULL_SFT_TRANSFORMER_REVISION or MODEL_REVISION or "").strip() or None FULL_SFT_STAGE2_LORA_REPO_EFFECTIVE = str(FULL_SFT_STAGE2_LORA_REPO_ID or MODEL_REPO_ID).strip() FULL_SFT_STAGE2_LORA_REVISION_EFFECTIVE = str(FULL_SFT_STAGE2_LORA_REVISION or MODEL_REVISION or "").strip() or None EFFECTIVE_DEFAULT_DURATION_SECONDS = _safe_config_float( "DEFAULT_DURATION_SECONDS", DEFAULT_DURATION_SECONDS, 1.0, 1.0, STANDARD_MAX_SECONDS ) EFFECTIVE_DEFAULT_LORA_STRENGTH = _safe_config_float( "DEFAULT_LORA_STRENGTH", DEFAULT_LORA_STRENGTH, 1.0, 0.0, 2.0 ) EFFECTIVE_FULL_SFT_STAGE2_LORA_STRENGTH = _safe_config_float( "FULL_SFT_STAGE2_LORA_STRENGTH", FULL_SFT_STAGE2_LORA_STRENGTH, 1.0, 0.0, 2.0 ) EFFECTIVE_DEFAULT_SEED = _safe_config_int("DEFAULT_SEED", DEFAULT_SEED, 42) EFFECTIVE_DEFAULT_RANDOMIZE_SEED = _safe_config_bool(DEFAULT_RANDOMIZE_SEED, True) EFFECTIVE_DIFFUSION_DECODER_ENABLED = _safe_config_bool(DIFFUSION_DECODER_ENABLED, True) EFFECTIVE_PROMPT_ENHANCER_ENABLED = _safe_config_bool(PROMPT_ENHANCER_ENABLED, True) EFFECTIVE_AUTO_DURATION_ENABLED = _safe_config_bool(AUTO_DURATION_ENABLED, True) EFFECTIVE_DEFAULT_USE_AUTO_DURATION = _safe_config_bool(DEFAULT_USE_AUTO_DURATION, False) and EFFECTIVE_AUTO_DURATION_ENABLED EFFECTIVE_AUTO_DURATION_MIN_SECONDS = _safe_config_float( "AUTO_DURATION_MIN_SECONDS", AUTO_DURATION_MIN_SECONDS, 1.0, 0.5, STANDARD_MAX_SECONDS - 0.5 ) EFFECTIVE_AUTO_DURATION_MAX_SECONDS = _safe_config_float( "AUTO_DURATION_MAX_SECONDS", AUTO_DURATION_MAX_SECONDS, 8.0, 1.0, STANDARD_MAX_SECONDS ) if EFFECTIVE_AUTO_DURATION_MIN_SECONDS >= EFFECTIVE_AUTO_DURATION_MAX_SECONDS: CONFIG_WARNINGS.append( "AUTO_DURATION_MIN_SECONDS must be less than AUTO_DURATION_MAX_SECONDS; using 1.0s / 8.0s." ) EFFECTIVE_AUTO_DURATION_MIN_SECONDS = 1.0 EFFECTIVE_AUTO_DURATION_MAX_SECONDS = 8.0 PROMPT_ENHANCER_POLICY = str(PROMPT_ENHANCER_QUANTIZATION_POLICY or "nf4_auto").strip().lower() if PROMPT_ENHANCER_POLICY not in {"nf4_auto", "repo_native"}: CONFIG_WARNINGS.append( f"Unsupported PROMPT_ENHANCER_QUANTIZATION_POLICY={PROMPT_ENHANCER_QUANTIZATION_POLICY!r}; " "using safe default 'nf4_auto'." ) PROMPT_ENHANCER_POLICY = "nf4_auto" EFFECTIVE_DEFAULT_USE_DIFFUSION_DECODER = ( _safe_config_bool(DEFAULT_USE_DIFFUSION_DECODER, False) and EFFECTIVE_DIFFUSION_DECODER_ENABLED ) try: app_helpers.parse_resolution_value(str(DEFAULT_RESOLUTION), resolutions=RESOLUTIONS) EFFECTIVE_DEFAULT_RESOLUTION = str(DEFAULT_RESOLUTION).strip() except Exception: EFFECTIVE_DEFAULT_RESOLUTION = next(iter(RESOLUTIONS), "512 × 512 · validated") CONFIG_WARNINGS.append( f"Invalid DEFAULT_RESOLUTION={DEFAULT_RESOLUTION!r}; using {EFFECTIVE_DEFAULT_RESOLUTION!r}." ) if isinstance(DEFAULT_SELECTED_LORAS, (list, tuple, set)): EFFECTIVE_DEFAULT_SELECTED_LORAS = [str(x) for x in DEFAULT_SELECTED_LORAS if str(x).strip()] else: CONFIG_WARNINGS.append("DEFAULT_SELECTED_LORAS must be a list/tuple/set; using no default LoRAs.") EFFECTIVE_DEFAULT_SELECTED_LORAS = [] ALLOW_PATTERNS = [ "model_index.json", "vae/*", "audio_vae/*", "vocoder/*", "connectors/*", "text_encoder/*", "tokenizer/*", "scheduler/*", "latent_upsampler/*", ] if IS_FULL_SFT_PROFILE: if ( FULL_SFT_TRANSFORMER_REPO_EFFECTIVE == str(MODEL_REPO_ID).strip() and FULL_SFT_TRANSFORMER_REVISION_EFFECTIVE == (str(MODEL_REVISION or "").strip() or None) ): ALLOW_PATTERNS.append(f"{str(FULL_SFT_TRANSFORMER_PATH or 'transformer_full').strip().strip('/')}/*") else: ALLOW_PATTERNS.append("transformer/*") if EFFECTIVE_DIFFUSION_DECODER_ENABLED: ALLOW_PATTERNS.append("diffusion_decoder/*") if EFFECTIVE_AUTO_DURATION_ENABLED: ALLOW_PATTERNS.append("duration_head/*")