| 8309 | } |
| 8310 | |
| 8311 | void llama_sample_typical(struct llama_context * ctx, llama_token_data_array * candidates, float p, size_t min_keep) { |
| 8312 | // Reference implementation: |
| 8313 | // https://github.com/huggingface/transformers/compare/main...cimeister:typical-sampling:typical-pr |
| 8314 | if (p >= 1.0f) { |
| 8315 | return; |
| 8316 | } |
| 8317 | |
| 8318 | // Compute the softmax of logits and calculate entropy |
| 8319 | llama_sample_softmax(nullptr, candidates); |
| 8320 | |
| 8321 | const int64_t t_start_sample_us = ggml_time_us(); |
| 8322 | |
| 8323 | float entropy = 0.0f; |
| 8324 | for (size_t i = 0; i < candidates->size; ++i) { |
| 8325 | entropy += -candidates->data[i].p * logf(candidates->data[i].p); |
| 8326 | } |
| 8327 | |
| 8328 | // Compute the absolute difference between negative log probability and entropy for each candidate |
| 8329 | std::vector<float> shifted_scores; |
| 8330 | for (size_t i = 0; i < candidates->size; ++i) { |
| 8331 | float shifted_score = fabsf(-logf(candidates->data[i].p) - entropy); |
| 8332 | shifted_scores.push_back(shifted_score); |
| 8333 | } |
| 8334 | |
| 8335 | // Sort tokens based on the shifted_scores and their corresponding indices |
| 8336 | std::vector<size_t> indices(candidates->size); |
| 8337 | std::iota(indices.begin(), indices.end(), 0); |
| 8338 | |
| 8339 | std::sort(indices.begin(), indices.end(), [&](size_t a, size_t b) { |
| 8340 | return shifted_scores[a] < shifted_scores[b]; |
| 8341 | }); |
| 8342 | |
| 8343 | // Compute the cumulative probabilities |
| 8344 | float cum_sum = 0.0f; |
| 8345 | size_t last_idx = indices.size(); |
| 8346 | |
| 8347 | for (size_t i = 0; i < indices.size(); ++i) { |
| 8348 | size_t idx = indices[i]; |
| 8349 | cum_sum += candidates->data[idx].p; |
| 8350 | |
| 8351 | // Check if the running sum is greater than typical or if we have kept at least min_keep tokens |
| 8352 | if (cum_sum > p && i >= min_keep - 1) { |
| 8353 | last_idx = i + 1; |
| 8354 | break; |
| 8355 | } |
| 8356 | } |
| 8357 | |
| 8358 | // Resize the output vector to keep only the locally typical tokens |
| 8359 | std::vector<llama_token_data> new_candidates; |
| 8360 | for (size_t i = 0; i < last_idx; ++i) { |
| 8361 | size_t idx = indices[i]; |
| 8362 | new_candidates.push_back(candidates->data[idx]); |
| 8363 | } |
| 8364 | |
| 8365 | // Replace the data in candidates with the new_candidates data |
| 8366 | std::copy(new_candidates.begin(), new_candidates.end(), candidates->data); |
| 8367 | candidates->size = new_candidates.size(); |
| 8368 | |