Views
No views yet

stacks/
├── chat/
│ ├── stack_1.pt # Chat domain, round 1
│ └── stack_2.pt # Chat domain, round 2 (residual)
├── code/
│ ├── stack_1.pt
│ └── stack_2.pt
├── math/
│ ├── stack_1.pt
│ └── stack_2.pt
├── medical/
│ ├── stack_1.pt
│ └── stack_2.pt
└── reasoning/
├── stack_1.pt
└── stack_2.pt
meta_router.pt # ~2M param sigmoid router
manifest.json # Domain block metadata
code/ # Full training + inference codeMoELoRADelta module:StackedMoELoRALayer wrappers, then loading each .pt file into MoELoRADelta modules.1from huggingface_hub import snapshot_download
2import torch, json, os, math
3import torch.nn as nn
4import torch.nn.functional as F
5import bitsandbytes as bnb
6from pathlib import Path
7from transformers import AutoModelForCausalLM, AutoTokenizer, BitsAndBytesConfig
8
9# 1. Download all weights + code
10local_dir = snapshot_download("MohammadAbuAyyash/brainstacks-gemma3-12b-it")
11
12# 2. Load base model (4-bit NF4)
13model = AutoModelForCausalLM.from_pretrained(
14 "google/gemma-3-12b-it",
15 quantization_config=BitsAndBytesConfig(
16 load_in_4bit=True, bnb_4bit_quant_type="nf4",
17 bnb_4bit_compute_dtype=torch.bfloat16, bnb_4bit_use_double_quant=True,
18 ),
19 device_map="auto", torch_dtype=torch.bfloat16,
20)
21tokenizer = AutoTokenizer.from_pretrained("google/gemma-3-12b-it")
22tokenizer.pad_token = tokenizer.eos_token
23device = torch.device("cuda")
24
25# 3. Inject StackedMoELoRALayer into all 7 projections
26# (replaces q/k/v/o/gate/up/down with wrappers that hold frozen stacks)
27# See code/brainstacks_inference.py for full class definitions
28import sys; sys.path.insert(0, os.path.join(local_dir, "code"))
29from brainstacks_inference import (
30 inject_stacked_layers, load_single_stack,
31 MetaRouter, set_domain_weights, clear_domain_weights, set_base_only
32)
33
34model, stacked_layers = inject_stacked_layers(model)
35
36# 4. Load all domain stacks from manifest
37with open(os.path.join(local_dir, "manifest.json")) as f:
38 manifest = json.load(f)
39
40domain_names = []
41for block in manifest["domains"]:
42 name = block["name"]
43 for sf in block["stack_files"]:
44 # Remap paths to local download dir
45 stack_path = os.path.join(local_dir, "stacks", name, os.path.basename(sf))
46 load_single_stack(model, stacked_layers, stack_path, device)
47 domain_names.append(name)
48 print(f" Loaded {name}: {len(block['stack_files'])} stacks")
49
50# Set domain stack counts on all layers
51counts = [len(block["stack_files"]) for block in manifest["domains"]]
52for layer in stacked_layers:
53 layer._domain_stack_counts = counts
54
55# 5. Load meta-router
56ckpt = torch.load(os.path.join(local_dir, "meta_router.pt"), map_location=device, weights_only=False)
57router = MetaRouter(token_dim=ckpt["token_dim"], n_domains=ckpt["n_domains"]).to(device)
58router.load_state_dict(ckpt["state_dict"])
59router.eval()
60
61print(f"Ready: {len(domain_names)} domains, {sum(counts)} stacks/layer")brainstacks_inference.py directly:python brainstacks_inference.py1from brainstacks_inference import DiskOffloadEngine
2
3domain_stack_paths = {}
4for block in manifest["domains"]:
5 name = block["name"]
6 domain_stack_paths[name] = [os.path.join(local_dir, "stacks", name, os.path.basename(sf)) for sf in block["stack_files"]]
7
8# Move stacks to GPU (they were loaded to CPU)
9for layer in stacked_layers:
10 for stack in layer.frozen_stacks:
11 stack.to(device)
12
13engine = DiskOffloadEngine(model, stacked_layers, router, tokenizer,
14 domain_names, domain_stack_paths, device)
15engine._loaded_domains = set(domain_names)
16
17for p in [
18 "Explain what a neural network is in simple terms.",
19 "Write a Python function to check if a number is prime.",
20 "What are the symptoms of type 2 diabetes?",
21 "If a train travels 120km in 2 hours, what is its speed?",
22 "A patient needs 500mg of medication per day split into 3 doses. How many mg per dose?",
23 "Prove that the square root of 2 is irrational.",
24 "Write Python code to calculate BMI given weight and height.",
25 "Explain the difference between type 1 and type 2 diabetes.",
26]:
27 resp, stats = engine.routed_generate(p)
28 print(f"\n> {p}")
29 print(f" Route: [{stats['route']}]")
30 print(f" {resp[:500]}")
31 print("-" * 70)| Domain | ~Samples | Sources |
|---|---|---|
| Chat | 40K | Nemotron v2 chat, UltraFeedback SFT, Daring-Anteater |
| Code | 48K | Python Code Instructions, Nemotron v2 code, OpenCodeReasoning, OpenThoughts |
| Math | 53K | GSM8K, OpenMathReasoning CoT, NuminaMath-CoT, Nemotron v2 math |
| Medical | 20K | MedQA-USMLE, medical-o1-reasoning-SFT, PubMedQA |
| Reasoning | 50K | OpenThoughts-114k, Nemotron v2 STEM, Sky-T1, OpenMathReasoning tool |
| Benchmark | Base | Routed | Delta |
|---|---|---|---|
| HellaSwag | 0.670 | 0.650 | -0.020 |
| ARC-Easy | 0.510 | 0.515 | +0.005 |
| ARC-Challenge | 0.525 | 0.495 | -0.030 |
| TruthfulQA | 0.350 | 0.370 | +0.020 |
| MMLU | 0.450 | 0.435 | -0.015 |
| GSM8K | 0.665 | 0.665 | 0.000 |
| MedQA | 0.385 | 0.350 | -0.035 |
| MedMCQA | 0.330 | 0.360 | +0.030 |
1@article{abuayyash2026brainstacks,
2 title={BrainStacks: Cross-Domain Cognitive Capabilities via Frozen MoE-LoRA Stacks for Continual LLM Learning},
3 author={Abu Ayyash, Mohammad R.},
4 year={2026},
5 institution={Brains Build Research}
6}