The home server's Ollama doesn't have gpt-oss:20b pulled; qwen3:14b is already there and is what mammon's chat agent uses. Switching the default now so the first deploy passes the /healthz ollama probe without an extra `ollama pull` step. The spec lists gpt-oss:20b as a concrete example; qwen3:14b is equally on-prem and Ollama-structured-output-compatible. Touched: AppConfig default, BankStatementHeader Request.default_model, .env.example, setup_server.sh ollama-list check, AGENTS.md, deployment.md, live tests. Unit tests that hard-coded the old model string but don't assert the default were left alone. Also: ASCII en-dash in e2e_smoke.py Paperless-style text (ruff RUF001). Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
70 lines
2.3 KiB
Python
70 lines
2.3 KiB
Python
"""Live tests for :class:`OllamaClient` — gated on ``IX_TEST_OLLAMA=1``.
|
|
|
|
Never runs in CI (Forgejo runner has no LAN access to Ollama). Run locally::
|
|
|
|
IX_TEST_OLLAMA=1 uv run pytest tests/live/test_ollama_client_live.py -v
|
|
|
|
Assumes the Ollama server at ``http://192.168.68.42:11434`` already has
|
|
``qwen3:14b`` pulled.
|
|
"""
|
|
|
|
from __future__ import annotations
|
|
|
|
import os
|
|
|
|
import pytest
|
|
|
|
from ix.genai.ollama_client import OllamaClient
|
|
from ix.use_cases.bank_statement_header import BankStatementHeader
|
|
|
|
pytestmark = [
|
|
pytest.mark.live,
|
|
pytest.mark.skipif(
|
|
os.environ.get("IX_TEST_OLLAMA") != "1",
|
|
reason="live: IX_TEST_OLLAMA=1 required",
|
|
),
|
|
]
|
|
|
|
_OLLAMA_URL = "http://192.168.68.42:11434"
|
|
_MODEL = "qwen3:14b"
|
|
|
|
|
|
async def test_structured_output_round_trip() -> None:
|
|
"""Real Ollama returns a parsed BankStatementHeader instance."""
|
|
client = OllamaClient(base_url=_OLLAMA_URL, per_call_timeout_s=300.0)
|
|
result = await client.invoke(
|
|
request_kwargs={
|
|
"model": _MODEL,
|
|
"messages": [
|
|
{
|
|
"role": "system",
|
|
"content": (
|
|
"You extract bank statement header fields. "
|
|
"Return valid JSON matching the given schema. "
|
|
"Do not invent values."
|
|
),
|
|
},
|
|
{
|
|
"role": "user",
|
|
"content": (
|
|
"Bank: Deutsche Kreditbank (DKB)\n"
|
|
"Currency: EUR\n"
|
|
"IBAN: DE89370400440532013000\n"
|
|
"Period: 2025-01-01 to 2025-01-31"
|
|
),
|
|
},
|
|
],
|
|
},
|
|
response_schema=BankStatementHeader,
|
|
)
|
|
assert isinstance(result.parsed, BankStatementHeader)
|
|
assert isinstance(result.parsed.bank_name, str)
|
|
assert result.parsed.bank_name # non-empty
|
|
assert isinstance(result.parsed.currency, str)
|
|
assert result.model_name # server echoes a model name
|
|
|
|
|
|
async def test_selfcheck_ok_against_real_server() -> None:
|
|
"""``selfcheck`` returns ``ok`` when the target model is pulled."""
|
|
client = OllamaClient(base_url=_OLLAMA_URL, per_call_timeout_s=5.0)
|
|
assert await client.selfcheck(expected_model=_MODEL) == "ok"
|