AQIT
0.1.0
Toggle main menu visibility
Loading...
Searching...
No Matches
boundary_eval_check.py
Go to the documentation of this file.
1
# Copyright (c) 2025-present Aquin Labs Private Limited. All Rights Reserved.
2
"""`aquin boundary-eval --check` — save JSON + diagram to the current working directory."""
3
4
from
__future__
import
annotations
5
6
import
json
7
from
datetime
import
datetime, timezone
8
from
pathlib
import
Path
9
from
typing
import
Any
10
11
_JSON_NAME =
"boundary-eval-check.json"
12
_PNG_NAME =
"boundary-eval-check.png"
13
14
15
def
_normalize_boundary_eval_result
(result: dict[str, Any]) -> dict[str, Any]:
16
if
not
isinstance(result, dict):
17
return
{
"error"
:
"Invalid boundary-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(
"boundary"
), dict):
26
data = data[
"boundary"
]
27
card = result.get(
"card"
)
28
if
isinstance(card, dict)
and
isinstance(card.get(
"data"
), dict):
29
nested = card[
"data"
].get(
"boundary"
)
30
if
isinstance(nested, dict):
31
data = nested
32
33
return
dict(data)
34
35
36
def
has_boundary_eval_payload
(result: dict[str, Any]) -> bool:
37
data =
_normalize_boundary_eval_result
(result)
38
if
data.get(
"error"
):
39
return
False
40
return
data.get(
"mean_robustness"
)
is
not
None
or
bool(data.get(
"probes"
))
41
42
43
def
write_boundary_eval_check
(
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
53
flat =
_normalize_boundary_eval_result
(result)
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_boundary_eval_check
(flat, png_path)
61
return
json_path, png_path
62
63
64
def
_plot_boundary_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
probes = result.get(
"probes"
)
or
[]
79
mean_rob = float(result.get(
"mean_robustness"
)
or
0)
80
title = f
"Boundary eval — mean robustness {mean_rob:.3f} · {len(probes)} probe(s)"
81
82
fig, axes = plt.subplots(1, 2, figsize=(11, max(4.5, min(10, len(probes) * 0.35 + 2))), facecolor=
"#0f1117"
)
83
fig.suptitle(title, color=
"#e5e7eb"
, fontsize=11, y=1.02)
84
85
_plot_robustness_panel
(axes[0], probes, mean_rob)
86
_plot_degradation_panel
(axes[1], probes)
87
88
for
ax
in
axes:
89
ax.set_facecolor(
"#0f1117"
)
90
for
spine
in
ax.spines.values():
91
spine.set_color(
"#374151"
)
92
93
fig.tight_layout()
94
fig.savefig(png_path, dpi=140, bbox_inches=
"tight"
, facecolor=
"#0f1117"
)
95
plt.close(fig)
96
97
98
def
_plot_robustness_panel
(ax: Any, probes: list[dict[str, Any]], mean_rob: float) ->
None
:
99
ax.set_title(
"Robustness by prompt"
, color=
"#e5e7eb"
, fontsize=10)
100
101
if
not
probes:
102
color =
_score_color
(mean_rob)
103
ax.barh([0], [mean_rob], color=color, height=0.45, alpha=0.92)
104
ax.set_xlim(0, 1.05)
105
ax.set_yticks([0])
106
ax.set_yticklabels([
"mean"
], fontsize=9, color=
"#d1d5db"
)
107
ax.set_xlabel(
"Robustness (0–1)"
, color=
"#9ca3af"
, fontsize=8)
108
ax.text(min(mean_rob + 0.02, 0.98), 0, f
"{mean_rob:.3f}"
, va=
"center"
, fontsize=8, color=
"#9ca3af"
)
109
ax.tick_params(axis=
"x"
, colors=
"#6b7280"
, labelsize=8)
110
ax.grid(axis=
"x"
, alpha=0.2, color=
"#4b5563"
)
111
return
112
113
labels = [
_trunc
(str(p.get(
"prompt"
)
or
""
), 22)
for
p
in
probes]
114
vals = [float(p.get(
"robustness_score"
)
or
0)
for
p
in
probes]
115
colors = [
_score_color
(v)
for
v
in
vals]
116
y_pos = list(range(len(probes)))
117
118
ax.barh(y_pos, vals, color=colors, height=0.65, alpha=0.9)
119
ax.axvline(mean_rob, color=
"#38bdf8"
, linestyle=
"--"
, linewidth=0.8, alpha=0.7)
120
ax.set_yticks(y_pos)
121
ax.set_yticklabels(labels, fontsize=7, color=
"#d1d5db"
)
122
ax.invert_yaxis()
123
ax.set_xlim(0, 1.05)
124
ax.set_xlabel(
"Robustness"
, color=
"#9ca3af"
, fontsize=8)
125
ax.tick_params(axis=
"x"
, colors=
"#6b7280"
, labelsize=8)
126
ax.grid(axis=
"x"
, alpha=0.2, color=
"#4b5563"
)
127
128
129
def
_plot_degradation_panel
(ax: Any, probes: list[dict[str, Any]]) ->
None
:
130
ax.set_title(
"Confidence drop & KL under corruption"
, color=
"#e5e7eb"
, fontsize=10)
131
132
if
not
probes:
133
ax.axis(
"off"
)
134
ax.text(0.5, 0.5,
"No probes"
, ha=
"center"
, va=
"center"
, color=
"#9ca3af"
)
135
return
136
137
labels = [
_trunc
(str(p.get(
"prompt"
)
or
""
), 12)
for
p
in
probes]
138
x = list(range(len(probes)))
139
width = 0.38
140
drops = [float(p.get(
"mean_confidence_drop"
)
or
0)
for
p
in
probes]
141
kls = [float(p.get(
"mean_kl"
)
or
0)
for
p
in
probes]
142
143
ax.bar([i - width / 2
for
i
in
x], drops, width=width, color=
"#f87171"
, alpha=0.9, label=
"conf drop"
)
144
ax.bar([i + width / 2
for
i
in
x], kls, width=width, color=
"#6366f1"
, alpha=0.9, label=
"mean KL"
)
145
ax.set_xticks(x)
146
ax.set_xticklabels(labels, fontsize=7, color=
"#d1d5db"
, rotation=30, ha=
"right"
)
147
ax.set_ylabel(
"Magnitude"
, color=
"#9ca3af"
, fontsize=8)
148
ax.legend(fontsize=7, facecolor=
"#0f1117"
, edgecolor=
"#374151"
, labelcolor=
"#d1d5db"
)
149
ax.tick_params(colors=
"#6b7280"
, labelsize=7)
150
ax.grid(axis=
"y"
, alpha=0.2, color=
"#4b5563"
)
151
152
153
def
_score_color
(val: float) -> str:
154
if
val >= 0.75:
155
return
"#34d399"
156
if
val >= 0.5:
157
return
"#fbbf24"
158
return
"#f87171"
159
160
161
def
_trunc
(text: str, limit: int) -> str:
162
t = text.strip()
163
if
len(t) <= limit:
164
return
t
or
"·"
165
return
t[: limit - 1] +
"…"
aquin.boundary_eval_check._plot_robustness_panel
None _plot_robustness_panel(Any ax, list[dict[str, Any]] probes, float mean_rob)
Definition
boundary_eval_check.py:102
aquin.boundary_eval_check._trunc
str _trunc(str text, int limit)
Definition
boundary_eval_check.py:165
aquin.boundary_eval_check.has_boundary_eval_payload
bool has_boundary_eval_payload(dict[str, Any] result)
Definition
boundary_eval_check.py:40
aquin.boundary_eval_check.write_boundary_eval_check
tuple[Path, Path] write_boundary_eval_check(dict[str, Any] result, *, str|None tool_name, str|Path cwd)
Definition
boundary_eval_check.py:52
aquin.boundary_eval_check._plot_degradation_panel
None _plot_degradation_panel(Any ax, list[dict[str, Any]] probes)
Definition
boundary_eval_check.py:133
aquin.boundary_eval_check._plot_boundary_eval_check
None _plot_boundary_eval_check(dict[str, Any] result, Path png_path)
Definition
boundary_eval_check.py:68
aquin.boundary_eval_check._normalize_boundary_eval_result
dict[str, Any] _normalize_boundary_eval_result(dict[str, Any] result)
Definition
boundary_eval_check.py:19
aquin.boundary_eval_check._score_color
str _score_color(float val)
Definition
boundary_eval_check.py:157
aquin
boundary_eval_check.py
AQIT · Aquin Labs Private Limited · Apache 2.0 · Generated by
1.18.0