| 71 | ctx, |
| 72 | contiguous, |
| 73 | core::TensorShape::from_dims({input.shape.dims[0], input.shape.dims[1], heads, dim})); |
| 74 | } |
| 75 | |
| 76 | core::TensorValue repeat_kv_heads(core::ModuleBuildContext & ctx, const core::TensorValue & input, int64_t repeats) { |
| 77 | if (repeats == 1) { |
| 78 | return input; |
| 79 | } |
| 80 | std::vector<core::TensorValue> heads; |
| 81 | heads.reserve(static_cast<size_t>(input.shape.dims[1] * repeats)); |
| 82 | for (int64_t head = 0; head < input.shape.dims[1]; ++head) { |
| 83 | auto one = modules::SliceModule({1, head, 1}).build(ctx, input); |
| 84 | for (int64_t rep = 0; rep < repeats; ++rep) { |
| 85 | heads.push_back(one); |
| 86 | } |
| 87 | } |
| 88 | auto output = heads.front(); |
| 89 | for (size_t i = 1; i < heads.size(); ++i) { |
| 90 | output = modules::ConcatModule({1}).build(ctx, output, heads[i]); |
| 91 | } |
| 92 | return output; |
| 93 | } |
| 94 | |
| 95 | core::TensorValue attention_from_heads( |
| 96 | core::ModuleBuildContext & ctx, |
| 97 | const core::TensorValue & q_heads, |
| 98 | const core::TensorValue & k_heads, |
| 99 | const core::TensorValue & v_heads, |
| 100 | int64_t dim, |
no test coverage detected