AQIT 0.1.0
Loading...
Searching...
No Matches
layer_analysis_check.py
Go to the documentation of this file.
1# Copyright (c) 2025-present Aquin Labs Private Limited. All Rights Reserved.
2"""`aquin check layer --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 = "layer-analysis-check.json"
12_PNG_NAME = "layer-analysis-check.png"
13
14
16 result: dict[str, Any],
17 *,
18 tool_name: str | None,
19 cwd: str | Path,
20) -> tuple[Path, Path]:
21 cwd = Path(cwd)
22 json_path = cwd / _JSON_NAME
23 png_path = cwd / _PNG_NAME
24
25 payload = {
26 "saved_at": datetime.now(timezone.utc).isoformat(),
27 "tool": tool_name,
28 **result,
29 }
30 json_path.write_text(json.dumps(payload, indent=2, default=str), encoding="utf-8")
31 _plot_layer_analysis_check(result, tool_name, png_path)
32 return json_path, png_path
33
34
35
37 result: dict[str, Any],
38 tool_name: str | None,
39 png_path: Path,
40) -> None:
41 import matplotlib
42
43 matplotlib.use("Agg")
44 import matplotlib.pyplot as plt
45 import numpy as np
46
47 if result.get("error"):
48 fig, ax = plt.subplots(figsize=(6, 2), facecolor="#0f1117")
49 ax.axis("off")
50 ax.text(0.5, 0.5, f"Error: {result['error']}", ha="center", va="center", wrap=True, color="#e5e7eb")
51 fig.savefig(png_path, dpi=140, bbox_inches="tight", facecolor="#0f1117")
52 plt.close(fig)
53 return
54
55 _ = tool_name
56 _plot_llm_layer_analysis(result, png_path, plt, np)
57
58
59def _plot_llm_layer_analysis(result: dict[str, Any], png_path: Path, plt: Any, np: Any) -> None:
60 stability = result.get("stability") or {}
61 ood = result.get("ood") or {}
62 localize = result.get("localize") if isinstance(result.get("localize"), dict) else None
63 stab_layers = stability.get("layers") or []
64 ood_layers = ood.get("layers") or []
65 loc_layers = (localize or {}).get("layers") or []
66
67 n_cols = 3 if loc_layers else 2
68 fig, axes = plt.subplots(1, n_cols, figsize=(5.5 * n_cols, 4.5), facecolor="#0f1117")
69 if n_cols == 1:
70 axes = [axes]
71 model = str(result.get("model_id") or "")
72 title = f"Layer analysis (LLM) — {model}"
73 if localize and localize.get("collapse_layer") is not None:
74 title += f" · collapse L{localize.get('collapse_layer')}"
75 fig.suptitle(title, color="#e5e7eb", fontsize=11, y=1.02)
76
77 ax0 = axes[0]
78 if stab_layers:
79 xs = [int(r["layer"]) for r in stab_layers]
80 pc1 = [float(r.get("top1_variance_ratio") or 0) for r in stab_layers]
81 colors = []
82 for r in stab_layers:
83 status = str(r.get("status") or "ok")
84 colors.append({"dead": "#f87171", "collapsed": "#fbbf24", "ok": "#34d399"}.get(status, "#9ca3af"))
85 ax0.bar(xs, pc1, color=colors, width=0.8)
86 ax0.axhline(0.85, color="#fbbf24", linestyle="--", linewidth=0.8, alpha=0.6, label="collapse")
87 ax0.set_xlabel("Layer", color="#9ca3af", fontsize=9)
88 ax0.set_ylabel("PC1 variance ratio", color="#9ca3af", fontsize=9)
89 ax0.set_title("Activation stability", color="#e5e7eb", fontsize=10)
90 ax0.tick_params(colors="#6b7280", labelsize=8)
91 else:
92 ax0.axis("off")
93 ax0.text(0.5, 0.5, "No stability data", ha="center", va="center", color="#9ca3af")
94
95 ax1 = axes[1]
96 if ood_layers:
97 xs = [int(r["layer"]) for r in ood_layers]
98 sep = [float(r.get("separation") or 0) for r in ood_layers]
99 ax1.plot(xs, sep, color="#34d399", marker="o", markersize=4, linewidth=1.5)
100 peak = ood.get("peak_layer")
101 if peak is not None:
102 ax1.axvline(int(peak), color="#facc15", linestyle="--", linewidth=0.8, alpha=0.7)
103 ax1.set_xlabel("Layer", color="#9ca3af", fontsize=9)
104 ax1.set_ylabel("OOD separation", color="#9ca3af", fontsize=9)
105 ax1.set_title("In-domain vs OOD", color="#e5e7eb", fontsize=10)
106 ax1.tick_params(colors="#6b7280", labelsize=8)
107 else:
108 ax1.axis("off")
109 ax1.text(0.5, 0.5, "No OOD data", ha="center", va="center", color="#9ca3af")
110
111 if loc_layers:
112 ax2 = axes[2]
113 xs = [int(r["layer"]) for r in loc_layers]
114 sig = [float(r.get("signal") or 0) for r in loc_layers]
115 ax2.plot(xs, sig, color="#a78bfa", marker="o", markersize=4, linewidth=1.5)
116 peak = localize.get("peak_layer") if localize else None
117 collapse = localize.get("collapse_layer") if localize else None
118 if peak is not None:
119 ax2.axvline(int(peak), color="#34d399", linestyle="--", linewidth=0.8, alpha=0.8, label="peak")
120 if collapse is not None:
121 ax2.axvline(int(collapse), color="#f87171", linestyle="--", linewidth=0.8, alpha=0.8, label="collapse")
122 ax2.set_xlabel("Layer", color="#9ca3af", fontsize=9)
123 ax2.set_ylabel("Deception signal", color="#9ca3af", fontsize=9)
124 ax2.set_title("Localize collapse", color="#e5e7eb", fontsize=10)
125 ax2.tick_params(colors="#6b7280", labelsize=8)
126 ax2.legend(fontsize=7, labelcolor="#9ca3af", frameon=False)
127
128 fig.tight_layout()
129 fig.savefig(png_path, dpi=140, bbox_inches="tight", facecolor="#0f1117")
130 plt.close(fig)
None _plot_layer_analysis_check(dict[str, Any] result, str|None tool_name, Path png_path)
None _plot_llm_layer_analysis(dict[str, Any] result, Path png_path, Any plt, Any np)
tuple[Path, Path] write_layer_analysis_check(dict[str, Any] result, *, str|None tool_name, str|Path cwd)