catBox-Docker / README.md
sivaratrisrinivas
polish: refine browser outcome and trace presentation
0035cb7
|
Raw
History Blame Contribute Delete
9.65 kB
metadata
title: Catbox
sdk: docker
app_port: 7860

catBox

Catbox is an interactive image-generation demo. You open a sealed box, a local image model runs, and the box turns into either a cozy cat scene or an eerie lifeless-cat scene.

What this project is

Catbox is a thin local product slice around a real image model. The user-facing experience is intentionally small: the Browser UI starts from a sealed box, the user observes it, and the local Model Backend generates one real Generated Outcome. The outcome is either a Living-Cat Outcome or a Dead-Cat Outcome.

The project is not a static reveal, a canvas-only animation, a gallery, or a prompt playground. The normal path does not let the Browser UI choose the outcome or tune generation. Those controls exist only in development paths for validation and reproducibility.

Why this exists

The model spike showed that sd_turbo_img2img can create recognizable cat and empty-box images after the model is loaded; Catbox now uses that same path for a living-cat branch and a non-graphic dead-cat branch. This backend turns that experiment into code the rest of Catbox can use:

  • the browser asks to observe the box instead of choosing the result itself;
  • the backend is the source of truth for which scene was chosen;
  • Dev Controls can force living or dead without changing normal observation behavior;
  • Dev Controls can pass a seed and generation settings to reproduce a run;
  • generated images are returned as local file paths plus details about the run;
  • real intermediate frames can be captured as a single-branch Captured Denoising Trace when the runner supports it;
  • failures stay visible instead of being hidden behind placeholder images.

Catbox v1 treats generated files as Ephemeral Outcomes. They may exist locally long enough for display and debugging, but the product does not provide gallery/history/save/share behavior.

Model backend and Browser UI

The current code defines the small Python boundary that the Browser UI calls:

  • readiness() says whether the model backend is ready.
  • observe() is the normal path. The backend chooses which scene to generate.
  • observe_with_dev_controls(...) is for development only. It can force the living-cat scene or the dead-cat scene, and it can reuse a seed or generation settings.
  • Successful observations return the chosen scene, a local image file path, timing details, and a short note for the reveal.
  • Failed observations return a clear error instead of pretending that an image was generated.

The SD Turbo runner is the real product path for the first Model Backend. It loads stabilityai/sd-turbo once, loads the shared Box Composition, picks the right Outcome Prompt, writes an ephemeral generated image under .runtime/, and returns the local file path plus generation metadata through the backend contract.

The fake runner is only for tests and early wiring. It lets the backend behavior be checked quickly without CUDA, model downloads, or slow image generation.

The local Browser UI is served by python -m catbox.browser_ui. It is a full-screen sealed-system interface rather than a card-based demo. It sends a normal observation request without choosing an outcome, polls for real Captured Denoising Trace frames while the Model Backend runs, and reveals the generated image only after the backend-provided local file reference has loaded. Observation Noise remains a fallback before the first captured frame appears, and the trace surface is intentionally treated as a secondary instrument view instead of competing with the final Generated Outcome. The Browser UI keeps each state in normal document flow so the header, apparatus view, status text, and controls do not overlap. When the generated outcome loads, the page scrolls the revealed apparatus into view so the image is visible inside the viewport, with the final image presented as the dominant visual state. The Browser UI keeps the Model Backend authoritative, shows the Reveal Note, and supports Reset back to the sealed box. If generation fails, the Browser UI shows Generation Failure with Retry and Reset instead of registering or serving a fake generated image.

How the project fits together

  • catbox/model_backend.py owns readiness, Outcome Selection, Dev Controls, and the observation response contract.
  • catbox/sd_turbo_runner.py owns the persistent SD Turbo image-to-image runner, prompt selection, generation settings, timing, and ephemeral file output.
  • catbox/browser_ui.py owns the local Browser UI, readiness polling, normal observation requests, trace polling, generated image serving, Progressive Waiting, Generation Failure, Retry, and Reset.
  • catbox/validate_sd_turbo_runner.py is the manual Dev Controls validation entrypoint for forcing outcomes and running Outcome Visibility tuning on the target GPU runtime.
  • tests/ covers the public backend, runner, Browser UI, and manual validation documentation contracts with fakes and stubs instead of requiring GPU access.
  • docs/adr/ records the project decisions that keep the Browser UI thin, the Model Backend authoritative, and Generated Outcomes ephemeral.

