| 1687 | } |
| 1688 | |
| 1689 | std::vector<VibeVoiceDecoderResult> VibeVoiceDecoderWeightsRuntime::cached_step_batch( |
| 1690 | const std::vector<std::vector<float>> & embeddings, |
| 1691 | const std::vector<VibeVoiceDecoderCachedState *> & states, |
| 1692 | int64_t cache_capacity) const { |
| 1693 | const auto & config = assets_->config.decoder; |
| 1694 | if (embeddings.empty()) { |
| 1695 | throw std::runtime_error("VibeVoice decoder cached batch step requires at least one sample"); |
| 1696 | } |
| 1697 | if (embeddings.size() != states.size()) { |
| 1698 | throw std::runtime_error("VibeVoice decoder cached batch step state count mismatch"); |
| 1699 | } |
| 1700 | if (cache_capacity <= 0) { |
| 1701 | throw std::runtime_error("VibeVoice decoder cached batch step requires positive cache capacity"); |
| 1702 | } |
| 1703 | for (const auto & embedding : embeddings) { |
| 1704 | if (static_cast<int64_t>(embedding.size()) != config.hidden_size) { |
| 1705 | throw std::runtime_error("VibeVoice decoder cached batch step embedding payload size mismatch"); |
| 1706 | } |
| 1707 | } |
| 1708 | for (auto * state : states) { |
| 1709 | if (state == nullptr) { |
| 1710 | throw std::runtime_error("VibeVoice decoder cached batch step received null state"); |
| 1711 | } |
| 1712 | } |
| 1713 | if (embeddings.size() == 1) { |
| 1714 | return {cached_step(embeddings.front(), *states.front(), cache_capacity)}; |
| 1715 | } |
| 1716 | |
| 1717 | auto state_current_end = [&](const VibeVoiceDecoderCachedState & state) -> int64_t { |
| 1718 | if (state.batch_owner_ != nullptr) { |
| 1719 | return find_cached_batch_graph(state)->current_end(); |
| 1720 | } |
| 1721 | return state.graph_has_state_ && state.graph_ != nullptr |
| 1722 | ? state.graph_->current_end() |
| 1723 | : state.pending_state_.current_end; |
| 1724 | }; |
| 1725 | |
| 1726 | const int64_t current_end = state_current_end(*states.front()); |
| 1727 | for (auto * state : states) { |
| 1728 | if (state_current_end(*state) != current_end) { |
| 1729 | throw std::runtime_error("VibeVoice decoder cached batch step requires matching current_end"); |
| 1730 | } |
| 1731 | } |
| 1732 | const int64_t required_capacity = cache_graph_capacity( |
| 1733 | std::max<int64_t>(cache_capacity, current_end + 1), |
| 1734 | config.max_position_embeddings); |
| 1735 | |
| 1736 | VibeVoiceDecoderCachedBatchStepGraph * graph = nullptr; |
| 1737 | for (const auto & candidate : cached_batch_graphs_) { |
| 1738 | if (candidate->matches(*this, states, required_capacity)) { |
| 1739 | graph = candidate.get(); |
| 1740 | break; |
| 1741 | } |
| 1742 | } |
| 1743 | |
| 1744 | if (graph == nullptr) { |
| 1745 | std::vector<const VibeVoiceDecoderCachedBatchStepGraph *> owners; |
| 1746 | for (auto * state : states) { |
no test coverage detected