Spaces:
Running on Zero
Running on Zero
Commit ·
c9744fe
1
Parent(s): b7f6530
feat: increase seq_len and auto-update of dim on UI during compute
Browse files- app.py +30 -3
- 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=
|
| 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 =
|
| 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[
|
| 23 |
|
| 24 |
_cache: dict[str, Any] = {"name": None, "model": None, "tokenizer": None}
|
| 25 |
|
| 26 |
|
| 27 |
-
|
|
|
|
|
|
|
|
|
|
| 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 =
|
| 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()
|