feat: add yaml_patcher service to apply LLM profiles to scenario YAML

This commit is contained in:
2026-06-16 16:21:19 +08:00
parent b19054bd66
commit e329f59139
2 changed files with 146 additions and 0 deletions

View File

@@ -65,3 +65,75 @@ def test_update_nonexistent(client):
def test_delete_nonexistent(client):
resp = client.delete("/api/llm-profiles/nope")
assert resp.status_code == 404
# ---------------------------------------------------------------------------
# YAML patcher tests
# ---------------------------------------------------------------------------
import yaml as yaml_lib
from webapp.services.yaml_patcher import apply_profiles_to_scenario
from webapp.models import LLMProfile
def test_apply_judge_profile(tmp_path):
"""Applying a judge profile patches judge_model in the YAML."""
scenario_file = tmp_path / "test-scenario.yaml"
scenario_file.write_text(
"scenario_name: test\nmode: offline\njudge_model: old-model\nembedding_model: emb\n"
"dataset: data.csv\nmetrics:\n- faithfulness\noutput_dir: outputs/test\n",
encoding="utf-8",
)
judge_p = LLMProfile(
profile_id="x", name="J", model="new-model",
base_url="http://x/v1", api_key="k", created_at="t", updated_at="t",
)
patched = apply_profiles_to_scenario(
scenario_path=str(scenario_file),
judge_profile=judge_p,
answer_profile=None,
dataset_profile=None,
_resolve_absolute=True,
)
assert "judge_model" in patched
data = yaml_lib.safe_load(scenario_file.read_text())
assert data["judge_model"] == "new-model"
def test_apply_answer_profile(tmp_path):
"""Applying an answer profile patches app_adapter.static_kwargs.model."""
scenario_file = tmp_path / "online.yaml"
scenario_file.write_text(
"scenario_name: online\nmode: online\njudge_model: j\nembedding_model: emb\n"
"dataset: d.csv\nmetrics:\n- faithfulness\noutput_dir: out\n"
"app_adapter:\n type: python\n callable: apps.foo:run\n"
" static_kwargs:\n model: old\n source_chunks_path: chunks.jsonl\n",
encoding="utf-8",
)
answer_p = LLMProfile(
profile_id="y", name="A", model="new-answer-model",
base_url="http://x/v1", api_key="k", created_at="t", updated_at="t",
)
patched = apply_profiles_to_scenario(
scenario_path=str(scenario_file),
judge_profile=None,
answer_profile=answer_p,
dataset_profile=None,
_resolve_absolute=True,
)
assert "app_adapter.static_kwargs.model" in patched
data = yaml_lib.safe_load(scenario_file.read_text())
assert data["app_adapter"]["static_kwargs"]["model"] == "new-answer-model"
def test_apply_no_profiles_returns_empty(tmp_path):
"""When no profiles are given, no fields are patched."""
scenario_file = tmp_path / "noop.yaml"
scenario_file.write_text("scenario_name: noop\njudge_model: m\n", encoding="utf-8")
patched = apply_profiles_to_scenario(
scenario_path=str(scenario_file),
judge_profile=None,
answer_profile=None,
dataset_profile=None,
_resolve_absolute=True,
)
assert patched == []