| 77 | contiguous, |
| 78 | core::TensorShape::from_dims({batch, kv_heads, 1, steps * dim})); |
| 79 | expanded = RepeatModule({core::TensorShape::from_dims({batch, kv_heads, repeats, steps * dim})}) |
| 80 | .build(ctx, expanded); |
| 81 | expanded = core::ensure_backend_addressable_layout(ctx, expanded); |
| 82 | return core::reshape_tensor( |
| 83 | ctx, |
| 84 | expanded, |
| 85 | core::TensorShape::from_dims({batch, kv_heads * repeats, steps, dim})); |
| 86 | } |
| 87 | |
| 88 | core::TensorValue attention_from_heads( |
| 89 | core::ModuleBuildContext & ctx, |
| 90 | const core::TensorValue & q_heads, |
| 91 | const core::TensorValue & k_heads, |
| 92 | const core::TensorValue & v_heads, |
| 93 | int64_t dim, |
| 94 | const std::optional<core::TensorValue> & attention_mask) { |
| 95 | const MatMulModule matmul; |
| 96 | auto scores = matmul.build(ctx, q_heads, TransposeModule({{0, 1, 3, 2}, k_heads.shape.rank}).build(ctx, k_heads)); |
| 97 | core::TensorValue attn; |
| 98 | if (attention_mask.has_value()) { |
| 99 | scores = core::ensure_backend_addressable_layout(ctx, scores); |
| 100 | attn = core::wrap_tensor( |
| 101 | ggml_soft_max_ext( |
| 102 | ctx.ggml, |
| 103 | scores.tensor, |
| 104 | attention_mask->tensor, |
| 105 | 1.0F / std::sqrt(static_cast<float>(dim)), |
| 106 | 0.0F), |
| 107 | scores.shape, |
| 108 | GGML_TYPE_F32); |
| 109 | } else { |
| 110 | scores = core::wrap_tensor( |
| 111 | ggml_scale(ctx.ggml, scores.tensor, 1.0F / std::sqrt(static_cast<float>(dim))), |
| 112 | scores.shape, |
| 113 | GGML_TYPE_F32); |
no test coverage detected