AQIT 0.1.0
Loading...
Searching...
No Matches
consistency_eval_check.py
Go to the documentation of this file.
1# Copyright (c) 2025-present Aquin Labs Private Limited. All Rights Reserved.
2"""`aquin consistency-eval --check` — save JSON + diagram to the current working directory."""
3
4from __future__ import annotations
5
6import json
7from datetime import datetime, timezone
8from pathlib import Path
9from typing import Any
10
11_JSON_NAME = "consistency-eval-check.json"
12_PNG_NAME = "consistency-eval-check.png"
13
14
15def _normalize_consistency_eval_result(result: dict[str, Any]) -> dict[str, Any]:
16 if not isinstance(result, dict):
17 return {"error": "Invalid consistency-eval result"}
18
19 if result.get("error"):
20 return dict(result)
21
22 data = result
23 if isinstance(result.get("content"), dict):
24 data = result["content"]
25 if isinstance(data.get("consistency"), dict):
26 data = data["consistency"]
27 card = result.get("card")
28 if isinstance(card, dict) and isinstance(card.get("data"), dict):
29 nested = card["data"].get("consistency")
30 if isinstance(nested, dict):
31 data = nested
32
33 return dict(data)
34
35
36def has_consistency_eval_payload(result: dict[str, Any]) -> bool:
38 if data.get("error"):
39 return False
40 return data.get("consistency_score") is not None or bool(data.get("variants"))
41
42
44 result: dict[str, Any],
45 *,
46 tool_name: str | None,
47 cwd: str | Path,
48) -> tuple[Path, Path]:
49 cwd = Path(cwd)
50 json_path = cwd / _JSON_NAME
51 png_path = cwd / _PNG_NAME
52
54 payload = {
55 "saved_at": datetime.now(timezone.utc).isoformat(),
56 "tool": tool_name,
57 **flat,
58 }
59 json_path.write_text(json.dumps(payload, indent=2, default=str), encoding="utf-8")
60 _plot_consistency_eval_check(flat, png_path)
61 return json_path, png_path
62
63
64def _plot_consistency_eval_check(result: dict[str, Any], png_path: Path) -> None:
65 import matplotlib
66
67 matplotlib.use("Agg")
68 import matplotlib.pyplot as plt
69
70 if result.get("error"):
71 fig, ax = plt.subplots(figsize=(6, 2), facecolor="#0f1117")
72 ax.axis("off")
73 ax.text(0.5, 0.5, f"Error: {result['error']}", ha="center", va="center", wrap=True, color="#e5e7eb")
74 fig.savefig(png_path, dpi=140, bbox_inches="tight", facecolor="#0f1117")
75 plt.close(fig)
76 return
77
78 query = _trunc(str(result.get("query") or ""), 56)
79 score = result.get("consistency_score")
80 mean_kl = result.get("mean_kl")
81 max_kl = result.get("max_kl")
82 variants = result.get("variants") or []
83
84 title = "Consistency eval"
85 if query:
86 title += f' — "{query}"'
87 subtitle_parts = []
88 if mean_kl is not None:
89 subtitle_parts.append(f"mean KL {float(mean_kl):.4f}")
90 if max_kl is not None:
91 subtitle_parts.append(f"max KL {float(max_kl):.4f}")
92
93 fig, axes = plt.subplots(1, 2, figsize=(11, 4.5), facecolor="#0f1117")
94 fig.suptitle(title, color="#e5e7eb", fontsize=11, y=1.03)
95 if subtitle_parts:
96 fig.text(0.5, 0.96, " · ".join(subtitle_parts), ha="center", fontsize=8, color="#9ca3af")
97
98 _plot_score_panel(axes[0], score)
99 _plot_variants_panel(axes[1], variants)
100
101 for ax in axes:
102 ax.set_facecolor("#0f1117")
103 for spine in ax.spines.values():
104 spine.set_color("#374151")
105
106 fig.tight_layout(rect=(0, 0, 1, 0.94))
107 fig.savefig(png_path, dpi=140, bbox_inches="tight", facecolor="#0f1117")
108 plt.close(fig)
109
110
111def _plot_score_panel(ax: Any, score: Any) -> None:
112 ax.set_title("Consistency score", color="#e5e7eb", fontsize=10)
113
114 if score is None:
115 ax.axis("off")
116 ax.text(0.5, 0.5, "No score", ha="center", va="center", color="#9ca3af")
117 return
118
119 val = float(score)
120 color = _score_color(val)
121 ax.barh([0], [val], color=color, height=0.45, alpha=0.92)
122 ax.set_xlim(0, 1.05)
123 ax.set_yticks([0])
124 ax.set_yticklabels(["score"], fontsize=9, color="#d1d5db")
125 ax.set_xlabel("Score (0–1, higher = more consistent)", color="#9ca3af", fontsize=8)
126 ax.text(min(val + 0.02, 0.98), 0, f"{val:.3f}", va="center", fontsize=9, color="#9ca3af")
127 ax.tick_params(axis="x", colors="#6b7280", labelsize=8)
128 ax.grid(axis="x", alpha=0.2, color="#4b5563")
129
130
131def _plot_variants_panel(ax: Any, variants: list[dict[str, Any]]) -> None:
132 ax.set_title("Paraphrase KL from anchor", color="#e5e7eb", fontsize=10)
133
134 if not variants:
135 ax.axis("off")
136 ax.text(0.5, 0.5, "No variants", ha="center", va="center", color="#9ca3af")
137 return
138
139 labels = []
140 kls = []
141 for i, v in enumerate(variants):
142 labels.append("anchor" if i == 0 else f"v{i}")
143 kls.append(float(v.get("kl_from_anchor") or 0))
144
145 colors = ["#78716c" if i == 0 else "#6366f1" for i in range(len(labels))]
146 y_pos = list(range(len(labels)))
147 ax.barh(y_pos, kls, color=colors, height=0.65, alpha=0.9)
148 ax.set_yticks(y_pos)
149 ax.set_yticklabels(labels, fontsize=9, color="#d1d5db")
150 ax.invert_yaxis()
151 ax.set_xlabel("KL divergence", color="#9ca3af", fontsize=8)
152 ax.tick_params(axis="x", colors="#6b7280", labelsize=8)
153 ax.grid(axis="x", alpha=0.2, color="#4b5563")
154 for i, kl in enumerate(kls):
155 if kl > 0:
156 ax.text(kl + max(kls) * 0.02 + 0.001, i, f"{kl:.4f}", va="center", fontsize=7, color="#9ca3af")
157
158
159def _score_color(val: float) -> str:
160 if val >= 0.75:
161 return "#34d399"
162 if val >= 0.5:
163 return "#fbbf24"
164 return "#f87171"
165
166
167def _trunc(text: str, limit: int) -> str:
168 t = text.strip()
169 if len(t) <= limit:
170 return t or "·"
171 return t[: limit - 1] + "…"
None _plot_consistency_eval_check(dict[str, Any] result, Path png_path)
tuple[Path, Path] write_consistency_eval_check(dict[str, Any] result, *, str|None tool_name, str|Path cwd)
bool has_consistency_eval_payload(dict[str, Any] result)
dict[str, Any] _normalize_consistency_eval_result(dict[str, Any] result)
None _plot_score_panel(Any ax, Any score)
None _plot_variants_panel(Any ax, list[dict[str, Any]] variants)