Text Generation
Transformers
Safetensors
mini-beatrix
byte-level
tokenizer-free
aleph
signed-address
custom_code
Instructions to use AbstractPhil/mini-beatrix-1 with libraries, inference providers, notebooks, and local apps. Follow these links to get started.
- Libraries
- Transformers
How to use AbstractPhil/mini-beatrix-1 with Transformers:
# Use a pipeline as a high-level helper from transformers import pipeline pipe = pipeline("text-generation", model="AbstractPhil/mini-beatrix-1", trust_remote_code=True)# Load model directly from transformers import AutoModelForCausalLM model = AutoModelForCausalLM.from_pretrained("AbstractPhil/mini-beatrix-1", trust_remote_code=True, device_map="auto") - Notebooks
- Google Colab
- Kaggle
- Local Apps Settings
- vLLM
How to use AbstractPhil/mini-beatrix-1 with vLLM:
Install from pip and serve model
# Install vLLM from pip: pip install vllm # Start the vLLM server: vllm serve "AbstractPhil/mini-beatrix-1" # Call the server using curl (OpenAI-compatible API): curl -X POST "http://localhost:8000/v1/completions" \ -H "Content-Type: application/json" \ --data '{ "model": "AbstractPhil/mini-beatrix-1", "prompt": "Once upon a time,", "max_tokens": 512, "temperature": 0.5 }'Use Docker
docker model run hf.co/AbstractPhil/mini-beatrix-1
- SGLang
How to use AbstractPhil/mini-beatrix-1 with SGLang:
Install from pip and serve model
# Install SGLang from pip: pip install sglang # Start the SGLang server: python3 -m sglang.launch_server \ --model-path "AbstractPhil/mini-beatrix-1" \ --host 0.0.0.0 \ --port 30000 # Call the server using curl (OpenAI-compatible API): curl -X POST "http://localhost:30000/v1/completions" \ -H "Content-Type: application/json" \ --data '{ "model": "AbstractPhil/mini-beatrix-1", "prompt": "Once upon a time,", "max_tokens": 512, "temperature": 0.5 }'Use Docker images
docker run --gpus all \ --shm-size 32g \ -p 30000:30000 \ -v ~/.cache/huggingface:/root/.cache/huggingface \ --env "HF_TOKEN=<secret>" \ --ipc=host \ lmsysorg/sglang:latest \ python3 -m sglang.launch_server \ --model-path "AbstractPhil/mini-beatrix-1" \ --host 0.0.0.0 \ --port 30000 # Call the server using curl (OpenAI-compatible API): curl -X POST "http://localhost:30000/v1/completions" \ -H "Content-Type: application/json" \ --data '{ "model": "AbstractPhil/mini-beatrix-1", "prompt": "Once upon a time,", "max_tokens": 512, "temperature": 0.5 }' - Docker Model Runner
How to use AbstractPhil/mini-beatrix-1 with Docker Model Runner:
docker model run hf.co/AbstractPhil/mini-beatrix-1
splat fast path (geolip 0.6.1 @a2436e6): fused 2K forward via oriented_cat, cached mask, lazy den stats, chunk 256 — 1.7x eager / 4.0x under torch.compile at ctx 2048, parity 1e-6 vs the naive oracle, grad-parity verified
Browse files- attention.py +59 -26
attention.py
CHANGED
|
@@ -63,17 +63,44 @@ class CausalSDPA(nn.Module):
|
|
| 63 |
|
| 64 |
class CausalSplatHUB(nn.Module):
|
| 65 |
def __init__(self, d: int, K: int = 512, D: int = 32, tau: float = 0.1,
|
| 66 |
-
chunk: int =
|
| 67 |
super().__init__()
|
| 68 |
self.addr = AlephAddress(K, D, tau)
|
| 69 |
-
self.chunk = chunk
|
| 70 |
self.q = nn.Linear(d, D, bias=False)
|
| 71 |
self.k = nn.Linear(d, D, bias=False)
|
| 72 |
self.v = nn.Linear(d, d, bias=False)
|
| 73 |
self.o = nn.Linear(d, d, bias=False)
|
| 74 |
for m in (self.q, self.k, self.v, self.o):
|
| 75 |
nn.init.orthogonal_(m.weight)
|
| 76 |
-
self.
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 77 |
|
| 78 |
def _halves(self, x):
|
| 79 |
qp, qn = self.addr.oriented(self.q(x))
|
|
@@ -81,36 +108,42 @@ class CausalSplatHUB(nn.Module):
|
|
| 81 |
return qp, qn, kp, kn, self.v(x)
|
| 82 |
|
| 83 |
def forward(self, x):
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 84 |
B, n, d = x.shape
|
| 85 |
-
|
|
|
|
|
|
|
| 86 |
C = min(self.chunk, n)
|
| 87 |
pad = (-n) % C
|
| 88 |
if pad:
|
| 89 |
-
|
| 90 |
-
|
|
|
|
| 91 |
nc = (n + pad) // C
|
| 92 |
-
|
| 93 |
-
|
|
|
|
| 94 |
v = v.view(B, nc, C, d)
|
| 95 |
-
mask =
|
| 96 |
-
|
| 97 |
-
|
| 98 |
-
|
| 99 |
-
|
| 100 |
-
|
| 101 |
-
|
| 102 |
-
|
| 103 |
-
|
| 104 |
-
|
| 105 |
-
|
| 106 |
-
|
| 107 |
-
|
| 108 |
-
num = num.view(B, nc * C, d)[:, :n]
|
| 109 |
-
den = den.view(B, nc * C, 1)[:, :n]
|
| 110 |
cl = dtype_floor(den)
|
| 111 |
-
|
| 112 |
-
|
| 113 |
-
(den <= cl).float().mean().item())
|
| 114 |
return self.o(num / den.clamp_min(cl))
|
| 115 |
|
| 116 |
# ---------------------------------------------------- incremental decode
|
|
|
|
| 63 |
|
| 64 |
class CausalSplatHUB(nn.Module):
|
| 65 |
def __init__(self, d: int, K: int = 512, D: int = 32, tau: float = 0.1,
|
| 66 |
+
chunk: int = 256):
|
| 67 |
super().__init__()
|
| 68 |
self.addr = AlephAddress(K, D, tau)
|
| 69 |
+
self.chunk = chunk # 256 measured best at ctx 2048 (bench)
|
| 70 |
self.q = nn.Linear(d, D, bias=False)
|
| 71 |
self.k = nn.Linear(d, D, bias=False)
|
| 72 |
self.v = nn.Linear(d, d, bias=False)
|
| 73 |
self.o = nn.Linear(d, d, bias=False)
|
| 74 |
for m in (self.q, self.k, self.v, self.o):
|
| 75 |
nn.init.orthogonal_(m.weight)
|
| 76 |
+
self._mask_cache: dict = {}
|
| 77 |
+
self._den_raw = None # (den tensor, floor) until read
|
| 78 |
+
self._den_stats = None # cached floats after first read
|
| 79 |
+
|
| 80 |
+
# den stats are LAZY: the reference forward paid three .item() GPU
|
| 81 |
+
# syncs per call just to keep this attribute warm; instruments read
|
| 82 |
+
# it at most once per health interval. Property keeps the tuple API.
|
| 83 |
+
@property
|
| 84 |
+
def last_den_stats(self):
|
| 85 |
+
if self._den_stats is None and self._den_raw is not None:
|
| 86 |
+
den, cl = self._den_raw
|
| 87 |
+
with torch.no_grad():
|
| 88 |
+
self._den_stats = (den.min().item(), den.mean().item(),
|
| 89 |
+
(den <= cl).float().mean().item())
|
| 90 |
+
return self._den_stats
|
| 91 |
+
|
| 92 |
+
@last_den_stats.setter
|
| 93 |
+
def last_den_stats(self, value):
|
| 94 |
+
self._den_stats = value
|
| 95 |
+
self._den_raw = None
|
| 96 |
+
|
| 97 |
+
def _mask(self, C: int, device, dtype):
|
| 98 |
+
key = (C, device, dtype)
|
| 99 |
+
m = self._mask_cache.get(key)
|
| 100 |
+
if m is None:
|
| 101 |
+
m = torch.tril(torch.ones(C, C, device=device, dtype=dtype))
|
| 102 |
+
self._mask_cache[key] = m
|
| 103 |
+
return m
|
| 104 |
|
| 105 |
def _halves(self, x):
|
| 106 |
qp, qn = self.addr.oriented(self.q(x))
|
|
|
|
| 108 |
return qp, qn, kp, kn, self.v(x)
|
| 109 |
|
| 110 |
def forward(self, x):
|
| 111 |
+
"""Fast path: the two oriented halves run as ONE 2K-wide pass —
|
| 112 |
+
every term is a sum of bilinear forms over the halves, so one
|
| 113 |
+
pass over cat(p, n) is the same arithmetic in half the kernels
|
| 114 |
+
(equal to forward_naive to fp reorder, ~1.5e-06; speed-harness
|
| 115 |
+
verdict 2026-08-15: 1.7x eager, 4.0x under torch.compile)."""
|
| 116 |
B, n, d = x.shape
|
| 117 |
+
qc = self.addr.oriented_cat(self.q(x)) # (B, n, 2K)
|
| 118 |
+
kc = self.addr.oriented_cat(self.k(x))
|
| 119 |
+
v = self.v(x)
|
| 120 |
C = min(self.chunk, n)
|
| 121 |
pad = (-n) % C
|
| 122 |
if pad:
|
| 123 |
+
qc = F.pad(qc, (0, 0, 0, pad))
|
| 124 |
+
kc = F.pad(kc, (0, 0, 0, pad))
|
| 125 |
+
v = F.pad(v, (0, 0, 0, pad))
|
| 126 |
nc = (n + pad) // C
|
| 127 |
+
K2 = qc.shape[-1]
|
| 128 |
+
qc = qc.view(B, nc, C, K2)
|
| 129 |
+
kc = kc.view(B, nc, C, K2)
|
| 130 |
v = v.view(B, nc, C, d)
|
| 131 |
+
mask = self._mask(C, x.device, v.dtype)
|
| 132 |
+
|
| 133 |
+
S = torch.einsum("bick,bicd->bikd", kc, v) # per-chunk 2KxD sums
|
| 134 |
+
P = torch.cumsum(S, dim=1) - S # exclusive prefix
|
| 135 |
+
zS = kc.sum(dim=2) # (B, nc, 2K)
|
| 136 |
+
zP = torch.cumsum(zS, dim=1) - zS
|
| 137 |
+
att = torch.einsum("bick,bijk->bicj", qc, kc) * mask # (B,nc,C,C)
|
| 138 |
+
num = torch.einsum("bick,bikd->bicd", qc, P) + att @ v
|
| 139 |
+
den = torch.einsum("bick,bik->bic", qc, zP).unsqueeze(-1) \
|
| 140 |
+
+ att.sum(dim=-1, keepdim=True)
|
| 141 |
+
|
| 142 |
+
num = num.reshape(B, nc * C, d)[:, :n]
|
| 143 |
+
den = den.reshape(B, nc * C, 1)[:, :n]
|
|
|
|
|
|
|
| 144 |
cl = dtype_floor(den)
|
| 145 |
+
self._den_raw = (den.detach(), cl)
|
| 146 |
+
self._den_stats = None
|
|
|
|
| 147 |
return self.o(num / den.clamp_min(cl))
|
| 148 |
|
| 149 |
# ---------------------------------------------------- incremental decode
|