Co-authored-by: Claude (Opus 4.6) <claude@hermes.local> Co-committed-by: Claude (Opus 4.6) <claude@hermes.local>
This commit was merged in pull request #1165.
This commit is contained in:
@@ -1,12 +1,9 @@
|
||||
"""Tests for the three-tier metabolic LLM router (issue #966)."""
|
||||
|
||||
import asyncio
|
||||
from unittest.mock import AsyncMock, MagicMock, patch
|
||||
from unittest.mock import AsyncMock, MagicMock
|
||||
|
||||
import pytest
|
||||
|
||||
pytestmark = pytest.mark.unit
|
||||
|
||||
from infrastructure.router.metabolic import (
|
||||
DEFAULT_TIER_MODELS,
|
||||
MetabolicRouter,
|
||||
@@ -16,6 +13,7 @@ from infrastructure.router.metabolic import (
|
||||
get_metabolic_router,
|
||||
)
|
||||
|
||||
pytestmark = pytest.mark.unit
|
||||
|
||||
# ── classify_complexity ──────────────────────────────────────────────────────
|
||||
|
||||
@@ -198,7 +196,12 @@ class TestMetabolicRouter:
|
||||
async def test_t1_uses_t1_model(self):
|
||||
mock_cascade = MagicMock()
|
||||
mock_cascade.complete = AsyncMock(
|
||||
return_value={"content": "ok", "provider": "ollama-local", "model": "qwen3:8b", "latency_ms": 100}
|
||||
return_value={
|
||||
"content": "ok",
|
||||
"provider": "ollama-local",
|
||||
"model": "qwen3:8b",
|
||||
"latency_ms": 100,
|
||||
}
|
||||
)
|
||||
router = MetabolicRouter(cascade=mock_cascade)
|
||||
await router.route("go north", state={})
|
||||
@@ -208,7 +211,12 @@ class TestMetabolicRouter:
|
||||
async def test_t2_uses_t2_model(self):
|
||||
mock_cascade = MagicMock()
|
||||
mock_cascade.complete = AsyncMock(
|
||||
return_value={"content": "ok", "provider": "ollama-local", "model": "qwen3:14b", "latency_ms": 300}
|
||||
return_value={
|
||||
"content": "ok",
|
||||
"provider": "ollama-local",
|
||||
"model": "qwen3:14b",
|
||||
"latency_ms": 300,
|
||||
}
|
||||
)
|
||||
router = MetabolicRouter(cascade=mock_cascade)
|
||||
await router.route("what should I say to the innkeeper", state={})
|
||||
@@ -218,7 +226,12 @@ class TestMetabolicRouter:
|
||||
async def test_t3_uses_t3_model(self):
|
||||
mock_cascade = MagicMock()
|
||||
mock_cascade.complete = AsyncMock(
|
||||
return_value={"content": "ok", "provider": "ollama-local", "model": "qwen3:30b", "latency_ms": 2000}
|
||||
return_value={
|
||||
"content": "ok",
|
||||
"provider": "ollama-local",
|
||||
"model": "qwen3:30b",
|
||||
"latency_ms": 2000,
|
||||
}
|
||||
)
|
||||
router = MetabolicRouter(cascade=mock_cascade)
|
||||
await router.route("plan the optimal quest route", state={})
|
||||
@@ -228,7 +241,12 @@ class TestMetabolicRouter:
|
||||
async def test_custom_tier_models_respected(self):
|
||||
mock_cascade = MagicMock()
|
||||
mock_cascade.complete = AsyncMock(
|
||||
return_value={"content": "ok", "provider": "test", "model": "custom-8b", "latency_ms": 100}
|
||||
return_value={
|
||||
"content": "ok",
|
||||
"provider": "test",
|
||||
"model": "custom-8b",
|
||||
"latency_ms": 100,
|
||||
}
|
||||
)
|
||||
custom = {ModelTier.T1_ROUTINE: "custom-8b"}
|
||||
router = MetabolicRouter(cascade=mock_cascade, tier_models=custom)
|
||||
@@ -239,7 +257,12 @@ class TestMetabolicRouter:
|
||||
async def test_t3_pauses_world_before_inference(self):
|
||||
mock_cascade = MagicMock()
|
||||
mock_cascade.complete = AsyncMock(
|
||||
return_value={"content": "ok", "provider": "ollama", "model": "qwen3:30b", "latency_ms": 1500}
|
||||
return_value={
|
||||
"content": "ok",
|
||||
"provider": "ollama",
|
||||
"model": "qwen3:30b",
|
||||
"latency_ms": 1500,
|
||||
}
|
||||
)
|
||||
router = MetabolicRouter(cascade=mock_cascade)
|
||||
|
||||
@@ -281,7 +304,12 @@ class TestMetabolicRouter:
|
||||
async def test_t1_does_not_pause_world(self):
|
||||
mock_cascade = MagicMock()
|
||||
mock_cascade.complete = AsyncMock(
|
||||
return_value={"content": "ok", "provider": "ollama", "model": "qwen3:8b", "latency_ms": 120}
|
||||
return_value={
|
||||
"content": "ok",
|
||||
"provider": "ollama",
|
||||
"model": "qwen3:8b",
|
||||
"latency_ms": 120,
|
||||
}
|
||||
)
|
||||
router = MetabolicRouter(cascade=mock_cascade)
|
||||
|
||||
@@ -297,7 +325,12 @@ class TestMetabolicRouter:
|
||||
async def test_t2_does_not_pause_world(self):
|
||||
mock_cascade = MagicMock()
|
||||
mock_cascade.complete = AsyncMock(
|
||||
return_value={"content": "ok", "provider": "ollama", "model": "qwen3:14b", "latency_ms": 350}
|
||||
return_value={
|
||||
"content": "ok",
|
||||
"provider": "ollama",
|
||||
"model": "qwen3:14b",
|
||||
"latency_ms": 350,
|
||||
}
|
||||
)
|
||||
router = MetabolicRouter(cascade=mock_cascade)
|
||||
|
||||
@@ -314,7 +347,12 @@ class TestMetabolicRouter:
|
||||
"""If world.act() raises, inference must still complete."""
|
||||
mock_cascade = MagicMock()
|
||||
mock_cascade.complete = AsyncMock(
|
||||
return_value={"content": "done", "provider": "ollama", "model": "qwen3:30b", "latency_ms": 2000}
|
||||
return_value={
|
||||
"content": "done",
|
||||
"provider": "ollama",
|
||||
"model": "qwen3:30b",
|
||||
"latency_ms": 2000,
|
||||
}
|
||||
)
|
||||
router = MetabolicRouter(cascade=mock_cascade)
|
||||
|
||||
@@ -329,7 +367,12 @@ class TestMetabolicRouter:
|
||||
async def test_no_world_adapter_t3_still_works(self):
|
||||
mock_cascade = MagicMock()
|
||||
mock_cascade.complete = AsyncMock(
|
||||
return_value={"content": "plan done", "provider": "ollama", "model": "qwen3:30b", "latency_ms": 2000}
|
||||
return_value={
|
||||
"content": "plan done",
|
||||
"provider": "ollama",
|
||||
"model": "qwen3:30b",
|
||||
"latency_ms": 2000,
|
||||
}
|
||||
)
|
||||
router = MetabolicRouter(cascade=mock_cascade)
|
||||
# No set_world() called
|
||||
@@ -347,7 +390,12 @@ class TestMetabolicRouter:
|
||||
"""Calling route without ui_state should not raise."""
|
||||
mock_cascade = MagicMock()
|
||||
mock_cascade.complete = AsyncMock(
|
||||
return_value={"content": "ok", "provider": "ollama", "model": "qwen3:8b", "latency_ms": 100}
|
||||
return_value={
|
||||
"content": "ok",
|
||||
"provider": "ollama",
|
||||
"model": "qwen3:8b",
|
||||
"latency_ms": 100,
|
||||
}
|
||||
)
|
||||
router = MetabolicRouter(cascade=mock_cascade)
|
||||
# No ui_state argument
|
||||
@@ -357,7 +405,12 @@ class TestMetabolicRouter:
|
||||
async def test_temperature_and_max_tokens_forwarded(self):
|
||||
mock_cascade = MagicMock()
|
||||
mock_cascade.complete = AsyncMock(
|
||||
return_value={"content": "ok", "provider": "ollama", "model": "qwen3:14b", "latency_ms": 200}
|
||||
return_value={
|
||||
"content": "ok",
|
||||
"provider": "ollama",
|
||||
"model": "qwen3:14b",
|
||||
"latency_ms": 200,
|
||||
}
|
||||
)
|
||||
router = MetabolicRouter(cascade=mock_cascade)
|
||||
await router.route("describe the scene", state={}, temperature=0.1, max_tokens=50)
|
||||
|
||||
@@ -15,7 +15,6 @@ from bannerlord.models import (
|
||||
WarReward,
|
||||
)
|
||||
|
||||
|
||||
# ── KingSubgoal ───────────────────────────────────────────────────────────────
|
||||
|
||||
|
||||
@@ -35,7 +34,7 @@ class TestKingSubgoal:
|
||||
KingSubgoal(token="NUKE_CALRADIA")
|
||||
|
||||
def test_priority_clamp(self):
|
||||
with pytest.raises(Exception):
|
||||
with pytest.raises(ValueError):
|
||||
KingSubgoal(token="TRADE", priority=3.0)
|
||||
|
||||
def test_optional_fields_default_none(self):
|
||||
|
||||
Reference in New Issue
Block a user