fix(llm): resolve score runtime config from saved profiles

Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com>
This commit is contained in:
2026-06-26 20:34:01 +08:00
parent 754a30ad59
commit 1df4010acc
5 changed files with 117 additions and 6 deletions

View File

@@ -1,6 +1,7 @@
"""Integration tests for /api/llm-profiles endpoints."""
import pytest
from fastapi.testclient import TestClient
from unittest.mock import patch
@pytest.fixture()
@@ -41,19 +42,23 @@ def test_update_profile(client):
pid = client.post("/api/llm-profiles", json=body).json()["profile_id"]
upd = {"name": "New", "model": "m2", "base_url": "http://x/v1", "api_key": "k", "timeout_seconds": 60}
resp = client.put(f"/api/llm-profiles/{pid}", json=upd)
with patch("webapp.services.inline_scorer.inline_scorer.invalidate_cache") as invalidate:
resp = client.put(f"/api/llm-profiles/{pid}", json=upd)
assert resp.status_code == 200
assert resp.json()["name"] == "New"
assert resp.json()["timeout_seconds"] == 60
invalidate.assert_called_once()
def test_delete_profile(client):
body = {"name": "Del", "model": "m", "base_url": "http://x/v1", "api_key": "k"}
pid = client.post("/api/llm-profiles", json=body).json()["profile_id"]
resp = client.delete(f"/api/llm-profiles/{pid}")
with patch("webapp.services.inline_scorer.inline_scorer.invalidate_cache") as invalidate:
resp = client.delete(f"/api/llm-profiles/{pid}")
assert resp.status_code == 200
assert resp.json()["deleted"] is True
assert len(client.get("/api/llm-profiles").json()["profiles"]) == 0
invalidate.assert_called_once()
def test_update_nonexistent(client):
@@ -185,7 +190,7 @@ def test_apply_doc_weights_patches_yaml(tmp_path):
# ---------------------------------------------------------------------------
# Connectivity test endpoint tests
# ---------------------------------------------------------------------------
from unittest.mock import MagicMock, patch
from unittest.mock import MagicMock
def test_probe_connectivity_success(client):

View File

@@ -98,3 +98,52 @@ def test_get_nonexistent(tmp_path):
def test_delete_nonexistent(tmp_path):
mgr = _make_manager(tmp_path)
assert mgr.delete("does-not-exist") is False
def test_resolve_openai_client_kwargs_prefers_matching_profile(tmp_path, monkeypatch):
"""Metric runtime should prefer the saved LLM Profile over .env defaults."""
from rag_eval.metrics.factory import _resolve_openai_client_kwargs
from rag_eval.settings import EvaluationSettings
import webapp.services.profile_manager as pm_mod
mgr = _make_manager(tmp_path)
mgr.create(
name="Judge",
model="gpt-5.5",
base_url="http://39.107.88.131:13000",
api_key="sk-profile",
timeout_seconds=300,
)
monkeypatch.setattr(pm_mod, "profile_manager", mgr)
settings = EvaluationSettings(
OPENAI_API_KEY="sk-env",
OPENAI_BASE_URL="http://env-base/v1",
OPENAI_TIMEOUT_SECONDS=30,
)
kwargs = _resolve_openai_client_kwargs("gpt-5.5", settings)
assert kwargs["api_key"] == "sk-profile"
assert kwargs["base_url"] == "http://39.107.88.131:13000"
assert kwargs["timeout"] == 300.0
def test_resolve_openai_client_kwargs_falls_back_to_env(tmp_path, monkeypatch):
"""When no saved profile matches, .env settings remain the fallback."""
from rag_eval.metrics.factory import _resolve_openai_client_kwargs
from rag_eval.settings import EvaluationSettings
import webapp.services.profile_manager as pm_mod
mgr = _make_manager(tmp_path)
monkeypatch.setattr(pm_mod, "profile_manager", mgr)
settings = EvaluationSettings(
OPENAI_API_KEY="sk-env",
OPENAI_BASE_URL="http://env-base/v1",
OPENAI_TIMEOUT_SECONDS=45,
)
kwargs = _resolve_openai_client_kwargs("gpt-5", settings)
assert kwargs["api_key"] == "sk-env"
assert kwargs["base_url"] == "http://env-base/v1"
assert kwargs["timeout"] == 45.0