Any-to-Any
Transformers
Safetensors
multilingual
spev
feature-extraction
multimodal
text
audio
image
video
decision-model
choice
qwen3-omni
lora
custom-code
custom_code
Instructions to use SpragAI/SPEV with libraries, inference providers, notebooks, and local apps. Follow these links to get started.
- Libraries
- Transformers
How to use SpragAI/SPEV with Transformers:
# pip install -U transformers accelerate # Load model directly from transformers import AutoModel model = AutoModel.from_pretrained("SpragAI/SPEV", trust_remote_code=True, device_map="auto") - Notebooks
- Google Colab
- Kaggle
File size: 4,507 Bytes
2e0601e | 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 112 113 114 115 116 | # SPDX-License-Identifier: Apache-2.0
# SPDX-FileCopyrightText: Copyright contributors to the vLLM-Omni project
"""Shared-prefix branch attention with request-local immutable mask metadata."""
from collections import defaultdict
from contextlib import contextmanager
from contextvars import ContextVar
import torch
from torch.nn import functional as F
REQUEST = ContextVar("spev_attention_request", default=None)
class RequestMaskCache:
def __init__(self):
self.tree = None
self.device = None
self.plan = None
self.builds = 0
self.hits = 0
def __call__(self, tree, device):
if tree is self.tree and device == self.device:
self.hits += 1
return self.plan
buckets = defaultdict(list)
start = tree.prefix_length
for length in tree.branch_lengths:
buckets[((length + 31) // 32) * 32].append((start, length))
start += length
assert start == tree.length
plan = []
p = tree.prefix_length
for width, branches in sorted(buckets.items()):
for offset in range(0, len(branches), 8):
block = branches[offset : offset + 8]
allowed = torch.zeros(8, 1, width, p + width, device=device, dtype=torch.bool)
allowed[:, :, :, 0] = True
for slot, (_, length) in enumerate(block):
allowed[slot, 0, :length, :p] = True
allowed[slot, 0, :length, p : p + length] = torch.ones(
length, length, device=device, dtype=torch.bool
).tril()
plan.append((width, block, allowed))
self.tree = tree
self.device = device
self.plan = plan
self.builds += 1
return plan
def stats(self):
return dict(
builds=self.builds,
hits=self.hits,
blocks=len(self.plan or []),
branches=sum(len(block) for _, block, _ in self.plan or []),
)
def branch_attention(
module, query, key, value, attention_mask=None, dropout=0.0, scaling=None, sliding_window=None, **kwargs
):
request = REQUEST.get()
tree = request[0] if request else None
if tree is None or query.shape[0] != 1 or key.shape[-2] != tree.length or query.shape[-2] != tree.length:
raise ValueError("Branch attention requires an explicit single-request tree layout")
if sliding_window is not None:
raise ValueError("Sliding-window branch attention is not implemented")
if dropout:
raise ValueError("Branch attention reference requires zero attention dropout")
groups = query.shape[1] // key.shape[1]
if groups > 1:
key = key.repeat_interleave(groups, dim=1)
value = value.repeat_interleave(groups, dim=1)
p = tree.prefix_length
output = torch.zeros_like(query)
output[:, :, :p] = F.scaled_dot_product_attention(
query[:, :, :p], key[:, :, :p], value[:, :, :p], is_causal=True, scale=scaling
)
cache = request[1]
heads, dim = query.shape[1], query.shape[-1]
batch_slots = 8
for width, block, allowed in cache(tree, query.device):
q = query.new_zeros(batch_slots, heads, width, dim)
k = key.new_zeros(batch_slots, heads, p + width, dim)
v = value.new_zeros(batch_slots, heads, p + width, dim)
for slot, (start, length) in enumerate(block):
q[slot, :, :length] = query[0, :, start : start + length]
k[slot, :, :p] = key[0, :, :p]
v[slot, :, :p] = value[0, :, :p]
k[slot, :, p : p + length] = key[0, :, start : start + length]
v[slot, :, p : p + length] = value[0, :, start : start + length]
values = F.scaled_dot_product_attention(q, k, v, attn_mask=allowed, scale=scaling)
for slot, (start, length) in enumerate(block):
output[0, :, start : start + length] = values[slot, :, :length]
return output.transpose(1, 2).contiguous(), None
def install(model):
from transformers.modeling_utils import ALL_ATTENTION_FUNCTIONS
implementation = f"{__name__}.isolated_branches"
ALL_ATTENTION_FUNCTIONS.register(implementation, branch_attention)
for layer in model.model.layers:
layer.self_attn.config._attn_implementation = implementation
@contextmanager
def request_context(tree):
token = REQUEST.set((tree, RequestMaskCache()))
try:
yield
finally:
REQUEST.reset(token)
|