AGILLM-4 / verify_anchor_memory_and_kv_buffer_agillm4.py
OpenTransformer's picture
Prepare AGILLM4 AR SAT NAT scaffold
528e0d6 verified
Raw
History Blame Contribute Delete
4.51 kB
#!/usr/bin/env python3
"""Verifier for AGILLM-4 anchor-memory wiring and KV-buffer harvest.
Two harvested/integrated features share this file because both touch
nB300_agillm4 and both need a regression-safe smoke test:
1. Anchor memory: AnchorMemoryLayer wired into Encoder at a configurable
mid-stack position. Default-off; enabled with ``--anchor_memory`` and
parameterised by ``--anchor_stride / --anchor_max / --anchor_position``.
2. KV buffer: ``KVBuffer`` replaces ``torch.cat``-based decode-time cache
growth. Default-off (legacy tuple cache still works); enabled per
call site by passing a pre-sized ``KVBuffer`` as ``kv_cache``.
Run:
python /workspace/agillm-4/verify_anchor_memory_and_kv_buffer_agillm4.py
"""
from __future__ import annotations
import pathlib
import sys
HERE = pathlib.Path(__file__).resolve().parent
if str(HERE) not in sys.path:
sys.path.insert(0, str(HERE))
import torch # noqa: E402
import nB300_agillm4 as m # noqa: E402
from anchor_memory import AnchorMemoryLayer # noqa: E402
DEV = "cuda" if torch.cuda.is_available() else "cpu"
FAILS = 0
def check(name: str, cond: bool, detail: str = ""):
global FAILS
tag = "OK " if cond else "FAIL"
if not cond:
FAILS += 1
print(f" [{tag}] {name}" + (f" — {detail}" if detail else ""))
def section(title: str):
print(f"\n=== {title} ===")
# ----- 1. KVBuffer -----
section("KVBuffer fill / view / overflow")
buf = m.KVBuffer(batch=2, heads=4, capacity=32, d_k=8, device=DEV, dtype=torch.float32)
check("initial length is 0", buf.length == 0)
check("k/v allocated", buf.k.shape == (2, 4, 32, 8) and buf.v.shape == (2, 4, 32, 8))
k1 = torch.randn(2, 4, 5, 8, device=DEV)
v1 = torch.randn(2, 4, 5, 8, device=DEV)
buf.append(k1, v1)
check("after append(5) length is 5", buf.length == 5)
k_view, v_view = buf.view()
check("view shape", k_view.shape == (2, 4, 5, 8))
check("k content correct", torch.allclose(k_view, k1))
check("v content correct", torch.allclose(v_view, v1))
buf.append(torch.randn(2, 4, 27, 8, device=DEV), torch.randn(2, 4, 27, 8, device=DEV))
check("filled to capacity (32)", buf.length == 32)
try:
buf.append(torch.zeros(2, 4, 1, 8, device=DEV), torch.zeros(2, 4, 1, 8, device=DEV))
check("overflow raises", False, "no exception")
except RuntimeError:
check("overflow raises", True)
# ----- 2. Encoder without anchor memory (regression) -----
section("Encoder regression (anchor disabled)")
cfg = {"d": 64, "layers": 4, "heads": 4, "rank": 8}
enc_plain = m.Encoder(cfg).to(DEV)
check("anchor module is None", enc_plain.anchor is None)
check("anchor_memory_enabled is False", enc_plain.anchor_memory_enabled is False)
ids = torch.randint(0, m.VOCAB, (1, 16), device=DEV)
with torch.no_grad():
out = enc_plain(ids, mask=None)
check("plain forward shape", out.shape == (1, 16, 64), str(out.shape))
# ----- 3. Encoder with anchor memory -----
section("Encoder with anchor memory enabled")
enc = m.Encoder(
cfg,
anchor_memory=True,
anchor_stride=8,
anchor_max=16,
anchor_position=-1,
).to(DEV)
check("anchor_memory_enabled", enc.anchor_memory_enabled is True)
check("anchor is AnchorMemoryLayer", isinstance(enc.anchor, AnchorMemoryLayer))
check("position resolved to mid-stack (4//2=2)", enc.anchor_position == 2, f"got {enc.anchor_position}")
ids2 = torch.randint(0, m.VOCAB, (1, 32), device=DEV)
out2 = enc(ids2, mask=None)
check("anchor-on forward shape", out2.shape == (1, 32, 64), str(out2.shape))
loss = out2.sum()
loss.backward()
grads = [p.grad for p in enc.anchor.parameters() if p.grad is not None]
check("anchor params got gradients", len(grads) > 0, f"{len(grads)} grads")
nonzero = sum(int(g.abs().sum() > 0) for g in grads)
check("anchor gradients non-zero", nonzero > 0, f"{nonzero}/{len(grads)}")
# ----- 4. Anchor position resolution -----
section("Anchor position resolution")
check("explicit position=1", m.Encoder(cfg, anchor_memory=True, anchor_position=1).anchor_position == 1)
check("oversized position clamped", m.Encoder(cfg, anchor_memory=True, anchor_position=99).anchor_position == cfg["layers"] - 1)
# ----- 5. Module-level defaults exposed -----
section("Module-level defaults present")
for name in ("DEFAULT_ANCHOR_MEMORY", "DEFAULT_ANCHOR_STRIDE", "DEFAULT_ANCHOR_MAX", "DEFAULT_ANCHOR_POSITION", "DEFAULT_KV_BUFFER"):
check(name, hasattr(m, name))
print()
if FAILS:
print(f"=== {FAILS} CHECK(S) FAILED ===")
sys.exit(1)
print("=== ALL CHECKS PASSED ===")
Free AI Image Generator No sign-up. Instant results. Open Now