seriffic's picture
Backend evolution: Phases 1-10 specialists + agentic FSM + Mellea + LiteLLM router
6a82282
"""End-to-end smoke test for the inference ensemble.
Verifies on the droplet that:
- All three adapters load cleanly into a shared TerraMind base.
- Hot-swapping between them produces different outputs.
- Each adapter's output shape matches its declared num_classes.
Run inside the terramind container:
cd /workspace/phase18
python3 scripts/smoke_ensemble.py
"""
from __future__ import annotations
import sys
from pathlib import Path
import torch
sys.path.insert(0, str(Path(__file__).resolve().parent.parent / "shared"))
from inference_ensemble import TerraMindNYCEnsemble # noqa: E402
def main():
ens = TerraMindNYCEnsemble(
adapters_root=Path(__file__).resolve().parent.parent / "adapters")
names = ens.discover()
print(f"Discovered adapters: {names}")
assert names, "no adapters found"
# Synthetic batch — temporal multi-modal, matching all three configs.
s2 = torch.randn(12, 4, 224, 224)
s1 = torch.randn(2, 4, 224, 224)
dem = torch.randn(1, 4, 224, 224)
for name in names:
out = ens.infer(s2l2a=s2, s1rtc=s1, dem=dem, tasks=[name])
pred = out[name]
print(f" {name}: pred shape={tuple(pred.shape)}, "
f"unique={pred.unique().tolist()}")
# Round-trip swap
print("\nSwap order: " + " -> ".join(names + [names[0]]))
seq = ens.infer(s2l2a=s2, s1rtc=s1, dem=dem, tasks=names + [names[0]])
a, b = seq[names[0] + "_2"] if names[0] + "_2" in seq else seq[names[0]], seq[names[0]]
# The infer() function returns a single key per task; swapping back
# to the same task should produce the same output deterministically
# (within fp precision).
print(f" Swap stability check: same-adapter outputs equal -> "
f"{'OK' if torch.equal(a, b) else 'WARN: not bitwise equal'}")
print(ens.info())
if __name__ == "__main__":
sys.exit(main())