AQIT
0.1.0
Toggle main menu visibility
Loading...
Searching...
No Matches
audit_check.py
Go to the documentation of this file.
1
# Copyright (c) 2025-present Aquin Labs Private Limited. All Rights Reserved.
2
"""`aquin audit --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 =
"audit-check.json"
12
_PNG_NAME =
"audit-check.png"
13
14
_STATUS_COLORS = {
15
"suppressed"
:
"#f87171"
,
16
"softened"
:
"#fbbf24"
,
17
"unfiltered"
:
"#34d399"
,
18
}
19
20
21
def
_normalize_audit_result
(result: dict[str, Any]) -> dict[str, Any]:
22
if
not
isinstance(result, dict):
23
return
{
"error"
:
"Invalid audit result"
}
24
25
data = result
26
card = result.get(
"card"
)
27
if
isinstance(card, dict)
and
isinstance(card.get(
"data"
), dict):
28
data = {**card[
"data"
],
"model_id"
: result.get(
"model_id"
)
or
card[
"data"
].get(
"model_id"
)}
29
elif
isinstance(result.get(
"content"
), dict):
30
data = result[
"content"
]
31
32
if
result.get(
"error"
):
33
data = {**data,
"error"
: result[
"error"
]}
34
return
data
35
36
37
def
has_audit_payload
(result: dict[str, Any]) -> bool:
38
data =
_normalize_audit_result
(result)
39
return
any(data.get(k)
for
k
in
(
"consistency"
,
"suppression"
,
"boundary"
))
40
41
42
def
write_audit_check
(
43
result: dict[str, Any],
44
*,
45
tool_name: str |
None
,
46
cwd: str | Path,
47
) -> tuple[Path, Path]:
48
cwd = Path(cwd)
49
json_path = cwd / _JSON_NAME
50
png_path = cwd / _PNG_NAME
51
52
flat =
_normalize_audit_result
(result)
53
payload = {
54
"saved_at"
: datetime.now(timezone.utc).isoformat(),
55
"tool"
: tool_name,
56
**flat,
57
}
58
json_path.write_text(json.dumps(payload, indent=2, default=str), encoding=
"utf-8"
)
59
_plot_audit_check
(flat, png_path)
60
return
json_path, png_path
61
62
63
def
_plot_audit_check
(result: dict[str, Any], png_path: Path) ->
None
:
64
import
matplotlib
65
66
matplotlib.use(
"Agg"
)
67
import
matplotlib.pyplot
as
plt
68
69
if
result.get(
"error"
)
and
not
has_audit_payload
(result):
70
fig, ax = plt.subplots(figsize=(6, 2), facecolor=
"#0f1117"
)
71
ax.axis(
"off"
)
72
ax.text(0.5, 0.5, f
"Error: {result['error']}"
, ha=
"center"
, va=
"center"
, wrap=
True
, color=
"#e5e7eb"
)
73
fig.savefig(png_path, dpi=140, bbox_inches=
"tight"
, facecolor=
"#0f1117"
)
74
plt.close(fig)
75
return
76
77
model = str(result.get(
"model_id"
)
or
""
)
78
title = f
"Audit — {model}"
if
model
else
"Audit"
79
80
fig, axes = plt.subplots(1, 3, figsize=(12, 4.8), facecolor=
"#0f1117"
)
81
fig.suptitle(title, color=
"#e5e7eb"
, fontsize=11, y=1.02)
82
83
_plot_consistency_panel
(axes[0], result.get(
"consistency"
)
or
{})
84
_plot_suppression_panel
(axes[1], result.get(
"suppression"
)
or
{})
85
_plot_boundary_panel
(axes[2], result.get(
"boundary"
)
or
{})
86
87
for
ax
in
axes:
88
ax.set_facecolor(
"#0f1117"
)
89
for
spine
in
ax.spines.values():
90
spine.set_color(
"#374151"
)
91
92
fig.tight_layout()
93
fig.savefig(png_path, dpi=140, bbox_inches=
"tight"
, facecolor=
"#0f1117"
)
94
plt.close(fig)
95
96
97
def
_plot_consistency_panel
(ax: Any, data: dict[str, Any]) ->
None
:
98
ax.set_title(
"Consistency"
, color=
"#e5e7eb"
, fontsize=10)
99
100
score = data.get(
"consistency_score"
)
101
query =
_trunc
(str(data.get(
"query"
)
or
""
), 40)
102
variants = data.get(
"variants"
)
or
[]
103
104
if
score
is
None
and
not
variants:
105
ax.axis(
"off"
)
106
ax.text(0.5, 0.5,
"No data"
, ha=
"center"
, va=
"center"
, color=
"#9ca3af"
)
107
return
108
109
if
score
is
not
None
:
110
color =
_score_color
(float(score))
111
ax.barh([0], [float(score)], color=color, height=0.5, alpha=0.92)
112
ax.set_xlim(0, 1.05)
113
ax.set_yticks([0])
114
ax.set_yticklabels([
"score"
], fontsize=9, color=
"#d1d5db"
)
115
ax.set_xlabel(
"Consistency (0–1)"
, color=
"#9ca3af"
, fontsize=8)
116
ax.text(min(float(score) + 0.02, 0.98), 0, f
"{float(score):.3f}"
, va=
"center"
, fontsize=8, color=
"#9ca3af"
)
117
if
query:
118
ax.set_title(f
"Consistency\n{query}"
, color=
"#e5e7eb"
, fontsize=9)
119
elif
variants:
120
labels = [f
"v{i}"
for
i
in
range(len(variants))]
121
kls = [float(v.get(
"kl_from_anchor"
)
or
0)
for
v
in
variants]
122
ax.barh(labels, kls, color=
"#6366f1"
, height=0.65, alpha=0.9)
123
ax.invert_yaxis()
124
ax.set_xlabel(
"KL from anchor"
, color=
"#9ca3af"
, fontsize=8)
125
126
ax.tick_params(colors=
"#6b7280"
, labelsize=8)
127
ax.grid(axis=
"x"
, alpha=0.2, color=
"#4b5563"
)
128
129
130
def
_plot_suppression_panel
(ax: Any, data: dict[str, Any]) ->
None
:
131
ax.set_title(
"Suppression"
, color=
"#e5e7eb"
, fontsize=10)
132
topics = data.get(
"topics"
)
or
[]
133
134
if
not
topics:
135
ax.axis(
"off"
)
136
ax.text(0.5, 0.5,
"No data"
, ha=
"center"
, va=
"center"
, color=
"#9ca3af"
)
137
return
138
139
rows = sorted(topics, key=
lambda
t: float(t.get(
"suppression_score"
)
or
0), reverse=
True
)[:8]
140
labels = [str(t.get(
"topic"
)
or
"?"
)
for
t
in
rows]
141
vals = [float(t.get(
"suppression_score"
)
or
0)
for
t
in
rows]
142
colors = [_STATUS_COLORS.get(str(t.get(
"status"
)
or
""
),
"#78716c"
)
for
t
in
rows]
143
144
y_pos = list(range(len(rows)))
145
ax.barh(y_pos, vals, color=colors, height=0.65, alpha=0.9)
146
ax.set_yticks(y_pos)
147
ax.set_yticklabels(labels, fontsize=8, color=
"#d1d5db"
)
148
ax.invert_yaxis()
149
ax.set_xlim(0, 1.05)
150
ax.set_xlabel(
"Suppression score"
, color=
"#9ca3af"
, fontsize=8)
151
ax.tick_params(axis=
"x"
, colors=
"#6b7280"
, labelsize=8)
152
ax.grid(axis=
"x"
, alpha=0.2, color=
"#4b5563"
)
153
for
i, v
in
enumerate(vals):
154
ax.text(min(v + 0.02, 0.98), i, f
"{v:.2f}"
, va=
"center"
, fontsize=7, color=
"#9ca3af"
)
155
156
157
def
_plot_boundary_panel
(ax: Any, data: dict[str, Any]) ->
None
:
158
mean_rob = data.get(
"mean_robustness"
)
159
probes = data.get(
"probes"
)
or
[]
160
ax.set_title(
"Boundary / robustness"
, color=
"#e5e7eb"
, fontsize=10)
161
162
if
not
probes
and
mean_rob
is
None
:
163
ax.axis(
"off"
)
164
ax.text(0.5, 0.5,
"No data"
, ha=
"center"
, va=
"center"
, color=
"#9ca3af"
)
165
return
166
167
if
len(probes) <= 1
and
mean_rob
is
not
None
:
168
color =
_score_color
(float(mean_rob))
169
ax.barh([0], [float(mean_rob)], color=color, height=0.5, alpha=0.92)
170
ax.set_xlim(0, 1.05)
171
ax.set_yticks([0])
172
ax.set_yticklabels([
"mean"
], fontsize=9, color=
"#d1d5db"
)
173
ax.set_xlabel(
"Robustness (0–1)"
, color=
"#9ca3af"
, fontsize=8)
174
ax.text(min(float(mean_rob) + 0.02, 0.98), 0, f
"{float(mean_rob):.3f}"
, va=
"center"
, fontsize=8, color=
"#9ca3af"
)
175
ax.tick_params(colors=
"#6b7280"
, labelsize=8)
176
ax.grid(axis=
"x"
, alpha=0.2, color=
"#4b5563"
)
177
return
178
179
labels = [
_trunc
(str(p.get(
"prompt"
)
or
""
), 18)
for
p
in
probes[:8]]
180
vals = [float(p.get(
"robustness_score"
)
or
0)
for
p
in
probes[:8]]
181
colors = [
_score_color
(v)
for
v
in
vals]
182
y_pos = list(range(len(labels)))
183
ax.barh(y_pos, vals, color=colors, height=0.65, alpha=0.9)
184
ax.set_yticks(y_pos)
185
ax.set_yticklabels(labels, fontsize=7, color=
"#d1d5db"
)
186
ax.invert_yaxis()
187
ax.set_xlim(0, 1.05)
188
ax.set_xlabel(
"Robustness"
, color=
"#9ca3af"
, fontsize=8)
189
ax.tick_params(axis=
"x"
, colors=
"#6b7280"
, labelsize=7)
190
ax.grid(axis=
"x"
, alpha=0.2, color=
"#4b5563"
)
191
192
193
def
_score_color
(val: float) -> str:
194
if
val >= 0.75:
195
return
"#34d399"
196
if
val >= 0.5:
197
return
"#fbbf24"
198
return
"#f87171"
199
200
201
def
_trunc
(text: str, limit: int) -> str:
202
t = text.strip()
203
if
len(t) <= limit:
204
return
t
or
"·"
205
return
t[: limit - 1] +
"…"
aquin.audit_check._plot_suppression_panel
None _plot_suppression_panel(Any ax, dict[str, Any] data)
Definition
audit_check.py:134
aquin.audit_check._plot_consistency_panel
None _plot_consistency_panel(Any ax, dict[str, Any] data)
Definition
audit_check.py:101
aquin.audit_check._trunc
str _trunc(str text, int limit)
Definition
audit_check.py:205
aquin.audit_check._plot_audit_check
None _plot_audit_check(dict[str, Any] result, Path png_path)
Definition
audit_check.py:67
aquin.audit_check._plot_boundary_panel
None _plot_boundary_panel(Any ax, dict[str, Any] data)
Definition
audit_check.py:161
aquin.audit_check.has_audit_payload
bool has_audit_payload(dict[str, Any] result)
Definition
audit_check.py:41
aquin.audit_check.write_audit_check
tuple[Path, Path] write_audit_check(dict[str, Any] result, *, str|None tool_name, str|Path cwd)
Definition
audit_check.py:51
aquin.audit_check._normalize_audit_result
dict[str, Any] _normalize_audit_result(dict[str, Any] result)
Definition
audit_check.py:25
aquin.audit_check._score_color
str _score_color(float val)
Definition
audit_check.py:197
aquin
audit_check.py
AQIT · Aquin Labs Private Limited · Apache 2.0 · Generated by
1.18.0