Instructions to use safffrron/25M2111-Week01-Track2-40-Submission01 with libraries, inference providers, notebooks, and local apps. Follow these links to get started.
- Libraries
- Transformers
How to use safffrron/25M2111-Week01-Track2-40-Submission01 with Transformers:
# Use a pipeline as a high-level helper from transformers import pipeline pipe = pipeline("text-generation", model="safffrron/25M2111-Week01-Track2-40-Submission01")# Load model directly from transformers import AutoModel model = AutoModel.from_pretrained("safffrron/25M2111-Week01-Track2-40-Submission01", device_map="auto") - Notebooks
- Google Colab
- Kaggle
- Local Apps Settings
- vLLM
How to use safffrron/25M2111-Week01-Track2-40-Submission01 with vLLM:
Install from pip and serve model
# Install vLLM from pip: pip install vllm # Start the vLLM server: vllm serve "safffrron/25M2111-Week01-Track2-40-Submission01" # Call the server using curl (OpenAI-compatible API): curl -X POST "http://localhost:8000/v1/completions" \ -H "Content-Type: application/json" \ --data '{ "model": "safffrron/25M2111-Week01-Track2-40-Submission01", "prompt": "Once upon a time,", "max_tokens": 512, "temperature": 0.5 }'Use Docker
docker model run hf.co/safffrron/25M2111-Week01-Track2-40-Submission01
- SGLang
How to use safffrron/25M2111-Week01-Track2-40-Submission01 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 "safffrron/25M2111-Week01-Track2-40-Submission01" \ --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": "safffrron/25M2111-Week01-Track2-40-Submission01", "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 "safffrron/25M2111-Week01-Track2-40-Submission01" \ --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": "safffrron/25M2111-Week01-Track2-40-Submission01", "prompt": "Once upon a time,", "max_tokens": 512, "temperature": 0.5 }' - Docker Model Runner
How to use safffrron/25M2111-Week01-Track2-40-Submission01 with Docker Model Runner:
docker model run hf.co/safffrron/25M2111-Week01-Track2-40-Submission01
File size: 8,982 Bytes
8e4dac5 | 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 117 118 119 120 121 122 123 124 125 126 127 128 129 130 131 132 133 134 135 136 137 138 139 140 141 142 143 144 145 146 147 148 149 150 151 152 153 154 155 156 157 158 159 160 161 162 163 164 165 166 167 168 169 170 171 172 173 174 175 176 177 178 179 180 181 182 183 184 185 186 187 188 189 190 191 192 193 194 195 196 197 198 199 200 201 202 203 204 205 206 207 208 209 210 211 212 213 214 215 216 217 218 219 220 221 222 223 224 225 226 227 228 229 230 231 232 233 234 | """Group-wise weight quantization with exact size accounting.
Simulated ("fake") quantization: weights are quantized then dequantized back to
bf16, so the saved checkpoint is still a normal HF model that vLLM and
`transformers` load unchanged. That is not a hack — it mirrors the submission
pipeline exactly, where ``convert_to_hf_checkpoint`` must emit a full bf16 model.
The *scored* size is computed analytically from the recipe, not from the bytes on
disk.
This lets us answer the question that decides our compression ceiling — how far
can each layer group be pushed before long chain-of-thought breaks — without
first committing to a packed format or a quantization toolchain.
Round-to-nearest is deliberate as a starting point: it is the floor, needs no
calibration data, and is enough to *rank* layer-group sensitivity.
But it is a worse floor than we assumed. arXiv 2606.25519 measures CoT *token
inflation* by quantizer on Qwen3-4B at group size 128, and RTN is the worst of
the lot: +42.5% at INT4 against GPTQ's +12.0% and rotation-based ParoQuant's
+4.7%. At INT3 the spread across methods reaches 10x. Since our accuracy is
gated by truncation, token inflation is the quantity that actually costs us
points -- so moving off RTN is worth considerably more here than the "1-2
points" that reconstruction-error framing would suggest.
"""
from __future__ import annotations
import re
from dataclasses import dataclass
from typing import Any, Iterable
import torch
KEEP_BITS = 16 # bf16 passthrough
@dataclass(frozen=True)
class QuantSpec:
"""Quantization for every parameter whose name matches ``pattern``.
``group_size`` groups along the input dimension (the last axis); 0 means one
group per output channel. Smaller groups cost more scale bytes but track the
weight distribution better.
"""
pattern: str
bits: int
group_size: int = 128
symmetric: bool = True
def bits_per_weight(self) -> float:
"""Effective stored bits per weight, including scale/zero-point overhead."""
if self.bits >= KEEP_BITS:
return float(KEEP_BITS)
if self.group_size <= 0:
return float(self.bits)
# fp16 scale per group, plus an int zero-point per group when asymmetric.
overhead = 16 + (0 if self.symmetric else self.bits)
return self.bits + overhead / self.group_size
def quantize_dequantize(
weight: torch.Tensor, spec: QuantSpec
) -> torch.Tensor:
"""Round-trip ``weight`` through ``spec``'s grid, returning the same dtype."""
if spec.bits >= KEEP_BITS:
return weight
original_dtype, original_shape = weight.dtype, weight.shape
group_size = spec.group_size if spec.group_size > 0 else original_shape[-1]
if original_shape[-1] % group_size != 0:
# Fall back to per-channel rather than silently mis-grouping.
group_size = original_shape[-1]
flat = weight.reshape(-1, group_size).float()
if spec.symmetric:
qmax = 2 ** (spec.bits - 1) - 1
scale = (flat.abs().amax(dim=1, keepdim=True) / qmax).clamp(min=1e-8)
q = torch.round(flat / scale).clamp(-qmax - 1, qmax)
out = q * scale
else:
qmax = 2**spec.bits - 1
wmin = flat.amin(dim=1, keepdim=True)
wmax = flat.amax(dim=1, keepdim=True)
scale = ((wmax - wmin) / qmax).clamp(min=1e-8)
zero = torch.round(-wmin / scale)
q = torch.clamp(torch.round(flat / scale) + zero, 0, qmax)
out = (q - zero) * scale
return out.reshape(original_shape).to(original_dtype)
class Recipe:
"""Ordered specs; first match wins, anything unmatched stays bf16."""
def __init__(self, specs: Iterable[QuantSpec]):
self.specs = list(specs)
self._compiled = [(re.compile(s.pattern), s) for s in self.specs]
def spec_for(self, name: str) -> QuantSpec | None:
for regex, spec in self._compiled:
if regex.search(name):
return spec
return None
# The vision tower and MTP head are never executed by a text-only math eval, and
# a real submission simply drops them (llama.cpp's text-only conversion of this
# model does exactly that). They are excluded from both quantization and the size
# accounting. We nonetheless keep them *present* in the saved checkpoint, because
# vLLM refuses to load a text-only Qwen3_5 config (vllm#39231).
EXCLUDED = r"visual|vision_tower|(^|\.)mtp\."
def apply_recipe(
model: torch.nn.Module, recipe: Recipe, device: str | None = None
) -> dict[str, Any]:
"""Fake-quantize ``model`` in place; return per-group size accounting.
Tied tensors are counted once — Qwen3.5 ties ``lm_head`` to ``embed_tokens``,
and double-counting would overstate the checkpoint by 1.27 GB.
"""
excluded_regex = re.compile(EXCLUDED)
seen_storage: set[int] = set()
groups: dict[str, dict[str, float]] = {}
total_bits = 0.0
total_params = 0
excluded_params = 0
with torch.no_grad():
for name, param in model.named_parameters():
if excluded_regex.search(name):
excluded_params += param.numel()
continue
spec = recipe.spec_for(name)
bits = spec.bits_per_weight() if spec else float(KEEP_BITS)
if spec is not None and spec.bits < KEEP_BITS:
target = param.data.to(device) if device else param.data
quantized = quantize_dequantize(target, spec)
param.data.copy_(quantized.to(param.data.device))
pointer = param.data_ptr()
if pointer in seen_storage:
continue # tied alias: already counted
seen_storage.add(pointer)
label = _group_label(name, spec)
entry = groups.setdefault(
label, {"params": 0, "bits_per_weight": bits, "bytes": 0.0}
)
entry["params"] += param.numel()
entry["bytes"] += param.numel() * bits / 8
total_params += param.numel()
total_bits += param.numel() * bits
total_bytes = total_bits / 8
return {
"total_params": total_params,
"total_bytes": int(total_bytes),
"total_gb": total_bytes / 1e9,
"effective_bits_per_weight": total_bits / total_params if total_params else 0.0,
"compression_vs_bf16": (total_params * 2) / total_bytes if total_bytes else 0.0,
"groups": groups,
# Present in the saved checkpoint for vLLM compatibility, excluded from
# the score because a real submission drops them.
"excluded_params": excluded_params,
"excluded_gb_bf16": excluded_params * 2 / 1e9,
}
def _group_label(name: str, spec: QuantSpec | None) -> str:
from .model import BUDGET_GROUPS
for group, pattern in BUDGET_GROUPS:
if re.search(pattern, name):
return f"{group}@{spec.bits if spec else KEEP_BITS}b"
return f"other@{spec.bits if spec else KEEP_BITS}b"
def format_size_report(report: dict[str, Any]) -> str:
lines = [
f"{'group':<22}{'params':>15}{'bpw':>7}{'GB':>9}",
"-" * 53,
]
for label, stats in sorted(report["groups"].items(), key=lambda kv: -kv[1]["params"]):
lines.append(
f"{label:<22}{stats['params']:>15,}"
f"{stats['bits_per_weight']:>7.2f}{stats['bytes'] / 1e9:>9.3f}"
)
lines.append("-" * 53)
lines.append(
f"{'TOTAL':<22}{report['total_params']:>15,}"
f"{report['effective_bits_per_weight']:>7.2f}{report['total_gb']:>9.3f}"
)
lines.append(f" compression vs bf16: {report['compression_vs_bf16']:.2f}x")
if report.get("excluded_params"):
lines.append(
f" excluded (vision+MTP, present on disk but not scored): "
f"{report['excluded_params']:,} params / {report['excluded_gb_bf16']:.2f} GB"
)
return "\n".join(lines)
# The SSM recurrence dynamics must stay high precision: error compounds through
# the linear recurrence instead of being renormalized each step, and naive
# low-bit PTQ on these collapses SSM models entirely. They are ~0.02% of
# parameters, so protecting all of them is nearly free.
PROTECTED = QuantSpec(
pattern=r"A_log|dt_bias|conv1d|in_proj_a|in_proj_b|norm|bias",
bits=KEEP_BITS,
)
def build_recipe(
mlp_bits: int = 16,
linear_attn_bits: int = 16,
full_attn_bits: int = 16,
embed_bits: int = 16,
group_size: int = 128,
symmetric: bool = True,
) -> Recipe:
"""Per-component recipe. PROTECTED comes first so it always wins."""
return Recipe(
[
PROTECTED,
QuantSpec(r"embed_tokens|lm_head", embed_bits, group_size, symmetric),
QuantSpec(r"linear_attn", linear_attn_bits, group_size, symmetric),
QuantSpec(r"self_attn", full_attn_bits, group_size, symmetric),
QuantSpec(r"\.mlp\.", mlp_bits, group_size, symmetric),
]
)
|