-
Notifications
You must be signed in to change notification settings - Fork 55
Expand file tree
/
Copy pathcalibrator.py
More file actions
170 lines (139 loc) · 5.72 KB
/
Copy pathcalibrator.py
File metadata and controls
170 lines (139 loc) · 5.72 KB
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
"""FlashRT — FP8 calibration cache.
Calibration scales are checkpoint-specific and sequence-length-specific.
Caching avoids re-running the dynamic calibration pass (~3-4s) on every startup.
Cache key design:
- Checkpoint identity: SHA256 of model.safetensors (first 64KB for speed)
- Sequence length Se: different prompt lengths produce different shapes
- Both are needed because:
- Same model, different Se → different buffer shapes → potentially different scales
- Same Se, different finetune → completely different activation distributions
Cache location: ~/.flash_rt/calibration/{ckpt_hash}_{Se}.json
"""
import hashlib
import json
import logging
import os
from pathlib import Path
from typing import Optional
logger = logging.getLogger(__name__)
CACHE_DIR = Path.home() / ".flash_rt" / "calibration"
def _checkpoint_hash(checkpoint_path: str, read_bytes: int = 65536) -> str:
"""Fast hash of checkpoint file (first 64KB + file size).
Hashes first 64KB + file size instead of the entire file (which can be
multiple GB) for speed. This is sufficient to distinguish different
finetunes because:
- Different models have different first-layer weights → different first 64KB
- Same model re-saved has identical content → same hash
- File size as extra discriminator catches truncated/corrupted files
"""
p = Path(checkpoint_path)
if p.is_dir():
# Look for a hashable file in the checkpoint directory
candidates = [
"model.safetensors", "model.pkl", "checkpoint.pkl",
# Sharded safetensors (e.g. GROOT): hash the index or first shard
"model.safetensors.index.json",
"model-00001-of-00002.safetensors",
"model-00001-of-00004.safetensors",
# Orbax (JAX): hash the manifest
"params/manifest.ocdbt",
"params/ocdbt.process_0/manifest.ocdbt",
]
for name in candidates:
candidate = p / name
if candidate.exists():
p = candidate
break
else:
raise FileNotFoundError(f"No checkpoint file found in {checkpoint_path}")
h = hashlib.sha256()
with open(p, "rb") as f:
h.update(f.read(read_bytes))
file_size = p.stat().st_size
h.update(str(file_size).encode())
return h.hexdigest()[:16] # 16 hex chars = 64 bits, collision-safe
def _cache_path(ckpt_hash: str, Se: int) -> Path:
return CACHE_DIR / f"{ckpt_hash}_Se{Se}.json"
def save_calibration(checkpoint_path: str, Se: int,
enc_scales: list, enc_alpha: list,
ae_scales: list, enc_w_scales: list,
metadata: dict | None = None):
"""Save calibration scales to local cache.
Args:
checkpoint_path: Path to the checkpoint (for hashing).
Se: Encoder sequence length (determines buffer shapes).
enc_scales: Encoder activation scales, len = num_layers * 4.
enc_alpha: Encoder alpha (= enc_scales * enc_w_scales), len = num_layers * 4.
ae_scales: Decoder (AE) activation scales, len = num_layers * 4.
enc_w_scales: Encoder weight scales (stored for alpha recomputation).
"""
ckpt_hash = _checkpoint_hash(checkpoint_path)
cache_file = _cache_path(ckpt_hash, Se)
CACHE_DIR.mkdir(parents=True, exist_ok=True)
data = {
"version": 1,
"ckpt_hash": ckpt_hash,
"Se": Se,
"num_enc_scales": len(enc_scales),
"num_ae_scales": len(ae_scales),
"enc_scales": enc_scales,
"enc_alpha": enc_alpha,
"ae_scales": ae_scales,
"enc_w_scales": enc_w_scales,
}
if metadata is not None:
data["metadata"] = metadata
with open(cache_file, "w") as f:
json.dump(data, f, indent=2)
logger.info(f"Calibration saved: {cache_file} "
f"(enc={len(enc_scales)}, ae={len(ae_scales)} scales)")
return cache_file
def load_calibration(checkpoint_path: str, Se: int) -> Optional[dict]:
"""Load calibration scales from local cache.
Returns dict with enc_scales, enc_alpha, ae_scales, enc_w_scales
or None if cache miss (file not found or version mismatch).
"""
try:
ckpt_hash = _checkpoint_hash(checkpoint_path)
except FileNotFoundError:
return None
cache_file = _cache_path(ckpt_hash, Se)
if not cache_file.exists():
logger.info(f"Calibration cache miss: {cache_file}")
return None
with open(cache_file) as f:
data = json.load(f)
# Validate
if data.get("version") != 1:
logger.warning(f"Calibration cache version mismatch, re-calibrating")
return None
if data.get("ckpt_hash") != ckpt_hash:
logger.warning(f"Calibration cache hash mismatch, re-calibrating")
return None
if data.get("Se") != Se:
logger.warning(f"Calibration cache Se mismatch ({data.get('Se')} != {Se})")
return None
logger.info(f"Calibration loaded from cache: {cache_file}")
return data
def clear_calibration(checkpoint_path: str = None):
"""Clear calibration cache.
Args:
checkpoint_path: If provided, only clear cache for this checkpoint.
If None, clear all cached calibrations.
"""
if not CACHE_DIR.exists():
return
if checkpoint_path is None:
# Clear all
count = 0
for f in CACHE_DIR.glob("*.json"):
f.unlink()
count += 1
logger.info(f"Cleared {count} calibration cache files")
else:
ckpt_hash = _checkpoint_hash(checkpoint_path)
count = 0
for f in CACHE_DIR.glob(f"{ckpt_hash}_*.json"):
f.unlink()
count += 1
logger.info(f"Cleared {count} calibration cache files for {ckpt_hash}")