Spaces:
Running
Running
| """LTX 2.3 CPU Space — feasibility reference + ZeroGPU upgrade recipe. | |
| This Space documents why LTX 2.3 (22B) on free HF CPU is impractical and | |
| shows the upgrade path. Generation is disabled on CPU; the UI mirrors what | |
| a ZeroGPU fork would look like so users can clone and switch hardware in | |
| one click. | |
| """ | |
| from pathlib import Path | |
| import gradio as gr | |
| FEASIBILITY_TABLE = """\ | |
| | Hardware | Per 2-sec clip | Notes | | |
| |-----------------------|----------------|-----------------------------------| | |
| | Free CPU (this Space) | not feasible | 22B at Q3_K_M does not fit in 16 GB | | |
| | CPU Upgrade 32 GB | 30-60 min | marginal, $0.30/clip | | |
| | ZeroGPU (Pro) | 25-40 sec | recommended path | | |
| | GPU L40S 48 GB | ~8 sec | dedicated | | |
| """ | |
| PIPELINE_NOTE = """\ | |
| **Path A** (used here): Unsloth `distilled-1.1` GGUF Q3_K_M, 10.6 GB DiT + Gemma-3-12B-it Q3_K_M 6 GB encoder. ComfyUI-GGUF loader. | |
| **Path C** (research): 10Eros fine-tune + cond_safe distill LoRA — fine-tune, not distilled. Larger LoRAs harm 10Eros fine-tune; needs tuning. | |
| **Text encoder cannot be swapped** — diffusion U-Net is bound to `google/gemma-3-12b-it`. Only quantisation, not replacement, is valid. | |
| """ | |
| def cpu_generate_stub(prompt: str, duration_sec: float, steps: int) -> str: | |
| return ( | |
| "CPU inference is disabled on this free Space — 22B + 16 GB RAM is\n" | |
| "infeasible. Fork to ZeroGPU (see README) to enable generation.\n\n" | |
| f"Prompt received: {prompt[:100]}\n" | |
| f"Duration: {duration_sec:.1f} s\n" | |
| f"Steps: {steps}" | |
| ) | |
| def health() -> str: | |
| return "ok — LTX 2.3 CPU Space (documentation mode)" | |
| DEMO_VIDEOS = sorted(str(p) for p in Path("/app/assets/videos").glob("*.mp4")) | |
| with gr.Blocks(title="LTX 2.3 CPU") as demo: | |
| gr.Markdown("**LTX 2.3 CPU** — feasibility reference + ZeroGPU recipe. 22B video diffusion does not run on free CPU; this is a fork-and-upgrade template.") | |
| with gr.Row(equal_height=True): | |
| with gr.Column(scale=1): | |
| prompt_in = gr.Textbox(label="Prompt", placeholder="A woman walking through a neon-lit Tokyo alley at night, cinematic", lines=3) | |
| with gr.Row(): | |
| duration_in = gr.Slider(1.0, 4.0, value=2.0, step=0.5, label="Duration (s)") | |
| steps_in = gr.Slider(4, 16, value=8, step=1, label="Steps (distilled)") | |
| run_btn = gr.Button("Generate (disabled on CPU — fork to ZeroGPU)", variant="primary") | |
| status = gr.Textbox(label="Status", lines=5, interactive=False, show_copy_button=True) | |
| with gr.Column(scale=1): | |
| gr.Markdown("### Feasibility") | |
| gr.Markdown(FEASIBILITY_TABLE) | |
| gr.Markdown("### Pipeline") | |
| gr.Markdown(PIPELINE_NOTE) | |
| if DEMO_VIDEOS: | |
| gr.Examples( | |
| examples=[[v] for v in DEMO_VIDEOS], | |
| inputs=[gr.Video(visible=False)], | |
| examples_per_page=6, | |
| cache_examples=False, | |
| label="Reference outputs (pre-generated on GPU)", | |
| ) | |
| run_btn.click(fn=cpu_generate_stub, inputs=[prompt_in, duration_in, steps_in], outputs=[status], api_name="generate") | |
| gr.Button(visible=False).click(fn=health, outputs=[gr.Textbox(visible=False)], api_name="health") | |
| demo.queue(default_concurrency_limit=1) | |
| demo.launch(server_name="0.0.0.0", server_port=7860, theme=gr.themes.Soft()) | |