Download RSS_AI_Engine/Hardware_Module/internal/sequential_ring_loader.py from Biraboro/RRas-ai-engine: direct link, hf CLI and curl.
- Browser
- Download file 13.7 kB
-
https://huggingface.co/Biraboro/RRas-ai-engine/resolve/main/RSS_AI_Engine/Hardware_Module/internal/sequential_ring_loader.py
- Command line
-
hf download hf://Biraboro/RRas-ai-engine/RSS_AI_Engine/Hardware_Module/internal/sequential_ring_loader.py
-
curl -L -o sequential_ring_loader.py https://huggingface.co/Biraboro/RRas-ai-engine/resolve/main/RSS_AI_Engine/Hardware_Module/internal/sequential_ring_loader.py
13.7 kB
| """Deterministic sequential ring loader (PRIVATE to Hardware_Module) - Tier 3 (1-2 GB RAM). | |
| The model skeleton is built with EMPTY parameters (zero-size tensors, real CPU buffers such as the | |
| rotary inv_freq). Forward pre/post hooks then stream weights from the safetensors files in the exact | |
| order embed -> layer 0 -> layer 1 -> ... -> layer N-1 -> norm -> lm_head (and wrap around to layer 0 for | |
| the next token). At most `window` (default 2) decoder layers are resident at any time. | |
| Parameters are always REPLACED by fresh nn.Parameter objects (never mutated in place), so autograd | |
| graphs / checkpoint recomputation that still reference an evicted weight stay valid. | |
| Extra capabilities used by the Elevator trainer: | |
| pin(idxs)/unpin(idxs, save=True) keep trainable layers resident, persist them as overlay shards | |
| export(dest) write the full (base + overlay) model as safetensors shards | |
| """ | |
| from __future__ import annotations | |
| import gc | |
| import json | |
| import shutil | |
| import time | |
| from collections import deque | |
| from pathlib import Path | |
| from typing import Dict, Iterator, List, Optional, Tuple | |
| import torch | |
| from torch import nn | |
| from safetensors import safe_open | |
| from safetensors.torch import save_file | |
| def _from_config(config, dtype): | |
| from transformers import AutoModelForCausalLM | |
| try: | |
| return AutoModelForCausalLM.from_config(config, dtype=dtype) | |
| except TypeError: | |
| return AutoModelForCausalLM.from_config(config, torch_dtype=dtype) | |
| class SequentialRingLoader: | |
| EMBED_KEY = "model.embed_tokens.weight" | |
| HEAD_KEY = "lm_head.weight" | |
| def __init__(self, model_dir, dtype=torch.bfloat16, window: int = 2, evict_ends: bool = True, | |
| overlay_dir: Optional[str] = None, row_recipe: Optional[Dict] = None, verbose: bool = True): | |
| self.model_dir = Path(model_dir) | |
| self.dtype = dtype | |
| self.window = max(1, int(window)) | |
| self.evict_ends = bool(evict_ends) | |
| self.overlay_dir = Path(overlay_dir) if overlay_dir else self.model_dir / ".rss_overlay" | |
| self.row_recipe = {int(k): [int(x) for x in v] for k, v in (row_recipe or {}).items()} | |
| self.verbose = verbose | |
| self.trace: deque = deque(maxlen=256) | |
| self.pinned: set = set() | |
| self.loaded: set = set() | |
| self.overlay_map: Dict[str, Path] = {} | |
| self.weight_map: Dict[str, str] = {} | |
| self._handles: Dict[str, object] = {} | |
| self.model = None | |
| self.segments: List[Dict] = [] | |
| self.by_name: Dict[str, Dict] = {} | |
| self.num_layers = 0 | |
| self.original_tied = False | |
| # ------------------------------------------------------------ indexing | |
| def _index_weights(self) -> None: | |
| index = self.model_dir / "model.safetensors.index.json" | |
| if index.exists(): | |
| self.weight_map = dict(json.loads(index.read_text(encoding="utf-8"))["weight_map"]) | |
| else: | |
| single = self.model_dir / "model.safetensors" | |
| if not single.exists(): | |
| raise FileNotFoundError(f"no model.safetensors / index in {self.model_dir}") | |
| with safe_open(str(single), framework="pt", device="cpu") as handle: | |
| self.weight_map = {k: "model.safetensors" for k in handle.keys()} | |
| def _handle(self, filename: str): | |
| if filename not in self._handles: | |
| self._handles[filename] = safe_open(str(self.model_dir / filename), framework="pt", device="cpu") | |
| return self._handles[filename] | |
| def _raw_get(self, key: str) -> torch.Tensor: | |
| if key in self.overlay_map: | |
| with safe_open(str(self.overlay_map[key]), framework="pt", device="cpu") as handle: | |
| return handle.get_tensor(key) | |
| return self._handle(self.weight_map[key]).get_tensor(key) | |
| def _get(self, key: str) -> torch.Tensor: | |
| tensor = self._raw_get(key) | |
| if self.row_recipe and key in (self.EMBED_KEY, self.HEAD_KEY): | |
| tensor = tensor.clone() | |
| for new_id, sources in self.row_recipe.items(): | |
| if new_id < tensor.shape[0] and sources: | |
| idx = torch.tensor([s for s in sources if s < tensor.shape[0]], dtype=torch.long) | |
| if len(idx): | |
| tensor[new_id] = tensor[idx].float().mean(0).to(tensor.dtype) | |
| return tensor | |
| # ---------------------------------------------------------------- build | |
| def build(self): | |
| from accelerate import init_empty_weights | |
| from transformers import AutoConfig | |
| self._index_weights() | |
| config = AutoConfig.from_pretrained(str(self.model_dir)) | |
| self.original_tied = bool(getattr(config, "tie_word_embeddings", False)) | |
| config.tie_word_embeddings = False # embed and lm_head are streamed independently | |
| with init_empty_weights(): # parameters on meta, buffers stay real | |
| model = _from_config(config, self.dtype) | |
| for module in model.modules(): | |
| for name, param in list(module._parameters.items()): | |
| if param is not None: | |
| module._parameters[name] = nn.Parameter(torch.empty(0, dtype=self.dtype), requires_grad=False) | |
| model.eval() | |
| model.config.use_cache = True | |
| inner = model.model | |
| self.num_layers = len(inner.layers) | |
| self.segments = [{"name": "embed", "module": inner.embed_tokens, "prefix": "model.embed_tokens", "idx": None}] | |
| for i, layer in enumerate(inner.layers): | |
| self.segments.append({"name": f"layer{i}", "module": layer, "prefix": f"model.layers.{i}", "idx": i}) | |
| self.segments.append({"name": "norm", "module": inner.norm, "prefix": "model.norm", "idx": None}) | |
| self.segments.append({"name": "head", "module": model.lm_head, "prefix": "lm_head", "idx": None}) | |
| self.by_name = {s["name"]: s for s in self.segments} | |
| self.model = model | |
| for seg in self.segments: | |
| self._install_hooks(seg) | |
| if not self.evict_ends: | |
| for name in ("embed", "norm", "head"): | |
| self._ensure(name) | |
| if self.verbose: | |
| print(f" [ring] built skeleton: {self.num_layers} layers on disk, window={self.window}, " | |
| f"evict_ends={self.evict_ends}, dtype={str(self.dtype).replace('torch.', '')}") | |
| return model | |
| # ------------------------------------------------------ key resolution | |
| def _key_for(self, seg: Dict, rel: str) -> Optional[str]: | |
| rel = rel.replace(".base_layer", "") | |
| if "lora_" in rel or "modules_to_save" in rel or "original_module" in rel: | |
| return None | |
| key = f"{seg['prefix']}.{rel}" | |
| if key in self.weight_map: | |
| return key | |
| if seg["name"] == "head" and rel == "weight" and self.EMBED_KEY in self.weight_map: | |
| return self.EMBED_KEY # tied checkpoint: head shares the embedding matrix | |
| return None | |
| def _managed(self, seg: Dict) -> Iterator[Tuple[str, nn.Module, str]]: | |
| for mod_name, mod in seg["module"].named_modules(): | |
| for pname, param in list(mod._parameters.items()): | |
| if param is None: | |
| continue | |
| rel = f"{mod_name}.{pname}" if mod_name else pname | |
| key = self._key_for(seg, rel) | |
| if key: | |
| yield key, mod, pname | |
| # ----------------------------------------------------------- load/evict | |
| def _ensure(self, name: str) -> None: | |
| if name in self.loaded: | |
| return | |
| started = time.time() | |
| for key, mod, pname in self._managed(self.by_name[name]): | |
| old = mod._parameters[pname] | |
| tensor = self._get(key).to(old.dtype) | |
| mod._parameters[pname] = nn.Parameter(tensor, requires_grad=old.requires_grad) | |
| self.loaded.add(name) | |
| self.trace.append(("load", name, round(time.time() - started, 3))) | |
| def _evict(self, name: str) -> None: | |
| if name not in self.loaded or name in self.pinned: | |
| return | |
| for _key, mod, pname in self._managed(self.by_name[name]): | |
| old = mod._parameters[pname] | |
| mod._parameters[pname] = nn.Parameter(torch.empty(0, dtype=self.dtype), requires_grad=old.requires_grad) | |
| self.loaded.discard(name) | |
| self.trace.append(("evict", name, 0.0)) | |
| # ---------------------------------------------------------------- hooks | |
| def _install_hooks(self, seg: Dict) -> None: | |
| name, idx = seg["name"], seg["idx"] | |
| module = seg["module"] | |
| if idx is not None: | |
| def pre(_m, _args, i=idx): | |
| self._enter_layer(i) | |
| def post(_m, _args, _out, i=idx): | |
| if self.window == 1: | |
| self._evict(f"layer{i}") | |
| module.register_forward_pre_hook(pre) | |
| module.register_forward_hook(post) | |
| else: | |
| def pre_end(_m, _args, n=name): | |
| self._ensure(n) | |
| def post_end(_m, _args, _out, n=name): | |
| if self.evict_ends: | |
| self._evict(n) | |
| module.register_forward_pre_hook(pre_end) | |
| module.register_forward_hook(post_end) | |
| def _enter_layer(self, i: int) -> None: | |
| keep = {f"layer{i}"} | |
| self._ensure(f"layer{i}") | |
| if self.window >= 2 and self.num_layers > 1: | |
| nxt = f"layer{(i + 1) % self.num_layers}" # ring: last layer prefetches layer 0 | |
| self._ensure(nxt) | |
| keep.add(nxt) | |
| for name in list(self.loaded): | |
| if name.startswith("layer") and name not in keep and name not in self.pinned: | |
| self._evict(name) | |
| # --------------------------------------------------- pin / overlay / io | |
| def pin(self, idxs) -> None: | |
| for i in idxs: | |
| self._ensure(f"layer{i}") | |
| self.pinned.add(f"layer{i}") | |
| def _save_overlay(self, i: int) -> None: | |
| seg = self.by_name[f"layer{i}"] | |
| tensors = {} | |
| for key, mod, pname in self._managed(seg): | |
| tensors[key] = mod._parameters[pname].detach().to(self.dtype).contiguous().clone() | |
| self.overlay_dir.mkdir(parents=True, exist_ok=True) | |
| path = self.overlay_dir / f"layer_{i}_{int(time.time() * 1000)}.safetensors" | |
| save_file(tensors, str(path), metadata={"format": "pt"}) | |
| for key in tensors: | |
| old = self.overlay_map.get(key) | |
| self.overlay_map[key] = path | |
| if old and old != path and old.exists() and old not in set(self.overlay_map.values()): | |
| old.unlink() | |
| def unpin(self, idxs, save: bool = True) -> None: | |
| for i in idxs: | |
| name = f"layer{i}" | |
| if save: | |
| self._save_overlay(i) | |
| self.pinned.discard(name) | |
| for _key, mod, pname in self._managed(self.by_name[name]): | |
| mod._parameters[pname].requires_grad_(False) | |
| self._evict(name) | |
| gc.collect() | |
| def export(self, dest) -> Path: | |
| """Write base + overlay weights as per-segment safetensors shards (1 segment in RAM at a time).""" | |
| dest = Path(dest) | |
| dest.mkdir(parents=True, exist_ok=True) | |
| covered = set() | |
| order = [s["name"] for s in self.segments] | |
| keys_by_segment: Dict[str, List[str]] = {} | |
| for name in order: | |
| seg = self.by_name[name] | |
| keys = sorted({key for key, _m, _p in self._managed(seg)}) | |
| if name == "head" and self.original_tied: | |
| keys = [] # keep the checkpoint tied: no duplicate matrix | |
| keys_by_segment[name] = keys | |
| covered.update(keys) | |
| leftovers = sorted(k for k in self.weight_map if k not in covered | |
| and not (self.original_tied and k == self.HEAD_KEY) | |
| and not (k == self.EMBED_KEY)) | |
| total_files = len([n for n in order if keys_by_segment[n]]) or 1 | |
| weight_map_out: Dict[str, str] = {} | |
| total_size = 0 | |
| shard_no = 0 | |
| for name in order: | |
| keys = keys_by_segment[name] | |
| if name == order[-1]: | |
| keys = keys + leftovers | |
| if not keys: | |
| continue | |
| shard_no += 1 | |
| fname = f"model-{shard_no:05d}-of-{total_files:05d}.safetensors" | |
| tensors = {k: self._get(k).to(self.dtype).contiguous() for k in keys} | |
| save_file(tensors, str(dest / fname), metadata={"format": "pt"}) | |
| for k, t in tensors.items(): | |
| weight_map_out[k] = fname | |
| total_size += t.numel() * t.element_size() | |
| del tensors | |
| gc.collect() | |
| (dest / "model.safetensors.index.json").write_text( | |
| json.dumps({"metadata": {"total_size": total_size}, "weight_map": weight_map_out}, indent=1), encoding="utf-8") | |
| for fname in ("config.json", "generation_config.json"): | |
| if (self.model_dir / fname).exists(): | |
| shutil.copy(self.model_dir / fname, dest / fname) | |
| if self.verbose: | |
| print(f" [ring] exported {shard_no} shards ({total_size / 1e9:.2f} GB) -> {dest}") | |
| return dest | |
| def describe(self) -> str: | |
| layers = sorted(int(n[5:]) for n in self.loaded if n.startswith("layer")) | |
| try: | |
| import psutil | |
| rss = psutil.Process().memory_info().rss / 1024 ** 3 | |
| mem = f"{rss:.2f} GiB RSS" | |
| except Exception: | |
| mem = "n/a" | |
| return f"ring: resident layers={layers} pinned={sorted(self.pinned)} | {mem}" |