AbstractPhil commited on
Commit
9f4bf83
·
verified ·
1 Parent(s): de15adb

serve the full 2s arm library (single, stacked, routed, gain, memory and recurrent arms) with the best-measured arm as default; text-frame arms get their own frame on the specials craft

Browse files
Files changed (5) hide show
  1. README.md +7 -4
  2. app.py +209 -140
  3. arm_mount.py +279 -0
  4. arms_catalog.json +0 -0
  5. requirements.txt +1 -1
README.md CHANGED
@@ -9,7 +9,7 @@ python_version: '3.12'
9
  app_file: app.py
10
  pinned: false
11
  license: mit
12
- short_description: Two byte-level AlephLLM crafts — arms and full splat
13
  ---
14
 
15
  # Beatrix — AlephLLM chat
@@ -23,9 +23,12 @@ adapters (3.2M–5.3M parameters), each trained on one exact frozen core.
23
 
24
  **mini-beatrix-2s** — 237.1M parameters, **full splat**: the signed
25
  address read runs in *every* block (v1 used it in three), governed from
26
- birth so the anchors never crowd. The active mission — still
27
- pretraining, no arms yet, and not yet through the phase that teaches a
28
- conversation frame, so **Completion** is the honest view of it.
 
 
 
29
 
30
  - **Chat** — conversation, in whichever frame the selected craft and arm
31
  were actually trained on.
 
9
  app_file: app.py
10
  pinned: false
11
  license: mit
12
+ short_description: Two byte-level AlephLLM crafts and their arm libraries
13
  ---
14
 
15
  # Beatrix — AlephLLM chat
 
23
 
24
  **mini-beatrix-2s** — 237.1M parameters, **full splat**: the signed
25
  address read runs in *every* block (v1 used it in three), governed from
26
+ birth so the anchors never crowd. Its mission is complete (16.1 billion
27
+ bytes); the closing anneal taught the conversation frame, so the core
28
+ chats on its own. It carries its own **arm library** — single arms,
29
+ stacks, routed dispatches and recurrent arms, each labelled with its
30
+ measured score and how settled it is — and opens on the best-measured
31
+ one.
32
 
33
  - **Chat** — conversation, in whichever frame the selected craft and arm
34
  were actually trained on.
app.py CHANGED
@@ -12,8 +12,11 @@ own config, its own byte format, and its own arm library:
12
  mini-beatrix-2s 237.1M · FULL SPLAT (a governed multi-constellation
13
  aleph read in every block) · the 0.8.0 SPECIALS format:
14
  structural tokens live on the invalid-UTF-8 bytes, so
15
- the frame is unforgeable by content. Arms are read
16
- from the repo for both crafts — 2s has none yet.
 
 
 
17
 
18
  Crafts are discovered from the repo at boot: a craft with no manifest or
19
  no checkpoint is skipped, and one that starts shipping appears on its
@@ -64,10 +67,7 @@ for _mod in list(sys.modules.values()):
64
  from huggingface_hub import HfApi, hf_hub_download
65
  from safetensors.torch import load_file
66
 
67
- import amoe
68
- from amoe.core.adapter import AdapterSpec, RelayPatchwork
69
- from amoe.io.checkpoint import load_anchor
70
- from amoe.runtime.attach import _per_block_state
71
  from geolip.alephllm.presets import AlephLMConfig
72
  from geolip.alephllm.model.alephlm import AlephLM
73
  from geolip.alephllm.amoe_bridge import CHAT_HEADER, USER_TAG, ASSISTANT_TAG
@@ -95,9 +95,8 @@ GEN_BUDGET_S = 95.0
95
  # for it are gated on manifest state (frame_trained) and switched
96
  # themselves off when anneal_mix went done. v1 stays one click away as
97
  # the detach exhibit: a core that does NOT chat plus a 3.2M arm that
