Files
llm-wiki/scripts/deep-research/tests/test_pipeline_mock.py
T

137 lines
4.6 KiB
Python
Raw Blame History

This file contains ambiguous Unicode characters
This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.
import pytest
from deep_research.pipeline import run_research
from deep_research.backends.mock import MockBackend
from deep_research.config import Config
from deep_research.schemas import Scope, Angle, Search, SearchResult, Extract, Claim, Verdict, Report
CFG = Config(MAX_FETCH=15, MAX_VERIFY_CLAIMS=25)
def _scope():
return Scope(question="Q", summary="s",
angles=[Angle(label=f"a{i}", query=f"q{i}") for i in range(3)])
def _search(prompt, label):
# 각 각도마다 고유 URL 1개
n = label.split(":")[1]
return Search(results=[SearchResult(url=f"http://{n}.com/x", title="t", relevance="high")])
def _extract(prompt, label):
return Extract(sourceQuality="primary",
claims=[Claim(claim="C-" + label, quote="q", importance="central")])
def _verdict_pass(prompt, label):
return Verdict(refuted=False, evidence="e", confidence="high")
def _report():
return Report(summary="done", findings=[], caveats="none")
async def test_happy_path_returns_report_and_stats():
backend = MockBackend({
"scope": _scope(),
"search:": _search,
"fetch:": _extract,
"v": _verdict_pass,
"synthesize": _report(),
})
out = await run_research("Q", backend, config=CFG)
assert out["summary"] == "done"
assert out["stats"]["confirmed"] == 3 # 3 각도 × 1 claim, 전부 생존
assert out["stats"]["angles"] == 3
async def test_empty_question_returns_error():
out = await run_research(" ", MockBackend({}), config=CFG)
assert "error" in out
async def test_no_claims_degenerate():
backend = MockBackend({
"scope": _scope(),
"search:": _search,
"fetch:": lambda p, l: Extract(sourceQuality="unreliable", claims=[]),
})
out = await run_research("Q", backend, config=CFG)
assert out["findings"] == [] and out["stats"]["claims"] == 0
async def test_all_refuted_degenerate():
backend = MockBackend({
"scope": _scope(),
"search:": _search,
"fetch:": _extract,
"v": lambda p, l: Verdict(refuted=True, evidence="e", confidence="high"),
})
out = await run_research("Q", backend, config=CFG)
assert out["findings"] == [] and out["stats"]["confirmed"] == 0
assert len(out["refuted"]) == 3
async def test_synth_failure_salvages_confirmed():
backend = MockBackend({
"scope": _scope(),
"search:": _search,
"fetch:": _extract,
"v": _verdict_pass,
"synthesize": None, # 합성 실패
})
out = await run_research("Q", backend, config=CFG)
assert out["findings"] == [] and len(out["confirmed"]) == 3
# ── Task 9: report.py ──────────────────────────────────────────────────────
from deep_research.report import to_markdown
def test_to_markdown_renders_summary_and_stats():
result = {
"question": "Q", "summary": "ans",
"findings": [{"claim": "F1", "confidence": "high", "sources": ["http://a"], "evidence": "e"}],
"caveats": "c", "refuted": [], "sources": [],
"stats": {"angles": 5, "confirmed": 1},
}
md = to_markdown(result)
assert "# Deep Research" in md and "ans" in md and "F1" in md
# ── Task 10: backends/codex.py ────────────────────────────────────────────
from deep_research.backends.codex import extract_final_json
def test_extract_final_json_from_jsonl():
jsonl = "\n".join([
'{"type":"reasoning","text":"thinking"}',
'{"type":"web_search","query":"x"}',
'{"type":"agent_message","text":"{\\"question\\":\\"Q\\",\\"summary\\":\\"s\\",\\"angles\\":[]}"}',
])
obj = extract_final_json(jsonl)
assert obj["summary"] == "s"
def test_extract_final_json_returns_none_when_absent():
assert extract_final_json('{"type":"reasoning","text":"only"}') is None
# ── Task 11: backends/antigravity.py ─────────────────────────────────────
from deep_research.backends.antigravity import extract_json_block
def test_extract_json_block_from_fenced():
text = 'prelude\n```json\n{"refuted": false, "evidence": "e", "confidence": "high"}\n```\ntrailing'
obj = extract_json_block(text)
assert obj["confidence"] == "high"
def test_extract_json_block_bare_object():
obj = extract_json_block('noise {"refuted": true, "evidence": "e", "confidence": "low"} more')
assert obj["refuted"] is True
def test_extract_json_block_none_when_absent():
assert extract_json_block("no json here") is None