| 318 | } // namespace |
| 319 | |
| 320 | VibeVoiceDecoderWeights load_vibevoice_decoder_weights( |
| 321 | const VibeVoiceAssets & assets, |
| 322 | ggml_backend_t backend, |
| 323 | core::BackendType backend_type, |
| 324 | size_t weight_context_bytes, |
| 325 | assets::TensorStorageType weight_storage_type) { |
| 326 | if (assets.model_weights == nullptr) { |
| 327 | throw std::runtime_error("VibeVoice decoder requires model weights"); |
| 328 | } |
| 329 | const auto & config = assets.config.decoder; |
| 330 | require_head_dim(config); |
| 331 | VibeVoiceDecoderWeights weights; |
| 332 | weights.store = std::make_shared<core::BackendWeightStore>( |
| 333 | backend, |
| 334 | backend_type, |
| 335 | "vibevoice.decoder.weights", |
| 336 | weight_context_bytes); |
| 337 | const auto queue_started = std::chrono::steady_clock::now(); |
| 338 | weights.token_embedding = weights.store->load_tensor( |
| 339 | *assets.model_weights, |
| 340 | "model.language_model.embed_tokens.weight", |
| 341 | weight_storage_type, |
| 342 | {config.vocab_size, config.hidden_size}); |
| 343 | if (config.tie_word_embeddings) { |
| 344 | weights.lm_head = weights.token_embedding; |
| 345 | } else { |
| 346 | weights.lm_head = weights.store->load_tensor( |
| 347 | *assets.model_weights, |
| 348 | assets.model_weights->require_tensor_name({"lm_head.weight", "model.lm_head.weight"}), |
| 349 | weight_storage_type, |
| 350 | {config.vocab_size, config.hidden_size}); |
| 351 | } |
| 352 | weights.layers.reserve(static_cast<size_t>(config.num_hidden_layers)); |
| 353 | for (int64_t layer = 0; layer < config.num_hidden_layers; ++layer) { |
| 354 | weights.layers.push_back(load_layer_weights( |
| 355 | *weights.store, |
| 356 | *assets.model_weights, |
| 357 | config, |
| 358 | layer, |
| 359 | weight_storage_type)); |
| 360 | } |
| 361 | weights.norm = assets.model_weights->require_f32_tensor("model.language_model.norm.weight", {config.hidden_size}); |
| 362 | engine::debug::timing_log_scalar( |
| 363 | "vibevoice.runtime.decoder_weight_queue_ms", |
| 364 | engine::debug::elapsed_ms(queue_started)); |
| 365 | const auto upload_started = std::chrono::steady_clock::now(); |
| 366 | weights.store->upload(); |
| 367 | engine::debug::timing_log_scalar( |
| 368 | "vibevoice.runtime.decoder_weight_upload_ms", |
| 369 | engine::debug::elapsed_ms(upload_started)); |
| 370 | return weights; |
| 371 | } |
| 372 | |
| 373 | class VibeVoiceDecoderEmbeddingGraph { |
| 374 | public: |
no test coverage detected