98
- # makes it chat, removable bit-for-bit. Both crafts READ the arm index:
99
- # 2s has no arms today, and the day one is trained on a 2s core it
100
- # appears in the picker with no code change.
101
  CRAFTS = [
102
  {"name": "mini-beatrix-1", "fmt": "v1tags", "wants_arms": True},
103
  {"name": "mini-beatrix-2s", "fmt": "specials", "wants_arms": True},
@@ -233,6 +232,20 @@ ALWAYS_OFFER = {"mini-beatrix-2s": [57607]}
233
  DEFAULT_ARM_NAME = {"mini-beatrix-1": "poly"}
234
  N_LISTED = 12 # newest N checkpoints offered in the dropdown
235
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
236
 
237
  def list_cores(files, craft):
238
  """{step: core_path} for every shipped checkpoint of one craft.
@@ -281,19 +294,43 @@ def load_arm_index(files, craft):
281
  else "behavior"),
282
  "behavior": "", "spec": None, "sites": None,
283
  "params": None})
 
 
 
 
 
 
 
 
 
 
 
 
284
  by_step = {}
285
- for r in rows:
286
  by_step.setdefault(int(r["step"]), []).append(r)
287
- for s in by_step: # chat first, then turn-end
288
  order = {"chat": 0, "turn-end": 1, "behavior": 2}
289
- by_step[s].sort(key=lambda r: (order.get(r["kind"], 3),
 
290
  r.get("group", ""), r["name"]))
291
  return by_step
292
 
293
 
 
 
 
 
 
 
 
294
  CHAT_STOPS = ("\nUser:", "\nBeatrix:", "User:", "Beatrix:")
295
  FRAME_TAG = {"chat": "chat transcript", "qa": "single-turn Q&A",
296
- "raw": "raw text (no frame)"}
 
 
 
 
297
 
298
 
299
  def _tmpl(arm):
@@ -311,6 +348,9 @@ def _tmpl(arm):
311
 
312
 
313
  def _arm_title(a):
 
 
 
314
  who = f"{a['group']}/{a['name']}" if a.get("group") else a["name"]
315
  t = _tmpl(a)
316
  bits = [who, FRAME_TAG.get(t["frame"], t["frame"])]
@@ -324,11 +364,12 @@ def _arm_title(a):
324
  return " · ".join(bits)
325
 
326
 
327
- def _verify_anchor(local_arm, craft, step):
328
  """amoe's strict= check is inert for AlephLM (no model.config), so
329
- provenance is asserted here from the anchor's own metadata."""
 
330
  try:
331
- got = load_anchor(local_arm).meta.get("base_model_id")
332
  except Exception:
333
  return False
334
  want = f"alephllm/{craft}@step{step}"
@@ -339,19 +380,16 @@ def _verify_anchor(local_arm, craft, step):
339
  return True
340
 
341
 
342
- def _spec_of(ck):
343
- """Read the adapter geometry from the anchor's OWN tensors. The arm
344
- library holds more than one shape (n_slots 16 and 32, hidden 178 and
345
- 256), and amoe builds its modules from a spec before loading state —
346
- assuming the default would raise on every wide arm."""
347
- cb, proj = ck.adapters.get("0.addr.codebook"), ck.adapters.get(
348
- "0.proj.weight")
349
- cons = ck.adapters.get("0.consume.0.weight")
350
- if cb is None or proj is None or cons is None:
351
- return AdapterSpec()
352
- d = int(cb.shape[1])
353
- return AdapterSpec(n_slots=int(proj.shape[0] // d), K=int(cb.shape[0]),
354
- D=d, hidden=int(cons.shape[0]))
355
 
356
 
357
  class Craft:
@@ -454,42 +492,28 @@ class Craft:
454
  self.model.eval()
455
  self.core_params = self.model.param_count()
456
 
457
- # attach ONCE so the adapter sites exist and ZeroGPU packs them;
458
- # the template is THIS checkpoint's own default arm when it has
459
- # one, so the common path needs no rebuild. Selecting an arm of
460
- # another geometry rebuilds the site modules for that request.
461
- self.wrappers, spec_now = [], None
462
- tmpl = self.default_arm(self.step) or next(iter(self.arm_by_path),
463
- None)
464
- if tmpl:
465
- local = hf_hub_download(REPO, tmpl)
466
- if _verify_anchor(local, self.name, self.arm_by_path[tmpl]["step"]):
467
- ck = load_anchor(local)
468
- spec_now = _spec_of(ck)
469
- amoe.attach(self.model, ck, spec=spec_now, strict=False)
470
- self.wrappers = [b for b in self.model.blocks
471
- if hasattr(b, "adapter")]
472
- print(f"[boot] {self.name}: adapter sites "
473
- f"{len(self.wrappers)} (template "
474
- f"{tmpl.split('/')[-1]}, n_slots={spec_now.n_slots}, "
475
- f"hidden={spec_now.hidden})", flush=True)
476
-
477
- # core-key -> live-key map: attach wraps blocks, so a core
478
- # checkpoint's "blocks.N.*" lands at "blocks.N.block.*".
479
  self.live = dict(self.model.named_parameters())
480
  self.live.update(dict(self.model.named_buffers()))
481
- self.keymap = {}
482
- for k in sd:
483
- if k in self.live:
484
- self.keymap[k] = k
485
- else:
486
- alt = re.sub(r"^blocks\.(\d+)\.", r"blocks.\1.block.", k)
487
- if alt in self.live:
488
- self.keymap[k] = alt
 
 
 
 
 
 
 
489
  self.model.to("cuda") # ZeroGPU packs here (standard pattern)
490
- self.loaded = {"step": self.step,
491
- "arm_path": tmpl if self.wrappers else None,
492
- "spec": spec_now}
493
  print(f"[boot] {self.name}: {len(self.cores)} cores, "
494
  f"{len(self.arm_by_path)} arms, {self.core_params/1e6:.1f}M "
495
  f"core, ctx {self.cfg.context}, fmt {self.fmt}", flush=True)
@@ -512,6 +536,10 @@ class Craft:
512
  so nothing is misrepresented as a chat arm."""
513
  step = int(step)
514
  arms = self.arms.get(step, [])
 
 
 
 
515
  want = DEFAULT_ARM_NAME.get(self.name)
516
  if want and step == getattr(self, "step", None):
517
  for a in arms:
@@ -644,7 +672,25 @@ def _select(craft, step, arm_path):
644
  c = S(craft)
645
  step = _step(c, step) # stale/typed values fall back
646
  t0 = time.time()
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
647
  if c.loaded["step"] != step:
 
648
  sd = load_file(hf_hub_download(REPO, c.cores[step]))
649
  with torch.no_grad():
650
  for k, v in sd.items():
@@ -652,52 +698,16 @@ def _select(craft, step, arm_path):
652
  if tgt is not None and tgt.shape == v.shape:
653
  tgt.copy_(v.to(tgt.device, tgt.dtype))
654
  c.loaded["step"] = step
655
-
656
- # an arm belongs to exactly one core: a stale pick from another
657
- # checkpoint (or another craft) is dropped rather than force-fitted
658
- arm = _resolve_arm(c, arm_path, step)
659
- if arm is None:
660
- arm_path = CORE_ONLY
661
- arm_on = bool(c.wrappers) and bool(arm)
662
- if arm_on and c.loaded.get("arm_path") != arm_path:
663
- local = hf_hub_download(REPO, arm_path)
664
- if _verify_anchor(local, c.name, step): # provenance, every switch
665
- ck = load_anchor(local)
666
- spec = _spec_of(ck)
667
- dev = next(c.model.parameters()).device
668
- # INVALIDATE FIRST, COMMIT LAST. This state survives the
669
- # request (a ZeroGPU worker is reused, not forked per call),
670
- # so a partial load must never be recorded as a complete
671
- # one: if the loop below raises, the wrappers hold a mix of
672
- # two arms, and a loaded[arm_path] still naming the old arm
673
- # would make the next request skip the reload and serve the
674
- # chimera under the wrong provenance label.
675
- prev_spec = c.loaded["spec"]
676
- c.loaded["arm_path"] = None
677
- if (spec.n_slots, spec.K, spec.D, spec.hidden) != (
678
- prev_spec.n_slots, prev_spec.K,
679
- prev_spec.D, prev_spec.hidden):
680
- # different adapter geometry: rebuild the site modules
681
- # for this request rather than forcing mismatched state
682
- d_hidden = int(ck.adapters["0.proj.weight"].shape[1])
683
- for w in c.wrappers:
684
- w.adapter = RelayPatchwork(d_hidden, spec).to(dev)
685
- c.loaded["spec"] = spec
686
- with torch.no_grad():
687
- for i, w in enumerate(c.wrappers):
688
- st = _per_block_state(ck.adapters, i)
689
- if st:
690
- w.adapter.load_state_dict(
691
- {k: v.to(next(w.adapter.parameters()).device)
692
- for k, v in st.items()})
693
- c.loaded["arm_path"] = arm_path # commit only now
694
- else:
695
- arm_on, arm = False, None
696
- for w in c.wrappers:
697
- w.enabled = arm_on
698
  return {"craft": c.name, "checkpoint_step": step,
699
- "arm": (arm_path.split("/")[-1] if arm_on else None),
700
  "arm_kind": (arm["kind"] if arm_on else "core-only"),
 
701
  "switch_s": round(time.time() - t0, 2)}
702
 
703
 
@@ -716,22 +726,29 @@ def status_md(craft, step, arm_path=CORE_ONLY):
716
  "`⟦SYS⟧ ⟦USER⟧ ⟦MODEL⟧ ⟦END⟧` frame a conversation. "
717
  "They live on bytes UTF-8 can never produce, so "
718
  "nothing you type can forge them.")
719
- elif not c.wrappers:
720
- arm_line = "**Arm:** adapter sites unavailable — core only"
721
  elif arm:
722
  sp = arm.get("spec") or {}
723
  t = _tmpl(arm)
724
- dt, dp, _ = _decode_of(arm)
 
725
  arm_line = (
726
  f"**Arm** `{arm['name']}`"
727
  + (f" ({arm['group']})" if arm.get("group") else "")
728
  + (f" · {arm['params']/1e6:.1f}M" if arm.get("params") else "")
729
  + (f" · {arm['sites']} sites" if arm.get("sites") else "")
730
- + (f" · n{sp['n_slots']}/h{sp['hidden']}" if sp else "")
 
 
731
  + " · trained on THIS core"
 
 
732
  + f" \n{FRAME_TAG.get(t['frame'], t['frame'])} · ends on "
733
  f"{t['turn_end']} · T={dt:g}/top-p {dp:g}"
 
 
 
734
  + (f" · *{arm['behavior']}*" if arm.get("behavior") else "")
 
735
  + (f" \n⚠️ {t['note']}" if t.get("note") else ""))
736
  else:
737
  arm_line = ("**Arm** none attached — raw core"
@@ -789,11 +806,17 @@ def status_md(craft, step, arm_path=CORE_ONLY):
789
  "conversational adapter"
790
  if arms and not any(a["kind"] == "chat" for a in arms)
791
  and (arm is None or arm["kind"] not in ("chat", "turn-end"))
792
- else ""),
 
 
 
 
 
793
  ("ℹ️ this arm was trained on a **single-turn** frame, so Chat sends "
794
  "one question at a time (no history) — that is the frame it "
795
  "learned; the Completion tab is the plainer view"
796
- if arm and _tmpl(arm)["frame"] == "qa" else ""),
 
797
  ("⚠️ this is a **representation** arm with no turn convention: it "
798
  "was trained on raw lines, not conversations. Use Completion — "
799
  "Chat will not read as dialogue"
@@ -815,10 +838,27 @@ CORE_EX = [["Hello!"], ["Who are you?"], ["What can you do?"],
815
  ["How are you today?"], ["Tell me about books."]]
816
 
817
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
818
  def _decode_of(arm):
 
 
 
819
  d = (arm or {}).get("decode") or {}
820
  return (float(d.get("temperature", 0.7)), float(d.get("top_p", 0.95)),
821
- d.get("why", ""))
822
 
823
 
824
  def _examples_of(arm):
@@ -834,10 +874,11 @@ def on_arm(craft, step, arm_path, auto_decode, fam_examples):
834
  switchable — the checkboxes leave the controls alone when off."""
835
  c = S(craft)
836
  arm = _resolve_arm(c, arm_path, _step(c, step))
837
- t, p, _ = _decode_of(arm)
838
  return (status_md(craft, step, arm_path),
839
  gr.update(value=t) if auto_decode else gr.update(),
840
  gr.update(value=p) if auto_decode else gr.update(),
 
841
  gr.update(samples=_examples_of(arm)) if fam_examples
842
  else gr.update())
843
 
@@ -990,6 +1031,9 @@ def _stream(craft, ids, max_new, temperature, top_p, use_cache, arm_path,
990
  c = S(craft)
991
  model = c.model
992
  dev = next(model.parameters()).device
 
 
 
993
  # The no-cache path recomputes the WHOLE context per byte, so on the
994
  # bigger craft it is minutes where the ZeroGPU budget is 120s. This
995
  # used to be a silent max_new = min(max_new, 96): the slider said 512
@@ -1011,13 +1055,14 @@ def _stream(craft, ids, max_new, temperature, top_p, use_cache, arm_path,
1011
  label = (f"{prov['craft']} · step {prov['checkpoint_step']:,} · "
1012
  + (f"arm `{prov['arm'].split('@')[0]}`" if prov["arm"]
1013
  else "core only")
 
1014
  + (f" · switched in {prov['switch_s']}s"
1015
  if prov["switch_s"] > 0.05 else ""))
 
1016
  with torch.no_grad():
1017
  cache, prefill_s = None, 0.0
1018
  if use_cache:
1019
- with torch.autocast("cuda", dtype=torch.bfloat16,
1020
- enabled=dev.type == "cuda"):
1021
  logits, cache = model.prefill(tids)
1022
  prefill_s = time.time() - t0
1023
  t1 = time.time()
@@ -1031,8 +1076,7 @@ def _stream(craft, ids, max_new, temperature, top_p, use_cache, arm_path,
1031
  nxt = model._sample(_rep_penalty(logits, out, rep),
1032
  temperature, top_p)
1033
  else:
1034
- with torch.autocast("cuda", dtype=torch.bfloat16,
1035
- enabled=dev.type == "cuda"):
1036
  fl, _ = model(tids[:, -c.cfg.context:])
1037
  nxt = model._sample(_rep_penalty(fl, out, rep),
1038
  temperature, top_p)
@@ -1057,8 +1101,7 @@ def _stream(craft, ids, max_new, temperature, top_p, use_cache, arm_path,
1057
  return
1058
  out.append(nid)
1059
  if use_cache:
1060
- with torch.autocast("cuda", dtype=torch.bfloat16,
1061
- enabled=dev.type == "cuda"):
1062
  logits = model.decode_step(nxt, cache)
1063
  text = _render(out, c.fmt)
1064
  cut = min((text.index(s) for s in stop if s in text),
@@ -1192,20 +1235,28 @@ def chat(craft, message, history, max_new, temperature, top_p, use_cache,
1192
  return
1193
  c = S(craft)
1194
  step_i = _step(c, ckpt_step)
1195
- # On a plain-text craft the tags ARE the syntax, so a message
1196
- # containing "User:" has to be defanged. On a specials craft the
1197
- # frame lives on bytes text cannot contain, so the message needs no
1198
- # mangling — defanging it there would contradict the guarantee the
1199
- # status panel makes and quietly edit what the visitor typed.
1200
- clean = _clean_turn if c.fmt != "specials" else (
 
 
 
 
 
 
 
 
 
1201
  lambda s: " ".join(str(s).split()))
1202
  message = clean(message)
1203
  history = [{"role": t["role"], "content": clean(_text(t["content"]))}
1204
  for t in (history or [])]
1205
- tmpl = _tmpl(_resolve_arm(c, arm_path, step_i))
1206
  stops, stop_ids = (), ()
1207
  room = _room(c.cfg.context, max_new)
1208
- if c.fmt == "specials":
1209
  # the frame's own terminators, as ids: END closes the turn, DOC
1210
  # means she started a new document instead of answering. Built
1211
  # to the SAME budget _fit enforces, so _fit never has to cut a
@@ -1213,6 +1264,8 @@ def chat(craft, message, history, max_new, temperature, top_p, use_cache,
1213
  ids = _specials_chat_ids(history, message, c.cfg.context, room)
1214
  stop_ids = (SP.END, SP.DOC, SP.USER)
1215
  else:
 
 
1216
  # the SELECTED arm's own frame and turn-end bytes, not one
1217
  # hardcoded chat format: a Q&A arm never saw a transcript, and a
1218
  # newline-pair arm's terminator is invisible to the "User:" stops
@@ -1235,7 +1288,7 @@ def chat(craft, message, history, max_new, temperature, top_p, use_cache,
1235
  "teaches the conversation frame — it has only ever read "
1236
  "documents. The Completion tab shows what it can do "
1237
  "today.)*")
1238
- elif tmpl["frame"] == "qa":
1239
  empty = ("*(this arm ended the turn immediately — it was trained "
1240
  "on single-turn task prompts, not conversation. Try one "
1241
  "of its examples below, or switch arms.)*")
@@ -1291,10 +1344,24 @@ address read runs in *every* block (v1 used it in three), with a
1291
  governor holding the anchors apart from birth. Its mission is
1292
  **complete** — 16.1 billion bytes over 61,422 steps, closing with a
1293
  two-phase anneal that taught the conversation frame, so this core
1294
- **chats on its own**: no arm is required, and none have been trained on
1295
- it yet. Its format is specials-native — SYS/USER/MODEL/END are single
1296
- reserved bytes rather than typed text, so the turn frame cannot be
1297
- forged by anything you type.
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1298
 
1299
  **mini-beatrix-1** — 112.5M parameters, pretrained on 15.3 billion raw
1300
  bytes, carrying a **library of detachable arms**: small adapters
@@ -1405,14 +1472,15 @@ with gr.Blocks(title="Beatrix — AlephLLM chat") as demo:
1405
  # auto-decode only fires on a change event, so a default arm that
1406
  # asks for greedy was otherwise served sampled on first paint —
1407
  # the exact setting its metadata says degenerates
1408
- _dt, _dp, _ = _decode_of(_C0.arm_by_path.get(_C0.default_arm(STEP)))
 
1409
  temperature = gr.Slider(0.0, 1.5, value=_dt, step=0.05,
1410
  label="Temperature")
1411
  top_p = gr.Slider(0.1, 1.0, value=_dp, step=0.05, label="Top-p")
1412
  # byte-level: this damps whatever would CONTINUE a repeated
1413
  # 8-byte phrase, not every byte already seen — on a 256-value
1414
  # vocabulary the textbook form would just tax ordinary English
1415
- rep = gr.Slider(1.0, 2.0, value=1.15, step=0.05,
1416
  label="Repetition penalty",
1417
  info="damps bytes that would repeat a recent "
1418
  "8-byte phrase · 1.0 = off")
@@ -1420,8 +1488,8 @@ with gr.Blocks(title="Beatrix — AlephLLM chat") as demo:
1420
  with gr.Accordion("Automation", open=False), gr.Row():
1421
  auto_decode = gr.Checkbox(
1422
  value=True, label="Auto decode per arm",
1423
- info="task arms switch to greedy on attach — they degenerate "
1424
- "into punctuation when sampled off-distribution")
1425
  fam_examples = gr.Checkbox(
1426
  value=True, label="Arm-family examples",
1427
  info="offer prompts from the selected arm's own training "
@@ -1499,13 +1567,14 @@ with gr.Blocks(title="Beatrix — AlephLLM chat") as demo:
1499
  # or nothing); decode and examples then follow the ARM, unless their
1500
  # toggles say otherwise
1501
  craft_pick.change(on_craft, [craft_pick, auto_decode, fam_examples],
1502
- [ckpt, arm_pick, status_box, temperature, top_p,
1503
  ex.dataset])
1504
  ckpt.change(on_checkpoint, [craft_pick, ckpt, auto_decode, fam_examples],
1505
- [ckpt, arm_pick, status_box, temperature, top_p, ex.dataset])
 
1506
  arm_pick.change(on_arm,
1507
  [craft_pick, ckpt, arm_pick, auto_decode, fam_examples],
1508
- [status_box, temperature, top_p, ex.dataset])
1509
  demo.load(js=RESIZE_JS)
1510
 
1511
  demo.launch()
 
12
  mini-beatrix-2s 237.1M · FULL SPLAT (a governed multi-constellation
13
  aleph read in every block) · the 0.8.0 SPECIALS format:
14
  structural tokens live on the invalid-UTF-8 bytes, so
15
+ the frame is unforgeable by content. Its arm library
16
+ holds several recipe types (single arms, stacks,
17
+ routed dispatches, recurrent arms); arm_mount.py
18
+ attaches any of them and detaches back to the bare
19
+ core, and arms_catalog.json describes each one.
20
 
21
  Crafts are discovered from the repo at boot: a craft with no manifest or
22
  no checkpoint is skipped, and one that starts shipping appears on its
 
67
  from huggingface_hub import HfApi, hf_hub_download
68
  from safetensors.torch import load_file
69
 
70
+ import arm_mount
 
 
 
71
  from geolip.alephllm.presets import AlephLMConfig
72
  from geolip.alephllm.model.alephlm import AlephLM
73
  from geolip.alephllm.amoe_bridge import CHAT_HEADER, USER_TAG, ASSISTANT_TAG
 
95
  # for it are gated on manifest state (frame_trained) and switched
96
  # themselves off when anneal_mix went done. v1 stays one click away as
97
  # the detach exhibit: a core that does NOT chat plus a 3.2M arm that
98
+ # makes it chat, removable bit-for-bit. Both crafts READ the arm index;
99
+ # 2s also reads arms_catalog.json, which overlays it.
 
100
  CRAFTS = [
101
  {"name": "mini-beatrix-1", "fmt": "v1tags", "wants_arms": True},
102
  {"name": "mini-beatrix-2s", "fmt": "specials", "wants_arms": True},
 
232
  DEFAULT_ARM_NAME = {"mini-beatrix-1": "poly"}
233
  N_LISTED = 12 # newest N checkpoints offered in the dropdown
234
 
235
+ # Space-side arm catalog (built from the training ledgers). For a craft it
236
+ # lists, its rows REPLACE the hub index rows with the same path and add
237
+ # the arms the hub index does not carry yet: stacks, routed dispatches,
238
+ # recurrent arms. Each row names its mount recipe, frame, decode, status
239
+ # and score, and at most one row per craft is marked the default — the
240
+ # best-measured arm on that craft's default checkpoint.
241
+ CATALOG_PATH = Path(__file__).with_name("arms_catalog.json")
242
+ try:
243
+ CATALOG = json.load(open(CATALOG_PATH, encoding="utf-8"))["crafts"]
244
+ except (OSError, ValueError, KeyError) as e:
245
+ print(f"[boot] no arm catalog ({type(e).__name__}) — hub index only",
246
+ flush=True)
247
+ CATALOG = {}
248
+
249
 
250
  def list_cores(files, craft):
251
  """{step: core_path} for every shipped checkpoint of one craft.
 
294
  else "behavior"),
295
  "behavior": "", "spec": None, "sites": None,
296
  "params": None})
297
+ over = (CATALOG.get(craft) or {}).get("rows") or []
298
+ if over:
299
+ mine = {r["path"] for r in over}
300
+ rows = [r for r in rows if r["path"] not in mine] + list(over)
301
+ # an arm is listed only when every file it mounts is on the hub:
302
+ # an index row can outlive its upload, and picking it would fail
303
+ # inside the GPU call instead of simply not being offered
304
+ present = set(files)
305
+ kept = [r for r in rows if all(p in present for p in _arm_files(r))]
306
+ if len(kept) < len(rows):
307
+ print(f"[boot] {craft}: {len(rows) - len(kept)} indexed arm(s) have "
308
+ "no file on the hub — not offered", flush=True)
309
  by_step = {}
310
+ for r in kept:
311
  by_step.setdefault(int(r["step"]), []).append(r)
312
+ for s in by_step: # catalog rank first, then chat, turn-end, behavior
313
  order = {"chat": 0, "turn-end": 1, "behavior": 2}
314
+ by_step[s].sort(key=lambda r: (r.get("rank", 99),
315
+ order.get(r["kind"], 3),
316
  r.get("group", ""), r["name"]))
317
  return by_step
318
 
319
 
320
+ def _arm_files(arm):
321
+ """The hub files one arm row mounts: its own checkpoint, or a stack's
322
+ members (a stack has no file of its own)."""
323
+ m = arm.get("mount") or {}
324
+ return list(m["members"]) if m.get("type") == "stack" else [arm["path"]]
325
+
326
+
327
  CHAT_STOPS = ("\nUser:", "\nBeatrix:", "User:", "Beatrix:")
328
  FRAME_TAG = {"chat": "chat transcript", "qa": "single-turn Q&A",
329
+ "text": "single-turn Q&A", "raw": "raw text (no frame)",
330
+ "specials": "specials frame"}
331
+ # frames whose prompt is ONE plain-text question (no history): "qa" is the
332
+ # v1 name and "text" the 2s ladder's name for the same bytes
333
+ SINGLE_TURN = ("qa", "text", "raw")
334
 
335
 
336
  def _tmpl(arm):
 
348
 
349
 
350
  def _arm_title(a):
351
+ if a.get("title"):
352
+ return a["title"] + (f" · {a['params']/1e6:.1f}M" if a.get("params")
353
+ else "")
354
  who = f"{a['group']}/{a['name']}" if a.get("group") else a["name"]
355
  t = _tmpl(a)
356
  bits = [who, FRAME_TAG.get(t["frame"], t["frame"])]
 
364
  return " · ".join(bits)
365
 
366
 
367
+ def _verify_arm(local_arm, craft, step):
368
  """amoe's strict= check is inert for AlephLM (no model.config), so
369
+ provenance is asserted here from the arm file's own metadata — every
370
+ format carries it (anchor, dispatch, relay-EMA, recurrent)."""
371
  try:
372
+ got = arm_mount.base_model_id(local_arm)
373
  except Exception:
374
  return False
375
  want = f"alephllm/{craft}@step{step}"
 
380
  return True
381
 
382
 
383
+ def _mount(c, arm, step):
384
+ """Download, verify and attach one arm row to the BARE model. Returns
385
+ the handle, or None when any file fails provenance. Adapter geometry
386
+ is read from each file's own tensors (the library holds more than one
387
+ shape), so nothing is assumed from a default spec."""
388
+ local = [hf_hub_download(REPO, p) for p in _arm_files(arm)]
389
+ if not all(_verify_arm(p, c.name, step) for p in local):
390
+ return None
391
+ return arm_mount.mount(c.model, arm.get("mount") or {"type": "anchor"},
392
+ local[0], local)
 
 
 
393
 
394
 
395
  class Craft:
 
492
  self.model.eval()
493
  self.core_params = self.model.param_count()
494
 
495
+ # core-key -> live-tensor map, taken on the BARE model: a core
496
+ # reload always detaches the arm first, and detach restores these
497
+ # very block objects, so the map stays valid across every switch.
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
498
  self.live = dict(self.model.named_parameters())
499
  self.live.update(dict(self.model.named_buffers()))
500
+ self.keymap = {k: k for k in sd if k in self.live}
501
+
502
+ # the default arm is mounted at import so the common first request
503
+ # needs no switch; every other arm mounts inside the GPU call.
504
+ # One handle at a time: an arm switch detaches back to the bare
505
+ # model before the next recipe attaches (recipes differ in shape —
506
+ # a stack, a routed dispatch and a recurrent arm share no sites).
507
+ self.handle, arm_now = None, None
508
+ want = self.default_arm(self.step)
509
+ if want:
510
+ self.handle = _mount(self, self.arm_by_path[want], self.step)
511
+ if self.handle is not None:
512
+ arm_now = want
513
+ print(f"[boot] {self.name}: default arm "
514
+ f"{want.split('/')[-1]} mounted", flush=True)
515
  self.model.to("cuda") # ZeroGPU packs here (standard pattern)
516
+ self.loaded = {"step": self.step, "arm_path": arm_now}
 
 
517
  print(f"[boot] {self.name}: {len(self.cores)} cores, "
518
  f"{len(self.arm_by_path)} arms, {self.core_params/1e6:.1f}M "
519
  f"core, ctx {self.cfg.context}, fmt {self.fmt}", flush=True)
 
536
  so nothing is misrepresented as a chat arm."""
537
  step = int(step)
538
  arms = self.arms.get(step, [])
539
+ if step == getattr(self, "step", None):
540
+ for a in arms: # the catalog's measured best
541
+ if a.get("default"):
542
+ return a["path"]
543
  want = DEFAULT_ARM_NAME.get(self.name)
544
  if want and step == getattr(self, "step", None):
545
  for a in arms:
 
672
  c = S(craft)
673
  step = _step(c, step) # stale/typed values fall back
674
  t0 = time.time()
675
+ # an arm belongs to exactly one core: a stale pick from another
676
+ # checkpoint (or another craft) is dropped rather than force-fitted
677
+ arm = _resolve_arm(c, arm_path, step)
678
+ want = arm["path"] if arm else None
679
+
680
+ # INVALIDATE FIRST, COMMIT LAST. This state survives the request (a
681
+ # ZeroGPU worker is reused, not forked per call), so a half-finished
682
+ # switch must never be recorded as a complete one. Any change of core
683
+ # or arm starts from the bare model: the handle is dropped and its
684
+ # bookkeeping cleared BEFORE detach, so if anything below raises, the
685
+ # next request finds "no arm loaded" and rebuilds rather than serving
686
+ # a stale mount under a new label. Core only = fully detached, so off
687
+ # is the untouched base model.
688
+ if c.handle is not None and (c.loaded["step"] != step
689
+ or c.loaded["arm_path"] != want):
690
+ h, c.handle, c.loaded["arm_path"] = c.handle, None, None
691
+ h.detach(verify=False)
692
  if c.loaded["step"] != step:
693
+ c.loaded["step"] = None
694
  sd = load_file(hf_hub_download(REPO, c.cores[step]))
695
  with torch.no_grad():
696
  for k, v in sd.items():
 
698
  if tgt is not None and tgt.shape == v.shape:
699
  tgt.copy_(v.to(tgt.device, tgt.dtype))
700
  c.loaded["step"] = step
701
+ if arm is not None and c.handle is None:
702
+ c.handle = _mount(c, arm, step) # provenance, every switch
703
+ if c.handle is not None:
704
+ c.loaded["arm_path"] = want # commit only now
705
+ arm_on = arm is not None and c.handle is not None
706
+ fp32 = arm_on and (arm.get("decode") or {}).get("precision") == "fp32"
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
707
  return {"craft": c.name, "checkpoint_step": step,
708
+ "arm": (want.split("/")[-1] if arm_on else None),
709
  "arm_kind": (arm["kind"] if arm_on else "core-only"),
710
+ "precision": "fp32" if fp32 else "bf16",
711
  "switch_s": round(time.time() - t0, 2)}
712
 
713
 
 
726
  "`⟦SYS⟧ ⟦USER⟧ ⟦MODEL⟧ ⟦END⟧` frame a conversation. "
727
  "They live on bytes UTF-8 can never produce, so "
728
  "nothing you type can forge them.")
 
 
729
  elif arm:
730
  sp = arm.get("spec") or {}
731
  t = _tmpl(arm)
732
+ dt, dp, dr = _decode_of(arm)
733
+ kind = (arm.get("mount") or {}).get("type", "anchor")
734
  arm_line = (
735
  f"**Arm** `{arm['name']}`"
736
  + (f" ({arm['group']})" if arm.get("group") else "")
737
  + (f" · {arm['params']/1e6:.1f}M" if arm.get("params") else "")
738
  + (f" · {arm['sites']} sites" if arm.get("sites") else "")
739
+ + (f" · n{sp['n_slots']}/h{sp['hidden']}"
740
+ if sp and kind == "anchor" else "")
741
+ + (f" · {MOUNT_TAG.get(kind, kind)}" if kind != "anchor" else "")
742
  + " · trained on THIS core"
743
+ + (f" \n**{arm['status_word']}** · {arm['score']}"
744
+ if arm.get("score") else "")
745
  + f" \n{FRAME_TAG.get(t['frame'], t['frame'])} · ends on "
746
  f"{t['turn_end']} · T={dt:g}/top-p {dp:g}"
747
+ + (f"/rep {dr:g}" if dr != 1.15 else "")
748
+ + (" · fp32" if (arm.get("decode") or {}).get("precision")
749
+ == "fp32" else "")
750
  + (f" · *{arm['behavior']}*" if arm.get("behavior") else "")
751
+ + (f" \nℹ️ {arm['note']}" if arm.get("note") else "")
752
  + (f" \n⚠️ {t['note']}" if t.get("note") else ""))
753
  else:
754
  arm_line = ("**Arm** none attached — raw core"
 
806
  "conversational adapter"
807
  if arms and not any(a["kind"] == "chat" for a in arms)
808
  and (arm is None or arm["kind"] not in ("chat", "turn-end"))
809
+ and not (c.fmt == "specials" and c.chats(step)) else ""),
810
+ ("ℹ️ this arm was trained on a **single-turn** frame, so Chat sends "
811
+ "one question at a time (no history) — that is the frame it "
812
+ "learned. *Core only* keeps the whole conversation"
813
+ if arm and _tmpl(arm)["frame"] in SINGLE_TURN
814
+ and c.fmt == "specials" else ""),
815
  ("ℹ️ this arm was trained on a **single-turn** frame, so Chat sends "
816
  "one question at a time (no history) — that is the frame it "
817
  "learned; the Completion tab is the plainer view"
818
+ if arm and _tmpl(arm)["frame"] in SINGLE_TURN
819
+ and c.fmt != "specials" else ""),
820
  ("⚠️ this is a **representation** arm with no turn convention: it "
821
  "was trained on raw lines, not conversations. Use Completion — "
822
  "Chat will not read as dialogue"
 
838
  ["How are you today?"], ["Tell me about books."]]
839
 
840
 
841
+ MOUNT_TAG = {"stack": "stacked arms (always on)",
842
+ "routed": "routed dispatch", "relay_ema": "arm + byte memory",
843
+ "recurrent": "recurrent arm"}
844
+ STATUS_WORD = {"best": "★ best trained", "settled": "replicated (two seeds)",
845
+ "one-seed": "one seed", "candidate": "candidate",
846
+ "refuted": "refuted", "control": "control row",
847
+ "superseded": "superseded", "in-progress": "still training",
848
+ "seed-unstable": "unstable across seeds",
849
+ "null": "no measured gain"}
850
+ for _c in CATALOG.values():
851
+ for _r in _c.get("rows", []):
852
+ _r["status_word"] = STATUS_WORD.get(_r.get("status"), _r.get("status"))
853
+
854
+
855
  def _decode_of(arm):
856
+ """(temperature, top_p, repetition penalty) an arm asks for. Task arms
857
+ are measured greedy with no repetition penalty; the penalty slider's
858
+ 1.15 default belongs to open chat on the bare core."""
859
  d = (arm or {}).get("decode") or {}
860
  return (float(d.get("temperature", 0.7)), float(d.get("top_p", 0.95)),
861
+ float(d.get("rep", 1.15)))
862
 
863
 
864
  def _examples_of(arm):
 
874
  switchable — the checkboxes leave the controls alone when off."""
875
  c = S(craft)
876
  arm = _resolve_arm(c, arm_path, _step(c, step))
877
+ t, p, r = _decode_of(arm)
878
  return (status_md(craft, step, arm_path),
879
  gr.update(value=t) if auto_decode else gr.update(),
880
  gr.update(value=p) if auto_decode else gr.update(),
881
+ gr.update(value=r) if auto_decode else gr.update(),
882
  gr.update(samples=_examples_of(arm)) if fam_examples
883
  else gr.update())
884
 
 
1031
  c = S(craft)
1032
  model = c.model
1033
  dev = next(model.parameters()).device
1034
+ # arms decode in fp32, the precision every arm score was measured in;
1035
+ # bf16 autocast stays the bare core's fast path
1036
+ ac = dev.type == "cuda" and prov.get("precision") != "fp32"
1037
  # The no-cache path recomputes the WHOLE context per byte, so on the
1038
  # bigger craft it is minutes where the ZeroGPU budget is 120s. This
1039
  # used to be a silent max_new = min(max_new, 96): the slider said 512
 
1055
  label = (f"{prov['craft']} · step {prov['checkpoint_step']:,} · "
1056
  + (f"arm `{prov['arm'].split('@')[0]}`" if prov["arm"]
1057
  else "core only")
1058
+ + (" · fp32" if prov.get("precision") == "fp32" else "")
1059
  + (f" · switched in {prov['switch_s']}s"
1060
  if prov["switch_s"] > 0.05 else ""))
1061
+ getattr(c.handle, "reset_state", lambda: None)() # fresh context
1062
  with torch.no_grad():
1063
  cache, prefill_s = None, 0.0
1064
  if use_cache:
1065
+ with torch.autocast("cuda", dtype=torch.bfloat16, enabled=ac):
 
1066
  logits, cache = model.prefill(tids)
1067
  prefill_s = time.time() - t0
1068
  t1 = time.time()
 
1076
  nxt = model._sample(_rep_penalty(logits, out, rep),
1077
  temperature, top_p)
1078
  else:
1079
+ with torch.autocast("cuda", dtype=torch.bfloat16, enabled=ac):
 
1080
  fl, _ = model(tids[:, -c.cfg.context:])
1081
  nxt = model._sample(_rep_penalty(fl, out, rep),
1082
  temperature, top_p)
 
1101
  return
1102
  out.append(nid)
1103
  if use_cache:
1104
+ with torch.autocast("cuda", dtype=torch.bfloat16, enabled=ac):
 
1105
  logits = model.decode_step(nxt, cache)
1106
  text = _render(out, c.fmt)
1107
  cut = min((text.index(s) for s in stop if s in text),
 
1235
  return
1236
  c = S(craft)
1237
  step_i = _step(c, ckpt_step)
1238
+ arm = _resolve_arm(c, arm_path, step_i)
1239
+ tmpl = _tmpl(arm)
1240
+ # The prompt is built in the frame the ARM was trained on. On the
1241
+ # specials craft that is the specials frame for the bare core, but a
1242
+ # single-turn text arm learned the plain-text tags — serving it the
1243
+ # specials frame is a different tokenizer, and it answers as if never
1244
+ # trained. (ARM TEMPLATE LAW: the template is the tokenizer.)
1245
+ specials_frame = c.fmt == "specials" and (
1246
+ arm is None or tmpl["frame"] not in SINGLE_TURN)
1247
+ # Where plain-text tags ARE the syntax, a message containing "User:"
1248
+ # has to be defanged. In the specials frame the structure lives on
1249
+ # bytes text cannot contain, so the message needs no mangling —
1250
+ # defanging it there would contradict the guarantee the status panel
1251
+ # makes and quietly edit what the visitor typed.
1252
+ clean = _clean_turn if not specials_frame else (
1253
  lambda s: " ".join(str(s).split()))
1254
  message = clean(message)
1255
  history = [{"role": t["role"], "content": clean(_text(t["content"]))}
1256
  for t in (history or [])]
 
1257
  stops, stop_ids = (), ()
1258
  room = _room(c.cfg.context, max_new)
1259
+ if specials_frame:
1260
  # the frame's own terminators, as ids: END closes the turn, DOC
1261
  # means she started a new document instead of answering. Built
1262
  # to the SAME budget _fit enforces, so _fit never has to cut a
 
1264
  ids = _specials_chat_ids(history, message, c.cfg.context, room)
1265
  stop_ids = (SP.END, SP.DOC, SP.USER)
1266
  else:
1267
+ if c.fmt == "specials": # a frame byte is never a reply
1268
+ stop_ids = (SP.END, SP.DOC, SP.USER)
1269
  # the SELECTED arm's own frame and turn-end bytes, not one
1270
  # hardcoded chat format: a Q&A arm never saw a transcript, and a
1271
  # newline-pair arm's terminator is invisible to the "User:" stops
 
1288
  "teaches the conversation frame — it has only ever read "
1289
  "documents. The Completion tab shows what it can do "
1290
  "today.)*")
1291
+ elif tmpl["frame"] in SINGLE_TURN:
1292
  empty = ("*(this arm ended the turn immediately — it was trained "
1293
  "on single-turn task prompts, not conversation. Try one "
1294
  "of its examples below, or switch arms.)*")
 
1344
  governor holding the anchors apart from birth. Its mission is
1345
  **complete** — 16.1 billion bytes over 61,422 steps, closing with a
1346
  two-phase anneal that taught the conversation frame, so this core
1347
+ **chats on its own** — pick *Core only* for a multi-turn conversation.
1348
+ Its format is specials-native — SYS/USER/MODEL/END are single reserved
1349
+ bytes rather than typed text, so the turn frame cannot be forged by
1350
+ anything you type.
1351
+
1352
+ **The 2s arm library.** Every arm trained on the final 2s core is
1353
+ selectable, each labelled with what it does, how settled it is
1354
+ (replicated across two seeds, one seed, candidate, refuted, control)
1355
+ and its measured score. The default is the best-measured arm: a
1356
+ rule-transfer arm that reads five if-then rules about words it has never
1357
+ seen and answers with only the final word, while still holding a
1358
+ conversation. Beyond single arms the library holds **stacks** (arms
1359
+ applied together, always on), **routed dispatches** (a learned signed
1360
+ router over several arms, some with a slowly varying per-arm gain) and
1361
+ **recurrent arms** (arms that carry state from byte to byte). These arms
1362
+ were trained on one question at a time, so Chat sends each message on its
1363
+ own with no history, and they decode greedy in fp32 exactly as they were
1364
+ measured.
1365
 
1366
  **mini-beatrix-1** — 112.5M parameters, pretrained on 15.3 billion raw
1367
  bytes, carrying a **library of detachable arms**: small adapters
 
1472
  # auto-decode only fires on a change event, so a default arm that
1473
  # asks for greedy was otherwise served sampled on first paint —
1474
  # the exact setting its metadata says degenerates
1475
+ _dt, _dp, _dr = _decode_of(
1476
+ _C0.arm_by_path.get(_C0.default_arm(STEP)))
1477
  temperature = gr.Slider(0.0, 1.5, value=_dt, step=0.05,
1478
  label="Temperature")
1479
  top_p = gr.Slider(0.1, 1.0, value=_dp, step=0.05, label="Top-p")
1480
  # byte-level: this damps whatever would CONTINUE a repeated
1481
  # 8-byte phrase, not every byte already seen — on a 256-value
1482
  # vocabulary the textbook form would just tax ordinary English
1483
+ rep = gr.Slider(1.0, 2.0, value=_dr, step=0.05,
1484
  label="Repetition penalty",
1485
  info="damps bytes that would repeat a recent "
1486
  "8-byte phrase · 1.0 = off")
 
1488
  with gr.Accordion("Automation", open=False), gr.Row():
1489
  auto_decode = gr.Checkbox(
1490
  value=True, label="Auto decode per arm",
1491
+ info="task arms switch to greedy with no repetition penalty on "
1492
+ "attach — the setting they were measured in")
1493
  fam_examples = gr.Checkbox(
1494
  value=True, label="Arm-family examples",
1495
  info="offer prompts from the selected arm's own training "
 
1567
  # or nothing); decode and examples then follow the ARM, unless their
1568
  # toggles say otherwise
1569
  craft_pick.change(on_craft, [craft_pick, auto_decode, fam_examples],
1570
+ [ckpt, arm_pick, status_box, temperature, top_p, rep,
1571
  ex.dataset])
1572
  ckpt.change(on_checkpoint, [craft_pick, ckpt, auto_decode, fam_examples],
1573
+ [ckpt, arm_pick, status_box, temperature, top_p, rep,
1574
+ ex.dataset])
1575
  arm_pick.change(on_arm,
1576
  [craft_pick, ckpt, arm_pick, auto_decode, fam_examples],
1577
+ [status_box, temperature, top_p, rep, ex.dataset])
1578
  demo.load(js=RESIZE_JS)
1579
 
1580
  demo.launch()
arm_mount.py ADDED
@@ -0,0 +1,279 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ """Arm mounting for the Beatrix Space.
2
+
3
+ `mount(model, recipe, path)` makes the live model carry exactly one arm
4
+ recipe and returns a handle whose `detach()` restores the bare blocks.
5
+ Every recipe is served from the files it was trained into; nothing is
6
+ re-derived at serve time.
7
+
8
+ Recipe types (the `mount.type` field of an arm-index row):
9
+ anchor one patchwork arm (an amoe anchor file)
10
+ stack several anchor arms applied always-on, nested inner to
11
+ outer, with no mixer between them
12
+ routed a dense signed dispatch over member arms; the checkpoint
13
+ carries the members and the router for every block
14
+ routed + gain
15
+ the same dispatch with a detached, bounded per-member gain
16
+ on the numerator, read per site or once at the first site
17
+ and shared by every site
18
+ relay_ema the patchwork organ plus two fixed-decay causal averages
19
+ of its own read feeding its head
20
+ recurrent a small recurrent cell per site fed by the attention read
21
+
22
+ The relay_ema, recurrent and gain recipes carry state across cached
23
+ decode steps; a fresh prefill starts that state over, and the uncached
24
+ path treats every forward as a fresh context.
25
+
26
+ Trained arms and their measurements:
27
+ huggingface.co/AbstractPhil/alephllm-mini-beatrix-training
28
+ (mini-beatrix-2s/arms/index.json and arms/dispatch_index.json).
29
+ """
30
+ from __future__ import annotations
31
+
32
+ import torch
33
+ import torch.nn as nn
34
+ import torch.nn.functional as F
35
+
36
+ import amoe
37
+ from amoe.binding.resolver import resolve
38
+ from amoe.core.adapter import AdapterSpec, RelayPatchwork
39
+ from amoe.core.dispatch import AnchorDispatch, BlockWithDispatch
40
+ from amoe.io.checkpoint import load_anchor, load_dispatch
41
+ from amoe.runtime.attach import AttachHandle, _probe
42
+
43
+ MOUNT_TYPES = ("anchor", "stack", "routed", "relay_ema", "recurrent")
44
+
45
+
46
+ # ------------------------------------------------------------- geometry
47
+ def spec_from_state(adapters: dict, prefix: str | None = None) -> AdapterSpec:
48
+ """Adapter geometry read from the arm's own tensors (the arm library
49
+ holds more than one shape, and modules are built before state loads).
50
+ `prefix` defaults to the first block the arm actually carries."""
51
+ if prefix is None:
52
+ blocks = sorted(int(k.split(".")[0]) for k in adapters
53
+ if k.endswith(".addr.codebook") and k.split(".")[0].isdigit())
54
+ prefix = f"{blocks[0]}." if blocks else "0."
55
+ cb = adapters.get(f"{prefix}addr.codebook")
56
+ proj = adapters.get(f"{prefix}proj.weight")
57
+ cons = adapters.get(f"{prefix}consume.0.weight")
58
+ if cb is None or proj is None or cons is None:
59
+ return AdapterSpec()
60
+ D = int(cb.shape[1])
61
+ return AdapterSpec(n_slots=int(proj.shape[0] // D), K=int(cb.shape[0]),
62
+ D=D, hidden=int(cons.shape[0]))
63
+
64
+
65
+ def _block_state(adapters: dict, i: int) -> dict:
66
+ pre = f"{i}."
67
+ return {k[len(pre):]: v for k, v in adapters.items() if k.startswith(pre)}
68
+
69
+
70
+ def base_model_id(path: str) -> str | None:
71
+ """The core an arm file was trained on, from its own metadata."""
72
+ blob = torch.load(path, map_location="cpu", weights_only=False)
73
+ return (blob.get("meta") or {}).get("base_model_id")
74
+
75
+
76
+ # ------------------------------------------------------------- handles
77
+ class StackHandle:
78
+ """Nested always-on handles, detached outermost first."""
79
+
80
+ def __init__(self, handles):
81
+ self.handles = list(handles)
82
+
83
+ def reset_state(self):
84
+ for h in self.handles:
85
+ getattr(h, "reset_state", lambda: None)()
86
+
87
+ def detach(self, *, verify: bool = False):
88
+ for h in reversed(self.handles):
89
+ h.detach(verify=verify)
90
+
91
+
92
+ # ------------------------------------------------------------- gain dispatch
93
+ class GainDispatch(AnchorDispatch):
94
+ """AnchorDispatch with a detached, bounded per-member gain alpha on the
95
+ numerator (the denominator still sums every member, masked or not):
96
+
97
+ out = x + sum_a alpha_a(t) (sinh u_a / sum_all cosh u) (arm_a(x) - x)
98
+ s_a(t) = cosh u_a / sum_all cosh u (the member's share)
99
+ ubar_a = causal EMA over bytes of s_a, rate rho, starting at 1/A
100
+ alpha_a = clamp(1 + gamma (A ubar_a - 1), a_min, a_max)
101
+
102
+ mode 'growth' lets the mean gain rise toward the cap; 'conserved'
103
+ renormalizes alpha to mean 1 over members at every byte.
104
+ coherent None reads alpha at every site; 'alpha' reads it once at the
105
+ first site and shares it; 'full' also shares the first site's signed
106
+ routing weight. Never a selector: no top-k, no softmax over members."""
107
+
108
+ def configure(self, *, mode, rho, gamma, a_min, a_max, coherent=None,
109
+ role="ref", holder=None):
110
+ self.mode, self.rho, self.gamma = mode, rho, gamma
111
+ self.a_min, self.a_max = a_min, a_max
112
+ self.coherent, self.role = coherent, role
113
+ self.holder = holder if holder is not None else {}
114
+ self._state, self._call = None, "forward"
115
+ return self
116
+
117
+ def _alpha(self, ep, en, z):
118
+ with torch.no_grad():
119
+ s = ((ep + en) / z).float()
120
+ B, T, A = s.shape
121
+ st = (self._state if (self._call == "step" and self._state is not None
122
+ and self._state.shape[0] == B) else None)
123
+ if st is None:
124
+ st = torch.full((B, A), 1.0 / A, device=s.device, dtype=torch.float32)
125
+ if T == 1:
126
+ st = st + self.rho * (s[:, 0] - st)
127
+ ubar = st.unsqueeze(1)
128
+ elif T <= 4200:
129
+ q = 1.0 - self.rho
130
+ t = torch.arange(1, T + 1, device=s.device, dtype=torch.float64)
131
+ acc = torch.cumsum((q ** -t).view(1, T, 1) * s.double(), dim=1)
132
+ ubar = ((q ** t).view(1, T, 1)
133
+ * (st.double().unsqueeze(1) + self.rho * acc)).float()
134
+ st = ubar[:, -1]
135
+ else:
136
+ ubar = torch.empty_like(s)
137
+ for i in range(T):
138
+ st = st + self.rho * (s[:, i] - st)
139
+ ubar[:, i] = st
140
+ self._state = st.clone() if self._call in ("prefill", "step") else None
141
+ alpha = (1.0 + self.gamma * (A * ubar - 1.0)).clamp(self.a_min, self.a_max)
142
+ if self.mode == "conserved":
143
+ alpha = alpha * (A / alpha.sum(dim=-1, keepdim=True))
144
+ return alpha.to(z.dtype)
145
+
146
+ def forward(self, x):
147
+ shared_route = self.coherent == "full" and self.role != "ref"
148
+ if not shared_route:
149
+ emb = F.normalize(x @ self.key_proj.T, dim=-1)
150
+ C = F.normalize(self.dispatch, dim=-1)
151
+ u = (emb @ C.T) / self.tau
152
+ m = u.abs().amax(dim=-1, keepdim=True)
153
+ ep, en = torch.exp(u - m), torch.exp(-u - m)
154
+ z = (ep + en).sum(dim=-1, keepdim=True)
155
+ g = (ep - en) / z
156
+ if self.coherent and self.role != "ref":
157
+ alpha = self.holder["alpha"]
158
+ if shared_route:
159
+ g = self.holder["g"]
160
+ else:
161
+ alpha = self._alpha(ep, en, z)
162
+ if self.coherent:
163
+ self.holder["alpha"], self.holder["g"] = alpha, g
164
+ out = x
165
+ for k, a in enumerate(self.anchors):
166
+ if self.enabled[k]:
167
+ out = out + (g[..., k:k + 1] * alpha[..., k:k + 1]) * (a(x) - x)
168
+ return out
169
+
170
+
171
+ class GainBlock(BlockWithDispatch):
172
+ """Marks cached-decode calls so the gain state is carried across steps."""
173
+
174
+ def prefill(self, *args, **kwargs):
175
+ out, cache = self.block.prefill(*args, **kwargs)
176
+ self.disp._call = "prefill"
177
+ try:
178
+ return self.disp(out), cache
179
+ finally:
180
+ self.disp._call = "forward"
181
+
182
+ def step(self, *args, **kwargs):
183
+ out = self.block.step(*args, **kwargs)
184
+ self.disp._call = "step"
185
+ try:
186
+ if isinstance(out, tuple):
187
+ return (self.disp(out[0]),) + out[1:]
188
+ return self.disp(out)
189
+ finally:
190
+ self.disp._call = "forward"
191
+
192
+
193
+ # ------------------------------------------------------------- mounts
194
+ def _mount_anchor(model, path):
195
+ ck = load_anchor(path)
196
+ return amoe.attach(model, ck, spec=spec_from_state(ck.adapters), strict=False)
197
+
198
+
199
+ def _mount_stack(model, paths):
200
+ handles = []
201
+ try:
202
+ for p in paths:
203
+ handles.append(_mount_anchor(model, p))
204
+ except Exception:
205
+ StackHandle(handles).detach() # never leave half a stack attached
206
+ raise
207
+ return StackHandle(handles)
208
+
209
+
210
+ def _mount_routed(model, path):
211
+ ck = load_dispatch(path)
212
+ b = resolve(model, None)
213
+ layers, d = list(b.layers(model)), b.hidden_size(model)
214
+ fingerprint = _probe(model, b)
215
+ names = list(ck.meta.get("anchors") or [])
216
+ A = len(names)
217
+ member0 = {k[len("anchors.0."):]: v for k, v in ck.dispatch[0].items()
218
+ if k.startswith("anchors.0.")}
219
+ spec = spec_from_state(member0, prefix="")
220
+ gain = ck.meta.get("alpha")
221
+ coherent = ck.meta.get("coherent_form")
222
+ holder, blocks = {}, []
223
+ for i, layer in enumerate(layers):
224
+ dev = next(layer.parameters()).device
225
+ members = nn.ModuleList([RelayPatchwork(d, spec) for _ in range(A)])
226
+ dp = AnchorDispatch(members, d)
227
+ dp.load_state_dict(ck.dispatch[i], strict=True)
228
+ dp.to(dev)
229
+ if gain:
230
+ dp.__class__ = GainDispatch
231
+ dp.configure(mode=ck.meta.get("alpha_mode") or "growth",
232
+ rho=float(gain["rho"]), gamma=float(gain["gamma"]),
233
+ a_min=float(gain["a_min"]), a_max=float(gain["a_max"]),
234
+ coherent=coherent, role="ref" if i == 0 else "follow",
235
+ holder=holder)
236
+ blocks.append(GainBlock(layer, dp))
237
+ else:
238
+ blocks.append(BlockWithDispatch(layer, dp))
239
+ b.set_layers(model, blocks)
240
+ return AttachHandle(model, b, layers, names, blocks, fingerprint)
241
+
242
+
243
+ def _mount_relay_ema(model, path):
244
+ from amoe.arms.relay_ema import RelayEMASpec, attach_relay_ema
245
+ blob = torch.load(path, map_location="cpu", weights_only=False)
246
+ st, sp = blob["state"], blob.get("spec") or {}
247
+ spec = RelayEMASpec(base=spec_from_state(st), rho1=float(sp.get("rho1", 1 / 16)),
248
+ rho2=float(sp.get("rho2", 1 / 64)))
249
+ name = (blob.get("meta") or {}).get("name", "relay_ema")
250
+ h = attach_relay_ema(model, name, spec, zero_bias=False)
251
+ with torch.no_grad():
252
+ for i, w in enumerate(h.wraps()):
253
+ w.arm.load_state_dict(_block_state(st, i), strict=True)
254
+ return h
255
+
256
+
257
+ def _mount_recurrent(model, path):
258
+ from amoe.arms.recurrent_wide import RecurrentSpec, attach_recurrent
259
+ blob = torch.load(path, map_location="cpu", weights_only=False)
260
+ name = (blob.get("meta") or {}).get("name", "recurrent")
261
+ return attach_recurrent(model, name, RecurrentSpec(**blob["spec"]), state=blob["state"])
262
+
263
+
264
+ def mount(model, recipe: dict, path: str, member_paths=None):
265
+ """Attach one arm recipe to the bare model. `path` is the local file of
266
+ the row's own checkpoint; `member_paths` are the local files of a
267
+ stack's members, inner first."""
268
+ kind = (recipe or {}).get("type", "anchor")
269
+ if kind == "anchor":
270
+ return _mount_anchor(model, path)
271
+ if kind == "stack":
272
+ return _mount_stack(model, member_paths)
273
+ if kind == "routed":
274
+ return _mount_routed(model, path)
275
+ if kind == "relay_ema":
276
+ return _mount_relay_ema(model, path)
277
+ if kind == "recurrent":
278
+ return _mount_recurrent(model, path)
279
+ raise ValueError(f"unknown mount type {kind!r}")
arms_catalog.json ADDED
The diff for this file is too large to render. See raw diff
 
requirements.txt CHANGED
@@ -4,4 +4,4 @@ safetensors>=0.4
4
  huggingface_hub>=0.24
5
  numpy
6
  geolip-alephllm @ git+https://github.com/AbstractEyes/alephllm@c6fff9fa3a9423a18d522635d8f2c666093d64c6
7
- amoe-lora @ git+https://github.com/AbstractEyes/amoe-lora@7e1baba9c0bb1cc38815e4424d969b80ae5a315d
 
4
  huggingface_hub>=0.24
5
  numpy
6
  geolip-alephllm @ git+https://github.com/AbstractEyes/alephllm@c6fff9fa3a9423a18d522635d8f2c666093d64c6
7
+ amoe-lora @ git+https://github.com/AbstractEyes/amoe-lora@e21baea08b065029f8bd1b80f7af15681e91ce3d