Files
OpenJarvis/tests/engine/test_mlx.py
T
Jon Saad-FalconandClaude Opus 4.6 24972e3e52 Add Phase 12+13: energy measurement, install polish, PWA, cross-hardware
Phase 12 — Energy Measurement Upgrade:
- EnergyMonitor ABC with multi-vendor support (NVIDIA hw counters,
  AMD amdsmi, Apple zeus-ml, CPU RAPL sysfs)
- EnergyBatch batch-level energy-per-token accounting
- SteadyStateDetector CV-based thermal equilibrium detection
- EnergyBenchmark with warmup phase
- InstrumentedEngine prefers EnergyMonitor over legacy GpuMonitor
- Telemetry store/aggregator extended with energy fields

Phase 13 — Install, Hosting, Cross-Hardware:
- jarvis doctor diagnostic command (8 checks, --json output)
- jarvis init post-setup guidance with engine-specific next steps
- README Quick Start section
- MLX engine backend (Apple Silicon → mlx recommendation)
- AMD VRAM/multi-GPU detection via rocm-smi
- PyTorch MPS device selection in orchestrator trainers
- PWA support (vite-plugin-pwa, service worker, manifest, icons)
- Server static file serving fix for PWA files
- Dockerfile.gpu.rocm + docker-compose.gpu.rocm.yml for ROCm
- Eval framework display module and efficiency metrics

2244 tests pass, 37 skipped.

Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
2026-02-26 20:09:07 +00:00

73 lines
2.4 KiB
Python

"""Tests for the MLX engine (OpenAI-compatible)."""
from __future__ import annotations
import httpx
import pytest
import respx
from openjarvis.core.registry import EngineRegistry
from openjarvis.core.types import Message, Role
from openjarvis.engine._base import EngineConnectionError
from openjarvis.engine.mlx import MLXEngine
@pytest.fixture()
def engine() -> MLXEngine:
EngineRegistry.register_value("mlx", MLXEngine)
return MLXEngine(host="http://testhost:8080")
class TestMLXGenerate:
def test_generate_returns_content(self, engine: MLXEngine) -> None:
with respx.mock:
respx.post("http://testhost:8080/v1/chat/completions").mock(
return_value=httpx.Response(
200,
json={
"choices": [
{
"message": {"content": "4"},
"finish_reason": "stop",
}
],
"usage": {
"prompt_tokens": 8,
"completion_tokens": 1,
"total_tokens": 9,
},
"model": "mlx-model",
},
)
)
result = engine.generate(
[Message(role=Role.USER, content="2+2")], model="mlx-model"
)
assert result["content"] == "4"
def test_generate_connection_error(self, engine: MLXEngine) -> None:
with respx.mock:
respx.post("http://testhost:8080/v1/chat/completions").mock(
side_effect=httpx.ConnectError("refused")
)
with pytest.raises(EngineConnectionError):
engine.generate(
[Message(role=Role.USER, content="Hi")], model="m"
)
class TestMLXHealth:
def test_health_true(self, engine: MLXEngine) -> None:
with respx.mock:
respx.get("http://testhost:8080/v1/models").mock(
return_value=httpx.Response(200, json={"data": []})
)
assert engine.health() is True
def test_health_false(self, engine: MLXEngine) -> None:
with respx.mock:
respx.get("http://testhost:8080/v1/models").mock(
side_effect=httpx.ConnectError("refused")
)
assert engine.health() is False