1- from typing import Optional , Tuple
2-
31import einops
42import jaxtyping
53import torch
64import torch .nn as nn
5+ from typing import Optional , Tuple
76from transformers import AutoTokenizer , AutoModelForCausalLM , TextStreamer , BitsAndBytesConfig
7+ from inspect import signature
88
99torch .inference_mode ()
1010
11- torch .set_default_device ("cpu" )
12-
13- MODEL_ID = "stabilityai/stablelm-2-zephyr-1_6b"
14- #MODEL_ID = "Qwen/Qwen1.5-1.8B-Chat"
15- #MODEL_ID = "Qwen/Qwen-1_8B-chat"
16- #MODEL_ID = "google/gemma-1.1-2b-it"
17- #MODEL_ID = "google/gemma-1.1-7b-it"
18- #MODEL_ID = "meta-llama/Meta-Llama-3-8B-Instruct"
19-
20- model = AutoModelForCausalLM .from_pretrained (MODEL_ID , trust_remote_code = True , device_map = "cuda" , quantization_config = BitsAndBytesConfig (load_in_4bit = True , bnb_4bit_compute_dtype = torch .float16 ))
11+ MODEL_ID = "tiiuae/Falcon3-1B-Instruct"
12+ # MODEL_ID = "Qwen/Qwen3-1.7B"
13+ # MODEL_ID = "stabilityai/stablelm-2-zephyr-1_6b"
14+ # MODEL_ID = "Qwen/Qwen1.5-1.8B-Chat"
15+ # MODEL_ID = "Qwen/Qwen-1_8B-chat"
16+ # MODEL_ID = "google/gemma-1.1-2b-it"
17+ # MODEL_ID = "google/gemma-1.1-7b-it"
18+ # MODEL_ID = "meta-llama/Meta-Llama-3-8B-Instruct"
19+
20+ model = AutoModelForCausalLM .from_pretrained (MODEL_ID ,
21+ trust_remote_code = True ,
22+ dtype = torch .float16 ,
23+ device_map = "cuda" ,
24+ quantization_config = BitsAndBytesConfig (load_in_4bit = True ,
25+ bnb_4bit_compute_dtype = torch .float16 ))
2126tokenizer = AutoTokenizer .from_pretrained (MODEL_ID , trust_remote_code = True )
2227
2328refusal_dir = torch .load (MODEL_ID .replace ("/" , "_" ) + "_refusal_dir.pt" )
2429
2530
2631def direction_ablation_hook (activation : jaxtyping .Float [torch .Tensor , "... d_act" ],
2732 direction : jaxtyping .Float [torch .Tensor , "d_act" ]):
28- proj = einops .einsum (activation , direction .view (- 1 , 1 ), '... d_act, d_act single -> ... single' ) * direction
33+ proj = einops .einsum (activation , direction .view (- 1 , 1 ),
34+ '... d_act, d_act single -> ... single' ) * direction
2935 return activation - proj
3036
3137
38+ # Some model developers thought it was stupid to pass a tuple of tuple of tuples around (rightfully so), but unfortunately now we have a divide
39+ sig = signature (model .model .layers [0 ].forward )
40+ simple = sig .return_annotation == torch .Tensor
41+
42+
3243class AblationDecoderLayer (nn .Module ):
44+ def __init__ (self ):
45+ super ().__init__ ()
46+ self .attention_type = "full_attention"
47+
3348 def forward (
3449 self ,
3550 hidden_states : torch .Tensor ,
@@ -40,24 +55,32 @@ def forward(
4055 use_cache : Optional [bool ] = False ,
4156 cache_position : Optional [torch .LongTensor ] = None ,
4257 ** kwargs ,
43- ) -> Tuple [ torch . FloatTensor , Optional [ Tuple [ torch . FloatTensor , torch . FloatTensor ]]] :
58+ ):
4459 assert not output_attentions
4560
46- ablated = direction_ablation_hook (hidden_states , refusal_dir .to (hidden_states .device )).to (hidden_states .device )
61+ ablated = direction_ablation_hook (hidden_states , refusal_dir .to (
62+ hidden_states .device )).to (hidden_states .device )
63+
64+ if simple :
65+ return ablated
4766
4867 outputs = (ablated ,)
4968
5069 if use_cache :
5170 outputs += (past_key_value ,)
5271
53- # noinspection PyTypeChecker
5472 return outputs
5573
5674
57- for idx in reversed (range (len (model .model .layers ))): # for qwen 1 this needs to be changed to model.transformer.h
75+ # for qwen 1 this needs to be changed to model.transformer.h
76+ for idx in reversed (range (len (model .model .layers ))):
5877 model .model .layers .insert (idx , AblationDecoderLayer ())
5978
60- conversation = []
79+ # bruh
80+ if hasattr (model , "config" ) and hasattr (model .config , "num_hidden_layers" ):
81+ model .config .num_hidden_layers *= 2
82+
83+ conversation = []
6184
6285streamer = TextStreamer (tokenizer )
6386
@@ -66,10 +89,9 @@ def forward(
6689 prompt = input ()
6790 conversation .append ({"role" : "user" , "content" : prompt })
6891 toks = tokenizer .apply_chat_template (conversation = conversation ,
69- add_generation_prompt = True , return_tensors = "pt" )
92+ add_generation_prompt = True , return_tensors = "pt" )
7093
7194 gen = model .generate (toks .to (model .device ), streamer = streamer , max_new_tokens = 1337 )
7295
7396 decoded = tokenizer .batch_decode (gen [0 ][len (toks [0 ]):], skip_special_tokens = True )
7497 conversation .append ({"role" : "assistant" , "content" : "" .join (decoded )})
75-
0 commit comments