cdpearlman commited on
Commit
2f4e4f3
·
1 Parent(s): 890f413

feat(ablation): Unify ablation execution into execute_forward_pass

Browse files
tests/test_unified_ablation.py ADDED
@@ -0,0 +1,56 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+
2
+ import sys
3
+ import os
4
+ import torch
5
+ import pytest
6
+ from transformers import AutoModelForCausalLM, AutoTokenizer
7
+
8
+ # Add project root to path
9
+ sys.path.append(os.path.abspath(os.path.join(os.path.dirname(__file__), '..')))
10
+
11
+ from utils.model_patterns import execute_forward_pass
12
+
13
+ def test_unified_ablation():
14
+ """
15
+ Verify that execute_forward_pass can handle ablation configuration.
16
+ """
17
+ model_name = "gpt2"
18
+ prompt = "The quick brown fox jumps over the"
19
+
20
+ tokenizer = AutoTokenizer.from_pretrained(model_name)
21
+ model = AutoModelForCausalLM.from_pretrained(model_name)
22
+ model.eval()
23
+
24
+ config = {
25
+ "attention_modules": ["transformer.h.0.attn"],
26
+ "block_modules": ["transformer.h.0"],
27
+ "norm_parameters": [],
28
+ "logit_lens_parameter": "transformer.ln_f.weight"
29
+ }
30
+
31
+ # 1. Baseline
32
+ baseline = execute_forward_pass(model, tokenizer, prompt, config)
33
+ baseline_prob = baseline['actual_output']['probability']
34
+
35
+ # 2. Ablated via execute_forward_pass (New API we want to support)
36
+ heads_to_ablate = {0: [0]} # Layer 0, Head 0
37
+
38
+ # We expect this to fail currently as the argument doesn't exist
39
+ try:
40
+ ablated = execute_forward_pass(
41
+ model, tokenizer, prompt, config,
42
+ ablation_config=heads_to_ablate
43
+ )
44
+ ablated_prob = ablated['actual_output']['probability']
45
+
46
+ print(f"Baseline: {baseline_prob}, Ablated: {ablated_prob}")
47
+
48
+ # Assert change
49
+ assert abs(baseline_prob - ablated_prob) > 1e-6
50
+ assert ablated.get('ablated_heads_by_layer') == heads_to_ablate
51
+
52
+ except TypeError:
53
+ pytest.fail("execute_forward_pass does not accept ablation_config argument yet")
54
+
55
+ if __name__ == "__main__":
56
+ test_unified_ablation()
utils/model_patterns.py CHANGED
@@ -148,7 +148,7 @@ def get_actual_model_output(model_output, tokenizer) -> Tuple[str, float]:
148
  return token_str, top_prob.item()
149
 
150
 
151
- def execute_forward_pass(model, tokenizer, prompt: str, config: Dict[str, Any]) -> Dict[str, Any]:
152
  """
153
  Execute forward pass with PyVene IntervenableModel to capture activations from specified modules.
154
 
@@ -157,10 +157,14 @@ def execute_forward_pass(model, tokenizer, prompt: str, config: Dict[str, Any])
157
  tokenizer: Loaded tokenizer
158
  prompt: Input text prompt
159
  config: Dict with module lists like {"attention_modules": [...], "block_modules": [...], ...}
 
160
 
161
  Returns:
162
  JSON-serializable dict with captured activations and metadata
163
  """
 
 
 
164
  print(f"Executing forward pass with prompt: '{prompt}'")
165
 
166
  # Extract module lists from config
 
148
  return token_str, top_prob.item()
149
 
150
 
151
+ def execute_forward_pass(model, tokenizer, prompt: str, config: Dict[str, Any], ablation_config: Optional[Dict[int, List[int]]] = None) -> Dict[str, Any]:
152
  """
153
  Execute forward pass with PyVene IntervenableModel to capture activations from specified modules.
154
 
 
157
  tokenizer: Loaded tokenizer
158
  prompt: Input text prompt
159
  config: Dict with module lists like {"attention_modules": [...], "block_modules": [...], ...}
160
+ ablation_config: Optional dict mapping layer numbers to list of head indices to ablate.
161
 
162
  Returns:
163
  JSON-serializable dict with captured activations and metadata
164
  """
165
+ if ablation_config:
166
+ return execute_forward_pass_with_multi_layer_head_ablation(model, tokenizer, prompt, config, ablation_config)
167
+
168
  print(f"Executing forward pass with prompt: '{prompt}'")
169
 
170
  # Extract module lists from config