"""Tests for the prompt-cache bootstrap script (mocked adapt/LLM).""" import asyncio import json from pydantic import BaseModel import scripts.build_judge_prompt_cache as builder class _In(BaseModel): question: str class _Out(BaseModel): statements: list[str] class _FakeAdapted: """Fake adapted prompt returned by prompt.adapt().""" def __init__(self): self.instruction = "中文指令。" self.language = "chinese" self.examples = [(_In(question="问题"), _Out(statements=["陈述"]))] class _FakePrompt: """Fake prompt with async adapt() that returns _FakeAdapted.""" def __init__(self): self.input_model = _In self.output_model = _Out self.instruction = "English." self.examples = [(_In(question="q"), _Out(statements=["s"]))] self.language = "english" async def adapt(self, target_language, llm, adapt_instruction=False): assert target_language == "chinese" assert adapt_instruction is True return _FakeAdapted() def test_serialize_prompt_shape(): """serialize_prompt emits the expected committed cache schema.""" data = builder.serialize_prompt( _FakeAdapted(), "hash123", "context_recall", "prompt", "zh", "0.4.3" ) assert data["metric"] == "context_recall" assert data["prompt_attr"] == "prompt" assert data["language"] == "chinese" assert data["source_hash"] == "hash123" assert data["instruction"] == "中文指令。" assert data["examples"] == [ {"input": {"question": "问题"}, "output": {"statements": ["陈述"]}} ] def test_build_cache_writes_all_files(tmp_path, monkeypatch): """build_cache writes one JSON per (metric, attr) under CACHE_ROOT//.""" # Build a fake registry where every prompt attr is a _FakePrompt. fake_registry = {name: type("M", (), {})() for name in builder.METRIC_PROMPT_ATTRS} for name, attrs in builder.METRIC_PROMPT_ATTRS.items(): for attr in attrs: setattr(fake_registry[name], attr, _FakePrompt()) monkeypatch.setattr(builder, "build_models", lambda j, e, s: (object(), object())) monkeypatch.setattr(builder, "build_metric_registry", lambda llm, emb: fake_registry) monkeypatch.setattr(builder, "CACHE_ROOT", tmp_path) written = asyncio.run(builder.build_cache("zh", "gpt-5", "emb", object())) expected_count = sum(len(a) for a in builder.METRIC_PROMPT_ATTRS.values()) assert len(written) == expected_count sample = tmp_path / "zh" / "context_recall__prompt.json" assert sample.exists() data = json.loads(sample.read_text(encoding="utf-8")) assert data["instruction"] == "中文指令。" assert data["metric"] == "context_recall"