| 39 | } |
| 40 | |
| 41 | int Sampler::sample(const InferenceState& s, float temperature, float top_p) { |
| 42 | if (temperature == 0.0) { |
| 43 | return sample_argmax(s); |
| 44 | } |
| 45 | const float* logits = s.logits(); |
| 46 | int* logit_indices = s.logit_indices(); |
| 47 | // Find max value to moderate the logits later on for numerical stability |
| 48 | float max_val = -FLT_MAX; |
| 49 | for (int i = 0; i < vocab_size; ++i) { |
| 50 | if (logits[i] > max_val) { |
| 51 | max_val = logits[i]; |
| 52 | } |
| 53 | } |
| 54 | float sum = 0; |
| 55 | for (int i = 0; i < vocab_size; ++i) { |
| 56 | sum += expf((logits[i] - max_val) / temperature); |
| 57 | } |
| 58 | // Sort logits descending for nucleus/top-p sampling (https://arxiv.org/abs/1904.09751) |
| 59 | if (top_p < 1.0) { |
| 60 | std::sort( |
| 61 | logit_indices, logit_indices + vocab_size, |
| 62 | [&logits](int i, int j) { return logits[i] > logits[j]; } |
| 63 | ); |
| 64 | } |
| 65 | // Randomly sample from the softmaxed logits distribution |
| 66 | float r = std::rand() / (float)RAND_MAX * top_p; |
| 67 | float cumsum = 0; |
| 68 | for (int i = 0; i < vocab_size; ++i) { |
| 69 | cumsum += expf((logits[i] - max_val) / temperature) / sum; |
| 70 | if (cumsum >= r) { |
| 71 | return i; |
| 72 | } |
| 73 | } |
| 74 | return vocab_size - 1; |
| 75 | } |
| 76 |
no test coverage detected