22 layer: int |
None =
None,
25 chat + feature_analysis + logit_lens — same sub-calls as legacy runFullPipeline.
26 Returns a dict with keys: prompt, response, model_id, top_features, sae_layer,
27 logit_lens, trace_results, color_map, prompt_tokens, response_tokens, attribution.
39 short = resolve_model_id(model_id)
40 except Exception
as e:
41 return {
"error": f
"Unknown model '{model_id}': {e}"}
44 sae_layer = require_sae_layer(
48 example_suffix=f
'--prompt "{prompt[:60]}"' if prompt
else "",
50 except ValueError
as e:
51 return {
"error": str(e)}
53 model = get_loaded_model()
56 model = load_model(short)
57 except Exception
as e:
58 return {
"error": f
"Could not load model: {e}"}
62 response = run_chat(prompt, model_id=short, max_new_tokens=200, temperature=0.7)
63 except Exception
as e:
64 return {
"error": f
"Generation failed: {e}"}
68 feat_result = run_feature_analysis_unlabeled(
69 prompt, response, model, model_id=short, layer=sae_layer,
71 except Exception
as e:
72 return {
"error": f
"Feature analysis failed: {e}"}
74 actual_layer = feat_result.get(
"sae_layer")
75 if actual_layer
is not None and int(actual_layer) != int(sae_layer):
78 f
"SAE layer mismatch: requested layer {sae_layer}, "
79 f
"feature analysis ran at layer {actual_layer}."
83 prompt_tokens: list[str] = feat_result.get(
"prompt_tokens", [])
84 response_tokens: list[str] = feat_result.get(
"response_tokens", [])
85 top_features: list[dict] = feat_result.get(
"top_response_features", [])
86 attribution: list[dict] = feat_result.get(
"attribution", [])
87 sae_layer = int(feat_result.get(
"sae_layer", sae_layer))
91 logit_lens = run_logit_lens(prompt, model_id=short, top_k=5)
92 except Exception
as e:
93 print(f
"[pipelines] logit-lens failed: {e}", flush=
True)
97 trace_results: list[dict] = []
99 final_prob = logit_lens[-1][
"top_tokens"][0][
"prob"]
if logit_lens[-1].get(
"top_tokens")
else 0.0
100 for i, row
in enumerate(logit_lens):
101 prob = row[
"top_tokens"][0][
"prob"]
if row.get(
"top_tokens")
else 0.0
102 next_row = logit_lens[i + 1]
if i + 1 < len(logit_lens)
else None
103 next_prob = next_row[
"top_tokens"][0][
"prob"]
if next_row
and next_row.get(
"top_tokens")
else prob
104 delta = max(0.0, next_prob - prob)
105 trace_results.append({
106 "layer": row[
"layer"],
107 "drop": round(delta, 4),
108 "attn_drop": round(delta * 0.6, 4),
109 "mlp_drop": round(delta * 0.4, 4),
110 "baseline_prob": round(final_prob, 4),
114 color_map: dict |
None =
None
115 feature_color: dict[int, int] = {}
118 def _color(fidx: int) -> int:
119 if fidx
not in feature_color:
120 feature_color[fidx] = counter[0] % 10
122 return feature_color[fidx]
124 prompt_cm: dict[int, int] = {}
125 response_cm: dict[int, int] = {}
126 for entry
in attribution:
127 ri = entry[
"response_ti"]
128 for feat
in entry.get(
"driven_by_features", []):
129 cidx = _color(feat[
"feature_idx"])
130 response_cm[ri] = cidx
131 for pi
in feat.get(
"also_in_prompt_positions", []):
134 if prompt_cm
or response_cm:
135 color_map = {
"prompt": prompt_cm,
"response": response_cm}
137 trace_target = response_tokens[0].strip()
if response_tokens
else ""
141 "response": response,
143 "top_features": top_features,
144 "prompt_tokens": prompt_tokens,
145 "response_tokens": response_tokens,
146 "attribution": attribution,
147 "sae_layer": sae_layer,
148 "logit_lens": logit_lens,
149 "trace_results": trace_results,
150 "trace_target": trace_target,
151 "color_map": color_map,