How to verify

Run the contract tests:

uv run python -m unittest discover -s tests

These tests use fakes and stubs around the expensive model path. They do not need GPU access or model downloads.

If you want Hugging Face authenticated downloads, create a local .env file:

cp .env.example .env

Then edit .env:

HF_TOKEN=hf_your_read_token_here

The Browser UI startup command and manual validation command load .env before the SD Turbo runner requests model files. .env is ignored by git and should not be committed.

Run the local Browser UI:

uv run python -m catbox.browser_ui

Then open http://127.0.0.1:8765. The page starts from the sealed box, sends a normal observation request to the Model Backend without choosing an outcome, and keeps backend startup separate from active observation. During observation it polls the trace endpoint and displays Captured Denoising Trace frames as they are registered by the Model Backend, including a final-trace display from the completed observation response if polling misses the last frame. It reveals a subtle Progressive Waiting status only if generation takes long enough, reveals the generated image from the returned local file reference, scrolls the revealed apparatus into view, shows the Reveal Note, and lets Reset return to the sealed box. The layout is vertically scrollable on small screens, and inactive states are removed from layout so they cannot cover the active state or controls. If generation fails, the Browser UI shows a Generation Failure state with Retry and Reset instead of substituting a static image or fake Generated Outcome. The first real run may download model files before the observation completes.

Manual GPU validation for the preferred GPU runtime:

uv run python -m catbox.validate_sd_turbo_runner --outcome all --seed 41100

That command preloads SD Turbo once, forces both Catbox outcomes through the development-only path, writes ephemeral generated images under .runtime/, and prints the same response shape the Browser UI will use.

To test one explicit tuning candidate, pass generation settings through Dev Controls:

uv run python -m catbox.validate_sd_turbo_runner --outcome dead --seed 41100 --steps 6 --strength 0.7 --width 512 --height 512

To run the first Outcome Visibility matrix on the deployed GPU runtime:

uv run python -m catbox.validate_sd_turbo_runner --matrix --seed 41100

The default matrix tries both outcomes with steps 4,6,8, sizes 512,768, Living-Cat Outcome strengths 0.75,0.8,0.85, and Dead-Cat Outcome strengths 0.6,0.7,0.8. Choose the fastest passing candidate where both final Generated Outcomes are immediately recognizable, the Dead-Cat Outcome remains non-graphic, the shared Box Composition is still legible, and metadata.generationSeconds stays under the Primary Runtime Target.

The current tuned SD Turbo defaults emphasize Outcome Visibility: both outcomes use 512px image-to-image generation with 6 steps. The Living-Cat Outcome uses strength 0.78, and the Dead-Cat Outcome uses strength 0.7.

For the complete first-observation GPU validation checklist, including Browser UI readiness, normal observation, forced Dev Controls outcomes, runtime timing, ephemeral output files, and failure retry/reset behavior, see docs/manual-gpu-validation.md.

Deploy on Hugging Face Spaces

The preferred public deployment target is a Docker Hugging Face Space with GPU hardware. The container serves Catbox on port 7860, which is the default external port for Spaces.

Create a new Hugging Face Space with these settings:

  • SDK: Docker
  • Visibility: Public or Protected
  • Hardware: start with 1x Nvidia L4; use Nvidia A10G - small if L4 is too slow or unavailable

Add a Space secret named HF_TOKEN if the model download requires authenticated Hugging Face access.

Push this repository's contents to the Space git remote. The Space README metadata at the top of this file tells Hugging Face to build the Docker image and expose port 7860. The Space will start python -m catbox.browser_ui, download sd-turbo on first startup if it is not already cached, and serve the app from the Space URL.

Generated outcomes and Captured Denoising Trace frames are still ephemeral in the deployed container. They are written under .runtime/generated-outcomes and may be lost when the Space restarts.