Text Generation
Transformers
PyTorch
English
shram
research
sparse-attention
mixture-of-experts
custom_code
Instructions to use smithblack-0/SHRAM with libraries, inference providers, notebooks, and local apps. Follow these links to get started.
- Libraries
- Transformers
How to use smithblack-0/SHRAM with Transformers:
# Use a pipeline as a high-level helper from transformers import pipeline pipe = pipeline("text-generation", model="smithblack-0/SHRAM", trust_remote_code=True)# Load model directly from transformers import AutoModel model = AutoModel.from_pretrained("smithblack-0/SHRAM", trust_remote_code=True, device_map="auto") - Notebooks
- Google Colab
- Kaggle
- Local Apps Settings
- vLLM
How to use smithblack-0/SHRAM with vLLM:
Install from pip and serve model
# Install vLLM from pip: pip install vllm # Start the vLLM server: vllm serve "smithblack-0/SHRAM" # Call the server using curl (OpenAI-compatible API): curl -X POST "http://localhost:8000/v1/completions" \ -H "Content-Type: application/json" \ --data '{ "model": "smithblack-0/SHRAM", "prompt": "Once upon a time,", "max_tokens": 512, "temperature": 0.5 }'Use Docker
docker model run hf.co/smithblack-0/SHRAM
- SGLang
How to use smithblack-0/SHRAM 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 "smithblack-0/SHRAM" \ --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": "smithblack-0/SHRAM", "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 "smithblack-0/SHRAM" \ --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": "smithblack-0/SHRAM", "prompt": "Once upon a time,", "max_tokens": 512, "temperature": 0.5 }' - Docker Model Runner
How to use smithblack-0/SHRAM with Docker Model Runner:
docker model run hf.co/smithblack-0/SHRAM
Update architecture and tokenizer
Browse files- huggingface.py +56 -85
huggingface.py
CHANGED
|
@@ -2825,86 +2825,57 @@ class MoSRAHRouter(nn.Module):
|
|
| 2825 |
self.expert_bias = nn.Parameter(torch.zeros(config.num_mosrah_heads))
|
| 2826 |
|
| 2827 |
@staticmethod
|
| 2828 |
-
def
|
| 2829 |
tensor: torch.Tensor,
|
| 2830 |
dim: int,
|
| 2831 |
n: int | torch.Tensor,
|
|
|
|
| 2832 |
) -> torch.Tensor:
|
| 2833 |
-
"""
|
| 2834 |
-
Returns the n-th largest value along dim, keepdim=True.
|
| 2835 |
|
| 2836 |
-
|
| 2837 |
-
|
|
|
|
|
|
|
| 2838 |
|
| 2839 |
-
|
| 2840 |
-
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 2841 |
|
| 2842 |
-
:
|
| 2843 |
-
|
| 2844 |
-
:param n: 1-indexed rank. Scalar int or tensor of ints broadcastable
|
| 2845 |
-
to tensor with dim removed.
|
| 2846 |
-
:return: Threshold with size 1 along dim, same dtype/device.
|
| 2847 |
"""
|
| 2848 |
-
# -------------------------------------------------------------------------
|
| 2849 |
-
# Algorithm overview
|
| 2850 |
-
# -------------------------------------------------------------------------
|
| 2851 |
-
#
|
| 2852 |
-
# Scalar n does not need a full sorted table. kthvalue selects the n-th
|
| 2853 |
-
# rank directly, and the two boundary sentinels are returned explicitly.
|
| 2854 |
-
#
|
| 2855 |
-
# Tensor n requires a full sorted table because each position along the
|
| 2856 |
-
# complementary dimensions may request a different rank. The table is
|
| 2857 |
-
# built once by sorting descending, then sentinel values are padded at
|
| 2858 |
-
# both ends so that boundary n values resolve correctly via gather:
|
| 2859 |
-
#
|
| 2860 |
-
# index 0 <- +inf sentinel (n == 0)
|
| 2861 |
-
# index 1..dim_length <- sorted values (valid ranks, 1-indexed)
|
| 2862 |
-
# index dim_length+1 <- -inf sentinel (n > dim_length)
|
| 2863 |
-
#
|
| 2864 |
-
# The critical invariant is that n is 1-indexed. This means valid ranks
|
| 2865 |
-
# map directly to their gather index without any offset, and index 0 is
|
| 2866 |
-
# naturally free for the +inf sentinel. n == 0 gathers +inf without
|
| 2867 |
-
# special-casing, and overflow n gathers -inf after clamping.
|
| 2868 |
-
#
|
| 2869 |
-
# F.pad specifies padding from the last dimension inward. Targeting an
|
| 2870 |
-
# arbitrary dim requires a positive index to compute how many trailing
|
| 2871 |
-
# dimensions to skip over in the pad spec.
|
| 2872 |
positive_dim = dim % tensor.ndim
|
| 2873 |
dim_length = tensor.shape[positive_dim]
|
|
|
|
| 2874 |
|
| 2875 |
-
|
| 2876 |
-
|
| 2877 |
-
|
| 2878 |
-
|
| 2879 |
-
|
| 2880 |
-
|
| 2881 |
-
|
| 2882 |
-
shape = list(tensor.shape)
|
| 2883 |
-
shape[positive_dim] = 1
|
| 2884 |
-
return tensor.new_full(shape, float('inf'))
|
| 2885 |
-
if n > dim_length:
|
| 2886 |
-
shape = list(tensor.shape)
|
| 2887 |
-
shape[positive_dim] = 1
|
| 2888 |
-
return tensor.new_full(shape, float('-inf'))
|
| 2889 |
-
return -torch.kthvalue(-tensor, n, dim=dim, keepdim=True).values
|
| 2890 |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 2891 |
else:
|
| 2892 |
-
|
| 2893 |
-
|
| 2894 |
-
|
| 2895 |
-
|
| 2896 |
-
|
| 2897 |
-
|
| 2898 |
-
leading_pad = [0] * num_padding_skips + [1, 0]
|
| 2899 |
-
trailing_pad = [0] * num_padding_skips + [0, 1]
|
| 2900 |
-
|
| 2901 |
-
sorted_desc = F.pad(sorted_desc, leading_pad, value=float('inf'))
|
| 2902 |
-
sorted_desc = F.pad(sorted_desc, trailing_pad, value=float('-inf'))
|
| 2903 |
-
|
| 2904 |
-
# unsqueeze restores the reduced dimension so gather sees the same
|
| 2905 |
-
# rank as the padded table along dim.
|
| 2906 |
-
gather_index = n.clamp(0, dim_length + 1).long().unsqueeze(dim)
|
| 2907 |
-
return sorted_desc.gather(dim, gather_index)
|
| 2908 |
@staticmethod
|
| 2909 |
def _check_bidding_converged(converged: torch.Tensor, max_rounds: int) -> None:
|
| 2910 |
"""Raise if the bidding loop exhausted max_rounds without satisfying all tokens.
|
|
@@ -2935,12 +2906,14 @@ class MoSRAHRouter(nn.Module):
|
|
| 2935 |
f"Increase mosrah_overallocation_factor or max_bid_rounds."
|
| 2936 |
)
|
| 2937 |
|
| 2938 |
-
@
|
| 2939 |
def _run_bidding(
|
|
|
|
| 2940 |
logits: torch.Tensor,
|
| 2941 |
remaining_capacity: int | torch.Tensor,
|
| 2942 |
min_choices: int,
|
| 2943 |
max_rounds: int,
|
|
|
|
| 2944 |
) -> torch.Tensor:
|
| 2945 |
"""Deferred-acceptance (Gale-Shapley) bidding solver for joint capacity enforcement.
|
| 2946 |
|
|
@@ -2960,6 +2933,8 @@ class MoSRAHRouter(nn.Module):
|
|
| 2960 |
min_choices: Minimum experts each token must have accepted (K).
|
| 2961 |
max_rounds: Iteration ceiling; raises via ``_check_bidding_converged``
|
| 2962 |
if exhausted.
|
|
|
|
|
|
|
| 2963 |
|
| 2964 |
Returns:
|
| 2965 |
accepted: (B, N, L) bool — True at positions accepted by the solver.
|
|
@@ -2984,18 +2959,13 @@ class MoSRAHRouter(nn.Module):
|
|
| 2984 |
# Tokens with fewer than min_choices accepted experts propose their
|
| 2985 |
# next-best unproposed expert(s). The deficit determines how many new
|
| 2986 |
# proposals each token makes this round; already-satisfied tokens
|
| 2987 |
-
# propose nothing (deficit = 0 →
|
| 2988 |
accepted_per_token = acceptances.sum(dim=-1) # (B, N)
|
| 2989 |
choices_deficit = (min_choices - accepted_per_token).clamp_min(0)
|
| 2990 |
|
| 2991 |
unproposed_logits = logits.masked_fill(proposals, float('-inf'))
|
| 2992 |
-
|
| 2993 |
-
unproposed_logits, dim=-1, n=choices_deficit,
|
| 2994 |
-
)
|
| 2995 |
-
new_proposals = (
|
| 2996 |
-
(unproposed_logits >= bid_threshold)
|
| 2997 |
-
& ~proposals
|
| 2998 |
-
& (choices_deficit.unsqueeze(-1) > 0)
|
| 2999 |
)
|
| 3000 |
updated_proposals = proposals | new_proposals
|
| 3001 |
|
|
@@ -3005,10 +2975,9 @@ class MoSRAHRouter(nn.Module):
|
|
| 3005 |
# Acceptances are recomputed from scratch each round so that a
|
| 3006 |
# stronger new proposal can displace a weaker prior one.
|
| 3007 |
proposed_logits = logits.masked_fill(~updated_proposals, float('-inf'))
|
| 3008 |
-
|
| 3009 |
-
proposed_logits, dim=-2, n=remaining_capacity,
|
| 3010 |
)
|
| 3011 |
-
updated_acceptances = updated_proposals & (proposed_logits >= accept_threshold)
|
| 3012 |
|
| 3013 |
return updated_proposals, updated_acceptances, round_count + 1
|
| 3014 |
|
|
@@ -3017,7 +2986,7 @@ class MoSRAHRouter(nn.Module):
|
|
| 3017 |
)
|
| 3018 |
|
| 3019 |
converged = (acceptances.sum(dim=-1) >= min_choices).all()
|
| 3020 |
-
|
| 3021 |
return acceptances
|
| 3022 |
|
| 3023 |
@classmethod
|
|
@@ -3101,8 +3070,7 @@ class MoSRAHRouter(nn.Module):
|
|
| 3101 |
# Mask computation runs under no_grad: the boolean mask is a hard routing
|
| 3102 |
# decision and must not accumulate gradient memory through the solver.
|
| 3103 |
with torch.no_grad():
|
| 3104 |
-
|
| 3105 |
-
col_capacity_mask = logits >= col_threshold # (B, N, L)
|
| 3106 |
if (col_capacity_mask.sum(dim=-1) >= min_choices).all():
|
| 3107 |
return logits.masked_fill(~col_capacity_mask, mask_value)
|
| 3108 |
|
|
@@ -3110,7 +3078,7 @@ class MoSRAHRouter(nn.Module):
|
|
| 3110 |
# enough that per-expert capacity limits leave some tokens with fewer
|
| 3111 |
# than min_choices choices. The bidding solver handles this jointly.
|
| 3112 |
with torch.no_grad():
|
| 3113 |
-
accepted = cls._run_bidding(logits, remaining_capacity, min_choices, max_rounds)
|
| 3114 |
return logits.masked_fill(~accepted, mask_value)
|
| 3115 |
def forward(
|
| 3116 |
self,
|
|
@@ -3352,7 +3320,10 @@ class MoSRAHLayer(nn.Module):
|
|
| 3352 |
def __init__(self, config: ShramConfig) -> None:
|
| 3353 |
super().__init__()
|
| 3354 |
self.num_experts = config.num_mosrah_heads
|
| 3355 |
-
|
|
|
|
|
|
|
|
|
|
| 3356 |
|
| 3357 |
self.router = MoSRAHRouter(config)
|
| 3358 |
self.positions = SparseMoSRAHPositions(config)
|
|
@@ -3621,7 +3592,7 @@ class DecoderLayer(nn.Module):
|
|
| 3621 |
self.mlp_norm = nn.RMSNorm(config.embedding_width, eps=config.rms_norm_eps)
|
| 3622 |
self.attention = SHRAMHybridLayer(config)
|
| 3623 |
self.mlp = SwiGLUMLP(config)
|
| 3624 |
-
self.residual_gate = nn.Parameter(torch.
|
| 3625 |
def num_mosrah_parameters(self) -> int:
|
| 3626 |
"""Return the total number of trainable MoSRAH parameters in this decoder layer."""
|
| 3627 |
return self.attention.num_mosrah_parameters()
|
|
|
|
| 2825 |
self.expert_bias = nn.Parameter(torch.zeros(config.num_mosrah_heads))
|
| 2826 |
|
| 2827 |
@staticmethod
|
| 2828 |
+
def get_mask(
|
| 2829 |
tensor: torch.Tensor,
|
| 2830 |
dim: int,
|
| 2831 |
n: int | torch.Tensor,
|
| 2832 |
+
capacity_scalar: int,
|
| 2833 |
) -> torch.Tensor:
|
| 2834 |
+
"""Return a boolean mask selecting the top-n entries along dim.
|
|
|
|
| 2835 |
|
| 2836 |
+
Uses topk to select exactly min(n_per_slice, dim_length) True entries
|
| 2837 |
+
per slice along dim. Unlike a threshold comparison, this never
|
| 2838 |
+
over-selects under tied logit values, which occurs when padding tokens
|
| 2839 |
+
contribute identical scores to multiple expert slots.
|
| 2840 |
|
| 2841 |
+
Args:
|
| 2842 |
+
tensor: Input tensor. Higher values rank first.
|
| 2843 |
+
dim: Dimension to select along.
|
| 2844 |
+
n: Per-slice selection count. Scalar int or tensor broadcastable
|
| 2845 |
+
to tensor with dim removed. Slices where n=0 produce all-False
|
| 2846 |
+
outputs.
|
| 2847 |
+
capacity_scalar: Static upper bound on n; used to derive topk k as
|
| 2848 |
+
min(tensor.shape[dim], capacity_scalar). Must be a Python int
|
| 2849 |
+
for compile compatibility.
|
| 2850 |
|
| 2851 |
+
Returns:
|
| 2852 |
+
Boolean mask of the same shape as tensor.
|
|
|
|
|
|
|
|
|
|
| 2853 |
"""
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 2854 |
positive_dim = dim % tensor.ndim
|
| 2855 |
dim_length = tensor.shape[positive_dim]
|
| 2856 |
+
k = min(dim_length, capacity_scalar)
|
| 2857 |
|
| 2858 |
+
topk_indices = tensor.topk(k, dim=dim).indices
|
| 2859 |
+
|
| 2860 |
+
# Rank tensor broadcast-compatible with topk_indices: rank r along dim
|
| 2861 |
+
# corresponds to the (r+1)-th highest value in that slice.
|
| 2862 |
+
rank_shape = [1] * tensor.ndim
|
| 2863 |
+
rank_shape[positive_dim] = k
|
| 2864 |
+
ranks = torch.arange(k, device=tensor.device, dtype=torch.long).view(rank_shape)
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 2865 |
|
| 2866 |
+
# element_included: True where this rank falls within the per-slice budget.
|
| 2867 |
+
# For scalar n all k ranks satisfy rank < n (since k = min(dim_length, n)).
|
| 2868 |
+
# For tensor n per-slice budgets differ; rank >= n[slice] yields False,
|
| 2869 |
+
# correctly excluding excess slots including those with n=0.
|
| 2870 |
+
if isinstance(n, int):
|
| 2871 |
+
element_included = ranks < n
|
| 2872 |
else:
|
| 2873 |
+
element_included = ranks < n.unsqueeze(positive_dim)
|
| 2874 |
+
|
| 2875 |
+
mask = torch.zeros_like(tensor, dtype=torch.bool)
|
| 2876 |
+
mask.scatter_(dim, topk_indices, element_included.expand_as(topk_indices))
|
| 2877 |
+
return mask
|
| 2878 |
+
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 2879 |
@staticmethod
|
| 2880 |
def _check_bidding_converged(converged: torch.Tensor, max_rounds: int) -> None:
|
| 2881 |
"""Raise if the bidding loop exhausted max_rounds without satisfying all tokens.
|
|
|
|
| 2906 |
f"Increase mosrah_overallocation_factor or max_bid_rounds."
|
| 2907 |
)
|
| 2908 |
|
| 2909 |
+
@classmethod
|
| 2910 |
def _run_bidding(
|
| 2911 |
+
cls,
|
| 2912 |
logits: torch.Tensor,
|
| 2913 |
remaining_capacity: int | torch.Tensor,
|
| 2914 |
min_choices: int,
|
| 2915 |
max_rounds: int,
|
| 2916 |
+
capacity_scalar: int,
|
| 2917 |
) -> torch.Tensor:
|
| 2918 |
"""Deferred-acceptance (Gale-Shapley) bidding solver for joint capacity enforcement.
|
| 2919 |
|
|
|
|
| 2933 |
min_choices: Minimum experts each token must have accepted (K).
|
| 2934 |
max_rounds: Iteration ceiling; raises via ``_check_bidding_converged``
|
| 2935 |
if exhausted.
|
| 2936 |
+
capacity_scalar: Static upper bound on remaining_capacity, passed to
|
| 2937 |
+
``get_mask`` as the topk k bound for the acceptance step.
|
| 2938 |
|
| 2939 |
Returns:
|
| 2940 |
accepted: (B, N, L) bool — True at positions accepted by the solver.
|
|
|
|
| 2959 |
# Tokens with fewer than min_choices accepted experts propose their
|
| 2960 |
# next-best unproposed expert(s). The deficit determines how many new
|
| 2961 |
# proposals each token makes this round; already-satisfied tokens
|
| 2962 |
+
# propose nothing (deficit = 0 → get_mask returns all-False).
|
| 2963 |
accepted_per_token = acceptances.sum(dim=-1) # (B, N)
|
| 2964 |
choices_deficit = (min_choices - accepted_per_token).clamp_min(0)
|
| 2965 |
|
| 2966 |
unproposed_logits = logits.masked_fill(proposals, float('-inf'))
|
| 2967 |
+
new_proposals = cls.get_mask(
|
| 2968 |
+
unproposed_logits, dim=-1, n=choices_deficit, capacity_scalar=min_choices,
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 2969 |
)
|
| 2970 |
updated_proposals = proposals | new_proposals
|
| 2971 |
|
|
|
|
| 2975 |
# Acceptances are recomputed from scratch each round so that a
|
| 2976 |
# stronger new proposal can displace a weaker prior one.
|
| 2977 |
proposed_logits = logits.masked_fill(~updated_proposals, float('-inf'))
|
| 2978 |
+
updated_acceptances = cls.get_mask(
|
| 2979 |
+
proposed_logits, dim=-2, n=remaining_capacity, capacity_scalar=capacity_scalar,
|
| 2980 |
)
|
|
|
|
| 2981 |
|
| 2982 |
return updated_proposals, updated_acceptances, round_count + 1
|
| 2983 |
|
|
|
|
| 2986 |
)
|
| 2987 |
|
| 2988 |
converged = (acceptances.sum(dim=-1) >= min_choices).all()
|
| 2989 |
+
cls._check_bidding_converged(converged, max_rounds)
|
| 2990 |
return acceptances
|
| 2991 |
|
| 2992 |
@classmethod
|
|
|
|
| 3070 |
# Mask computation runs under no_grad: the boolean mask is a hard routing
|
| 3071 |
# decision and must not accumulate gradient memory through the solver.
|
| 3072 |
with torch.no_grad():
|
| 3073 |
+
col_capacity_mask = cls.get_mask(logits, dim=-2, n=remaining_capacity, capacity_scalar=capacity)
|
|
|
|
| 3074 |
if (col_capacity_mask.sum(dim=-1) >= min_choices).all():
|
| 3075 |
return logits.masked_fill(~col_capacity_mask, mask_value)
|
| 3076 |
|
|
|
|
| 3078 |
# enough that per-expert capacity limits leave some tokens with fewer
|
| 3079 |
# than min_choices choices. The bidding solver handles this jointly.
|
| 3080 |
with torch.no_grad():
|
| 3081 |
+
accepted = cls._run_bidding(logits, remaining_capacity, min_choices, max_rounds, capacity)
|
| 3082 |
return logits.masked_fill(~accepted, mask_value)
|
| 3083 |
def forward(
|
| 3084 |
self,
|
|
|
|
| 3320 |
def __init__(self, config: ShramConfig) -> None:
|
| 3321 |
super().__init__()
|
| 3322 |
self.num_experts = config.num_mosrah_heads
|
| 3323 |
+
if config.use_cache:
|
| 3324 |
+
self.packed_length = config.mosrah_cache_length
|
| 3325 |
+
else:
|
| 3326 |
+
self.packed_length = config.mosrah_packed_length
|
| 3327 |
|
| 3328 |
self.router = MoSRAHRouter(config)
|
| 3329 |
self.positions = SparseMoSRAHPositions(config)
|
|
|
|
| 3592 |
self.mlp_norm = nn.RMSNorm(config.embedding_width, eps=config.rms_norm_eps)
|
| 3593 |
self.attention = SHRAMHybridLayer(config)
|
| 3594 |
self.mlp = SwiGLUMLP(config)
|
| 3595 |
+
self.residual_gate = nn.Parameter(1e-6*torch.randn([config.embedding_width]))
|
| 3596 |
def num_mosrah_parameters(self) -> int:
|
| 3597 |
"""Return the total number of trainable MoSRAH parameters in this decoder layer."""
|
| 3598 |
return self.attention.num_mosrah_parameters()
|