Files
awoooi/apps/api/tests/test_chat_manager_ollama_routing.py
Your Name 3953ef6d57
All checks were successful
CD Pipeline / tests (push) Successful in 1m31s
Code Review / ai-code-review (push) Successful in 26s
CD Pipeline / build-and-deploy (push) Successful in 5m27s
CD Pipeline / post-deploy-checks (push) Successful in 1m40s
fix(ollama): disable thinking for deepseek call sites
2026-05-25 23:19:31 +08:00

115 lines
3.3 KiB
Python

from __future__ import annotations
from pathlib import Path
from types import SimpleNamespace
from typing import Any
import pytest
from src.services import chat_manager as chat_module
from src.services.chat_manager import ChatManager
class _FakeResponse:
def __init__(self, content: str = "老闆,系統目前穩定。") -> None:
self._content = content
def raise_for_status(self) -> None:
return None
def json(self) -> dict[str, Any]:
return {
"message": {"content": self._content},
"prompt_eval_count": 11,
"eval_count": 13,
}
class _FakeAsyncClient:
posted: list[tuple[str, dict[str, Any]]] = []
def __init__(self, *args: Any, **kwargs: Any) -> None:
self.args = args
self.kwargs = kwargs
async def __aenter__(self) -> _FakeAsyncClient:
return self
async def __aexit__(self, *args: Any) -> None:
return None
async def post(self, url: str, *, json: dict[str, Any]) -> _FakeResponse:
self.posted.append((url, json))
return _FakeResponse()
def _settings() -> SimpleNamespace:
return SimpleNamespace(OPENCLAW_DEFAULT_MODEL="qwen3:14b")
def _fake_ollama_order(_workload_type: str) -> tuple[SimpleNamespace, ...]:
return (
SimpleNamespace(url="http://gcp-a:11435", provider_name="ollama_gcp_a"),
SimpleNamespace(url="http://gcp-b:11436", provider_name="ollama_gcp_b"),
SimpleNamespace(url="http://local-111:11434", provider_name="ollama_local"),
)
@pytest.fixture(autouse=True)
def _reset_fake_client() -> None:
_FakeAsyncClient.posted = []
@pytest.mark.asyncio
async def test_openclaw_chat_uses_ollama_interactive_lane(
monkeypatch: pytest.MonkeyPatch,
) -> None:
monkeypatch.setattr(chat_module.httpx, "AsyncClient", _FakeAsyncClient)
monkeypatch.setattr(chat_module, "get_settings", _settings)
monkeypatch.setattr(
chat_module,
"resolve_ollama_order",
_fake_ollama_order,
)
result = await ChatManager()._call_openclaw("system context", "幫我看狀態")
assert result is not None
assert "qwen3:14b" in result
assert "免費" in result
assert len(_FakeAsyncClient.posted) == 1
url, payload = _FakeAsyncClient.posted[0]
assert url == "http://gcp-a:11435/api/chat"
assert payload["model"] == "qwen3:14b"
assert payload["messages"][0]["role"] == "system"
assert payload["messages"][1] == {"role": "user", "content": "幫我看狀態"}
@pytest.mark.asyncio
async def test_nemoclaw_chat_uses_resolved_interactive_lane(
monkeypatch: pytest.MonkeyPatch,
) -> None:
monkeypatch.setattr(chat_module.httpx, "AsyncClient", _FakeAsyncClient)
monkeypatch.setattr(
chat_module,
"resolve_ollama_order",
_fake_ollama_order,
)
result = await ChatManager()._call_nemotron("system context", "補充觀點")
assert result is not None
url, payload = _FakeAsyncClient.posted[0]
assert url == "http://gcp-a:11435/api/chat"
assert payload["model"] == "deepseek-r1:14b"
assert payload["think"] is False
def test_chat_manager_has_no_direct_gemini_generation_path() -> None:
source_path = Path(chat_module.__file__).resolve()
source = source_path.read_text(encoding="utf-8")
assert "generativelanguage.googleapis.com" not in source
assert "GEMINI_API_KEY" not in source