"""Phase 8 component test: /api/reload-loras hot-swap. Verifies that ``VideoEngine.load_loras`` can be called again after startup and the idle clip is regenerated to reflect the new style. This test is the 'real model' version of test_07's reload endpoint stub. Run: docker compose exec voice-chat python -m tests.component.test_08_lora_reload """ from __future__ import annotations import hashlib from server.video import LoRASpec, VideoConfig, VideoEngine from tests.component._common import ensure_sample_avatar, get_logger, write_bytes log = get_logger("test_08") def run(): avatar_path = ensure_sample_avatar() cfg = VideoConfig.from_dict({"enabled": True, "mode": "reflective"}) engine = VideoEngine(cfg) engine.load_models() # Initial state: no LoRAs engine.set_avatar(avatar_path) idle_a = engine.get_idle_clip() assert idle_a is not None hash_a = hashlib.sha256(idle_a).hexdigest() write_bytes("phase8_idle_noloras.mp4", idle_a) log.info("idle (no LoRAs) sha256=%s", hash_a[:16]) # Hot-reload flow: unload (no-op), reload empty list, verify clip still generates. # There are no published 5B-Turbo-compatible LoRAs yet; when one exists, # construct a LoRASpec(path=..., target="both", weight=1.0) and compare hashes. engine.load_loras([]) engine.set_avatar(avatar_path) idle_b = engine.get_idle_clip() assert idle_b is not None hash_b = hashlib.sha256(idle_b).hexdigest() write_bytes("phase8_idle_reloaded.mp4", idle_b) log.info("idle (post-reload) sha256=%s", hash_b[:16]) log.info("PASS: hot-reload round-trip completed " "(hash match=%s — expected without a real LoRA applied).", hash_a == hash_b) if __name__ == "__main__": run()