AQIT
0.1.0
Toggle main menu visibility
Loading...
Searching...
No Matches
trace_check.py
Go to the documentation of this file.
1
# Copyright (c) 2025-present Aquin Labs Private Limited. All Rights Reserved.
2
"""`aquin trace --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 =
"trace-check.json"
12
_PNG_NAME =
"trace-check.png"
13
14
15
def
_flatten_trace_result
(result: dict[str, Any]) -> dict[str, Any]:
16
if
result.get(
"error"
):
17
return
dict(result)
18
19
content = result.get(
"content"
)
or
{}
20
card_data = (result.get(
"card"
)
or
{}).get(
"data"
)
or
{}
21
22
def
pick(snake: str, camel: str, default: Any =
None
) -> Any:
23
val = content.get(snake)
24
if
val
is
None
or
val ==
""
or
val == []:
25
val = card_data.get(camel, default)
26
return
default
if
val
is
None
else
val
27
28
flat = {
29
"prompt"
: pick(
"prompt"
,
"prompt"
,
""
),
30
"response"
: pick(
"response"
,
"response"
,
""
),
31
"model_id"
: pick(
"model_id"
,
"modelId"
,
""
),
32
"sae_layer"
: pick(
"sae_layer"
,
"saeLayer"
),
33
"top_features"
: pick(
"top_features"
,
"topFeatures"
, []),
34
"prompt_tokens"
: card_data.get(
"promptTokens"
, content.get(
"prompt_tokens"
, [])),
35
"response_tokens"
: card_data.get(
"responseTokens"
, content.get(
"response_tokens"
, [])),
36
"attribution"
: card_data.get(
"attribution"
, content.get(
"attribution"
, [])),
37
"logit_lens"
: card_data.get(
"logitLensResults"
, content.get(
"logit_lens"
, [])),
38
"trace_results"
: card_data.get(
"traceResults"
, content.get(
"trace_results"
, [])),
39
"trace_target"
: card_data.get(
"traceTarget"
, content.get(
"trace_target"
,
""
)),
40
"color_map"
: card_data.get(
"colorMap"
, content.get(
"color_map"
)),
41
}
42
if
result.get(
"error"
):
43
flat[
"error"
] = result[
"error"
]
44
return
flat
45
46
47
def
write_trace_check
(
48
result: dict[str, Any],
49
*,
50
tool_name: str |
None
,
51
cwd: str | Path,
52
) -> tuple[Path, Path]:
53
cwd = Path(cwd)
54
json_path = cwd / _JSON_NAME
55
png_path = cwd / _PNG_NAME
56
57
flat =
_flatten_trace_result
(result)
58
payload = {
59
"saved_at"
: datetime.now(timezone.utc).isoformat(),
60
"tool"
: tool_name,
61
**flat,
62
}
63
json_path.write_text(json.dumps(payload, indent=2, default=str), encoding=
"utf-8"
)
64
_plot_trace_check
(flat, png_path)
65
return
json_path, png_path
66
67
68
def
_plot_trace_check
(result: dict[str, Any], png_path: Path) ->
None
:
69
import
matplotlib
70
71
matplotlib.use(
"Agg"
)
72
import
matplotlib.pyplot
as
plt
73
74
if
result.get(
"error"
):
75
fig, ax = plt.subplots(figsize=(6, 2), facecolor=
"#0f1117"
)
76
ax.axis(
"off"
)
77
ax.text(0.5, 0.5, f
"Error: {result['error']}"
, ha=
"center"
, va=
"center"
, wrap=
True
, color=
"#e5e7eb"
)
78
fig.savefig(png_path, dpi=140, bbox_inches=
"tight"
, facecolor=
"#0f1117"
)
79
plt.close(fig)
80
return
81
82
model = str(result.get(
"model_id"
)
or
""
)
83
prompt = str(result.get(
"prompt"
)
or
""
)[:64]
84
response = str(result.get(
"response"
)
or
""
)[:80]
85
sae_layer = result.get(
"sae_layer"
,
"?"
)
86
87
fig = plt.figure(figsize=(12, 7), facecolor=
"#0f1117"
)
88
gs = fig.add_gridspec(2, 2, hspace=0.38, wspace=0.28)
89
ax_feat = fig.add_subplot(gs[0, 0])
90
ax_lens = fig.add_subplot(gs[0, 1])
91
ax_trace = fig.add_subplot(gs[1, 0])
92
ax_text = fig.add_subplot(gs[1, 1])
93
94
fig.suptitle(f
"Full trace — {model} · SAE layer {sae_layer}"
, color=
"#e5e7eb"
, fontsize=11, y=0.98)
95
96
_plot_top_features
(ax_feat, result.get(
"top_features"
)
or
[])
97
_plot_logit_lens
(ax_lens, result.get(
"logit_lens"
)
or
[], result.get(
"trace_target"
)
or
""
)
98
_plot_trace
(ax_trace, result.get(
"trace_results"
)
or
[])
99
_plot_summary
(ax_text, prompt, response, result.get(
"attribution"
)
or
[])
100
101
for
ax
in
(ax_feat, ax_lens, ax_trace):
102
ax.set_facecolor(
"#0f1117"
)
103
for
spine
in
ax.spines.values():
104
spine.set_color(
"#374151"
)
105
106
ax_text.set_facecolor(
"#0f1117"
)
107
for
spine
in
ax_text.spines.values():
108
spine.set_color(
"#374151"
)
109
110
fig.savefig(png_path, dpi=140, bbox_inches=
"tight"
, facecolor=
"#0f1117"
)
111
plt.close(fig)
112
113
114
def
_plot_top_features
(ax: Any, features: list[dict[str, Any]]) ->
None
:
115
rows = sorted(features, key=
lambda
f: float(f.get(
"activation"
)
or
0), reverse=
True
)[:12]
116
if
not
rows:
117
ax.axis(
"off"
)
118
ax.text(0.5, 0.5,
"No top features"
, ha=
"center"
, va=
"center"
, color=
"#9ca3af"
)
119
ax.set_title(
"Top SAE features"
, color=
"#e5e7eb"
, fontsize=10)
120
return
121
122
labels = []
123
vals = []
124
for
f
in
rows:
125
ref = f.get(
"feature_ref"
)
or
f.get(
"feature_idx"
,
"?"
)
126
label = f.get(
"causal_label"
)
or
f.get(
"label"
)
or
""
127
tok = f.get(
"token"
)
or
""
128
suffix = f
" · {tok!r}"
if
tok
else
(f
" · {label[:18]}"
if
label
else
""
)
129
labels.append(f
"{ref}{suffix}"
[:28])
130
vals.append(float(f.get(
"activation"
)
or
0))
131
132
y_pos = list(range(len(rows)))
133
ax.barh(y_pos, vals, color=
"#6366f1"
, height=0.72, alpha=0.9)
134
ax.set_yticks(y_pos)
135
ax.set_yticklabels(labels, fontsize=7, color=
"#d1d5db"
)
136
ax.invert_yaxis()
137
ax.set_xlabel(
"Activation"
, color=
"#9ca3af"
, fontsize=8)
138
ax.set_title(
"Top SAE features"
, color=
"#e5e7eb"
, fontsize=10)
139
ax.tick_params(axis=
"x"
, colors=
"#6b7280"
, labelsize=7)
140
ax.grid(axis=
"x"
, alpha=0.2, color=
"#4b5563"
)
141
142
143
def
_plot_logit_lens
(ax: Any, logit_lens: list[dict[str, Any]], trace_target: str) ->
None
:
144
if
not
logit_lens:
145
ax.axis(
"off"
)
146
ax.text(0.5, 0.5,
"No logit lens data"
, ha=
"center"
, va=
"center"
, color=
"#9ca3af"
)
147
ax.set_title(
"Logit lens"
, color=
"#e5e7eb"
, fontsize=10)
148
return
149
150
layers = []
151
probs = []
152
top_token = trace_target
or
""
153
for
row
in
logit_lens:
154
layer = int(row.get(
"layer"
, len(layers)))
155
tops = row.get(
"top_tokens"
)
or
[]
156
if
not
tops:
157
continue
158
best = tops[0]
159
layers.append(layer)
160
probs.append(float(best.get(
"prob"
)
or
0))
161
if
not
top_token:
162
top_token = str(best.get(
"token"
)
or
""
)
163
164
if
not
layers:
165
ax.axis(
"off"
)
166
ax.text(0.5, 0.5,
"No logit lens data"
, ha=
"center"
, va=
"center"
, color=
"#9ca3af"
)
167
ax.set_title(
"Logit lens"
, color=
"#e5e7eb"
, fontsize=10)
168
return
169
170
ax.plot(layers, probs, color=
"#34d399"
, marker=
"o"
, markersize=3, linewidth=1.5)
171
ax.set_xlabel(
"Layer"
, color=
"#9ca3af"
, fontsize=8)
172
ax.set_ylabel(
"P(top token)"
, color=
"#9ca3af"
, fontsize=8)
173
title = f
'Logit lens — top token {top_token!r}'
if
top_token
else
"Logit lens"
174
ax.set_title(title[:48], color=
"#e5e7eb"
, fontsize=9)
175
ax.tick_params(colors=
"#6b7280"
, labelsize=7)
176
ax.grid(alpha=0.2, color=
"#4b5563"
)
177
178
179
def
_plot_trace
(ax: Any, trace_results: list[dict[str, Any]]) ->
None
:
180
if
not
trace_results:
181
ax.axis(
"off"
)
182
ax.text(0.5, 0.5,
"No trace data"
, ha=
"center"
, va=
"center"
, color=
"#9ca3af"
)
183
ax.set_title(
"Layer probability delta"
, color=
"#e5e7eb"
, fontsize=10)
184
return
185
186
layers = [int(r.get(
"layer"
, i))
for
i, r
in
enumerate(trace_results)]
187
drops = [float(r.get(
"drop"
)
or
0)
for
r
in
trace_results]
188
ax.bar(layers, drops, color=
"#fbbf24"
, width=0.75, alpha=0.85)
189
ax.set_xlabel(
"Layer"
, color=
"#9ca3af"
, fontsize=8)
190
ax.set_ylabel(
"Δ prob"
, color=
"#9ca3af"
, fontsize=8)
191
ax.set_title(
"Layer probability delta"
, color=
"#e5e7eb"
, fontsize=10)
192
ax.tick_params(colors=
"#6b7280"
, labelsize=7)
193
ax.grid(axis=
"y"
, alpha=0.2, color=
"#4b5563"
)
194
195
196
def
_plot_summary
(ax: Any, prompt: str, response: str, attribution: list[dict[str, Any]]) ->
None
:
197
ax.axis(
"off"
)
198
ax.set_title(
"Summary"
, color=
"#e5e7eb"
, fontsize=10, loc=
"left"
)
199
200
lines = [
201
f
'Prompt: "{prompt}"'
,
202
""
,
203
f
'Response: "{response}"'
,
204
""
,
205
f
"Attribution: {len(attribution)} response tokens with driving features"
,
206
]
207
if
attribution:
208
lines.append(
""
)
209
for
a
in
attribution[:4]:
210
tok = a.get(
"response_token"
,
""
)
211
driven = a.get(
"driven_by_features"
)
or
[]
212
refs =
", "
.join(
213
str(d.get(
"feature_ref"
)
or
d.get(
"feature_idx"
,
"?"
))
214
for
d
in
driven[:3]
215
)
216
lines.append(f
" {tok!r} ← {refs}"
)
217
218
ax.text(
219
0.02,
220
0.96,
221
"\n"
.join(lines),
222
transform=ax.transAxes,
223
va=
"top"
,
224
ha=
"left"
,
225
fontsize=8,
226
color=
"#d1d5db"
,
227
family=
"monospace"
,
228
wrap=
True
,
229
)
aquin.trace_check._plot_logit_lens
None _plot_logit_lens(Any ax, list[dict[str, Any]] logit_lens, str trace_target)
Definition
trace_check.py:147
aquin.trace_check._plot_summary
None _plot_summary(Any ax, str prompt, str response, list[dict[str, Any]] attribution)
Definition
trace_check.py:200
aquin.trace_check._plot_trace_check
None _plot_trace_check(dict[str, Any] result, Path png_path)
Definition
trace_check.py:72
aquin.trace_check._plot_trace
None _plot_trace(Any ax, list[dict[str, Any]] trace_results)
Definition
trace_check.py:183
aquin.trace_check._flatten_trace_result
dict[str, Any] _flatten_trace_result(dict[str, Any] result)
Definition
trace_check.py:19
aquin.trace_check._plot_top_features
None _plot_top_features(Any ax, list[dict[str, Any]] features)
Definition
trace_check.py:118
aquin.trace_check.write_trace_check
tuple[Path, Path] write_trace_check(dict[str, Any] result, *, str|None tool_name, str|Path cwd)
Definition
trace_check.py:56
aquin
trace_check.py
AQIT · Aquin Labs Private Limited · Apache 2.0 · Generated by
1.18.0