| 399 | } |
| 400 | |
| 401 | gpt_vocab::id gpt_sample_top_k_top_p( |
| 402 | const gpt_vocab & vocab, |
| 403 | const float * logits, |
| 404 | int top_k, |
| 405 | double top_p, |
| 406 | double temp, |
| 407 | std::mt19937 & rng) { |
| 408 | int n_logits = vocab.id_to_token.size(); |
| 409 | |
| 410 | std::vector<std::pair<double, gpt_vocab::id>> logits_id; |
| 411 | logits_id.reserve(n_logits); |
| 412 | |
| 413 | { |
| 414 | const double scale = 1.0/temp; |
| 415 | for (int i = 0; i < n_logits; ++i) { |
| 416 | logits_id.push_back(std::make_pair(logits[i]*scale, i)); |
| 417 | } |
| 418 | } |
| 419 | |
| 420 | // find the top K tokens |
| 421 | std::partial_sort( |
| 422 | logits_id.begin(), |
| 423 | logits_id.begin() + top_k, logits_id.end(), |
| 424 | [](const std::pair<double, gpt_vocab::id> & a, const std::pair<double, gpt_vocab::id> & b) { |
| 425 | return a.first > b.first; |
| 426 | }); |
| 427 | |
| 428 | logits_id.resize(top_k); |
| 429 | |
| 430 | double maxl = -INFINITY; |
| 431 | for (const auto & kv : logits_id) { |
| 432 | maxl = std::max(maxl, kv.first); |
| 433 | } |
| 434 | |
| 435 | // compute probs for the top K tokens |
| 436 | std::vector<double> probs; |
| 437 | probs.reserve(logits_id.size()); |
| 438 | |
| 439 | double sum = 0.0; |
| 440 | for (const auto & kv : logits_id) { |
| 441 | double p = exp(kv.first - maxl); |
| 442 | probs.push_back(p); |
| 443 | sum += p; |
| 444 | } |
| 445 | |
| 446 | // normalize the probs |
| 447 | for (auto & p : probs) { |
| 448 | p /= sum; |
| 449 | } |
| 450 | |
| 451 | if (top_p < 1.0f) { |
| 452 | double cumsum = 0.0f; |
| 453 | for (int i = 0; i < top_k; i++) { |
| 454 | cumsum += probs[i]; |
| 455 | if (cumsum >= top_p) { |
| 456 | top_k = i + 1; |
| 457 | probs.resize(top_k); |
| 458 | logits_id.resize(top_k); |