Instructions to use masahiroid/pyrite-stream with libraries, inference providers, notebooks, and local apps. Follow these links to get started.
- Libraries
- MLX
How to use masahiroid/pyrite-stream with MLX:
# Make sure mlx-lm is installed # pip install --upgrade mlx-lm # if on a CUDA device, also pip install mlx[cuda] # Generate text with mlx-lm from mlx_lm import load, generate model, tokenizer = load("masahiroid/pyrite-stream") prompt = "Once upon a time in" text = generate(model, tokenizer, prompt=prompt, verbose=True) - Notebooks
- Google Colab
- Kaggle
- Local Apps Settings
- LM Studio
- MLX LM
How to use masahiroid/pyrite-stream with MLX LM:
Generate or start a chat session
# Install MLX LM uv tool install mlx-lm # Generate some text mlx_lm.generate --model "masahiroid/pyrite-stream" --prompt "Once upon a time"
- Atomic Chat
Release Project Pyrite Phase 2: MoE-Stream Engine with Mixtral-8x22B & DeepSeek support
cab2ef1 verified Download moe_stream_layer.py from masahiroid/pyrite-stream: direct link, hf CLI and curl.
- Browser
- Download file 7.74 kB
-
https://huggingface.co/masahiroid/pyrite-stream/resolve/main/moe_stream_layer.py
- Command line
-
hf download hf://masahiroid/pyrite-stream/moe_stream_layer.py
-
curl -L -o moe_stream_layer.py https://huggingface.co/masahiroid/pyrite-stream/resolve/main/moe_stream_layer.py
7.74 kB
| #!/usr/bin/env python3 | |
| """Streaming MoE Layer Implementation for Apple Silicon MLX with Quantized Metal Matmul. | |
| Replaces standard heavy MoE layer. Keeps routing gate and shared experts resident in RAM, | |
| while streaming routed experts on-demand from NVMe storage with an LRU cache. | |
| """ | |
| from collections import OrderedDict | |
| from typing import Dict, List, Optional, Tuple, Any | |
| import mlx.core as mx | |
| import mlx.nn as nn | |
| from expert_registry import SafetensorsIndex, ModelSafetensorsIndex | |
| class ExpertLRUCache: | |
| """Least-Recently-Used (LRU) In-Memory Cache for MoE Experts.""" | |
| def __init__(self, max_experts_in_ram: int = 16): | |
| self.max_experts = max_experts_in_ram | |
| self.cache: OrderedDict[int, Dict[str, mx.array]] = OrderedDict() | |
| def get(self, expert_id: int) -> Optional[Dict[str, mx.array]]: | |
| if expert_id in self.cache: | |
| self.cache.move_to_end(expert_id) | |
| return self.cache[expert_id] | |
| return None | |
| def put(self, expert_id: int, weights: Dict[str, mx.array]): | |
| if expert_id in self.cache: | |
| self.cache.move_to_end(expert_id) | |
| else: | |
| if len(self.cache) >= self.max_experts: | |
| self.cache.popitem(last=False) | |
| self.cache[expert_id] = weights | |
| class StreamingMoELayer(nn.Module): | |
| """Memory-efficient streaming MoE layer for Apple Silicon MLX. | |
| Dynamically routes tokens to experts, streaming weights directly from | |
| NVMe mmap indices without loading entire multi-gigabyte models into RAM. | |
| """ | |
| def __init__( | |
| self, | |
| layer_idx: int, | |
| gate_weight: mx.array, | |
| shared_experts: Optional[Dict[str, mx.array]], | |
| index_reader: Any, | |
| top_k: int = 6, | |
| gate_scales: Optional[mx.array] = None, | |
| gate_biases: Optional[mx.array] = None, | |
| routed_scaling_factor: float = 1.0, | |
| topk_method: str = "greedy", | |
| n_group: int = 1, | |
| topk_group: int = 1, | |
| max_cache_experts: int = 16, | |
| moe_prefix: str = "mlp", | |
| softmax_before_topk: bool = True, | |
| ): | |
| super().__init__() | |
| self.layer_idx = layer_idx | |
| self.gate_weight = gate_weight | |
| self.gate_scales = gate_scales | |
| self.gate_biases = gate_biases | |
| self.shared = shared_experts | |
| self.index_reader = index_reader | |
| self.top_k = top_k | |
| self.routed_scaling_factor = routed_scaling_factor | |
| self.topk_method = topk_method | |
| self.n_group = n_group | |
| self.topk_group = topk_group | |
| self.moe_prefix = moe_prefix | |
| self.softmax_before_topk = softmax_before_topk | |
| self.cache = ExpertLRUCache(max_experts_in_ram=max_cache_experts) | |
| def _get_expert_tensors(self, expert_id: int) -> Dict[str, mx.array]: | |
| cached = self.cache.get(expert_id) | |
| if cached is not None: | |
| return cached | |
| l_str = f"model.layers.{self.layer_idx}.{self.moe_prefix}.switch_mlp" | |
| weights = { | |
| "gate_w": self.index_reader.get_expert_slice(f"{l_str}.gate_proj.weight", expert_id), | |
| "gate_s": self.index_reader.get_expert_slice(f"{l_str}.gate_proj.scales", expert_id), | |
| "gate_b": self.index_reader.get_expert_slice(f"{l_str}.gate_proj.biases", expert_id), | |
| "up_w": self.index_reader.get_expert_slice(f"{l_str}.up_proj.weight", expert_id), | |
| "up_s": self.index_reader.get_expert_slice(f"{l_str}.up_proj.scales", expert_id), | |
| "up_b": self.index_reader.get_expert_slice(f"{l_str}.up_proj.biases", expert_id), | |
| "down_w": self.index_reader.get_expert_slice(f"{l_str}.down_proj.weight", expert_id), | |
| "down_s": self.index_reader.get_expert_slice(f"{l_str}.down_proj.scales", expert_id), | |
| "down_b": self.index_reader.get_expert_slice(f"{l_str}.down_proj.biases", expert_id), | |
| } | |
| self.cache.put(expert_id, weights) | |
| return weights | |
| def _qmatmul(x: mx.array, w: mx.array, s: mx.array, b: Optional[mx.array] = None) -> mx.array: | |
| """Dynamic quantized matrix multiplication auto-detecting bits and group size.""" | |
| k = x.shape[-1] | |
| bits = (w.shape[-1] * 32) // k | |
| group_size = k // s.shape[-1] | |
| return mx.quantized_matmul( | |
| x, w, scales=s, biases=b, transpose=True, group_size=group_size, bits=bits | |
| ) | |
| def forward_expert(self, x: mx.array, exp_id: int) -> mx.array: | |
| """Run forward pass for a single expert.""" | |
| exp_t = self._get_expert_tensors(exp_id) | |
| h_gate = self._qmatmul(x, exp_t["gate_w"], exp_t["gate_s"], exp_t["gate_b"]) | |
| h_up = self._qmatmul(x, exp_t["up_w"], exp_t["up_s"], exp_t["up_b"]) | |
| h_expert = nn.silu(h_gate) * h_up | |
| return self._qmatmul(h_expert, exp_t["down_w"], exp_t["down_s"], exp_t["down_b"]) | |
| def __call__(self, x: mx.array) -> mx.array: | |
| orig_shape = x.shape | |
| x_flat = x.reshape(-1, orig_shape[-1]) | |
| num_tokens, hidden_dim = x_flat.shape | |
| # 1. Router Gate (resident in RAM) | |
| if self.gate_scales is not None: | |
| logits = self._qmatmul(x_flat, self.gate_weight, self.gate_scales, self.gate_biases) | |
| else: | |
| logits = x_flat @ self.gate_weight.T | |
| k = self.top_k | |
| if self.softmax_before_topk: | |
| scores = mx.softmax(logits, axis=-1, precise=True) | |
| if self.topk_method == "group_limited_greedy" and self.n_group > 1: | |
| grouped_scores = scores.reshape(num_tokens, self.n_group, -1) | |
| group_scores = grouped_scores.max(axis=-1, keepdims=True) | |
| k_grp = self.n_group - self.topk_group | |
| group_idx = mx.argpartition(group_scores, kth=k_grp - 1, axis=-2)[..., :k_grp, :] | |
| scores = mx.put_along_axis( | |
| grouped_scores, group_idx, mx.array(0.0, scores.dtype), axis=-2 | |
| ).reshape(num_tokens, -1) | |
| top_k_indices = mx.argpartition(-scores, kth=k - 1, axis=-1)[..., :k] | |
| top_k_scores = mx.take_along_axis(scores, top_k_indices, axis=-1) | |
| if self.routed_scaling_factor != 1.0: | |
| top_k_scores = top_k_scores * self.routed_scaling_factor | |
| else: | |
| # Mixtral style: Top-k on logits first, then softmax across the top-k chosen logits | |
| top_k_indices = mx.stop_gradient(mx.argpartition(-logits, kth=k - 1, axis=-1)[..., :k]) | |
| chosen_logits = mx.take_along_axis(logits, top_k_indices, axis=-1) | |
| top_k_scores = mx.softmax(chosen_logits, axis=-1, precise=True) | |
| # 2. Shared Experts (resident in RAM) | |
| if self.shared is not None: | |
| sh_gate = self._qmatmul(x_flat, self.shared["gate_w"], self.shared["gate_s"], self.shared.get("gate_b")) | |
| sh_up = self._qmatmul(x_flat, self.shared["up_w"], self.shared["up_s"], self.shared.get("up_b")) | |
| h_shared = nn.silu(sh_gate) * sh_up | |
| out_shared = self._qmatmul(h_shared, self.shared["down_w"], self.shared["down_s"], self.shared.get("down_b")) | |
| else: | |
| out_shared = mx.zeros_like(x_flat) | |
| # 3. Dynamic Routed Experts Streaming (Vectorized on Metal GPU) | |
| out_routed = mx.zeros_like(x_flat) | |
| unique_experts = list(set(top_k_indices.flatten().tolist())) | |
| for exp_id in unique_experts: | |
| weight = mx.where( | |
| top_k_indices == exp_id, | |
| top_k_scores, | |
| mx.zeros_like(top_k_scores) | |
| ).sum(axis=-1, keepdims=True) | |
| exp_out = self.forward_expert(x_flat, exp_id) | |
| out_routed = out_routed + exp_out * weight | |
| final_out = (out_shared + out_routed).reshape(orig_shape) | |
| return final_out | |