Omibranch commited on
Commit
361b6dc
·
verified ·
1 Parent(s): dc41d9c

Upload colab_xfamily_crossformat.py with huggingface_hub

Browse files
Files changed (1) hide show
  1. colab_xfamily_crossformat.py +100 -0
colab_xfamily_crossformat.py ADDED
@@ -0,0 +1,100 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ """Cross-FORMAT x cross-FAMILY deception transfer — the template-confound killer.
2
+
3
+ Format A = roleplay deception ("pretend X is W, stay in character").
4
+ Format B = bluff game ("make the user believe something false about X").
5
+ These are syntactically and pragmatically different ways to elicit a lie.
6
+
7
+ If a probe trained on format-A deception (in one model) detects format-B
8
+ deception (in another model), it cannot be keying on the prompt template -- it
9
+ is keying on the deception itself. We test all train/test combinations of
10
+ {format} x {family}.
11
+ """
12
+ import json, numpy as np
13
+ from sklearn.linear_model import LogisticRegression
14
+ from sklearn.preprocessing import StandardScaler
15
+ from sklearn.metrics import roc_auc_score
16
+
17
+ A = json.load(open("/content/rift_xfamily_reps.json")) # roleplay
18
+ B = json.load(open("/content/rift_xfamily_reps_B.json")) # bluff
19
+ MODELS = [m for m in A["models"] if m in A["data"] and m in B["data"]]
20
+ short = {m: m.split("/")[-1] for m in MODELS}
21
+
22
+ def prep(blob):
23
+ Z = {}
24
+ for m in MODELS:
25
+ X = np.nan_to_num(np.array(blob["data"][m]["X"], dtype=float))
26
+ y = np.array(blob["data"][m]["y"])
27
+ Z[m] = (np.nan_to_num(StandardScaler().fit_transform(X)), y)
28
+ return Z
29
+ ZA, ZB = prep(A), prep(B)
30
+ banks = {"A": ZA, "B": ZB}
31
+
32
+ def probe():
33
+ return LogisticRegression(C=1.0, max_iter=5000)
34
+
35
+ rng = np.random.default_rng(0); NP = 5000
36
+ def perm_p(yte, sc, auc):
37
+ null = np.array([roc_auc_score(rng.permutation(yte), sc) for _ in range(NP)])
38
+ return float((null >= auc).mean())
39
+
40
+ print("=" * 72)
41
+ print("CROSS-FORMAT x CROSS-FAMILY DECEPTION TRANSFER")
42
+ print("A = roleplay lie, B = bluff-game lie (different templates)")
43
+ print("=" * 72)
44
+
45
+ # The key quantity: train on format A, test on format B (and vice versa),
46
+ # across every family pair. Pure cross-format (template changes every time).
47
+ xfmt_xfam = [] # different format AND different family (hardest)
48
+ xfmt_same = [] # different format, same family
49
+ results = {}
50
+ for tr_f in ["A", "B"]:
51
+ te_f = "B" if tr_f == "A" else "A"
52
+ for trm in MODELS:
53
+ Xtr, ytr = banks[tr_f][trm]
54
+ pr = probe().fit(Xtr, ytr)
55
+ for tem in MODELS:
56
+ Xte, yte = banks[te_f][tem]
57
+ sc = pr.predict_proba(Xte)[:, 1]
58
+ auc = roc_auc_score(yte, sc)
59
+ p = perm_p(yte, sc, auc)
60
+ key = f"{tr_f}:{short[trm]} -> {te_f}:{short[tem]}"
61
+ results[key] = {"auc": float(auc), "p": p}
62
+ if trm == tem:
63
+ xfmt_same.append(auc)
64
+ else:
65
+ xfmt_xfam.append(auc)
66
+
67
+ # print as readable blocks
68
+ for tr_f in ["A", "B"]:
69
+ te_f = "B" if tr_f == "A" else "A"
70
+ print(f"\n--- train format {tr_f} ({'roleplay' if tr_f=='A' else 'bluff'}), "
71
+ f"test format {te_f} ({'roleplay' if te_f=='A' else 'bluff'}) ---")
72
+ for trm in MODELS:
73
+ cells = []
74
+ for tem in MODELS:
75
+ r = results[f"{tr_f}:{short[trm]} -> {te_f}:{short[tem]}"]
76
+ star = "*" if tem != trm else " "
77
+ cells.append(f"{short[tem][:9]:>9s}:{r['auc']:.3f}(p{r['p']:.3f}){star}")
78
+ print(f" {short[trm]:24s} -> " + " | ".join(cells))
79
+
80
+ xs = np.array(xfmt_same); xf = np.array(xfmt_xfam)
81
+ print("\n" + "=" * 72)
82
+ print(f"CROSS-FORMAT, SAME family (n={len(xs)}): mean AUC {xs.mean():.3f} "
83
+ f"[{xs.min():.3f}, {xs.max():.3f}]")
84
+ print(f"CROSS-FORMAT + CROSS-FAMILY (n={len(xf)}): mean AUC {xf.mean():.3f} "
85
+ f"[{xf.min():.3f}, {xf.max():.3f}] <-- hardest: template AND architecture differ")
86
+ allp = [v["p"] for v in results.values()]
87
+ print(f"significant (p<0.05): {sum(p < 0.05 for p in allp)}/{len(allp)}")
88
+
89
+ verdict = ("DECEPTION, NOT TEMPLATE: probe transfers across BOTH format and family"
90
+ if xf.mean() > 0.7 and (np.array([results[k]['p'] for k in results
91
+ if k.split(':')[1].split(' ')[0] != k.split('> ')[1].split(':')[1]]) < 0.05).mean() > 0.8
92
+ else "PARTIAL: cross-format weaker than within-format (some template signal)"
93
+ if xf.mean() > 0.6 else "TEMPLATE-BOUND: signal does not survive format change")
94
+ print(f"\nVERDICT: {verdict}")
95
+
96
+ json.dump({"results": results, "xfmt_same_mean": float(xs.mean()),
97
+ "xfmt_xfam_mean": float(xf.mean()), "xfmt_xfam_aucs": xf.tolist(),
98
+ "verdict": verdict},
99
+ open("/content/rift_crossformat_results.json", "w"), indent=2)
100
+ print("\nsaved /content/rift_crossformat_results.json")