HomePilot Deploy Bot
chore(hf): sync HomePilot to HF Space
921d377
|
Raw
History Blame Contribute Delete
4.71 kB
# Live-play playback subsystem
The live-play surface (`POST /v1/interactive/play/sessions/{sid}/chat`
+ `GET /pending`) runs the real-time scene-generation loop: chat
arrives, the planner composes a scene, a render job goes to the
video backend, and the clip streams back to the `InteractivePlayer`
in the frontend.
## Module map
| File | Responsibility |
|---|---|
| `scene_memory.py` | Rolling context snapshot (persona, mood, last N turns, synopsis). Pure, synchronous. |
| `scene_planner.py` | `plan_next_scene` (sync heuristic) + `plan_next_scene_async` (LLM first, heuristic fallback). |
| `llm_composer.py` | LLM-backed composer — `app.llm.chat_ollama` with strict JSON mode. |
| `video_job.py` | `ix_scene_queue` CRUD + `render_now` (sync stub) + `render_now_async` (real-first, stub fallback). |
| `render_adapter.py` | Thin async wrapper over `app.comfy.run_workflow` + `app.asset_registry.register_asset`. |
| `asset_urls.py` | `resolve_asset_url` — registry lookup for the frontend `<video src>`. |
| `schema.py` | Defensive `CREATE IF NOT EXISTS` for `ix_scene_queue`. |
| `playback_config.py` | Env-flag + tuning-knob loader. |
## Enabling Phase-2 in production
All flags default **off** so upgrading is a no-op until you opt in.
```bash
# LLM scene composer — uses the configured Ollama / OpenAI-compatible backend
export INTERACTIVE_PLAYBACK_LLM=1
export INTERACTIVE_PLAYBACK_LLM_TIMEOUT_S=12 # optional, default 12
export INTERACTIVE_PLAYBACK_LLM_MAX_TOKENS=350 # optional, default 350
export INTERACTIVE_PLAYBACK_LLM_TEMPERATURE=0.65 # optional, default 0.65
# Video renderer — submits scene prompts to ComfyUI via run_workflow
export INTERACTIVE_PLAYBACK_RENDER=1
export INTERACTIVE_PLAYBACK_RENDER_WORKFLOW=animate # optional, default 'animate'
export INTERACTIVE_PLAYBACK_RENDER_TIMEOUT_S=180 # optional, default 180
# Ollama + Comfy endpoints use the app-level config (unchanged)
export OLLAMA_BASE_URL=http://localhost:11434
export OLLAMA_MODEL=llama3.1:8b-instruct
export COMFY_BASE_URL=http://localhost:8188
```
Flip one or both flags per deployment — for example staging can
run the LLM composer with a stub renderer while the real video
backend warms up.
## Failure modes (graceful by design)
| Failure | Behaviour |
|---|---|
| `INTERACTIVE_PLAYBACK_LLM=1` but the LLM is unreachable / slow / malformed JSON | Falls back to the heuristic composer. No user-visible error. Structured log lines: `playback_llm_timeout`, `playback_llm_error`, `playback_llm_malformed_json`. |
| `INTERACTIVE_PLAYBACK_RENDER=1` but ComfyUI is down / times out / no output | Falls back to the phase-1 stub asset id. Job still lands `ready`. Logs: `playback_render_timeout`, `playback_render_error`, `playback_render_no_output`. |
| `asset_registry.get_asset` throws | `resolve_asset_url` returns `None`; frontend shows the mood backdrop. |
| Policy gate (`check_free_input`) blocks the message | `/chat` returns `{"status": "blocked", …}` without invoking the planner or render pipeline. |
Each fallback keeps the player's polling loop in a terminal
state, so the UI never hangs on a half-resolved turn.
## Observability
All structured logs share an `extra={"session_id": …}` field for
correlation. Grep-friendly event names:
- `playback_llm_timeout` / `playback_llm_error` / `playback_llm_malformed_json` / `playback_llm_empty_content` / `playback_llm_missing_fields`
- `playback_render_timeout` / `playback_render_error` / `playback_render_no_output`
- `playback_asset_register_failed`
- `playback_asset_lookup_failed`
Job-id stamps in `ix_scene_queue.job_id` carry a prefix so you
can separate the two render paths at a glance:
- `stub-*` — phase-1 fallback path used this request
- `live-*` — phase-2 real render was attempted
## Test coverage
The subsystem ships with 60+ tests across 7 files:
```
tests/test_interactive_playback_memory.py rolling context + synopsis
tests/test_interactive_playback_planner.py heuristic composer
tests/test_interactive_playback_planner_async.py LLM-first dispatch
tests/test_interactive_playback_llm_composer.py LLM parsing + guardrails
tests/test_interactive_playback_jobs.py scene queue + state machine
tests/test_interactive_playback_jobs_async.py render_now_async fallback
tests/test_interactive_playback_render_adapter.py ComfyUI adapter contract
tests/test_interactive_playback_chat.py /chat route end-to-end
tests/test_interactive_playback_asset_urls.py URL resolver
tests/test_interactive_playback_config.py env flag loader
```
Every test monkey-patches the real external call (chat_ollama,
run_workflow, register_asset) so CI never reaches for a network.