53 lines
1.7 KiB
Python
53 lines
1.7 KiB
Python
"""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()
|