DebasishDhal99 commited on
Commit
c9744fe
·
1 Parent(s): b7f6530

feat: increase seq_len and auto-update of dim on UI during compute

Browse files
Files changed (2) hide show
  1. app.py +30 -3
  2. src/extract.py +24 -4
app.py CHANGED
@@ -14,6 +14,7 @@ from src.extract import (
14
  MODEL_CHOICES,
15
  expand_kv_heads,
16
  extract_from_model,
 
17
  random_qk,
18
  select_head,
19
  )
@@ -90,6 +91,22 @@ def _safe_slider_max(n: int) -> int:
90
  return max(int(n), 1)
91
 
92
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
93
  def compute(
94
  source: str,
95
  sentence: str,
@@ -249,7 +266,7 @@ def toggle_source(source: str):
249
  is_random = source.startswith("Random")
250
  return (
251
  gr.update(visible=is_random),
252
- gr.update(visible=is_random),
253
  gr.update(visible=is_random),
254
  gr.update(visible=not is_random),
255
  gr.update(visible=not is_random),
@@ -287,8 +304,8 @@ with gr.Blocks(title="RoPE Explorer") as demo:
287
  )
288
  with gr.Row():
289
  seq_len = gr.Slider(2, MAX_SEQ_LEN, value=16, step=1, label="Sequence length")
290
- dim = gr.Slider(4, 128, value=32, step=2, label="Dimension (even)")
291
- seed = gr.Number(value=0, label="Seed", precision=0)
292
  base = gr.Number(
293
  value=10000,
294
  label="RoPE base (overridden by config.rope_theta for real models)",
@@ -335,6 +352,16 @@ with gr.Blocks(title="RoPE Explorer") as demo:
335
  inputs=[source],
336
  outputs=[seq_len, dim, seed, sentence, model_name],
337
  )
 
 
 
 
 
 
 
 
 
 
338
 
339
  bulk_inputs = [state, which, head, mod_2pi]
340
  bulk_outputs = [bulk_main, bulk_norm, bulk_theta, bulk_freq]
 
14
  MODEL_CHOICES,
15
  expand_kv_heads,
16
  extract_from_model,
17
+ get_model_head_dim,
18
  random_qk,
19
  select_head,
20
  )
 
91
  return max(int(n), 1)
92
 
93
 
