Text Classification
MLX
English
decision-model
calibration
lora
activated-lora
adaptive-reasoning
on-device
Instructions to use suhaas-teja/Dev-4B with libraries, inference providers, notebooks, and local apps. Follow these links to get started.
- Libraries
- MLX
How to use suhaas-teja/Dev-4B with MLX:
# Download the model from the Hub pip install huggingface_hub[hf_xet] hf download suhaas-teja/Dev-4B --local-dir Dev-4B
- Notebooks
- Google Colab
- Kaggle
- Local Apps Settings
- LM Studio
- Atomic Chat
Download dmm/cache.py from suhaas-teja/Dev-4B: direct link, hf CLI and curl.
- Browser
- Download file 2.94 kB
-
https://huggingface.co/suhaas-teja/Dev-4B/resolve/main/dmm/cache.py
- Command line
-
hf download hf://suhaas-teja/Dev-4B/dmm/cache.py
-
curl -L -o cache.py https://huggingface.co/suhaas-teja/Dev-4B/resolve/main/dmm/cache.py
2.94 kB
| """Shared prefill: encode a state once with the base, then run questions or generation on it. | |
| The state is prefilled with the adapter off, which is exactly what the masked adapter computes | |
| on state tokens. Each question suffix then runs with the adapter on against that cache, and the | |
| cache is cropped back to the state afterwards, so any number of questions, and an escalation to | |
| generation, reuse one prefill. | |
| """ | |
| import numpy as np | |
| import torch | |
| from dmm import lora | |
| from dmm.head import option_logits | |
| from dmm.template import Template, decision_text | |
| class StateCache: | |
| def __init__(self, model, ids: list[int]): | |
| self.model, self.ids = model, list(ids) | |
| with torch.no_grad(), lora.disabled(model): | |
| out = model.model(input_ids=torch.tensor([ids], device=model.device), use_cache=True) | |
| self.kv = out.past_key_values | |
| def __len__(self) -> int: | |
| return len(self.ids) | |
| def run_suffix(self, suffix: list[int], adapter: bool = True) -> torch.Tensor: | |
| """Final hidden state at the suffix's last token; the cache is cropped back after.""" | |
| try: | |
| ctx = lora.disabled(self.model) if not adapter else _null() | |
| with ctx: | |
| out = self.model.model( | |
| input_ids=torch.tensor([suffix], device=self.model.device), | |
| past_key_values=self.kv, | |
| use_cache=True, | |
| ) | |
| return out.last_hidden_state[0, -1] | |
| finally: | |
| self.kv.crop(len(self.ids)) | |
| class _null: | |
| def __enter__(self): | |
| return None | |
| def __exit__(self, *exc): | |
| return False | |
| class CachedDecisionModel: | |
| """decide(items) through the shared-prefill path: one state prefill per distinct state.""" | |
| def __init__(self, model, tokenizer, head, temperatures=None): | |
| self.model, self.head, self.tpl = model, head, Template(tokenizer) | |
| self.temperatures = temperatures or {} | |
| self.prefills = 0 | |
| def option_logits(self, items: list[dict]) -> list[torch.Tensor]: | |
| out: list = [None] * len(items) | |
| by_state: dict[str, list[int]] = {} | |
| for i, it in enumerate(items): | |
| by_state.setdefault(it["state"], []).append(i) | |
| for _, idx in by_state.items(): | |
| cache = StateCache(self.model, self.tpl.state_ids(items[idx[0]])) | |
| self.prefills += 1 | |
| for i in idx: | |
| h = cache.run_suffix(self.tpl.encode(decision_text(items[i]))) | |
| out[i] = option_logits(self.head(h[None]), [items[i]])[0].float().cpu() | |
| return out | |
| def decide(self, items: list[dict]) -> list[np.ndarray]: | |
| out = [] | |
| for z, it in zip(self.option_logits(items), items, strict=True): | |
| z = z / self.temperatures.get(it["kind"], 1.0) | |
| out.append(torch.softmax(z, -1).numpy().astype(np.float64)) | |
| return out | |