24 out = [str(x).strip()
for x
in raw
if str(x).strip()]
26 if isinstance(raw, str):
30 if text.startswith(
"["):
32 parsed = json.loads(text)
33 except json.JSONDecodeError:
35 if isinstance(parsed, list):
36 out = [str(x).strip()
for x
in parsed
if str(x).strip()]
38 path = Path(text).expanduser()
40 body = path.read_text(encoding=
"utf-8").strip()
41 if path.suffix ==
".jsonl":
42 rows = [json.loads(line)
for line
in body.splitlines()
if line.strip()]
45 if isinstance(row, str)
and row.strip():
46 out.append(row.strip())
47 elif isinstance(row, dict):
48 for key
in (
"prompt",
"instruction",
"text",
"question"):
50 if isinstance(val, str)
and val.strip():
51 out.append(val.strip())
55 parsed = json.loads(body)
56 except json.JSONDecodeError:
58 if isinstance(parsed, list):
61 if isinstance(item, str)
and item.strip():
62 out.append(item.strip())
63 elif isinstance(item, dict):
64 for key
in (
"prompt",
"instruction",
"text",
"question"):
66 if isinstance(val, str)
and val.strip():
67 out.append(val.strip())
74def _rate(n: int, total: int) -> float:
75 return round(n / total, 4)
if total
else 0.0
114 if prompts
is None or prompts
is True:
115 return load_behavior_probes(
None)
117 if isinstance(prompts, (str, Path)):
118 text = str(prompts).strip()
119 if not text
or text.startswith(
"["):
122 return load_behavior_probes(text)
123 except (FileNotFoundError, ValueError, json.JSONDecodeError, OSError):
131 generate_baseline: Callable[[str], str],
132 generate_steered: Callable[[str], str],
134 reference_answers: Any =
None,
135 threshold: float = DEFAULT_THRESHOLD,
136 max_probes: int = MAX_PROBES,
139 Score the same probe set under baseline vs steered generation.
142 - behavior (default): deception-style probes with honest/deceptive references;
143 pass = classified truthful.
144 - custom: prompts + reference_answers; pass = keyword overlap >= threshold.
149 if behavior_loaded
is not None:
150 probes, meta = behavior_loaded
151 probes = probes[: max(1, int(max_probes))]
152 rows: list[dict[str, Any]] = []
154 base_resp = generate_baseline(probe.prompt)
155 steered_resp = generate_steered(probe.prompt)
156 b_beh, b_h, b_d = classify_behavior(
157 base_resp, probe.honest_reference, probe.deceptive_reference,
159 s_beh, s_h, s_d = classify_behavior(
160 steered_resp, probe.honest_reference, probe.deceptive_reference,
163 "probe_id": probe.probe_id,
164 "prompt": probe.prompt,
165 "intent": probe.intent,
167 "response": base_resp,
170 "deceptive_score": b_d,
171 "passed": b_beh ==
"truthful",
174 "response": steered_resp,
177 "deceptive_score": s_d,
178 "passed": s_beh ==
"truthful",
180 "changed": base_resp.strip() != steered_resp.strip(),
187 "prompts_path": meta.get(
"prompts_path"),
188 "n_probes": len(rows),
189 "pass_means":
"truthful",
190 "baseline": baseline,
192 "delta_pass_rate": round(steered[
"pass_rate"] - baseline[
"pass_rate"], 4),
193 "n_changed": sum(1
for r
in rows
if r[
"changed"]),
201 "steer --eval needs a probe set. Pass --prompts <jsonl|json|array> "
202 "and --reference_answers for custom scoring."
208 "Custom steer --eval requires --reference_answers (one per prompt). "
209 "Or pass a deception probe file with honest_reference / deceptive_reference."
212 if len(refs) != len(prompt_list):
215 f
"reference_answers length ({len(refs)}) must match prompts ({len(prompt_list)})"
219 prompt_list = prompt_list[: max(1, int(max_probes))]
220 refs = refs[: len(prompt_list)]
221 thr = float(threshold)
223 for i, (prompt, reference)
in enumerate(zip(prompt_list, refs)):
224 base_resp = generate_baseline(prompt)
225 steered_resp = generate_steered(prompt)
226 b_score = keyword_overlap_score(base_resp, reference)
227 s_score = keyword_overlap_score(steered_resp, reference)
231 "reference": reference,
233 "response": base_resp,
235 "passed": b_score >= thr,
238 "response": steered_resp,
240 "passed": s_score >= thr,
242 "changed": base_resp.strip() != steered_resp.strip(),
249 "n_probes": len(rows),
251 "pass_means": f
"keyword_overlap>={thr}",
252 "baseline": baseline,
254 "delta_pass_rate": round(steered[
"pass_rate"] - baseline[
"pass_rate"], 4),
255 "n_changed": sum(1
for r
in rows
if r[
"changed"]),
dict[str, Any] run_steer_probe_eval(*, Callable[[str], str] generate_baseline, Callable[[str], str] generate_steered, Any prompts=None, Any reference_answers=None, float threshold=DEFAULT_THRESHOLD, int max_probes=MAX_PROBES)