| """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 |
|
|
|
|
| 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" |
|
|
| |
| 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()}") |
|
|
| |
| 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]] |
| |
| |
| |
| 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()) |
|
|