Text Generation
TensorRT
Safetensors
PyTorch
English
llama
code
developer-agent
blackwell
rtx-5070
slm
conversational
Instructions to use Vivid86/MiniTransformer-91M with libraries, inference providers, notebooks, and local apps. Follow these links to get started.
- Libraries
- TensorRT
How to use Vivid86/MiniTransformer-91M with TensorRT:
# No code snippets available yet for this library. # To use this model, check the repository files and the library's documentation. # Want to help? PRs adding snippets are welcome at: # https://github.com/huggingface/huggingface.js
- Notebooks
- Google Colab
- Kaggle
Download inference/generate.py from Vivid86/MiniTransformer-91M: direct link, hf CLI and curl.
- Browser
- Download file 7.41 kB
-
https://huggingface.co/Vivid86/MiniTransformer-91M/resolve/main/inference/generate.py
- Command line
-
hf download hf://Vivid86/MiniTransformer-91M/inference/generate.py
-
curl -L -o generate.py https://huggingface.co/Vivid86/MiniTransformer-91M/resolve/main/inference/generate.py
7.41 kB
| """ | |
| Text generation with top-k + nucleus (top-p) sampling. | |
| SAMPLING STRATEGIES: | |
| βββββββββββββββββββββ | |
| GREEDY (temperature=0): | |
| Always picks the highest-probability token. Fast but repetitive β the model | |
| gets stuck in loops because the same high-probability token is chosen forever. | |
| TEMPERATURE SCALING: | |
| Divides logits by `temperature` before softmax: | |
| - temperature < 1.0 β sharper distribution β more confident, focused | |
| - temperature > 1.0 β flatter distribution β more random, creative | |
| - temperature = 1.0 β unmodified model distribution | |
| TOP-K FILTERING: | |
| Zeros out all but the K highest-probability tokens. Prevents sampling from | |
| the long tail of very unlikely tokens. Typical values: 40β100. | |
| TOP-P (NUCLEUS) SAMPLING: | |
| Sort tokens by probability (descending). Keep only the smallest set whose | |
| cumulative probability sum reaches `top_p`. The cutoff adapts to the shape | |
| of the distribution β if the model is confident (one token has 80% prob), | |
| nucleus is tight. If the model is uncertain, more tokens are included. | |
| COMBINING TOP-K AND TOP-P: | |
| Apply top-k first, then top-p on the survivors. This clips both the | |
| absolute count and the probability mass of the sampling pool. | |
| KV-CACHE AT INFERENCE: | |
| During training, the full sequence is processed in one forward pass. | |
| During autoregressive generation, each step appends one token and re-runs | |
| the model over the entire grown sequence β O(TΒ²) total compute. | |
| The KV-cache stores K, V tensors from all previous steps. Each new step | |
| only processes the single new token, then appends to the cache. | |
| Total compute drops to O(T) β a massive speedup for long generations. | |
| This implementation uses the cache from MiniTransformer. | |
| """ | |
| import torch | |
| import torch.nn.functional as F | |
| from tokenizer.bpe_tokenizer import BPETokenizer | |
| def sample_logits( | |
| logits: torch.Tensor, | |
| temperature: float = 1.0, | |
| top_k: int = 50, | |
| top_p: float = 0.9, | |
| ) -> int: | |
| """ | |
| Sample a single token ID from a logits tensor. | |
| Args: | |
| logits: Raw logits, shape [1, vocab_size]. | |
| temperature: Scaling factor. 0 β greedy argmax. | |
| top_k: Keep only top-k tokens (None or 0 to disable). | |
| top_p: Nucleus probability threshold (None or 1.0 to disable). | |
| Returns: | |
| A single integer token ID. | |
| """ | |
| # Greedy shortcut | |
| if temperature <= 0: | |
| return int(logits.argmax(dim=-1).item()) | |
| logits = logits / temperature | |
| # ββ Top-k filtering βββββββββββββββββββββββββββββββββββββββββββββββββββββββ | |
| if top_k and top_k > 0: | |
| k = min(top_k, logits.size(-1)) | |
| v, _ = torch.topk(logits, k) | |
| # v[:, -1:] is the k-th highest value per row β shape [B, 1] for broadcast | |
| logits = logits.masked_fill(logits < v[:, -1:], float("-inf")) | |
| # ββ Top-p (nucleus) filtering βββββββββββββββββββββββββββββββββββββββββββββ | |
| if top_p and top_p < 1.0: | |
| sorted_logits, sorted_indices = torch.sort(logits, descending=True) | |
| cumulative_probs = torch.cumsum(F.softmax(sorted_logits, dim=-1), dim=-1) | |
| # Remove tokens once the cumulative probability exceeds top_p. | |
| # Shift right by 1 so we always keep at least the top-1 token. | |
| remove_mask = (cumulative_probs - F.softmax(sorted_logits, dim=-1)) > top_p | |
| sorted_logits = sorted_logits.masked_fill(remove_mask, float("-inf")) | |
| # Scatter back to original token order | |
| logits = torch.zeros_like(logits).scatter_(1, sorted_indices, sorted_logits) | |
| probs = F.softmax(logits, dim=-1) | |
| return int(torch.multinomial(probs, num_samples=1).item()) | |
| def generate( | |
| model, | |
| prompt: str, | |
| tokenizer: "BPETokenizer | None" = None, | |
| max_new_tokens: int = 50, | |
| temperature: float = 0.8, | |
| top_k: int = 50, | |
| top_p: float = 0.9, | |
| device: str = "cuda" if torch.cuda.is_available() else "cpu", | |
| use_kv_cache: bool = True, | |
| repetition_penalty: float = 1.15, | |
| penalty_window: int = 64, | |
| ) -> str: | |
| """ | |
| Autoregressively generate text from a prompt using the trained model. | |
| Args: | |
| model: A trained MiniTransformer. | |
| prompt: Input text string to condition generation on. | |
| tokenizer: BPETokenizer instance. Created if not provided. | |
| Pass one in to avoid reloading from disk each call. | |
| max_new_tokens: Maximum number of tokens to generate. | |
| temperature: Sampling temperature (0 = greedy). | |
| top_k: Top-k filtering. Disable with None or 0. | |
| top_p: Nucleus sampling. Disable with None or 1.0. | |
| device: Device for inference ("cuda" or "cpu"). | |
| use_kv_cache: Use KV-cache for faster autoregressive inference. | |
| repetition_penalty: Multiplier to penalize repeated tokens (> 1.0 discourages loops). | |
| penalty_window: How many recent tokens to consider for the repetition penalty. | |
| Returns: | |
| The decoded generated string (prompt + continuation), cleaned. | |
| """ | |
| if tokenizer is None: | |
| tokenizer = BPETokenizer("dataProcessed/tokenizer.json") | |
| context_len = model.config.context_len | |
| model.eval() | |
| model.to(device) | |
| # Encode prompt to token IDs | |
| tokens = torch.tensor( | |
| tokenizer.encode(prompt), dtype=torch.long, device=device | |
| ).unsqueeze(0) # [1, prompt_len] | |
| past_kvs: list | None = None | |
| temperature = max(temperature, 1e-5) | |
| with torch.no_grad(): | |
| for _ in range(max_new_tokens): | |
| if use_kv_cache and past_kvs is not None: | |
| # KV-cache mode: only feed the single newest token | |
| context = tokens[:, -1:] | |
| else: | |
| # Full-context mode (first step or no cache): truncate to window | |
| context = tokens[:, -context_len:] | |
| logits, past_kvs_new = model(context, past_kvs if use_kv_cache else None) | |
| if use_kv_cache: | |
| past_kvs = past_kvs_new | |
| next_logits = logits[:, -1, :].clone() # [1, vocab_size] | |
| # Apply repetition penalty to recent tokens within the window | |
| if repetition_penalty > 1.0 and tokens.shape[1] > 0: | |
| recent_tokens = tokens[0, -penalty_window:].tolist() | |
| for token_id in set(recent_tokens): | |
| if next_logits[0, token_id] > 0: | |
| next_logits[0, token_id] /= repetition_penalty | |
| else: | |
| next_logits[0, token_id] *= repetition_penalty | |
| next_id = sample_logits(next_logits, temperature, top_k, top_p) | |
| # Stop generation when the model produces the EOS token | |
| if next_id == tokenizer.eos_id: | |
| break | |
| next_tensor = torch.tensor([[next_id]], dtype=torch.long, device=device) | |
| tokens = torch.cat([tokens, next_tensor], dim=1) | |
| decoded = tokenizer.decode(tokens[0].tolist()) | |
| return tokenizer.clean(decoded) | |