Spaces:
Sleeping
Sleeping
File size: 7,257 Bytes
a42d9ad | 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 171 172 173 174 175 176 177 | """Stage Llama-layout query ranges from safetensors and select one global mask."""
from dataclasses import dataclass
import json
from pathlib import Path
import shutil
import struct
import tempfile
import ml_dtypes
import numpy as np
from .files import _input_path, _open_npy, _publish_masks
_DTYPES = {"F16": np.dtype("<f2"), "BF16": np.dtype(ml_dtypes.bfloat16),
"F32": np.dtype("<f4"), "F64": np.dtype("<f8")}
_CHUNK = 8 * 1024**2
_HEADROOM = 1024**3
def _object(pairs):
result = {}
for key, value in pairs:
if key in result:
raise ValueError(f"Duplicate JSON key: {key}")
result[key] = value
return result
def _json_object(raw):
value = json.loads(raw, object_pairs_hook=_object)
if not isinstance(value, dict):
raise ValueError("Expected a JSON object")
return value
def _json_file(path, limit):
with path.open("rb") as stream:
raw = stream.read(limit + 1)
if len(raw) > limit:
raise ValueError(f"{path.name} exceeds the supported metadata size")
return _json_object(raw)
def _layout(config):
layers = config.get("num_hidden_layers")
heads = config.get("num_attention_heads")
width = config.get("hidden_size")
if any(type(n) is not int or n < 1 for n in (layers, heads, width)) or layers > 1024:
raise ValueError("Expected valid Llama-layout layer, head and hidden sizes")
channels = config.get("head_dim")
if channels is None:
channels, extra = divmod(width, heads)
if extra:
raise ValueError("hidden_size must be divisible by num_attention_heads")
if type(channels) is not int or channels < 1:
raise ValueError("Invalid head_dim")
return layers, (heads, channels, width)
def _header(path):
with path.open("rb") as stream:
prefix = stream.read(8)
if len(prefix) != 8:
raise ValueError(f"Incomplete safetensors header: {path.name}")
size, = struct.unpack("<Q", prefix)
if not 2 <= size <= 100_000_000:
raise ValueError(f"Invalid safetensors header length: {path.name}")
raw = stream.read(size)
if len(raw) != size or not raw.startswith(b"{"):
raise ValueError(f"Invalid safetensors header: {path.name}")
start = 8 + size
return _json_object(raw), start, path.stat().st_size - start
@dataclass(frozen=True)
class QueryRange:
name: str
shard: Path
offset: int
length: int
shape: tuple[int, int, int]
dtype: np.dtype
def _queries(checkpoint, max_weights):
root = Path(checkpoint).resolve(strict=True)
layers, shape = _layout(_json_file(_input_path(root, "config.json", ".json"), 1024**2))
heads, channels, width = shape
total = layers * heads * channels * width
if total > max_weights:
raise ValueError("Checkpoint exceeds the configured eligible weight limit")
names = [f"model.layers.{layer}.self_attn.q_proj.weight" for layer in range(layers)]
index = root / "model.safetensors.index.json"
if index.exists():
mapping = _json_file(_input_path(root, index.name, ".json"), 16 * 1024**2).get("weight_map")
if not isinstance(mapping, dict) or any(name not in mapping for name in names):
raise ValueError("Expected one named Llama-layout query tensor for every layer")
else:
mapping = dict.fromkeys(names, "model.safetensors")
headers = {}
queries = []
ranges = {}
for name in names:
shard = _input_path(root, mapping[name], ".safetensors")
if shard not in headers:
headers[shard] = _header(shard)
header, start, payload_size = headers[shard]
item = header.get(name)
if not isinstance(item, dict) or item.get("shape") != [heads * channels, width]:
raise ValueError(f"Unexpected query shape: {name}")
dtype = _DTYPES.get(item.get("dtype"))
if dtype is None:
raise ValueError(f"Expected dense floating-point query weights: {name}")
offsets = item.get("data_offsets")
length = heads * channels * width * dtype.itemsize
if (not isinstance(offsets, list) or len(offsets) != 2
or any(type(n) is not int for n in offsets)):
raise ValueError(f"Invalid safetensors offsets: {name}")
low, high = offsets
if not 0 <= low < high <= payload_size or high - low != length:
raise ValueError(f"Invalid safetensors byte range: {name}")
ranges.setdefault(shard, []).append((low, high))
queries.append(QueryRange(name, shard, start + low, length, shape, dtype))
for shard, spans in ranges.items():
ordered = sorted(spans)
if any(left[1] > right[0] for left, right in zip(ordered, ordered[1:])):
raise ValueError(f"Overlapping query byte ranges: {shard.name}")
return queries, total
def _copy_query(query, path):
with query.shard.open("rb") as src, path.open("wb") as dst:
src.seek(query.offset)
remaining = query.length
while remaining:
block = src.read(min(remaining, _CHUNK))
if not block:
raise OSError(f"Shard ended during staging: {query.shard.name}")
dst.write(block)
remaining -= len(block)
return np.memmap(path, dtype=query.dtype, mode="r", shape=query.shape)
def prune_checkpoint(checkpoint, output_dir, *, keep, workspace, max_weights,
input_root=None, moments_manifest=None, threads=1, seed=0):
"""Read only the eligible query bytes and write per-layer Boolean masks."""
queries, total = _queries(checkpoint, max_weights)
if not 0 <= keep <= total:
raise ValueError("keep must be between zero and the eligible query slot count")
names = [query.name for query in queries]
moments = None
if moments_manifest is not None:
root = Path(input_root).resolve(strict=True)
sources = _json_file(_input_path(root, moments_manifest, ".json"), 1024**2)
if set(sources) != set(names):
raise ValueError("Moment manifest must map every eligible query name to an .npy vector")
moments = [_open_npy(root, sources[name]) for name in names]
workspace = Path(workspace)
output_dir = Path(output_dir)
if workspace.stat().st_dev != output_dir.parent.stat().st_dev:
raise ValueError("Checkpoint work and output must use the same local filesystem")
needed = sum(query.length for query in queries) + total + 4096 * len(queries)
if 0 < keep < total:
needed += 4 * total
if shutil.disk_usage(workspace).free < needed + _HEADROOM:
raise OSError(f"Insufficient local disk: need {needed + _HEADROOM:,} bytes free")
with tempfile.TemporaryDirectory(prefix="query-staging-", dir=workspace) as stage:
staged = {}
for index, query in sorted(enumerate(queries), key=lambda row: (row[1].shard, row[1].offset)):
staged[index] = _copy_query(query, Path(stage) / f"{index:04d}.bin")
arrays = [staged[index] for index in range(len(queries))]
return _publish_masks(names, arrays, moments, keep, output_dir,
scratch_dir=workspace, threads=threads, seed=seed)
|