| 193 | } |
| 194 | |
| 195 | static void test_sampler_queue(const size_t n_vocab, const std::string & samplers_sequence, const int top_k, const float top_p, const float min_p |
| 196 | ) { |
| 197 | sampler_tester tester(n_vocab); |
| 198 | |
| 199 | llama_token min_token_id = 0; |
| 200 | const llama_token max_token_id = n_vocab-1; |
| 201 | |
| 202 | for (auto s : samplers_sequence) { |
| 203 | switch (s){ |
| 204 | case 'k': tester.apply(llama_sampler_init_top_k(top_k)); break; |
| 205 | case 'y': GGML_ABORT("typical test not implemented"); |
| 206 | case 'p': tester.apply(llama_sampler_init_top_p(top_p, 1)); break; |
| 207 | case 'm': tester.apply(llama_sampler_init_min_p(min_p, 1)); break; |
| 208 | case 't': GGML_ABORT("temperature test not implemented"); |
| 209 | default : GGML_ABORT("Unknown sampler"); |
| 210 | } |
| 211 | |
| 212 | tester.apply(llama_sampler_init_dist(0)); |
| 213 | |
| 214 | auto & cur_p = tester.cur_p; |
| 215 | |
| 216 | const int size = cur_p.size; |
| 217 | |
| 218 | if (s == 'k') { |
| 219 | const int expected_size = std::min(size, top_k); |
| 220 | min_token_id = std::max(min_token_id, (llama_token)(n_vocab - top_k)); |
| 221 | |
| 222 | GGML_ASSERT(size == expected_size); |
| 223 | GGML_ASSERT(cur_p.data[0].id == max_token_id); |
| 224 | GGML_ASSERT(cur_p.data[expected_size-1].id == min_token_id); |
| 225 | } else if (s == 'p') { |
| 226 | const int softmax_divisor = n_vocab * (n_vocab-1) / 2 - min_token_id * (min_token_id-1) / 2; |
| 227 | const int softmax_numerator_target = ceilf(top_p * softmax_divisor); |
| 228 | |
| 229 | min_token_id = n_vocab; |
| 230 | int expected_size = 0; |
| 231 | int cumsum = 0; |
| 232 | do { // do-while because always at least one token is sampled |
| 233 | min_token_id--; |
| 234 | expected_size++; |
| 235 | |
| 236 | cumsum += min_token_id; |
| 237 | } while (cumsum < softmax_numerator_target); |
| 238 | |
| 239 | // token 0 has p == 0, need special consideration for cumsum because top_p immediately returns |
| 240 | if (min_token_id == 1) { |
| 241 | min_token_id--; |
| 242 | expected_size += 1; |
| 243 | } |
| 244 | |
| 245 | GGML_ASSERT(size == expected_size); |
| 246 | GGML_ASSERT(cur_p.data[0].id == max_token_id); |
| 247 | GGML_ASSERT(cur_p.data[expected_size-1].id == min_token_id); |
| 248 | } else if (s == 'm') { |
| 249 | int expected_size = ceilf((1.0f-min_p) * n_vocab); |
| 250 | expected_size = std::max(expected_size, 1); |
| 251 | expected_size = std::min(expected_size, size); |
| 252 |
no test coverage detected