| 1767 | } |
| 1768 | |
| 1769 | VibeVoiceDecoderLayerOutputs build_vibevoice_decoder_layer( |
| 1770 | core::ModuleBuildContext & ctx, |
| 1771 | const core::TensorValue & input, |
| 1772 | const core::TensorValue & positions, |
| 1773 | const VibeVoiceDecoderLayerWeights & weights, |
| 1774 | const VibeVoiceDecoderConfig & config, |
| 1775 | core::ConstantTensorCache & constants, |
| 1776 | const std::optional<core::TensorValue> & prefix_key, |
| 1777 | const std::optional<core::TensorValue> & prefix_value, |
| 1778 | const std::optional<core::TensorValue> & attention_mask) { |
| 1779 | if (prefix_key.has_value() != prefix_value.has_value()) { |
| 1780 | throw std::runtime_error("VibeVoice decoder layer requires both prefix key and value or neither"); |
| 1781 | } |
| 1782 | const int64_t dim = require_head_dim(config); |
| 1783 | const int64_t kv_repeats = config.num_attention_heads / config.num_key_value_heads; |
| 1784 | const modules::LinearModule q_proj( |
| 1785 | binding::linear_config(config.hidden_size, config.num_attention_heads * dim, true)); |
| 1786 | const modules::LinearModule k_proj( |
| 1787 | binding::linear_config(config.hidden_size, config.num_key_value_heads * dim, true)); |
| 1788 | const modules::LinearModule v_proj( |
| 1789 | binding::linear_config(config.hidden_size, config.num_key_value_heads * dim, true)); |
| 1790 | const modules::LinearModule o_proj( |
| 1791 | binding::linear_config(config.num_attention_heads * dim, config.hidden_size, false)); |
| 1792 | const modules::RMSNormModule hidden_norm({config.hidden_size, config.rms_norm_eps, true, false}); |
| 1793 | const modules::AddModule add; |
| 1794 | |
| 1795 | auto attn_in = hidden_norm.build(ctx, input, binding::norm_data(constants, weights.input_norm)); |
| 1796 | auto q = q_proj.build( |
| 1797 | ctx, |
| 1798 | attn_in, |
| 1799 | binding::linear_data(constants, weights.self_attention.q_weight, weights.self_attention.q_bias)); |
| 1800 | auto k = k_proj.build( |
| 1801 | ctx, |
| 1802 | attn_in, |
| 1803 | binding::linear_data(constants, weights.self_attention.k_weight, weights.self_attention.k_bias)); |
| 1804 | auto v = v_proj.build( |
| 1805 | ctx, |
| 1806 | attn_in, |
| 1807 | binding::linear_data(constants, weights.self_attention.v_weight, weights.self_attention.v_bias)); |
| 1808 | q = reshape_heads(ctx, q, config.num_attention_heads, dim); |
| 1809 | k = reshape_heads(ctx, k, config.num_key_value_heads, dim); |
| 1810 | v = reshape_heads(ctx, v, config.num_key_value_heads, dim); |
| 1811 | q = modules::RoPEModule({dim, GGML_ROPE_TYPE_NEOX, config.rope_theta}).build(ctx, q, positions); |
| 1812 | k = modules::RoPEModule({dim, GGML_ROPE_TYPE_NEOX, config.rope_theta}).build(ctx, k, positions); |
| 1813 | k = core::ensure_backend_addressable_layout(ctx, k); |
| 1814 | v = core::ensure_backend_addressable_layout(ctx, v); |
| 1815 | |
| 1816 | auto q_heads = modules::TransposeModule({{0, 2, 1, 3}, q.shape.rank}).build(ctx, q); |
| 1817 | auto all_k = prefix_key.has_value() ? modules::ConcatModule({1}).build(ctx, *prefix_key, k) : k; |
| 1818 | auto all_v = prefix_value.has_value() ? modules::ConcatModule({1}).build(ctx, *prefix_value, v) : v; |
| 1819 | core::TensorValue context; |
| 1820 | if (!prefix_key.has_value() && attention_mask.has_value()) { |
| 1821 | q_heads = core::wrap_tensor(ggml_cont(ctx.ggml, q_heads.tensor), q_heads.shape, q_heads.type); |
| 1822 | auto k_heads = modules::TransposeModule({{0, 2, 1, 3}, all_k.shape.rank}).build(ctx, all_k); |
| 1823 | auto v_heads = modules::TransposeModule({{0, 2, 1, 3}, all_v.shape.rank}).build(ctx, all_v); |
| 1824 | context = flash_attention_from_grouped_heads_view_kv(ctx, q_heads, k_heads, v_heads, dim, *attention_mask); |
| 1825 | } else { |
| 1826 | auto k_heads = repeat_kv_heads( |
no test coverage detected