Sample a single next token from logits [B, vocab].
(
logits: torch.Tensor,
temperature: float,
top_k: int,
top_p: float,
)
| 314 | |
| 315 | @staticmethod |
| 316 | def _sample_next_token( |
| 317 | logits: torch.Tensor, |
| 318 | temperature: float, |
| 319 | top_k: int, |
| 320 | top_p: float, |
| 321 | ) -> torch.Tensor: |
| 322 | """Sample a single next token from logits [B, vocab].""" |
| 323 | next_logits = logits.clone() |
| 324 | |
| 325 | if temperature > 0: |
| 326 | next_logits = next_logits / temperature |
| 327 | |
| 328 | if top_k > 0: |
| 329 | topk_vals, _ = torch.topk(next_logits, top_k) |
| 330 | next_logits[next_logits < topk_vals[:, -1:]] = float("-inf") |
| 331 | |
| 332 | if top_p < 1.0: |
| 333 | sorted_logits, sorted_indices = torch.sort( |
| 334 | next_logits, descending=True |
| 335 | ) |
| 336 | cumulative_probs = ( |
| 337 | torch.softmax(sorted_logits, dim=-1).cumsum(dim=-1) |
| 338 | ) |
| 339 | remove_mask = cumulative_probs > top_p |
| 340 | remove_mask[:, 1:] = remove_mask[:, :-1].clone() |
| 341 | remove_mask[:, 0] = False |
| 342 | sorted_logits[remove_mask] = float("-inf") |
| 343 | next_logits = sorted_logits.scatter( |
| 344 | 1, sorted_indices, sorted_logits |
| 345 | ) |
| 346 | |
| 347 | probs = torch.softmax(next_logits, dim=-1) |
| 348 | next_token = torch.multinomial(probs, num_samples=1) |
| 349 | else: |
| 350 | next_token = next_logits.argmax(dim=-1, keepdim=True) |
| 351 | |
| 352 | return next_token |
| 353 | |
| 354 | @torch.no_grad() |
| 355 | def generate( |
no outgoing calls
no test coverage detected