Text Generation
Transformers
Safetensors
English
qwen2
speculative-decoding
set-block-decoding
text-to-sql
lossless-acceleration
inference-acceleration
conversational
custom_code
text-generation-inference
Instructions to use belumind/sbd-sql-0.5b with libraries, inference providers, notebooks, and local apps. Follow these links to get started.
- Libraries
- Transformers
How to use belumind/sbd-sql-0.5b with Transformers:
# Use a pipeline as a high-level helper from transformers import pipeline pipe = pipeline("text-generation", model="belumind/sbd-sql-0.5b", trust_remote_code=True) messages = [ {"role": "user", "content": "Who are you?"}, ] pipe(messages)# pip install -U transformers accelerate # Load model directly from transformers import AutoTokenizer, AutoModelForCausalLM tokenizer = AutoTokenizer.from_pretrained("belumind/sbd-sql-0.5b", trust_remote_code=True) model = AutoModelForCausalLM.from_pretrained("belumind/sbd-sql-0.5b", trust_remote_code=True, device_map="auto") messages = [ {"role": "user", "content": "Who are you?"}, ] inputs = tokenizer.apply_chat_template( messages, add_generation_prompt=True, tokenize=True, return_dict=True, return_tensors="pt", ).to(model.device) outputs = model.generate(**inputs, max_new_tokens=256) print(tokenizer.decode(outputs[0][inputs["input_ids"].shape[-1]:])) - Notebooks
- Google Colab
- Kaggle
- Local Apps Settings
- vLLM
How to use belumind/sbd-sql-0.5b with vLLM:
Install from pip and serve model
# Install vLLM from pip: pip install vllm # Start the vLLM server: vllm serve "belumind/sbd-sql-0.5b" # Call the server using curl (OpenAI-compatible API): curl -X POST "http://localhost:8000/v1/chat/completions" \ -H "Content-Type: application/json" \ --data '{ "model": "belumind/sbd-sql-0.5b", "messages": [ { "role": "user", "content": "What is the capital of France?" } ] }'Use Docker
docker model run hf.co/belumind/sbd-sql-0.5b
- SGLang
How to use belumind/sbd-sql-0.5b 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 "belumind/sbd-sql-0.5b" \ --host 0.0.0.0 \ --port 30000 # Call the server using curl (OpenAI-compatible API): curl -X POST "http://localhost:30000/v1/chat/completions" \ -H "Content-Type: application/json" \ --data '{ "model": "belumind/sbd-sql-0.5b", "messages": [ { "role": "user", "content": "What is the capital of France?" } ] }'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 "belumind/sbd-sql-0.5b" \ --host 0.0.0.0 \ --port 30000 # Call the server using curl (OpenAI-compatible API): curl -X POST "http://localhost:30000/v1/chat/completions" \ -H "Content-Type: application/json" \ --data '{ "model": "belumind/sbd-sql-0.5b", "messages": [ { "role": "user", "content": "What is the capital of France?" } ] }' - Docker Model Runner
How to use belumind/sbd-sql-0.5b with Docker Model Runner:
docker model run hf.co/belumind/sbd-sql-0.5b
Download modeling_sbd.py from belumind/sbd-sql-0.5b: direct link, hf CLI and curl.
- Browser
- Download file 7.28 kB
-
https://huggingface.co/belumind/sbd-sql-0.5b/resolve/main/modeling_sbd.py
- Command line
-
hf download hf://belumind/sbd-sql-0.5b/modeling_sbd.py
-
curl -L -o modeling_sbd.py https://huggingface.co/belumind/sbd-sql-0.5b/resolve/main/modeling_sbd.py
7.28 kB
| """Set Block Decoding inference wrapper for Qwen2 (Belumind). | |
| Adds sbd_generate(): lossless speculative decoding driven by three proposal | |
| sources -- the causal NTP frontier, MATP over a trailing masked block, and | |
| n-gram lookup over the prompt -- with exact verification folded into the next | |
| proposal forward pass. | |
| Reference implementation. It runs without a KV cache: every step recomputes the | |
| whole sequence. tokens/forward is an accounting metric, not a wall-clock claim. | |
| See the model card. | |
| """ | |
| import torch | |
| from transformers.models.qwen2.modeling_qwen2 import Qwen2ForCausalLM | |
| DEFAULT_MASK_TOKEN_ID = 151662 # <|fim_pad|> in the Qwen2.5 vocabulary | |
| def sliding_block_mask(total_len, block_start, device, dtype): | |
| """Causal over the prefix, bidirectional from block_start onward. | |
| The block slides with the frontier instead of sitting on a fixed grid, so | |
| the last committed position always has a purely causal context and a valid | |
| NTP prediction always exists. | |
| """ | |
| idx = torch.arange(total_len, device=device) | |
| causal = idx.view(1, total_len) <= idx.view(total_len, 1) | |
| inblk = idx >= block_start | |
| allowed = causal | (inblk.view(1, total_len) & inblk.view(total_len, 1)) | |
| m = torch.zeros(total_len, total_len, device=device, dtype=dtype) | |
| m.masked_fill_(~allowed, torch.finfo(dtype).min) | |
| return m.view(1, 1, total_len, total_len) | |
| def ngram_propose(ids, k, n_max=4, window=3000): | |
| """Most recent match of the longest suffix, and whatever followed it.""" | |
| n_ids = len(ids) | |
| for n in range(n_max, 1, -1): | |
| if n_ids < n: | |
| continue | |
| pat = ids[-n:] | |
| lo = max(0, n_ids - window) | |
| for i in range(n_ids - n - 1, lo - 1, -1): | |
| if ids[i:i + n] == pat: | |
| cand = ids[i + n:i + n + k] | |
| if cand: | |
| return cand | |
| return [] | |
| class SBDQwen2ForCausalLM(Qwen2ForCausalLM): | |
| """Qwen2 with a Set Block Decoding entrypoint. generate() is unaffected.""" | |
| def sbd_generate(self, input_ids, attention_mask=None, max_new_tokens=128, | |
| block_size=8, threshold=0.6, | |
| sources=("ntp", "matp", "ngram"), | |
| mask_token_id=None, eos_token_id=None, | |
| stop_at_eos=True, return_stats=False, **kwargs): | |
| if input_ids.dim() != 2 or input_ids.shape[0] != 1: | |
| raise ValueError("sbd_generate supports batch size 1 only") | |
| if attention_mask is not None and int(attention_mask.sum()) != attention_mask.numel(): | |
| raise ValueError("padded prompts are not supported") | |
| dev = input_ids.device | |
| dt = next(self.parameters()).dtype | |
| if mask_token_id is None: | |
| mask_token_id = getattr(self.config, "sbd_mask_token_id", DEFAULT_MASK_TOKEN_ID) | |
| if eos_token_id is None: | |
| eos_token_id = self.config.eos_token_id | |
| if not stop_at_eos or eos_token_id is None: | |
| eos_ids = set() | |
| elif isinstance(eos_token_id, int): | |
| eos_ids = {eos_token_id} | |
| else: | |
| eos_ids = set(eos_token_id) | |
| use_matp = "matp" in sources | |
| use_ngram = "ngram" in sources | |
| B = max(1, int(block_size)) | |
| p0 = input_ids.shape[1] | |
| seq = input_ids.clone() | |
| verified = p0 | |
| fwd = 0 | |
| rollbacks = 0 | |
| acc = {"ntp": 0, "matp": 0, "ngram": 0} | |
| pend = [] | |
| stop_at = None | |
| cap = int(max_new_tokens) + 4 | |
| while fwd < cap: | |
| bs = seq.shape[1] | |
| block = torch.full((1, B), mask_token_id, device=dev, dtype=seq.dtype) | |
| inp = torch.cat([seq, block], 1) | |
| mask = sliding_block_mask(inp.shape[1], bs, dev, dt) | |
| logits = self(input_ids=inp, attention_mask=mask, use_cache=False).logits[0] | |
| fwd += 1 | |
| # ---- verification. Free: this forward computed these conditionals | |
| # anyway in order to make the next proposal. | |
| if bs > verified: | |
| pred = logits[verified - 1:bs - 1].argmax(-1) | |
| bad = (pred != seq[0, verified:bs]).nonzero() | |
| if len(bad): | |
| k = int(bad[0]) | |
| rollbacks += 1 | |
| for j in range(max(0, k - 1)): | |
| acc[pend[j]] += 1 | |
| acc["ntp"] += 1 if k == 0 else 2 | |
| seq = torch.cat([seq[:, :verified + k], pred[k].view(1, 1)], 1) | |
| verified = verified + k + 1 | |
| pend = [] | |
| stop_at = self._first_eos(seq, p0, verified, eos_ids) | |
| if stop_at is not None or verified - p0 >= max_new_tokens: | |
| break | |
| # the rest of this forward described a prefix that was just | |
| # rejected; it cannot be used to propose. Take a fresh one. | |
| continue | |
| acc["ntp"] += 1 | |
| for j in range(len(pend)): | |
| acc[pend[j]] += 1 | |
| verified = bs | |
| pend = [] | |
| stop_at = self._first_eos(seq, p0, verified, eos_ids) | |
| if stop_at is not None: | |
| break | |
| if verified - p0 >= max_new_tokens: | |
| break | |
| # ---- proposal | |
| ntp = int(logits[bs - 1].argmax()) | |
| nxt = [ntp] | |
| src = [] | |
| if use_matp or use_ngram: | |
| conf, arg = logits[bs:bs + B].float().softmax(-1).max(-1) | |
| matp = [] | |
| if use_matp: | |
| j = 1 | |
| while j < B and float(conf[j]) >= threshold: | |
| matp.append(int(arg[j])) | |
| j += 1 | |
| if use_ngram: | |
| ngm = ngram_propose(seq[0].tolist() + [ntp], B - 1) | |
| if len(matp) < B - 1 and len(ngm) > len(matp): | |
| extra = ngm[len(matp):B - 1] | |
| else: | |
| extra = [] | |
| else: | |
| extra = [] | |
| nxt += matp | |
| src += ["matp"] * len(matp) | |
| nxt += extra | |
| src += ["ngram"] * len(extra) | |
| pend = src | |
| seq = torch.cat([seq, torch.tensor([nxt], device=dev, dtype=seq.dtype)], 1) | |
| committed = verified - p0 | |
| end = verified if stop_at is None else stop_at | |
| end = min(end, p0 + max_new_tokens) | |
| out = seq[:, :end] | |
| if not return_stats: | |
| return out | |
| tot = sum(acc.values()) | |
| stats = { | |
| "forwards": fwd, | |
| "tokens_committed": committed, | |
| "tokens_returned": end - p0, | |
| "tokens_per_forward": (committed / fwd) if fwd else 0.0, | |
| "rollbacks": rollbacks, | |
| "accepted": dict(acc), | |
| "pct_from_ngram": (acc["ngram"] / tot) if tot else 0.0, | |
| "pct_from_matp": (acc["matp"] / tot) if tot else 0.0, | |
| } | |
| return out, stats | |
| def _first_eos(seq, p0, verified, eos_ids): | |
| if not eos_ids: | |
| return None | |
| for i in range(p0, verified): | |
| if int(seq[0, i]) in eos_ids: | |
| return i + 1 | |
| return None | |