90 lines
3.4 KiB
Python
90 lines
3.4 KiB
Python
from __future__ import annotations
|
|
|
|
import json
|
|
import sys
|
|
from pathlib import Path
|
|
|
|
ROOT = Path(__file__).resolve().parents[2]
|
|
sys.path.insert(0, str(ROOT / "scripts"))
|
|
|
|
import report_quality_metrics as metrics_script # noqa: E402
|
|
|
|
|
|
def write_jsonl(path: Path, records: list[dict]) -> None:
|
|
path.parent.mkdir(parents=True, exist_ok=True)
|
|
with path.open("w", encoding="utf-8") as handle:
|
|
for record in records:
|
|
handle.write(json.dumps(record, ensure_ascii=False) + "\n")
|
|
|
|
|
|
def test_report_quality_metrics_summarizes_failures_and_breakdowns(tmp_path: Path) -> None:
|
|
root = tmp_path / "reports" / "observability" / "onec-agent"
|
|
write_jsonl(
|
|
root / "turn_audit" / "20260705.jsonl",
|
|
[
|
|
{
|
|
"event_type": "turn_audit",
|
|
"timestamp": "2026-07-01T10:00:00+00:00",
|
|
"outcome": "success",
|
|
"failure_type": "none",
|
|
"user_text": "ok",
|
|
},
|
|
{
|
|
"event_type": "turn_audit",
|
|
"timestamp": "2026-07-02T10:00:00+00:00",
|
|
"outcome": "failure",
|
|
"failure_type": "adapter_error",
|
|
"user_text": "Повтори проверку",
|
|
},
|
|
{
|
|
"event_type": "turn_audit",
|
|
"timestamp": "2026-07-03T10:00:00+00:00",
|
|
"outcome": "failure",
|
|
"failure_type": "adapter_error",
|
|
"user_text": "Повтори проверку",
|
|
},
|
|
],
|
|
)
|
|
write_jsonl(
|
|
root / "model_calls" / "20260705.jsonl",
|
|
[
|
|
{"event_type": "model_calls", "route_name": "1c", "served_model_name": "stub-model", "latency_ms": 40},
|
|
{"event_type": "model_calls", "route_name": "1c", "served_model_name": "stub-model", "latency_ms": 60},
|
|
],
|
|
)
|
|
write_jsonl(
|
|
root / "tool_calls" / "20260705.jsonl",
|
|
[
|
|
{"event_type": "tool_calls", "tool_name": "tool.echo", "duration_ms": 7},
|
|
{"event_type": "tool_calls", "tool_name": "tool.echo", "duration_ms": 9},
|
|
],
|
|
)
|
|
write_jsonl(
|
|
root / "retrieval_events" / "20260705.jsonl",
|
|
[
|
|
{"event_type": "retrieval_events", "plugin": "1c", "profile": "official", "sources_json": [{"a": 1}, {"a": 2}]},
|
|
],
|
|
)
|
|
|
|
records = metrics_script.iter_records(tmp_path / "reports" / "observability")
|
|
summary = metrics_script.summarize(records, limit=10)
|
|
|
|
assert summary["records"] == 8
|
|
assert summary["weekly_turns"][0]["turns"] == 3
|
|
assert summary["weekly_turns"][0]["failure"] == 2
|
|
assert summary["top_failure_types"][0] == {"key": "adapter_error", "count": 2}
|
|
assert summary["top_repeated_failed_prompts"][0] == {"key": "Повтори проверку", "count": 2}
|
|
assert summary["model_breakdown"][0]["key"] == "1c :: stub-model"
|
|
assert summary["model_breakdown"][0]["avg_latency_ms"] == 50
|
|
assert summary["tool_breakdown"][0]["key"] == "tool.echo"
|
|
assert summary["tool_breakdown"][0]["avg_duration_ms"] == 8
|
|
assert summary["rag_breakdown"][0]["key"] == "1c :: official"
|
|
assert summary["rag_breakdown"][0]["avg_sources"] == 2.0
|
|
|
|
|
|
def test_report_quality_metrics_writes_output_file(tmp_path: Path) -> None:
|
|
output = tmp_path / "quality-report.json"
|
|
payload = {"records": 1, "weekly_turns": []}
|
|
metrics_script.write_report(output, payload)
|
|
assert json.loads(output.read_text(encoding="utf-8"))["records"] == 1
|