From 74b2fd6f2c719413183852f0a49ea3261ad50556 Mon Sep 17 00:00:00 2001 From: Dhruv Parashar Date: Fri, 29 Aug 2025 01:24:57 -0400 Subject: [PATCH 1/3] Refactor: src/scripts/artifacts structure; one-pass compile+export; lean parity checker --- .../tracr_transformer_pt.cpython-313.pyc | Bin 5231 -> 6101 bytes artifacts/input_tokens.json | 1 + artifacts/token_to_id.json | 6 + artifacts/tracr_majority_params.npz | Bin 0 -> 45154 bytes artifacts/tracr_output.npy | Bin 0 -> 728 bytes artifacts/tracr_param_keys.json | 40 ++ export_tracr_params.py | 60 --- graph.gv | 366 ------------------ graph.gv.pdf | Bin 74266 -> 0 bytes input_tokens.json | 1 + load_and_visualize_with_torchlens.py | 70 ---- my_majority_program.py | 183 --------- my_majority_torchlens.py | 56 --- scripts/compile_export.py | 139 +++++++ scripts/parity_check.py | 77 ++++ src/__init__.py | 0 .../tracr_pt_model.cpython-313.pyc | Bin 0 -> 6099 bytes src/tracr_pt_model.py | 66 ++++ token_to_id.json | 6 + tracr_majority_graph.pdf | Bin 56012 -> 0 bytes tracr_majority_params.npz | Bin 30178 -> 45154 bytes tracr_output.npy | Bin 0 -> 728 bytes tracr_param_keys.json | 40 ++ tracr_transformer_pt.py | 60 --- 24 files changed, 376 insertions(+), 795 deletions(-) create mode 100644 artifacts/input_tokens.json create mode 100644 artifacts/token_to_id.json create mode 100644 artifacts/tracr_majority_params.npz create mode 100644 artifacts/tracr_output.npy create mode 100644 artifacts/tracr_param_keys.json delete mode 100644 export_tracr_params.py delete mode 100644 graph.gv delete mode 100644 graph.gv.pdf create mode 100644 input_tokens.json delete mode 100644 load_and_visualize_with_torchlens.py delete mode 100644 my_majority_program.py delete mode 100644 my_majority_torchlens.py create mode 100644 scripts/compile_export.py create mode 100644 scripts/parity_check.py create mode 100644 src/__init__.py create mode 100644 src/__pycache__/tracr_pt_model.cpython-313.pyc create mode 100644 src/tracr_pt_model.py create mode 100644 token_to_id.json delete mode 100644 tracr_majority_graph.pdf create mode 100644 tracr_output.npy create mode 100644 tracr_param_keys.json delete mode 100644 tracr_transformer_pt.py diff --git a/__pycache__/tracr_transformer_pt.cpython-313.pyc b/__pycache__/tracr_transformer_pt.cpython-313.pyc index 1f6d124f0f7505b18cf17c5ce179d50fb5b91e3e..5a5b73c1f447ef31f20623a966eea86d0bd4bfc2 100644 GIT binary patch literal 6101 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 IK+#zBKSz&Zi2wiq literal 5231 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 diff --git a/artifacts/input_tokens.json b/artifacts/input_tokens.json new file mode 100644 index 0000000..3674a71 --- /dev/null +++ b/artifacts/input_tokens.json @@ -0,0 +1 @@ +["BOS", 1, 0, 1, 1, 0] \ No newline at end of file diff --git a/artifacts/token_to_id.json b/artifacts/token_to_id.json new file mode 100644 index 0000000..6966287 --- /dev/null +++ b/artifacts/token_to_id.json @@ -0,0 +1,6 @@ +{ + "BOS": 2, + "0": 0, + "1": 1, + "PAD": 3 +} \ No newline at end of file diff --git a/artifacts/tracr_majority_params.npz b/artifacts/tracr_majority_params.npz new file mode 100644 index 0000000000000000000000000000000000000000..ce7aa3a4a39ab56550053e58898a3959f70fbfb4 GIT binary patch literal 45154 zcmeI5OKclO7{}L1%1b>&s6a~vI10+6BvJF~1B!|&6xtL}1maK-Y#h94L;S*a5}5$< zg@=F(?F9)HQ7R!2;lKqUE^q*;NIg+0Ck{cXKtc_iKu8F|OzqjujAu79UhmdU{;pP& zb=Uv-_UG@L{XCw}J9WIhW6-KRx~$3R_4t3)$1ZD!mCF`vCq3gN?MjoJ%bY9>WpbsM z)oESqsJx7|XC8m*v8fX=YtdTnO*)0=^S$@Sdk@Wy^$x^)XS4ZYK9RAr`J_XipGc$% z4tc(CDv@)@e&6u$KzwApe<1!!yw1lh)w77ODIboeGxSp*XK({IO2FI?ri5Yfn00BD z4U4t=b0THckR`EC{;LxiNldK>!3m z00ck)1VCV`5D@dm+s1xPu)MKTz$zBxwl+FNKj2qX z>G}Hz=kIJO6>Ed~K_D-Ppo)Rg6#1=x|L|RAaYXoq6Gx-hyV{8PUaikH_L=7BNAv^! z`%#ZdAabEVC6F9H2ftcgVDY2H&5a#a0mRy%V-G5U8XKjxYNl~(dOYpX^fji(qmSD6 z)$bWozNW|H{qUn-`+ufhb5zl}C2(%Ib)0j6szCIRWzRiDb^{51L^KDcD5#l1g z(--!iV`;Z8zK}BSMpObtROse)h%md6sl*k_##4MkP@Aae3j0Ss$jyQ+3nVm>!Ql!hH|%e(3XUR#y6F zfFoOxz){0--1PWXWCEMRCQyIQjY=Rs=f3h_*IC`18MuC2W+EWw+!~cYWS)ByR00+L{e)%69u*+9=jqN%vkD;A2402T&`KbAY?Akz z$@`+WMf7)mMU|c(pc07xr1{&&kNj*FN1Lw_D6061svo_W6yu2he$=C)g}m{o1d^8| z^1qX)#m&72u?is82EGR2o+(Yztenpi>C6MF?WOrsLlPkrnPK(_Oh_ylep!Mzv^vn;d-DYt__=OWk*ZrPA zvX7ehx%^s_{iym8ZJIhBYa47ItUlRgO-`@JFLqcK-F9(@mapDFEtf6WPI|^k+Lb0b zmpNIWVI<2Ovo5W6wpkY4b_+6hY_qIlcHYV83DIwC*N6b!ddS8eL3bWaK z+R2l<+a*e**;`wwBpXM+%cPYzbQ3jKZqm@a>i4oH9f9chLAQQpBx%dB%eVS#3M)Ki zS-RGdnJUV5@6eM~TFX=I6RdsiZhu++TXES~o~x+(-aT5XhPM7li1>K`Kbxp;>-PJ! zRF$^Uyo=sRk#2hgt`p;4s;VqZwwB)ekY*`#6Lp97Y3eHN<-Jza-FHAomt93=d+9yq z)b=hO)YMhl%loYuxvxH;)OCN?b>1meulTa9^nP9}#6-<64{2yB?c}+NVf*`pzozeK zK<|OTOciAZkLt-Pt>vkTaeL|se_6lLfc|zYGgegn=t(VALtB4()?d|cG@!q^rMC5U zTT4}GtM_OyHRq+OH5!oLKTt>4ffqD&mG<&pD~<*arF3+?Mgv-BuC}+F*3?zn%loYu zxo>8by2L=aidh~F_-mM``E5=^Q)ws9RSes|U-H-V9Syv5gZ(e-$ttbosfux%f8Af! zZ#3Y!imEGbXsH_7`pdiis(zz^x2^FrTB=H0y+?zm&w8oqj0SWLL>*m6KG4)v+RJ;b pI2ufTsH5vO8qm+0YJ1;0r>R@DciRm##p)sdzTR$Gr_a;9{{hP~-!K3G literal 0 HcmV?d00001 diff --git a/artifacts/tracr_output.npy b/artifacts/tracr_output.npy new file mode 100644 index 0000000000000000000000000000000000000000..a802065652a5b0caae36ba8cec63d37c43b0ef25 GIT binary patch literal 728 zcmbR27wQ`j$;eQ~P_3SlTAW;@Zl$1ZlV+l>qoAIaUsO_*m=~X4l#&V(cT3DEP6dh= zXCxM+0{I$-Itpew3Pz@yItsN4WC1P)s(}W3Ors!T-~QKw=7Q%!kdouble_underscore to be filesystem-friendly --- -npz_dict = {} -for k, v in leaves_with_paths: - safe = k.replace("/", "__") - npz_dict[safe] = np.array(v) - -np.savez("tracr_majority_params.npz", **npz_dict) -print("Exported => tracr_majority_params.npz") diff --git a/graph.gv b/graph.gv deleted file mode 100644 index 2470339..0000000 --- a/graph.gv +++ /dev/null @@ -1,366 +0,0 @@ -// Computational graph for the feedforward sweep -digraph TracrTransformerPT { - graph [label=<TracrTransformerPT
77 tensors total (36.7 KB)
4656 params total (22.7 KB)
> labeljust=left labelloc=t ordering=out rankdir=BT] - node [ordering=out] - input_1 [label=<input_1
1x6 (176 B)
@input.token_ids> color=black fillcolor="#98FB98" fontcolor=black ordering=out shape=oval style="filled,solid"] - input_1 -> embedding_1_1 [arrowsize=.7 color=black fontcolor=black labelfontsize=8 style=solid] - embedding_1_1 [label=<embedding_1_1
1x6x24 (720 B)
params: 4x24
@token_emb> color=black fillcolor="#E6E6E6" fontcolor=black ordering=out shape=box style="filled,solid"] - embedding_1_1 -> add_1_6 [arrowsize=.7 color=black fontcolor=black labelfontsize=8 style=solid] - arange_1_2 [label=<arange_1_2
x6 (160 B)> color=black fillcolor=white fontcolor=black ordering=out shape=oval style="filled,dashed"] - arange_1_2 -> unsqueeze_1_3 [arrowsize=.7 color=black fontcolor=black labelfontsize=8 style=dashed] - unsqueeze_1_3 [label=<unsqueeze_1_3
1x6 (176 B)> color=black fillcolor=white fontcolor=black ordering=out shape=oval style="filled,dashed"] - unsqueeze_1_3 -> expand_1_4 [arrowsize=.7 color=black fontcolor=black labelfontsize=8 style=dashed] - expand_1_4 [label=<expand_1_4
1x6 (176 B)> color=black fillcolor=white fontcolor=black ordering=out shape=oval style="filled,dashed"] - expand_1_4 -> embedding_2_5 [arrowsize=.7 color=black fontcolor=black labelfontsize=8 style=dashed] - embedding_2_5 [label=<embedding_2_5
1x6x24 (720 B)
params: 11x24
@pos_emb> color=black fillcolor="#E6E6E6" fontcolor=black ordering=out shape=box style="filled,dashed"] - embedding_2_5 -> add_1_6 [arrowsize=.7 color=black fontcolor=black labelfontsize=8 style=dashed] - add_1_6 [label=<add_1_6
1x6x24 (720 B)> color=black fillcolor=white fontcolor=black ordering=out shape=oval style="filled,solid"] - add_1_6 -> linear_1_7 [arrowsize=.7 color=black fontcolor=black labelfontsize=8 style=solid] - add_1_6 -> linear_2_10 [arrowsize=.7 color=black fontcolor=black labelfontsize=8 style=solid] - add_1_6 -> linear_3_13 [arrowsize=.7 color=black fontcolor=black labelfontsize=8 style=solid] - add_1_6 -> add_2_25pass1 [arrowsize=.7 color=black fontcolor=black labelfontsize=8 style=solid] - linear_1_7 [label=<linear_1_7
1x6x12 (432 B)
params: 12x24, x12
@layers.0.attn.W_q> color=black fillcolor="#E6E6E6" fontcolor=black ordering=out shape=box style="filled,solid"] - view_1_8 [label=<view_1_8
1x6x3x4 (448 B)> color=black fillcolor=white fontcolor=black ordering=out shape=oval style="filled,solid"] - transpose_1_9 [label=<transpose_1_9
1x3x6x4 (448 B)> color=black fillcolor=white fontcolor=black ordering=out shape=oval style="filled,solid"] - linear_2_10 [label=<linear_2_10
1x6x12 (432 B)
params: 12x24, x12
@layers.0.attn.W_k> color=black fillcolor="#E6E6E6" fontcolor=black ordering=out shape=box style="filled,solid"] - view_2_11 [label=<view_2_11
1x6x3x4 (448 B)> color=black fillcolor=white fontcolor=black ordering=out shape=oval style="filled,solid"] - transpose_2_12 [label=<transpose_2_12
1x3x6x4 (448 B)> color=black fillcolor=white fontcolor=black ordering=out shape=oval style="filled,solid"] - linear_3_13 [label=<linear_3_13
1x6x12 (432 B)
params: 12x24, x12
@layers.0.attn.W_v> color=black fillcolor="#E6E6E6" fontcolor=black ordering=out shape=box style="filled,solid"] - view_3_14 [label=<view_3_14
1x6x3x4 (448 B)> color=black fillcolor=white fontcolor=black ordering=out shape=oval style="filled,solid"] - transpose_3_15 [label=<transpose_3_15
1x3x6x4 (448 B)> color=black fillcolor=white fontcolor=black ordering=out shape=oval style="filled,solid"] - transpose_4_16 [label=<transpose_4_16
1x3x4x6 (448 B)> color=black fillcolor=white fontcolor=black ordering=out shape=oval style="filled,solid"] - matmul_1_17 [label=<matmul_1_17
1x3x6x6 (592 B)> color=black fillcolor=white fontcolor=black ordering=out shape=oval style="filled,solid"] - truediv_1_18 [label=<truediv_1_18
1x3x6x6 (592 B)> color=black fillcolor=white fontcolor=black ordering=out shape=oval style="filled,solid"] - softmax_1_19 [label=<softmax_1_19
1x3x6x6 (592 B)> color=black fillcolor=white fontcolor=black ordering=out shape=oval style="filled,solid"] - matmul_2_20 [label=<matmul_2_20
1x3x6x4 (448 B)> color=black fillcolor=white fontcolor=black ordering=out shape=oval style="filled,solid"] - transpose_5_21 [label=<transpose_5_21
1x6x3x4 (448 B)> color=black fillcolor=white fontcolor=black ordering=out shape=oval style="filled,solid"] - contiguous_1_22 [label=<contiguous_1_22
1x6x3x4 (448 B)> color=black fillcolor=white fontcolor=black ordering=out shape=oval style="filled,solid"] - view_4_23 [label=<view_4_23
1x6x12 (432 B)> color=black fillcolor=white fontcolor=black ordering=out shape=oval style="filled,solid"] - linear_4_24 [label=<linear_4_24
1x6x24 (720 B)
params: 24x12, x24
@layers.0.attn.W_o> color=black fillcolor="#E6E6E6" fontcolor=black ordering=out shape=box style="filled,solid"] - add_2_25pass1 [label=<add_2_25:1
1x6x24 (720 B)> color=black fillcolor=white fontcolor=black ordering=out shape=oval style="filled,solid"] - linear_5_26 [label=<linear_5_26
1x6x4 (240 B)
params: 4x24, x4
@layers.0.mlp.0> color=black fillcolor="#E6E6E6" fontcolor=black ordering=out shape=box style="filled,solid"] - gelu_1_27 [label=<gelu_1_27
1x6x4 (240 B)
@layers.0.mlp.1> color=black fillcolor=white fontcolor=black ordering=out shape=box style="filled,solid"] - linear_6_28 [label=<linear_6_28
1x6x24 (720 B)
params: 24x4, x24
@layers.0.mlp.2> color=black fillcolor="#E6E6E6" fontcolor=black ordering=out shape=box style="filled,solid"] - add_2_25pass2 [label=<add_2_25:2
1x6x24 (720 B)> color=black fillcolor=white fontcolor=black ordering=out shape=oval style="filled,solid"] - add_2_25pass2 -> linear_7_29 [arrowsize=.7 color=black fontcolor=black labelfontsize=8 style=solid] - add_2_25pass2 -> linear_8_32 [arrowsize=.7 color=black fontcolor=black labelfontsize=8 style=solid] - add_2_25pass2 -> linear_9_35 [arrowsize=.7 color=black fontcolor=black labelfontsize=8 style=solid] - add_2_25pass2 -> add_3_47pass1 [arrowsize=.7 color=black fontcolor=black labelfontsize=8 style=solid] - linear_7_29 [label=<linear_7_29
1x6x12 (432 B)
params: 12x24, x12
@layers.1.attn.W_q> color=black fillcolor="#E6E6E6" fontcolor=black ordering=out shape=box style="filled,solid"] - view_5_30 [label=<view_5_30
1x6x3x4 (448 B)> color=black fillcolor=white fontcolor=black ordering=out shape=oval style="filled,solid"] - transpose_6_31 [label=<transpose_6_31
1x3x6x4 (448 B)> color=black fillcolor=white fontcolor=black ordering=out shape=oval style="filled,solid"] - linear_8_32 [label=<linear_8_32
1x6x12 (432 B)
params: 12x24, x12
@layers.1.attn.W_k> color=black fillcolor="#E6E6E6" fontcolor=black ordering=out shape=box style="filled,solid"] - view_6_33 [label=<view_6_33
1x6x3x4 (448 B)> color=black fillcolor=white fontcolor=black ordering=out shape=oval style="filled,solid"] - transpose_7_34 [label=<transpose_7_34
1x3x6x4 (448 B)> color=black fillcolor=white fontcolor=black ordering=out shape=oval style="filled,solid"] - linear_9_35 [label=<linear_9_35
1x6x12 (432 B)
params: 12x24, x12
@layers.1.attn.W_v> color=black fillcolor="#E6E6E6" fontcolor=black ordering=out shape=box style="filled,solid"] - view_7_36 [label=<view_7_36
1x6x3x4 (448 B)> color=black fillcolor=white fontcolor=black ordering=out shape=oval style="filled,solid"] - transpose_8_37 [label=<transpose_8_37
1x3x6x4 (448 B)> color=black fillcolor=white fontcolor=black ordering=out shape=oval style="filled,solid"] - transpose_9_38 [label=<transpose_9_38
1x3x4x6 (448 B)> color=black fillcolor=white fontcolor=black ordering=out shape=oval style="filled,solid"] - matmul_3_39 [label=<matmul_3_39
1x3x6x6 (592 B)> color=black fillcolor=white fontcolor=black ordering=out shape=oval style="filled,solid"] - truediv_2_40 [label=<truediv_2_40
1x3x6x6 (592 B)> color=black fillcolor=white fontcolor=black ordering=out shape=oval style="filled,solid"] - softmax_2_41 [label=<softmax_2_41
1x3x6x6 (592 B)> color=black fillcolor=white fontcolor=black ordering=out shape=oval style="filled,solid"] - matmul_4_42 [label=<matmul_4_42
1x3x6x4 (448 B)> color=black fillcolor=white fontcolor=black ordering=out shape=oval style="filled,solid"] - transpose_10_43 [label=<transpose_10_43
1x6x3x4 (448 B)> color=black fillcolor=white fontcolor=black ordering=out shape=oval style="filled,solid"] - contiguous_2_44 [label=<contiguous_2_44
1x6x3x4 (448 B)> color=black fillcolor=white fontcolor=black ordering=out shape=oval style="filled,solid"] - view_8_45 [label=<view_8_45
1x6x12 (432 B)> color=black fillcolor=white fontcolor=black ordering=out shape=oval style="filled,solid"] - linear_10_46 [label=<linear_10_46
1x6x24 (720 B)
params: 24x12, x24
@layers.1.attn.W_o> color=black fillcolor="#E6E6E6" fontcolor=black ordering=out shape=box style="filled,solid"] - add_3_47pass1 [label=<add_3_47:1
1x6x24 (720 B)> color=black fillcolor=white fontcolor=black ordering=out shape=oval style="filled,solid"] - linear_11_48 [label=<linear_11_48
1x6x4 (240 B)
params: 4x24, x4
@layers.1.mlp.0> color=black fillcolor="#E6E6E6" fontcolor=black ordering=out shape=box style="filled,solid"] - gelu_2_49 [label=<gelu_2_49
1x6x4 (240 B)
@layers.1.mlp.1> color=black fillcolor=white fontcolor=black ordering=out shape=box style="filled,solid"] - linear_12_50 [label=<linear_12_50
1x6x24 (720 B)
params: 24x4, x24
@layers.1.mlp.2> color=black fillcolor="#E6E6E6" fontcolor=black ordering=out shape=box style="filled,solid"] - add_3_47pass2 [label=<add_3_47:2
1x6x24 (720 B)> color=black fillcolor=white fontcolor=black ordering=out shape=oval style="filled,solid"] - add_3_47pass2 -> linear_13_51 [arrowsize=.7 color=black fontcolor=black labelfontsize=8 style=solid] - add_3_47pass2 -> linear_14_54 [arrowsize=.7 color=black fontcolor=black labelfontsize=8 style=solid] - add_3_47pass2 -> linear_15_57 [arrowsize=.7 color=black fontcolor=black labelfontsize=8 style=solid] - add_3_47pass2 -> add_4_69pass1 [arrowsize=.7 color=black fontcolor=black labelfontsize=8 style=solid] - linear_13_51 [label=<linear_13_51
1x6x12 (432 B)
params: 12x24, x12
@layers.2.attn.W_q> color=black fillcolor="#E6E6E6" fontcolor=black ordering=out shape=box style="filled,solid"] - view_9_52 [label=<view_9_52
1x6x3x4 (448 B)> color=black fillcolor=white fontcolor=black ordering=out shape=oval style="filled,solid"] - transpose_11_53 [label=<transpose_11_53
1x3x6x4 (448 B)> color=black fillcolor=white fontcolor=black ordering=out shape=oval style="filled,solid"] - linear_14_54 [label=<linear_14_54
1x6x12 (432 B)
params: 12x24, x12
@layers.2.attn.W_k> color=black fillcolor="#E6E6E6" fontcolor=black ordering=out shape=box style="filled,solid"] - view_10_55 [label=<view_10_55
1x6x3x4 (448 B)> color=black fillcolor=white fontcolor=black ordering=out shape=oval style="filled,solid"] - transpose_12_56 [label=<transpose_12_56
1x3x6x4 (448 B)> color=black fillcolor=white fontcolor=black ordering=out shape=oval style="filled,solid"] - linear_15_57 [label=<linear_15_57
1x6x12 (432 B)
params: 12x24, x12
@layers.2.attn.W_v> color=black fillcolor="#E6E6E6" fontcolor=black ordering=out shape=box style="filled,solid"] - view_11_58 [label=<view_11_58
1x6x3x4 (448 B)> color=black fillcolor=white fontcolor=black ordering=out shape=oval style="filled,solid"] - transpose_13_59 [label=<transpose_13_59
1x3x6x4 (448 B)> color=black fillcolor=white fontcolor=black ordering=out shape=oval style="filled,solid"] - transpose_14_60 [label=<transpose_14_60
1x3x4x6 (448 B)> color=black fillcolor=white fontcolor=black ordering=out shape=oval style="filled,solid"] - matmul_5_61 [label=<matmul_5_61
1x3x6x6 (592 B)> color=black fillcolor=white fontcolor=black ordering=out shape=oval style="filled,solid"] - truediv_3_62 [label=<truediv_3_62
1x3x6x6 (592 B)> color=black fillcolor=white fontcolor=black ordering=out shape=oval style="filled,solid"] - softmax_3_63 [label=<softmax_3_63
1x3x6x6 (592 B)> color=black fillcolor=white fontcolor=black ordering=out shape=oval style="filled,solid"] - matmul_6_64 [label=<matmul_6_64
1x3x6x4 (448 B)> color=black fillcolor=white fontcolor=black ordering=out shape=oval style="filled,solid"] - transpose_15_65 [label=<transpose_15_65
1x6x3x4 (448 B)> color=black fillcolor=white fontcolor=black ordering=out shape=oval style="filled,solid"] - contiguous_3_66 [label=<contiguous_3_66
1x6x3x4 (448 B)> color=black fillcolor=white fontcolor=black ordering=out shape=oval style="filled,solid"] - view_12_67 [label=<view_12_67
1x6x12 (432 B)> color=black fillcolor=white fontcolor=black ordering=out shape=oval style="filled,solid"] - linear_16_68 [label=<linear_16_68
1x6x24 (720 B)
params: 24x12, x24
@layers.2.attn.W_o> color=black fillcolor="#E6E6E6" fontcolor=black ordering=out shape=box style="filled,solid"] - add_4_69pass1 [label=<add_4_69:1
1x6x24 (720 B)> color=black fillcolor=white fontcolor=black ordering=out shape=oval style="filled,solid"] - linear_17_70 [label=<linear_17_70
1x6x4 (240 B)
params: 4x24, x4
@layers.2.mlp.0> color=black fillcolor="#E6E6E6" fontcolor=black ordering=out shape=box style="filled,solid"] - gelu_3_71 [label=<gelu_3_71
1x6x4 (240 B)
@layers.2.mlp.1> color=black fillcolor=white fontcolor=black ordering=out shape=box style="filled,solid"] - linear_18_72 [label=<linear_18_72
1x6x24 (720 B)
params: 24x4, x24
@layers.2.mlp.2> color=black fillcolor="#E6E6E6" fontcolor=black ordering=out shape=box style="filled,solid"] - add_4_69pass2 [label=<add_4_69:2
1x6x24 (720 B)> color=black fillcolor=white fontcolor=black ordering=out shape=oval style="filled,solid"] - add_4_69pass2 -> output_1 [arrowsize=.7 color=black fontcolor=black labelfontsize=8 style=solid] - output_1 [label=<output_1
1x6x24 (720 B)
@output> color=black fillcolor="#ff9999" fontcolor=black ordering=out shape=oval style="filled,solid"] - { - rank=sink - output_1 - } - subgraph cluster_token_emb_pass1 { - fillcolor=white label=<@token_emb
(Embedding)
> labelloc=b penwidth=5.0 style="filled,dashed" - } - subgraph cluster_pos_emb_pass1 { - fillcolor=white label=<@pos_emb
(Embedding)
> labelloc=b penwidth=5.0 style="filled,dashed" - } - subgraph "cluster_layers.0_pass1" { - fillcolor=white label=<@layers.0
(EncoderBlock)
> labelloc=b penwidth=5.0 style="filled,solid" - linear_4_24 -> add_2_25pass1 [arrowsize=.7 color=black fontcolor=black labelfontsize=8 style=solid] - add_2_25pass1 -> linear_5_26 [arrowsize=.7 color=black fontcolor=black labelfontsize=8 style=solid] - add_2_25pass1 -> add_2_25pass2 [arrowsize=.7 color=black fontcolor=black labelfontsize=8 style=solid] - linear_6_28 -> add_2_25pass2 [arrowsize=.7 color=black fontcolor=black labelfontsize=8 style=solid] - } - subgraph "cluster_layers.1_pass1" { - fillcolor=white label=<@layers.1
(EncoderBlock)
> labelloc=b penwidth=5.0 style="filled,solid" - linear_10_46 -> add_3_47pass1 [arrowsize=.7 color=black fontcolor=black labelfontsize=8 style=solid] - add_3_47pass1 -> linear_11_48 [arrowsize=.7 color=black fontcolor=black labelfontsize=8 style=solid] - add_3_47pass1 -> add_3_47pass2 [arrowsize=.7 color=black fontcolor=black labelfontsize=8 style=solid] - linear_12_50 -> add_3_47pass2 [arrowsize=.7 color=black fontcolor=black labelfontsize=8 style=solid] - } - subgraph "cluster_layers.2_pass1" { - fillcolor=white label=<@layers.2
(EncoderBlock)
> labelloc=b penwidth=5.0 style="filled,solid" - linear_16_68 -> add_4_69pass1 [arrowsize=.7 color=black fontcolor=black labelfontsize=8 style=solid] - add_4_69pass1 -> linear_17_70 [arrowsize=.7 color=black fontcolor=black labelfontsize=8 style=solid] - add_4_69pass1 -> add_4_69pass2 [arrowsize=.7 color=black fontcolor=black labelfontsize=8 style=solid] - linear_18_72 -> add_4_69pass2 [arrowsize=.7 color=black fontcolor=black labelfontsize=8 style=solid] - } - subgraph "cluster_layers.0_pass1" { - subgraph "cluster_layers.0.attn_pass1" { - fillcolor=white label=<@layers.0.attn
(MultiheadSelfAttention)
> labelloc=b penwidth=3.5 style="filled,solid" - linear_1_7 -> view_1_8 [arrowsize=.7 color=black fontcolor=black labelfontsize=8 style=solid] - view_1_8 -> transpose_1_9 [arrowsize=.7 color=black fontcolor=black labelfontsize=8 style=solid] - transpose_1_9 -> matmul_1_17 [label=<arg 0> arrowsize=.7 color=black fontcolor=black labelfontsize=8 style=solid] - linear_2_10 -> view_2_11 [arrowsize=.7 color=black fontcolor=black labelfontsize=8 style=solid] - view_2_11 -> transpose_2_12 [arrowsize=.7 color=black fontcolor=black labelfontsize=8 style=solid] - transpose_2_12 -> transpose_4_16 [arrowsize=.7 color=black fontcolor=black labelfontsize=8 style=solid] - linear_3_13 -> view_3_14 [arrowsize=.7 color=black fontcolor=black labelfontsize=8 style=solid] - view_3_14 -> transpose_3_15 [arrowsize=.7 color=black fontcolor=black labelfontsize=8 style=solid] - transpose_3_15 -> matmul_2_20 [label=<arg 1> arrowsize=.7 color=black fontcolor=black labelfontsize=8 style=solid] - transpose_4_16 -> matmul_1_17 [label=<arg 1> arrowsize=.7 color=black fontcolor=black labelfontsize=8 style=solid] - matmul_1_17 -> truediv_1_18 [arrowsize=.7 color=black fontcolor=black labelfontsize=8 style=solid] - truediv_1_18 -> softmax_1_19 [arrowsize=.7 color=black fontcolor=black labelfontsize=8 style=solid] - softmax_1_19 -> matmul_2_20 [label=<arg 0> arrowsize=.7 color=black fontcolor=black labelfontsize=8 style=solid] - matmul_2_20 -> transpose_5_21 [arrowsize=.7 color=black fontcolor=black labelfontsize=8 style=solid] - transpose_5_21 -> contiguous_1_22 [arrowsize=.7 color=black fontcolor=black labelfontsize=8 style=solid] - contiguous_1_22 -> view_4_23 [arrowsize=.7 color=black fontcolor=black labelfontsize=8 style=solid] - view_4_23 -> linear_4_24 [arrowsize=.7 color=black fontcolor=black labelfontsize=8 style=solid] - } - } - subgraph "cluster_layers.0_pass1" { - subgraph "cluster_layers.0.mlp_pass1" { - fillcolor=white label=<@layers.0.mlp
(Sequential)
> labelloc=b penwidth=3.5 style="filled,solid" - linear_5_26 -> gelu_1_27 [arrowsize=.7 color=black fontcolor=black labelfontsize=8 style=solid] - gelu_1_27 -> linear_6_28 [arrowsize=.7 color=black fontcolor=black labelfontsize=8 style=solid] - } - } - subgraph "cluster_layers.1_pass1" { - subgraph "cluster_layers.1.attn_pass1" { - fillcolor=white label=<@layers.1.attn
(MultiheadSelfAttention)
> labelloc=b penwidth=3.5 style="filled,solid" - linear_7_29 -> view_5_30 [arrowsize=.7 color=black fontcolor=black labelfontsize=8 style=solid] - view_5_30 -> transpose_6_31 [arrowsize=.7 color=black fontcolor=black labelfontsize=8 style=solid] - transpose_6_31 -> matmul_3_39 [label=<arg 0> arrowsize=.7 color=black fontcolor=black labelfontsize=8 style=solid] - linear_8_32 -> view_6_33 [arrowsize=.7 color=black fontcolor=black labelfontsize=8 style=solid] - view_6_33 -> transpose_7_34 [arrowsize=.7 color=black fontcolor=black labelfontsize=8 style=solid] - transpose_7_34 -> transpose_9_38 [arrowsize=.7 color=black fontcolor=black labelfontsize=8 style=solid] - linear_9_35 -> view_7_36 [arrowsize=.7 color=black fontcolor=black labelfontsize=8 style=solid] - view_7_36 -> transpose_8_37 [arrowsize=.7 color=black fontcolor=black labelfontsize=8 style=solid] - transpose_8_37 -> matmul_4_42 [label=<arg 1> arrowsize=.7 color=black fontcolor=black labelfontsize=8 style=solid] - transpose_9_38 -> matmul_3_39 [label=<arg 1> arrowsize=.7 color=black fontcolor=black labelfontsize=8 style=solid] - matmul_3_39 -> truediv_2_40 [arrowsize=.7 color=black fontcolor=black labelfontsize=8 style=solid] - truediv_2_40 -> softmax_2_41 [arrowsize=.7 color=black fontcolor=black labelfontsize=8 style=solid] - softmax_2_41 -> matmul_4_42 [label=<arg 0> arrowsize=.7 color=black fontcolor=black labelfontsize=8 style=solid] - matmul_4_42 -> transpose_10_43 [arrowsize=.7 color=black fontcolor=black labelfontsize=8 style=solid] - transpose_10_43 -> contiguous_2_44 [arrowsize=.7 color=black fontcolor=black labelfontsize=8 style=solid] - contiguous_2_44 -> view_8_45 [arrowsize=.7 color=black fontcolor=black labelfontsize=8 style=solid] - view_8_45 -> linear_10_46 [arrowsize=.7 color=black fontcolor=black labelfontsize=8 style=solid] - } - } - subgraph "cluster_layers.1_pass1" { - subgraph "cluster_layers.1.mlp_pass1" { - fillcolor=white label=<@layers.1.mlp
(Sequential)
> labelloc=b penwidth=3.5 style="filled,solid" - linear_11_48 -> gelu_2_49 [arrowsize=.7 color=black fontcolor=black labelfontsize=8 style=solid] - gelu_2_49 -> linear_12_50 [arrowsize=.7 color=black fontcolor=black labelfontsize=8 style=solid] - } - } - subgraph "cluster_layers.2_pass1" { - subgraph "cluster_layers.2.attn_pass1" { - fillcolor=white label=<@layers.2.attn
(MultiheadSelfAttention)
> labelloc=b penwidth=3.5 style="filled,solid" - linear_13_51 -> view_9_52 [arrowsize=.7 color=black fontcolor=black labelfontsize=8 style=solid] - view_9_52 -> transpose_11_53 [arrowsize=.7 color=black fontcolor=black labelfontsize=8 style=solid] - transpose_11_53 -> matmul_5_61 [label=<arg 0> arrowsize=.7 color=black fontcolor=black labelfontsize=8 style=solid] - linear_14_54 -> view_10_55 [arrowsize=.7 color=black fontcolor=black labelfontsize=8 style=solid] - view_10_55 -> transpose_12_56 [arrowsize=.7 color=black fontcolor=black labelfontsize=8 style=solid] - transpose_12_56 -> transpose_14_60 [arrowsize=.7 color=black fontcolor=black labelfontsize=8 style=solid] - linear_15_57 -> view_11_58 [arrowsize=.7 color=black fontcolor=black labelfontsize=8 style=solid] - view_11_58 -> transpose_13_59 [arrowsize=.7 color=black fontcolor=black labelfontsize=8 style=solid] - transpose_13_59 -> matmul_6_64 [label=<arg 1> arrowsize=.7 color=black fontcolor=black labelfontsize=8 style=solid] - transpose_14_60 -> matmul_5_61 [label=<arg 1> arrowsize=.7 color=black fontcolor=black labelfontsize=8 style=solid] - matmul_5_61 -> truediv_3_62 [arrowsize=.7 color=black fontcolor=black labelfontsize=8 style=solid] - truediv_3_62 -> softmax_3_63 [arrowsize=.7 color=black fontcolor=black labelfontsize=8 style=solid] - softmax_3_63 -> matmul_6_64 [label=<arg 0> arrowsize=.7 color=black fontcolor=black labelfontsize=8 style=solid] - matmul_6_64 -> transpose_15_65 [arrowsize=.7 color=black fontcolor=black labelfontsize=8 style=solid] - transpose_15_65 -> contiguous_3_66 [arrowsize=.7 color=black fontcolor=black labelfontsize=8 style=solid] - contiguous_3_66 -> view_12_67 [arrowsize=.7 color=black fontcolor=black labelfontsize=8 style=solid] - view_12_67 -> linear_16_68 [arrowsize=.7 color=black fontcolor=black labelfontsize=8 style=solid] - } - } - subgraph "cluster_layers.2_pass1" { - subgraph "cluster_layers.2.mlp_pass1" { - fillcolor=white label=<@layers.2.mlp
(Sequential)
> labelloc=b penwidth=3.5 style="filled,solid" - linear_17_70 -> gelu_3_71 [arrowsize=.7 color=black fontcolor=black labelfontsize=8 style=solid] - gelu_3_71 -> linear_18_72 [arrowsize=.7 color=black fontcolor=black labelfontsize=8 style=solid] - } - } - subgraph "cluster_layers.0_pass1" { - subgraph "cluster_layers.0.attn_pass1" { - subgraph "cluster_layers.0.attn.W_q_pass1" { - fillcolor=white label=<@layers.0.attn.W_q
(Linear)
> labelloc=b penwidth=2.0 style="filled,dashed" - } - } - } - subgraph "cluster_layers.0_pass1" { - subgraph "cluster_layers.0.attn_pass1" { - subgraph "cluster_layers.0.attn.W_k_pass1" { - fillcolor=white label=<@layers.0.attn.W_k
(Linear)
> labelloc=b penwidth=2.0 style="filled,dashed" - } - } - } - subgraph "cluster_layers.0_pass1" { - subgraph "cluster_layers.0.attn_pass1" { - subgraph "cluster_layers.0.attn.W_v_pass1" { - fillcolor=white label=<@layers.0.attn.W_v
(Linear)
> labelloc=b penwidth=2.0 style="filled,dashed" - } - } - } - subgraph "cluster_layers.0_pass1" { - subgraph "cluster_layers.0.attn_pass1" { - subgraph "cluster_layers.0.attn.W_o_pass1" { - fillcolor=white label=<@layers.0.attn.W_o
(Linear)
> labelloc=b penwidth=2.0 style="filled,dashed" - } - } - } - subgraph "cluster_layers.0_pass1" { - subgraph "cluster_layers.0.mlp_pass1" { - subgraph "cluster_layers.0.mlp.0_pass1" { - fillcolor=white label=<@layers.0.mlp.0
(Linear)
> labelloc=b penwidth=2.0 style="filled,dashed" - } - } - } - subgraph "cluster_layers.0_pass1" { - subgraph "cluster_layers.0.mlp_pass1" { - subgraph "cluster_layers.0.mlp.1_pass1" { - fillcolor=white label=<@layers.0.mlp.1
(GELU)
> labelloc=b penwidth=2.0 style="filled,dashed" - } - } - } - subgraph "cluster_layers.0_pass1" { - subgraph "cluster_layers.0.mlp_pass1" { - subgraph "cluster_layers.0.mlp.2_pass1" { - fillcolor=white label=<@layers.0.mlp.2
(Linear)
> labelloc=b penwidth=2.0 style="filled,dashed" - } - } - } - subgraph "cluster_layers.1_pass1" { - subgraph "cluster_layers.1.attn_pass1" { - subgraph "cluster_layers.1.attn.W_q_pass1" { - fillcolor=white label=<@layers.1.attn.W_q
(Linear)
> labelloc=b penwidth=2.0 style="filled,dashed" - } - } - } - subgraph "cluster_layers.1_pass1" { - subgraph "cluster_layers.1.attn_pass1" { - subgraph "cluster_layers.1.attn.W_k_pass1" { - fillcolor=white label=<@layers.1.attn.W_k
(Linear)
> labelloc=b penwidth=2.0 style="filled,dashed" - } - } - } - subgraph "cluster_layers.1_pass1" { - subgraph "cluster_layers.1.attn_pass1" { - subgraph "cluster_layers.1.attn.W_v_pass1" { - fillcolor=white label=<@layers.1.attn.W_v
(Linear)
> labelloc=b penwidth=2.0 style="filled,dashed" - } - } - } - subgraph "cluster_layers.1_pass1" { - subgraph "cluster_layers.1.attn_pass1" { - subgraph "cluster_layers.1.attn.W_o_pass1" { - fillcolor=white label=<@layers.1.attn.W_o
(Linear)
> labelloc=b penwidth=2.0 style="filled,dashed" - } - } - } - subgraph "cluster_layers.1_pass1" { - subgraph "cluster_layers.1.mlp_pass1" { - subgraph "cluster_layers.1.mlp.0_pass1" { - fillcolor=white label=<@layers.1.mlp.0
(Linear)
> labelloc=b penwidth=2.0 style="filled,dashed" - } - } - } - subgraph "cluster_layers.1_pass1" { - subgraph "cluster_layers.1.mlp_pass1" { - subgraph "cluster_layers.1.mlp.1_pass1" { - fillcolor=white label=<@layers.1.mlp.1
(GELU)
> labelloc=b penwidth=2.0 style="filled,dashed" - } - } - } - subgraph "cluster_layers.1_pass1" { - subgraph "cluster_layers.1.mlp_pass1" { - subgraph "cluster_layers.1.mlp.2_pass1" { - fillcolor=white label=<@layers.1.mlp.2
(Linear)
> labelloc=b penwidth=2.0 style="filled,dashed" - } - } - } - subgraph "cluster_layers.2_pass1" { - subgraph "cluster_layers.2.attn_pass1" { - subgraph "cluster_layers.2.attn.W_q_pass1" { - fillcolor=white label=<@layers.2.attn.W_q
(Linear)
> labelloc=b penwidth=2.0 style="filled,dashed" - } - } - } - subgraph "cluster_layers.2_pass1" { - subgraph "cluster_layers.2.attn_pass1" { - subgraph "cluster_layers.2.attn.W_k_pass1" { - fillcolor=white label=<@layers.2.attn.W_k
(Linear)
> labelloc=b penwidth=2.0 style="filled,dashed" - } - } - } - subgraph "cluster_layers.2_pass1" { - subgraph "cluster_layers.2.attn_pass1" { - subgraph "cluster_layers.2.attn.W_v_pass1" { - fillcolor=white label=<@layers.2.attn.W_v
(Linear)
> labelloc=b penwidth=2.0 style="filled,dashed" - } - } - } - subgraph "cluster_layers.2_pass1" { - subgraph "cluster_layers.2.attn_pass1" { - subgraph "cluster_layers.2.attn.W_o_pass1" { - fillcolor=white label=<@layers.2.attn.W_o
(Linear)
> labelloc=b penwidth=2.0 style="filled,dashed" - } - } - } - subgraph "cluster_layers.2_pass1" { - subgraph "cluster_layers.2.mlp_pass1" { - subgraph "cluster_layers.2.mlp.0_pass1" { - fillcolor=white label=<@layers.2.mlp.0
(Linear)
> labelloc=b penwidth=2.0 style="filled,dashed" - } - } - } - subgraph "cluster_layers.2_pass1" { - subgraph "cluster_layers.2.mlp_pass1" { - subgraph "cluster_layers.2.mlp.1_pass1" { - fillcolor=white label=<@layers.2.mlp.1
(GELU)
> labelloc=b penwidth=2.0 style="filled,dashed" - } - } - } - subgraph "cluster_layers.2_pass1" { - subgraph "cluster_layers.2.mlp_pass1" { - subgraph "cluster_layers.2.mlp.2_pass1" { - fillcolor=white label=<@layers.2.mlp.2
(Linear)
> labelloc=b penwidth=2.0 style="filled,dashed" - } - } - } -} diff --git a/graph.gv.pdf b/graph.gv.pdf deleted file mode 100644 index 308a93f242364b40578ff5fa4d5f92bc4b5788bf..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 74266 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 JN}4e8{{T9 transpose=True) ---- -for i in range(3): # layers 0..2 - # Attention projections - copy_(sd[f"layers.{i}.attn.W_q.weight"], npz[f"transformer__layer_{i}__attn__query__w"], transpose=True) # (24,12)->(12,24) - copy_(sd[f"layers.{i}.attn.W_q.bias"], npz[f"transformer__layer_{i}__attn__query__b"]) - copy_(sd[f"layers.{i}.attn.W_k.weight"], npz[f"transformer__layer_{i}__attn__key__w"], transpose=True) - copy_(sd[f"layers.{i}.attn.W_k.bias"], npz[f"transformer__layer_{i}__attn__key__b"]) - copy_(sd[f"layers.{i}.attn.W_v.weight"], npz[f"transformer__layer_{i}__attn__value__w"], transpose=True) - copy_(sd[f"layers.{i}.attn.W_v.bias"], npz[f"transformer__layer_{i}__attn__value__b"]) - - # Attention output projection ("linear") - copy_(sd[f"layers.{i}.attn.W_o.weight"], npz[f"transformer__layer_{i}__attn__linear__w"], transpose=True) # (12,24)->(24,12) - copy_(sd[f"layers.{i}.attn.W_o.bias"], npz[f"transformer__layer_{i}__attn__linear__b"]) - - # MLP 24->4->24 - copy_(sd[f"layers.{i}.mlp.0.weight"], npz[f"transformer__layer_{i}__mlp__linear_1__w"], transpose=True) # (24,4)->(4,24) - copy_(sd[f"layers.{i}.mlp.0.bias"], npz[f"transformer__layer_{i}__mlp__linear_1__b"]) - copy_(sd[f"layers.{i}.mlp.2.weight"], npz[f"transformer__layer_{i}__mlp__linear_2__w"], transpose=True) # (4,24)->(24,4) - copy_(sd[f"layers.{i}.mlp.2.bias"], npz[f"transformer__layer_{i}__mlp__linear_2__b"]) - -# Commit weights to the module -model.load_state_dict(sd) - -# ---- TorchLens over the SAME model ---- -# If you have your exact token-indexing, encode it here. For a quick diagram, dummy IDs in [0..3] work. -x = torch.randint(low=0, high=4, size=(1, 6)) # (B=1, T=6) e.g., [BOS, 1,0,1,1,0] with the right indices if you prefer -model.eval() - -# 1) Save full forward history AND 2) render the layered graph (unrolled by layer): -log = tl.log_forward_pass(model, x, vis_opt="unrolled") -tl.show_model_graph(model, (x,), vis_opt="unrolled", file_name="torchlens_majority_graph") diff --git a/my_majority_program.py b/my_majority_program.py deleted file mode 100644 index bc06cf4..0000000 --- a/my_majority_program.py +++ /dev/null @@ -1,183 +0,0 @@ -import os, sys -tracr_path = os.path.join(os.path.dirname(__file__), "Tracr", "tracr") -sys.path.insert(0, tracr_path) - -import numpy as np -import jax -import jax.random as random - -from tracr.compiler import compiling -from tracr.rasp import rasp - -# --- The robust function to import show_model --- -# --- The robust function to import show_model (returns None if not found) --- -def _get_show_model(): - import importlib, pkgutil, tracr - for modpath in ("tracr.compiler.visualization", "tracr.visualization"): - try: - mod = importlib.import_module(modpath) - fn = getattr(mod, "show_model", None) - if callable(fn): - return fn - except Exception: - pass - for _, name, _ in pkgutil.walk_packages(tracr.__path__, tracr.__name__ + "."): - try: - mod = importlib.import_module(name) - fn = getattr(mod, "show_model", None) - if callable(fn): - return fn - except Exception: - continue - return None # <- do NOT raise here -# --- Fallback: render a clean Tracr-style diagram from compiled params --- -def render_block_diagram_from_compiled(compiled_model, out_basename="tracr_majority_graph"): - import re - from graphviz import Digraph - # get params from the compiled model - try: - params = compiled_model.params - except AttributeError: - params = compiled_model.weights - - # flatten nested dict into "path" -> ndarray - flat = {} - def walk(path, node): - if isinstance(node, dict): - for k, v in node.items(): - walk(path + (k,), v) - else: - flat["/".join(path)] = np.array(node) - walk((), params) - - # read shapes - tok_key = next(k for k in flat if k.endswith("token_embed/embeddings")) - pos_key = next(k for k in flat if k.endswith("pos_embed/embeddings")) - vocab_size, d_model = flat[tok_key].shape - max_seq_len = flat[pos_key].shape[0] - - layer_nums = sorted({int(m.group(1)) - for k in flat - for m in [re.search(r"transformer/layer_(\d+)/", k)] - if m}) - # attn proj and mlp hidden from layer 0 - proj_dim = flat[f"transformer/layer_{layer_nums[0]}/attn/query/w"].shape[1] - mlp_hidden = flat[f"transformer/layer_{layer_nums[0]}/mlp/linear_1/w"].shape[1] - - dot = Digraph("tracr_majority_transformer", format="pdf") - dot.attr(rankdir="LR", fontsize="12", labelloc="t", - label=f"Tracr-compiled Majority Transformer\n" - f"vocab={vocab_size}, d_model={d_model}, layers={len(layer_nums)}, " - f"proj_dim={proj_dim}, mlp_hidden={mlp_hidden}") - - with dot.subgraph(name="cluster_embed") as c: - c.attr(label="Embeddings") - c.node("tok_emb", f"Token Embedding\n({vocab_size}×{d_model})", shape="box") - c.node("pos_emb", f"Positional Embedding\n({max_seq_len}×{d_model})", shape="box") - c.node("sum", "Add", shape="circle") - c.edges([("tok_emb", "sum"), ("pos_emb", "sum")]) - - prev = "sum" - for i in layer_nums: - with dot.subgraph(name=f"cluster_layer_{i}") as c: - c.attr(label=f"Encoder Block {i}") - c.node(f"attn_{i}", f"MHA proj {proj_dim}", shape="box") - c.node(f"add_attn_{i}", "Add", shape="circle") - c.node(f"mlp_{i}", f"MLP {d_model}→{mlp_hidden}→{d_model}", shape="box") - c.node(f"add_mlp_{i}", "Add", shape="circle") - dot.edge(prev, f"attn_{i}") - dot.edge(f"attn_{i}", f"add_attn_{i}") - dot.edge(f"add_attn_{i}", f"mlp_{i}") - dot.edge(f"mlp_{i}", f"add_mlp_{i}") - prev = f"add_mlp_{i}" - - dot.node("out", f"Output\n(seq_len×{d_model})", shape="box") - dot.edge(prev, "out") - out_path = dot.render(out_basename, cleanup=True) - print(f"Saved {out_path}") - - -show_model = _get_show_model() - - - -VOCAB = {0, 1} -MAX_SEQ_LEN = 10 -COMPILER_BOS = "BOS" - -# --- Majority Score Program --- -def majority_score_program(): - """ - RASP program that outputs whether 1s or 0s are the majority. - Positive = majority of 1s, Negative = majority of 0s, 0 = tie. - """ - # Select all positions - all_positions = rasp.Select(rasp.indices, rasp.indices, rasp.Comparison.TRUE) - - # Count number of 1s - select_ones = rasp.Select(rasp.tokens, rasp.tokens, rasp.Comparison.EQ) - num_ones = rasp.Aggregate(select_ones, rasp.tokens) - - # Count number of 0s (total length - num_ones) - seq_length = rasp.Aggregate(all_positions, rasp.tokens * 0 + 1) # sum of 1s over all positions - num_zeros = seq_length - num_ones - - # Majority score = (#1s - #0s) - majority_score = num_ones - num_zeros - - return majority_score - -# --- Compile --- -print("Compiling majority RASP program to transformer model...") -compiled_model = compiling.compile_rasp_to_model( - majority_score_program(), - vocab=VOCAB, - max_seq_len=MAX_SEQ_LEN, - compiler_bos=COMPILER_BOS, -) -print("Compilation complete!\n") - -# --- Save transformer diagram --- -print("Generating transformer visualization...") -show_model = _get_show_model() -if show_model is not None: - graph = show_model(compiled_model, max_seq_len=MAX_SEQ_LEN, return_graph=True) - graph.render("tracr_majority_graph", format="pdf", cleanup=True) -else: - print("Tracr show_model not found — using fallback renderer.") - render_block_diagram_from_compiled(compiled_model, out_basename="tracr_majority_graph") -print("Diagram saved as tracr_majority_graph.pdf ✅\n") - - -# --- Example --- -example_input_sequence = [1, 0, 1, 1, 0] - -print(f"Raw input sequence (no BOS): {example_input_sequence}") - -# Prepend BOS manually, since Tracr expects it -input_with_bos = [COMPILER_BOS] + example_input_sequence -print(f"Input sequence with BOS: {input_with_bos}") - -# Run model -output_logits = compiled_model.apply(input_with_bos) - -# Interpret output -vocab_list = sorted(list(VOCAB)) + [COMPILER_BOS] -predicted_tokens = [vocab_list[np.argmax(logits)] for logits in output_logits] - -print("\n--- Model Output ---") -print("Raw logits:\n", output_logits) -print("Predicted tokens:", predicted_tokens) - -# --- Run RASP directly --- -rasp_output = majority_score_program()(example_input_sequence) -print("Raw RASP output:", rasp_output) -print("\nRASP execution output:", rasp_output) - -majority_val = rasp_output[0] -if majority_val > 0: - print("Majority element: 1 ✅") -elif majority_val < 0: - print("Majority element: 0 ✅") -else: - print("Tie between 0 and 1 🤝") diff --git a/my_majority_torchlens.py b/my_majority_torchlens.py deleted file mode 100644 index 904ead7..0000000 --- a/my_majority_torchlens.py +++ /dev/null @@ -1,56 +0,0 @@ -import torch -import torch.nn as nn -import torchlens as tl # ★ import as a module; tl.show_model_graph used below - -class MyTransformer(nn.Module): - def __init__(self, input_dim=128, hidden_dim=256, num_layers=2, num_heads=4): - super().__init__() - self.embedding = nn.Linear(input_dim, hidden_dim) - encoder_layer = nn.TransformerEncoderLayer( - d_model=hidden_dim, nhead=num_heads, batch_first=True - ) - self.encoder = nn.TransformerEncoder(encoder_layer, num_layers=num_layers) - self.decoder = nn.Linear(hidden_dim, 10) - - def forward(self, x): - x = self.embedding(x) - x = self.encoder(x) - return self.decoder(x) - -# Optional wrapper not required for TorchLens; it will trace submodules anyway. -transformer = MyTransformer() - -# Example input (B, T, D_in) -x = torch.randn(2, 5, 128) - -# Option A: one-liner that logs activations and ALSO renders the graph. -log = tl.log_forward_pass(transformer, x, layers_to_save=None, vis_opt="unrolled") - - -# --- Make a wrapper that exposes internals clearly --- -class TransformerWrapper(nn.Module): - def __init__(self, transformer): - super().__init__() - self.model = transformer - - def forward(self, x): - # Instead of doing everything in one call, we explicitly call submodules - x = self.model.embedding(x) - # Go through each encoder layer explicitly so TorchLens can track them - for i, layer in enumerate(self.model.encoder.layers): - x = layer(x) - x = self.model.decoder(x) - return x - -# --- Instantiate and wrap the model --- -transformer = MyTransformer() -wrapped_model = TransformerWrapper(transformer) - -# --- Dummy input --- -x = torch.randn(2, 5, 128) - -# --- Run TorchLens logging --- -log = log_forward_pass(wrapped_model, x) - -# --- Visualize graph --- -show_model_graph(log) diff --git a/scripts/compile_export.py b/scripts/compile_export.py new file mode 100644 index 0000000..7d5a8a8 --- /dev/null +++ b/scripts/compile_export.py @@ -0,0 +1,139 @@ +#!/usr/bin/env python3 +# scripts/compile_export.py +import os, sys, json +import numpy as np +from pathlib import Path +import sys + +REPO_ROOT = Path(__file__).resolve().parents[1] + +# Look for tracr in common locations +CANDIDATES = [ + REPO_ROOT / "external" / "Tracr" / "tracr", # new suggested location + REPO_ROOT / "Tracr" / "tracr", # your old location + REPO_ROOT / "tracr", # just in case +] + +for p in CANDIDATES: + if p.is_dir(): + sys.path.insert(0, str(p)) + break +else: + raise ModuleNotFoundError( + "Couldn't find the tracr package.\n" + "Either clone it to external/Tracr or Tracr at the repo root, " + "or install it with pip (see Option B)." + ) + +from tracr.compiler import compiling +from tracr.rasp import rasp + + +# -------- Config -------- +VOCAB = {0, 1} +MAX_SEQ_LEN = 10 +COMPILER_BOS = "BOS" +COMPILER_PAD = "PAD" +CAUSAL = True +EXAMPLE = [1, 0, 1, 1, 0] + +ART = REPO_ROOT / "artifacts" +ART.mkdir(exist_ok=True) + +def majority_program(): + # majority = 2 * (#ones) - seq_len + all_pos = rasp.Select(rasp.indices, rasp.indices, rasp.Comparison.EQ) + ones_vec = rasp.Map(lambda t: t, rasp.tokens) # 0/1 numeric + num_ones = rasp.Aggregate(all_pos, ones_vec) + ones_const = rasp.Map(lambda _: 1, rasp.tokens) + seq_len = rasp.Aggregate(all_pos, ones_const) + return (2 * num_ones) - seq_len + +def compile_tracr(prog): + kw = dict(vocab=VOCAB, max_seq_len=MAX_SEQ_LEN, compiler_bos=COMPILER_BOS) + try: + return compiling.compile_rasp_to_model(prog, compiler_pad=COMPILER_PAD, causal=CAUSAL, **kw) + except TypeError: + pass + try: + return compiling.compile_rasp_to_model(prog, causal=CAUSAL, **kw) + except TypeError: + return compiling.compile_rasp_to_model(prog, **kw) + +def get_tok2id_or_fallback(model): + cands = [ + getattr(model, "tokenizer", None), + getattr(model, "vocab", None), + getattr(model, "vocabulary", None), + getattr(getattr(model, "transformer", None), "tokenizer", None), + getattr(getattr(model, "transformer", None), "vocab", None), + getattr(getattr(model, "transformer", None), "vocabulary", None), + ] + for obj in cands: + if obj is None: continue + if isinstance(obj, dict) and obj: return obj + if hasattr(obj, "token_to_id") and isinstance(obj.token_to_id, dict): + return obj.token_to_id + if hasattr(obj, "id_to_token") and isinstance(obj.id_to_token, dict): + return {tok: int(i) for i, tok in obj.id_to_token.items()} + # fallback mapping (deterministic) + ordered = [COMPILER_BOS] + sorted(list(VOCAB), key=lambda x: repr(x)) + [COMPILER_PAD] + mapping = {tok: i for i, tok in enumerate(ordered)} + print("[WARN] Using fallback token mapping:", mapping) + return mapping + +def export_params_npz(compiled, out_path: Path, keys_path: Path): + try: + params = compiled.params + except AttributeError: + params = compiled.weights + + leaves = [] + def walk(path, node): + if isinstance(node, dict): + for k, v in node.items(): walk(path + (k,), v) + elif isinstance(node, (list, tuple)): + for i, v in enumerate(node): walk(path + (str(i),), v) + else: + leaves.append(("/".join(path), np.array(node))) + + walk((), params) + npz_dict = {k.replace("/", "__"): v for k, v in leaves} + np.savez(out_path, **npz_dict) + keys_path.write_text(json.dumps(sorted(npz_dict.keys()), indent=2)) + print(f"Exported params -> {out_path} (keys -> {keys_path})") + +def main(): + print("Compiling RASP → Tracr transformer…") + compiled = compile_tracr(majority_program()) + print("Done.\n") + + # tokenizer mapping: only write fallback if no existing discovered mapping + tok_map_path = ART / "token_to_id.json" + tok2id = get_tok2id_or_fallback(compiled) + if not tok_map_path.exists(): + tok_map_path.write_text(json.dumps(tok2id)) + print("Saved token_to_id.json") + else: + print("token_to_id.json exists; keeping discovered mapping.") + + # exact tokens used for the reference pass + tokens = [COMPILER_BOS] + EXAMPLE + (ART / "input_tokens.json").write_text(json.dumps(tokens)) + print("Saved input_tokens.json") + + # forward pass on assembled model + out = compiled.apply(tokens) + arr = np.array(getattr(out, "transformer_output", out), dtype=np.float32) + if arr.ndim == 2: arr = arr[None, ...] + np.save(ART / "tracr_output.npy", arr) + print(f"Saved tracr_output.npy with shape {arr.shape} (dtype={arr.dtype})") + + # export params from THIS compiled model + export_params_npz(compiled, ART / "tracr_majority_params.npz", ART / "tracr_param_keys.json") + + print("\nNow run:") + print(" python scripts/parity_check.py") + +if __name__ == "__main__": + main() diff --git a/scripts/parity_check.py b/scripts/parity_check.py new file mode 100644 index 0000000..f89a6f9 --- /dev/null +++ b/scripts/parity_check.py @@ -0,0 +1,77 @@ +#!/usr/bin/env python3 +# scripts/parity_check.py +import json, itertools, numpy as np, torch +from pathlib import Path +import sys + +ROOT = Path(__file__).resolve().parents[1] +ART = ROOT / "artifacts" +sys.path.append(str(ROOT / "src")) + +from tracr_pt_model import TracrTransformerPT + +# ---- Load NPZ & infer dims ---- +npz = np.load(ART / "tracr_majority_params.npz") +def get(k): return npz.get(k, npz[k.replace("/", "__")]) + +vocab_size, d_model = get("token_embed/embeddings").shape +max_len = get("pos_embed/embeddings").shape[0] +proj_dim = int(get("transformer/layer_0/attn/query/w").shape[1]) # JAX (in,out) +d_mlp = int(get("transformer/layer_0/mlp/linear_1/w").shape[1]) +n_layers = sum((f"transformer/layer_{i}/attn/query/w".replace("/", "__") in npz) for i in range(64)) + +# Your matched config +n_heads, head_dim = 2, proj_dim // 2 + +print(f"Inferred -> d_model={d_model}, vocab={vocab_size}, max_seq_len={max_len}, " + f"layers={n_layers}, proj_dim={proj_dim}, d_mlp={d_mlp}, heads={n_heads}, head_dim={head_dim}") + +# ---- Build PT model & load weights ---- +model = TracrTransformerPT(vocab_size, max_len, int(d_model), int(n_layers), int(d_mlp), + n_heads=int(n_heads), head_dim=int(head_dim)).eval() + +def load_linear(L, w_key, b_key): + w = torch.from_numpy(get(w_key)).float().t().contiguous() # (in,out) -> (out,in) + b = torch.from_numpy(get(b_key)).float() + with torch.no_grad(): L.weight.copy_(w); L.bias.copy_(b) + +with torch.no_grad(): + model.token_emb.weight.copy_(torch.from_numpy(get("token_embed/embeddings")).float()) + model.pos_emb.weight.copy_(torch.from_numpy(get("pos_embed/embeddings")).float()) + +for i in range(n_layers): + P = f"transformer/layer_{i}" + blk = model.layers[i] + load_linear(blk.attn.W_q, f"{P}/attn/query/w", f"{P}/attn/query/b") + load_linear(blk.attn.W_k, f"{P}/attn/key/w", f"{P}/attn/key/b") + load_linear(blk.attn.W_v, f"{P}/attn/value/w", f"{P}/attn/value/b") + load_linear(blk.attn.W_o, f"{P}/attn/linear/w", f"{P}/attn/linear/b") + load_linear(blk.mlp.fc1, f"{P}/mlp/linear_1/w", f"{P}/mlp/linear_1/b") + load_linear(blk.mlp.fc2, f"{P}/mlp/linear_2/w", f"{P}/mlp/linear_2/b") + +# ---- Read tokens & Tracr reference ---- +tokens = json.loads((ART / "input_tokens.json").read_text()) # ["BOS", 1, 0, 1, 1, 0] +ref = torch.from_numpy(np.load(ART / "tracr_output.npy")).float() + +# ---- Discover BOS/0/1/PAD mapping once ---- +TOKS = ["BOS", "0", "1", "PAD"] +best = None +for perm in itertools.permutations(range(vocab_size), vocab_size): + tok2id = {TOKS[i]: perm[i] for i in range(vocab_size)} + ids = [tok2id["BOS"]] + [tok2id[str(t)] for t in tokens[1:]] + ids = torch.tensor([ids], dtype=torch.long) + with torch.no_grad(): out = model(ids) + md = (out - ref).abs().max().item() + ok = torch.allclose(out, ref, atol=1e-5) + cand = (tok2id, md, ok) + if best is None or md < best[1]: best = cand + if ok: break + +tok2id, md, ok = best +(ART / "token_to_id.json").write_text(json.dumps(tok2id, indent=2)) + +print("\n--- Mapping search ---") +print(f"tok2id={tok2id}, max_diff={md:.6g}, match={ok}") +print("\n--- Sanity Check ---") +print(f"Outputs match: {ok}") +print(f"Max abs diff: {md:.6g}") diff --git a/src/__init__.py b/src/__init__.py new file mode 100644 index 0000000..e69de29 diff --git a/src/__pycache__/tracr_pt_model.cpython-313.pyc b/src/__pycache__/tracr_pt_model.cpython-313.pyc new file mode 100644 index 0000000000000000000000000000000000000000..d15c121c83791602061709427da57353d7495b23 GIT binary patch literal 6099 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 diff --git a/tracr_majority_params.npz b/tracr_majority_params.npz index 437d52d9dbfb72409c61e2006df6c18110e5bf29..ce7aa3a4a39ab56550053e58898a3959f70fbfb4 100644 GIT binary patch literal 45154 zcmeI5OKclO7{}L1%1b>&s6a~vI10+6BvJF~1B!|&6xtL}1maK-Y#h94L;S*a5}5$< zg@=F(?F9)HQ7R!2;lKqUE^q*;NIg+0Ck{cXKtc_iKu8F|OzqjujAu79UhmdU{;pP& zb=Uv-_UG@L{XCw}J9WIhW6-KRx~$3R_4t3)$1ZD!mCF`vCq3gN?MjoJ%bY9>WpbsM z)oESqsJx7|XC8m*v8fX=YtdTnO*)0=^S$@Sdk@Wy^$x^)XS4ZYK9RAr`J_XipGc$% z4tc(CDv@)@e&6u$KzwApe<1!!yw1lh)w77ODIboeGxSp*XK({IO2FI?ri5Yfn00BD z4U4t=b0THckR`EC{;LxiNldK>!3m z00ck)1VCV`5D@dm+s1xPu)MKTz$zBxwl+FNKj2qX z>G}Hz=kIJO6>Ed~K_D-Ppo)Rg6#1=x|L|RAaYXoq6Gx-hyV{8PUaikH_L=7BNAv^! z`%#ZdAabEVC6F9H2ftcgVDY2H&5a#a0mRy%V-G5U8XKjxYNl~(dOYpX^fji(qmSD6 z)$bWozNW|H{qUn-`+ufhb5zl}C2(%Ib)0j6szCIRWzRiDb^{51L^KDcD5#l1g z(--!iV`;Z8zK}BSMpObtROse)h%md6sl*k_##4MkP@Aae3j0Ss$jyQ+3nVm>!Ql!hH|%e(3XUR#y6F zfFoOxz){0--1PWXWCEMRCQyIQjY=Rs=f3h_*IC`18MuC2W+EWw+!~cYWS)ByR00+L{e)%69u*+9=jqN%vkD;A2402T&`KbAY?Akz z$@`+WMf7)mMU|c(pc07xr1{&&kNj*FN1Lw_D6061svo_W6yu2he$=C)g}m{o1d^8| z^1qX)#m&72u?is82EGR2o+(Yztenpi>C6MF?WOrsLlPkrnPK(_Oh_ylep!Mzv^vn;d-DYt__=OWk*ZrPA zvX7ehx%^s_{iym8ZJIhBYa47ItUlRgO-`@JFLqcK-F9(@mapDFEtf6WPI|^k+Lb0b zmpNIWVI<2Ovo5W6wpkY4b_+6hY_qIlcHYV83DIwC*N6b!ddS8eL3bWaK z+R2l<+a*e**;`wwBpXM+%cPYzbQ3jKZqm@a>i4oH9f9chLAQQpBx%dB%eVS#3M)Ki zS-RGdnJUV5@6eM~TFX=I6RdsiZhu++TXES~o~x+(-aT5XhPM7li1>K`Kbxp;>-PJ! zRF$^Uyo=sRk#2hgt`p;4s;VqZwwB)ekY*`#6Lp97Y3eHN<-Jza-FHAomt93=d+9yq z)b=hO)YMhl%loYuxvxH;)OCN?b>1meulTa9^nP9}#6-<64{2yB?c}+NVf*`pzozeK zK<|OTOciAZkLt-Pt>vkTaeL|se_6lLfc|zYGgegn=t(VALtB4()?d|cG@!q^rMC5U zTT4}GtM_OyHRq+OH5!oLKTt>4ffqD&mG<&pD~<*arF3+?Mgv-BuC}+F*3?zn%loYu zxo>8by2L=aidh~F_-mM``E5=^Q)ws9RSes|U-H-V9Syv5gZ(e-$ttbosfux%f8Af! zZ#3Y!imEGbXsH_7`pdiis(zz^x2^FrTB=H0y+?zm&w8oqj0SWLL>*m6KG4)v+RJ;b pI2ufTsH5vO8qm+0YJ1;0r>R@DciRm##p)sdzTR$Gr_a;9{{hP~-!K3G literal 30178 zcmeHQU1%It6rSym^|$^-v<=7xYBq^!Y?iH-SX!-GQbX&$R1n2slT2)y%_iC1R8kcd zM18Pe@dpK^1bh<<3gUx52o<3Z)t5@~p-9jdp%1s?d*wu7)?w>CgMt^>VR;j5SjQ>P*4m`)i6>()|AP-Vq=Uac? zEmB=4OLf(mDW{}QcGe~r+-)NzyIj;`c0&DizcA;7=+4hvPVB4cYM89xPEZRtZ zHJI&>qM%H81N#-^Vf#DVt_R}bWx<2B)g{7hBk_=B0XCS8LPcO6JpZA0!~ij{_6%V1 zxZldvI>vwA#&wui-`@H68zQgvHqn>jWXUNo*{Ms+l8Y|dsHrtdUJWBLjpUfOKdBzMt^*9 zmk=2w6Y*#a^?cepfXKQQGBA9ogX6@7VW2TF`QC5nhCHGXKjTA@Bx7OD%_0Mx()`G<)<1U`KT(jzgV7_Pe%#FPl#-%(?r>Rb0 zf|mU1gj}4bc|&sje{m`Lc80HfiV7OSx{f(?|qu;gu1>^ zbpohD{r1}R^Fora)WxGpEvZfr&K=IH#L?6e1H=F^5R?I^N^-A9GbdkHrDRtpe79J- zDntg!L_8Xk$m#?>bBbAnH)B34&&JZ{)%>m&pW-~NZihq6(zn_M!VAhkc#TPRb;8lV z`X0n;3{@ut^*Z`|vKgTMabQKTh%poop6*d~Li|okXCMZMfpx(E)ED`CpJs}^ zt}j%b0ICyS|8VcTkR&X1@u*Tus}t6R6O)m|05Omt2B0d*y&lb+d|j22U7aBJdyq`T zqcMrBPDoGy(WMXr#DI~3@EVis>VzN~L)8gJ7o(lT05PzE8Gssts7_%0m}FEZjGTPx zdodiQnL%#6RPZ4$1ghimzy&kmQHq&l_2OhzOH`P5^U_0UMq^;s@d*hy0FqeCY;2`?fJ4)RQOt znEbg7%THinl>`v;u^SPX%dzCgMl)_?QpJ%`3`E5A>Q@C1nYJ9A=%CqPW4oieX5Y#$ylV;Zvo z|NXo$6~fLvgo9ODE3*pY_EOFaYsv=vcbLLhhr&jsvSb&D(#iM7G{I1PhxO&*?`y6s_nh+FcMd3uk5!la;w8i zTxOuZveKUo_}HoN1c>?S5d@~vPMKF2w!a=TV;ZvouU8SKLfG5$I9R2%GOI9dPaZeJ znzDh+D@3h6i$V=(>o3onQBB!EZ|iR_piq^z>a#(1RELVm27H`G9bNa2A#s)V%3cez m!D$DBtIGzw|Ejk4>j@;TYwy+@_*blM_V>-LmUY)8U;7_<{`l(v diff --git a/tracr_output.npy b/tracr_output.npy new file mode 100644 index 0000000000000000000000000000000000000000..a802065652a5b0caae36ba8cec63d37c43b0ef25 GIT binary patch literal 728 zcmbR27wQ`j$;eQ~P_3SlTAW;@Zl$1ZlV+l>qoAIaUsO_*m=~X4l#&V(cT3DEP6dh= zXCxM+0{I$-Itpew3Pz@yItsN4WC1P)s(}W3Ors!T-~QKw=7Q%!k 12 - self.W_k = nn.Linear(d_model, n_heads * head_dim, bias=bias) # 24 -> 12 - self.W_v = nn.Linear(d_model, n_heads * head_dim, bias=bias) # 24 -> 12 - self.W_o = nn.Linear(n_heads * head_dim, d_model, bias=bias) # 12 -> 24 - - - def forward(self, x): - B, T, C = x.shape - q = self.W_q(x).view(B, T, self.n_heads, self.head_dim).transpose(1, 2) # (B,H,T,4) - k = self.W_k(x).view(B, T, self.n_heads, self.head_dim).transpose(1, 2) - v = self.W_v(x).view(B, T, self.n_heads, self.head_dim).transpose(1, 2) - - att = torch.matmul(q, k.transpose(-2, -1)) / math.sqrt(self.head_dim) # (B,H,T,T) - att = torch.softmax(att, dim=-1) - y = torch.matmul(att, v) # (B,H,T,4) - y = y.transpose(1, 2).contiguous().view(B, T, self.proj_dim) # (B,T,12) - return self.W_o(y) # (B,T,24) - -class EncoderBlock(nn.Module): - def __init__(self, d_model=24, n_heads=3, head_dim=4, d_mlp=4): - super().__init__() - self.attn = MultiheadSelfAttention(d_model=d_model, n_heads=n_heads, head_dim=head_dim, bias=True) - self.mlp = nn.Sequential( - nn.Linear(d_model, d_mlp, bias=True), # 24 -> 4 - nn.GELU(), - nn.Linear(d_mlp, d_model, bias=True), # 4 -> 24 - ) - - def forward(self, x): - x = x + self.attn(x) - x = x + self.mlp(x) - return x - -class TracrTransformerPT(nn.Module): - def __init__(self, vocab_size=4, max_seq_len=11, d_model=24, n_heads=3, head_dim=4, n_layers=3, d_mlp=4): - super().__init__() - self.token_emb = nn.Embedding(vocab_size, d_model) - self.pos_emb = nn.Embedding(max_seq_len, d_model) - self.layers = nn.ModuleList([EncoderBlock(d_model, n_heads, head_dim, d_mlp) for _ in range(n_layers)]) - - def forward(self, token_ids): - B, T = token_ids.shape - x = self.token_emb(token_ids) + self.pos_emb(torch.arange(T, device=token_ids.device).unsqueeze(0).expand(B, T)) - for blk in self.layers: - x = blk(x) - return x # (B, T, 24) From 59c99a9290ea7729b4c2eda22ae5beba62d59ed7 Mon Sep 17 00:00:00 2001 From: Dhruv Parashar Date: Fri, 29 Aug 2025 01:36:51 -0400 Subject: [PATCH 2/3] CI: add parity check workflow --- .github/workflows/parity.yml | 27 +++++++++++++++++++++++++++ scripts/parity_check.py | 2 ++ 2 files changed, 29 insertions(+) create mode 100644 .github/workflows/parity.yml diff --git a/.github/workflows/parity.yml b/.github/workflows/parity.yml new file mode 100644 index 0000000..238edfe --- /dev/null +++ b/.github/workflows/parity.yml @@ -0,0 +1,27 @@ +name: Parity check + +on: + push: + pull_request: + +jobs: + parity: + runs-on: ubuntu-latest + steps: + - uses: actions/checkout@v4 + - uses: actions/setup-python@v5 + with: + python-version: "3.11" + + - name: Install deps (CPU only) + run: | + python -m pip install --upgrade pip + pip install --index-url https://download.pytorch.org/whl/cpu torch + pip install numpy "jax[cpu]" dm-haiku + pip install git+https://github.com/google-deepmind/tracr.git + + - name: Compile & export tracr + run: python scripts/compile_export.py + + - name: Verify parity (fail if mismatch) + run: python scripts/parity_check.py diff --git a/scripts/parity_check.py b/scripts/parity_check.py index f89a6f9..f6383e1 100644 --- a/scripts/parity_check.py +++ b/scripts/parity_check.py @@ -75,3 +75,5 @@ def load_linear(L, w_key, b_key): print("\n--- Sanity Check ---") print(f"Outputs match: {ok}") print(f"Max abs diff: {md:.6g}") + +sys.exit(0 if ok else 1) \ No newline at end of file From 8afa9247635331a8685450045553e9d26fb21cfc Mon Sep 17 00:00:00 2001 From: Dhruv Parashar Date: Fri, 29 Aug 2025 02:10:48 -0400 Subject: [PATCH 3/3] =?UTF-8?q?CI:=20don=E2=80=99t=20require=20local=20tra?= =?UTF-8?q?cr=20path;=20allow=20pip-installed=20tracr?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- scripts/compile_export.py | 19 ++++++------------- 1 file changed, 6 insertions(+), 13 deletions(-) diff --git a/scripts/compile_export.py b/scripts/compile_export.py index 7d5a8a8..f92caf2 100644 --- a/scripts/compile_export.py +++ b/scripts/compile_export.py @@ -7,24 +7,17 @@ REPO_ROOT = Path(__file__).resolve().parents[1] -# Look for tracr in common locations -CANDIDATES = [ - REPO_ROOT / "external" / "Tracr" / "tracr", # new suggested location - REPO_ROOT / "Tracr" / "tracr", # your old location +# Add local tracr paths if they exist; otherwise rely on pip-installed package +for p in [ + REPO_ROOT / "external" / "Tracr" / "tracr", # optional vendored location + REPO_ROOT / "Tracr" / "tracr", # older local layout REPO_ROOT / "tracr", # just in case -] - -for p in CANDIDATES: +]: if p.is_dir(): sys.path.insert(0, str(p)) break -else: - raise ModuleNotFoundError( - "Couldn't find the tracr package.\n" - "Either clone it to external/Tracr or Tracr at the repo root, " - "or install it with pip (see Option B)." - ) +# Now import (works with either local path OR pip-installed package) from tracr.compiler import compiling from tracr.rasp import rasp