| 419 | }; |
| 420 | |
| 421 | int32_t select_vibevoice_constrained_token( |
| 422 | const VibeVoiceDecoderLogits & logits, |
| 423 | const VibeVoiceTextTokenizer & text_tokenizer, |
| 424 | const VibeVoiceGenerationOptions & options, |
| 425 | std::mt19937 & rng) { |
| 426 | if (logits.vocab_size <= 0 || static_cast<int64_t>(logits.values.size()) != logits.vocab_size) { |
| 427 | throw std::runtime_error("VibeVoice constrained token selection received invalid logits"); |
| 428 | } |
| 429 | const int32_t candidates[] = { |
| 430 | text_tokenizer.speech_start_id(), |
| 431 | text_tokenizer.speech_end_id(), |
| 432 | text_tokenizer.speech_diffusion_id(), |
| 433 | text_tokenizer.eos_id(), |
| 434 | }; |
| 435 | int32_t best_token = candidates[0]; |
| 436 | float best_score = -std::numeric_limits<float>::infinity(); |
| 437 | for (const int32_t token : candidates) { |
| 438 | if (token < 0 || token >= logits.vocab_size) { |
| 439 | throw std::runtime_error("VibeVoice constrained token candidate is outside logits vocabulary"); |
| 440 | } |
| 441 | const float score = logits.values[static_cast<size_t>(token)]; |
| 442 | if (score > best_score) { |
| 443 | best_score = score; |
| 444 | best_token = token; |
| 445 | } |
| 446 | } |
| 447 | if (!options.do_sample) { |
| 448 | return best_token; |
| 449 | } |
| 450 | if (!(options.temperature > 0.0F) || !std::isfinite(options.temperature)) { |
| 451 | throw std::runtime_error("VibeVoice sampler temperature must be finite and positive"); |
| 452 | } |
| 453 | if (options.top_k < 0) { |
| 454 | throw std::runtime_error("VibeVoice sampler top_k must be non-negative"); |
| 455 | } |
| 456 | if (!(options.top_p > 0.0F && options.top_p <= 1.0F) || !std::isfinite(options.top_p)) { |
| 457 | throw std::runtime_error("VibeVoice sampler top_p must be finite and in (0, 1]"); |
| 458 | } |
| 459 | auto candidate_order = [](const VibeVoiceSamplingCandidate & lhs, const VibeVoiceSamplingCandidate & rhs) { |
| 460 | if (lhs.score == rhs.score) { |
| 461 | return lhs.token < rhs.token; |
| 462 | } |
| 463 | return lhs.score > rhs.score; |
| 464 | }; |
| 465 | std::vector<VibeVoiceSamplingCandidate> scores; |
| 466 | scores.reserve(sizeof(candidates) / sizeof(candidates[0])); |
| 467 | for (const int32_t token : candidates) { |
| 468 | scores.push_back({token, logits.values[static_cast<size_t>(token)] / options.temperature}); |
| 469 | } |
| 470 | if (options.top_k > 0 && static_cast<size_t>(options.top_k) < scores.size()) { |
| 471 | const auto top_end = scores.begin() + static_cast<std::ptrdiff_t>(options.top_k); |
| 472 | std::nth_element(scores.begin(), top_end, scores.end(), candidate_order); |
| 473 | std::sort(scores.begin(), top_end, candidate_order); |
| 474 | scores.erase(top_end, scores.end()); |
| 475 | } else { |
| 476 | std::sort(scores.begin(), scores.end(), candidate_order); |
| 477 | } |
| 478 | const float max_score = scores.front().score; |
no test coverage detected