"""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 with a distill LoRA specs = [ LoRASpec( path="lightx2v/Wan2.2-Distill-Loras:" "wan2.2_i2v_A14b_high_noise_lora_rank64_lightx2v_4step.safetensors", weight=1.0, target="high_noise", name="distill-hi", ), ] engine.load_loras(specs) 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_withlora.mp4", idle_b) log.info("idle (with LoRA) sha256=%s", hash_b[:16]) if hash_a != hash_b: log.info("PASS: idle clip changed after LoRA reload") else: log.warning("clips identical — LoRA may not be applied; eyeball _out/*.mp4") if __name__ == "__main__": run()