94
+ def update_dimension(source: str, model_name: str):
95
+ if source.startswith("Random"):
96
+ return gr.update(minimum=4, maximum=128, value=32, step=2, interactive=True)
97
+ try:
98
+ model_dim = get_model_head_dim(model_name)
99
+ return gr.update(
100
+ minimum=4,
101
+ maximum=max(128, model_dim),
102
+ value=model_dim,
103
+ step=2,
104
+ interactive=False,
105
+ )
106
+ except Exception:
107
+ return gr.update()
108
+
109
+
110
  def compute(
111
  source: str,
112
  sentence: str,
 
266
  is_random = source.startswith("Random")
267
  return (
268
  gr.update(visible=is_random),
269
+ gr.update(visible=True, interactive=is_random),
270
  gr.update(visible=is_random),
271
  gr.update(visible=not is_random),
272
  gr.update(visible=not is_random),
 
304
  )
305
  with gr.Row():
306
  seq_len = gr.Slider(2, MAX_SEQ_LEN, value=16, step=1, label="Sequence length")
307
+ dim = gr.Slider(4, 128, value=32, step=2, label="Dimension (even; per attention head)")
308
+ seed = gr.Number(value=42, label="Seed", precision=0)
309
  base = gr.Number(
310
  value=10000,
311
  label="RoPE base (overridden by config.rope_theta for real models)",
 
352
  inputs=[source],
353
  outputs=[seq_len, dim, seed, sentence, model_name],
354
  )
355
+ source.change(
356
+ update_dimension,
357
+ inputs=[source, model_name],
358
+ outputs=[dim],
359
+ )
360
+ model_name.change(
361
+ update_dimension,
362
+ inputs=[source, model_name],
363
+ outputs=[dim],
364
+ )
365
 
366
  bulk_inputs = [state, which, head, mod_2pi]
367
  bulk_outputs = [bulk_main, bulk_norm, bulk_theta, bulk_freq]
src/extract.py CHANGED
@@ -11,20 +11,24 @@ import numpy as np
11
 
12
  from src.rope import apply_rope
13
 
14
- MAX_SEQ_LEN = 64
15
 
16
  # Ungated Llama-like checkpoints (q_proj / k_proj + rotary). No HF token required.
17
  MODEL_CHOICES = [
 
18
  "HuggingFaceTB/SmolLM2-135M",
19
  "Qwen/Qwen2.5-0.5B-Instruct",
20
  "TinyLlama/TinyLlama-1.1B-Chat-v1.0",
21
  ]
22
- DEFAULT_MODEL = MODEL_CHOICES[0]
23
 
24
  _cache: dict[str, Any] = {"name": None, "model": None, "tokenizer": None}
25
 
26
 
27
- def random_matrix(seq_len: int, dim: int, seed: int = 0) -> np.ndarray:
 
 
 
28
  if dim % 2 != 0:
29
  raise ValueError(f"dim must be even for RoPE, got {dim}")
30
  seq_len = int(np.clip(seq_len, 1, MAX_SEQ_LEN))
@@ -35,7 +39,7 @@ def random_matrix(seq_len: int, dim: int, seed: int = 0) -> np.ndarray:
35
  def random_qk(
36
  seq_len: int,
37
  dim: int,
38
- seed: int = 0,
39
  base: float = 10000.0,
40
  ) -> dict[str, Any]:
41
  q = random_matrix(seq_len, dim, seed=seed)
@@ -104,6 +108,22 @@ def _require_hf():
104
  return torch, AutoModelForCausalLM, AutoTokenizer
105
 
106
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
107
  def get_model(model_name: str):
108
  """Load tokenizer + causal LM on CPU; cache the last selection."""
109
  torch, AutoModelForCausalLM, AutoTokenizer = _require_hf()
 
11
 
12
  from src.rope import apply_rope
13
 
14
+ MAX_SEQ_LEN = 2048
15
 
16
  # Ungated Llama-like checkpoints (q_proj / k_proj + rotary). No HF token required.
17
  MODEL_CHOICES = [
18
+ "HuggingFaceM4/tiny-random-LlamaForCausalLM",
19
  "HuggingFaceTB/SmolLM2-135M",
20
  "Qwen/Qwen2.5-0.5B-Instruct",
21
  "TinyLlama/TinyLlama-1.1B-Chat-v1.0",
22
  ]
23
+ DEFAULT_MODEL = MODEL_CHOICES[1]
24
 
25
  _cache: dict[str, Any] = {"name": None, "model": None, "tokenizer": None}
26
 
27
 
28
+ _config_cache: dict[str, Any] = {}
29
+
30
+
31
+ def random_matrix(seq_len: int, dim: int, seed: int = 42) -> np.ndarray:
32
  if dim % 2 != 0:
33
  raise ValueError(f"dim must be even for RoPE, got {dim}")
34
  seq_len = int(np.clip(seq_len, 1, MAX_SEQ_LEN))
 
39
  def random_qk(
40
  seq_len: int,
41
  dim: int,
42
+ seed: int = 42,
43
  base: float = 10000.0,
44
  ) -> dict[str, Any]:
45
  q = random_matrix(seq_len, dim, seed=seed)
 
108
  return torch, AutoModelForCausalLM, AutoTokenizer
109
 
110
 
111
+ def get_model_head_dim(model_name: str) -> int:
112
+ """Return the Q/K dimension per attention head without loading model weights."""
113
+ if model_name not in _config_cache:
114
+ try:
115
+ from transformers import AutoConfig
116
+ except ImportError as exc:
117
+ raise RuntimeError("Real-model mode needs `transformers`.") from exc
118
+ _config_cache[model_name] = AutoConfig.from_pretrained(model_name)
119
+
120
+ config = _config_cache[model_name]
121
+ configured_head_dim = getattr(config, "head_dim", None)
122
+ if configured_head_dim is not None:
123
+ return int(configured_head_dim)
124
+ return int(config.hidden_size) // int(config.num_attention_heads)
125
+
126
+
127
  def get_model(model_name: str):
128
  """Load tokenizer + causal LM on CPU; cache the last selection."""
129
  torch, AutoModelForCausalLM, AutoTokenizer = _require_hf()