char-fork/llama.cpp
git clone https://git.t4t.associates/char-fork/llama.cpp
890f1a27e
char/aliceai-t5-moe
1#include "../node_context.h" 2#include "../op_table.h" 3#include "../utils.h" 4 5#include <climits> 6#include <cstdint> 7#include <memory> 8#include <openvino/core/node.hpp> 9#include <openvino/op/add.hpp> 10#include <openvino/op/concat.hpp> 11#include <openvino/op/constant.hpp> 12#include <openvino/op/reshape.hpp> 13#include <openvino/op/slice.hpp> 14#include <openvino/op/transpose.hpp> 15#include <vector> 16 17namespace ov { 18namespace frontend { 19namespace ggml { 20namespace op { 21 22OutputVector translate_permute (const NodeContext & context ) { 23num_inputs_check (context ,1 ,1 ); 24 25int op_case = context .get_op_case (); 26FRONT_END_CHECK_IMPLEMENTED (op_case != 0 ,"Unsupported PERMUTE case" ); 27// op_case 1 is trivial permute 28// op_case 2 is to permute Q. It has a preceding VIEW that reshapes Q to restore the sequqence dimension 29// op_case 3 4 it to permute KV cache in the default layout 30// op_case 5 6 is to permute V cache when `-fa off`, where v_trans=true 31 32 ov::Output < Node > res ; 33 ov::Output < Node > src ; 34if (op_case == 3 || op_case == 4 || op_case == 5 || op_case == 6 ) { 35src = context .get_input (0 ); 36 }else { 37src = process_view_input_new (context ,0 ); 38 } 39 std::vector < int64_t > perm_values {0 ,2 ,1 ,3 }; 40const int32_t * op_params = context .get_output_op_params (); 41if (op_params != nullptr ) { 42for (size_t input_axis = 0 ;input_axis < perm_values .size ();++ input_axis ) { 43const size_t output_axis = static_cast < size_t > (op_params [input_axis ]); 44perm_values [perm_values .size ()- 1 - output_axis ]= 45static_cast < int64_t > (perm_values .size ()- 1 - input_axis ); 46 } 47 } 48auto perm = ov::op::v0::Constant ::create (ov::element::i64 , {4 },perm_values ); 49 50if (op_case == 1 || context .is_stateful ()) { 51res = std::make_shared < ov::op::v1::Transpose > (src ,perm ); 52 }else if (op_case == 2 ) { 53auto output_shape = context .get_output_shape ().to_shape (); 54auto n_heads = ov::op::v0::Constant ::create (ov::element::i64 , {1 }, {output_shape [1 ]}); 55auto head_size = ov::op::v0::Constant ::create (ov::element::i64 , {1 }, {output_shape [3 ]}); 56auto n_seq_active = context .has_input ("n_seq_active" ) ? 57context .get_input ("n_seq_active" ) : 58 ov::op::v0::Constant ::create (ov::element::i64 , {1 }, {output_shape [0 ]}); 59auto neg_one = ov::op::v0::Constant ::create (ov::element::i64 , {1 }, {-1 }); 60 61auto new_shape = 62 std::make_shared < ov::op::v0::Concat > (ov::OutputVector {n_seq_active ,neg_one ,n_heads ,head_size },0 ); 63 64// // Alternative 65// auto zero = ov::op::v0::Constant::create(ov::element::i64, {1}, {0}); 66// auto new_shape = std::make_shared<ov::op::v0::Concat>(ov::OutputVector{n_seq_active, neg_one, zero, zero}, 0); 67 68auto reshaped = std::make_shared < ov::op::v1::Reshape > (src ,new_shape , true); 69res = std::make_shared < ov::op::v1::Transpose > (reshaped ,perm ); 70 }else { 71auto cache_shape = src .get_partial_shape (); 72auto output_shape = context .get_output_shape ().to_shape (); 73int64_t head_size = output_shape [3 ]; 74int64_t n_heads = output_shape [1 ]; 75if (op_case == 5 || op_case == 6 ) { 76head_size = output_shape [2 ]; 77n_heads = output_shape [1 ]; 78 } 79int64_t ctx_per_seq = cache_shape [2 ].is_static () ?cache_shape [2 ].get_length () :-1 ; 80int64_t n_seq = cache_shape [1 ].get_length (); 81 82Output < Node > attention_size ; 83if (!context .has_input ("attention_size" )) { 84attention_size = ov::op::v0::Constant ::create (ov::element::i64 , {1 }, {output_shape [2 ]}); 85 }else if (op_case == 3 || op_case == 5 ) { 86attention_size = context .get_input ("attention_size" ); 87 }else { 88attention_size = context .get_input ("attention_size_swa" ); 89 } 90 91Output < Node > seq_active_start ; 92Output < Node > seq_active_end ; 93if (context .has_input ("seq_active_start" )) { 94seq_active_start = context .get_input ("seq_active_start" ); 95seq_active_end = context .get_input ("seq_active_end" ); 96 }else { 97int64_t n_seq_active = output_shape [0 ]; 98size_t offset = * ((size_t * )context .get_input_op_params (0 )); 99int64_t seq_active_start_val = offset /context .get_input_stride (0 )[0 ]; 100int64_t seq_active_end_val = seq_active_start_val + n_seq_active ; 101seq_active_start = ov::op::v0::Constant ::create (ov::element::i64 , {1 }, {seq_active_start_val }); 102seq_active_end = ov::op::v0::Constant ::create (ov::element::i64 , {1 }, {seq_active_end_val }); 103 } 104 105// 1. reshape to [n_seq, ctx_per_seq, n_heads, head_size] (for `-fa off` [n_seq, n_heads, head_size, ctx_per_seq]) 106// 2. slice out the active sequences 107// 3. slice out the attention part in each sequence 108// 4. permute (skip for `-fa off`) 109auto zero = ov::op::v0::Constant ::create (ov::element::i64 , {1 }, {0 }); 110auto one = ov::op::v0::Constant ::create (ov::element::i64 , {1 }, {1 }); 111 112if (op_case == 3 || op_case == 4 ) { 113auto src_reshaped = std::make_shared < ov::op::v1::Reshape > ( 114src , ov::op::v0::Constant ::create (ov::element::i64 , {4 }, {n_seq ,ctx_per_seq ,n_heads ,head_size }), 115 false); 116 ov::Output < ov::Node > after_seq_slice ; 117if (n_seq == 1 ) { 118after_seq_slice = src_reshaped ; 119 }else { 120after_seq_slice = 121 std::make_shared < ov::op::v8::Slice > (src_reshaped ,seq_active_start ,seq_active_end ,one ,zero ); 122 } 123auto slice2 = std::make_shared < ov::op::v8::Slice > (after_seq_slice ,zero ,attention_size ,one ,one ); 124res = std::make_shared < ov::op::v1::Transpose > (slice2 ,perm ); 125 }else { 126auto three = ov::op::v0::Constant ::create (ov::element::i64 , {1 }, {3 }); 127auto src_reshaped = std::make_shared < ov::op::v1::Reshape > ( 128src , ov::op::v0::Constant ::create (ov::element::i64 , {4 }, {n_seq ,n_heads ,head_size ,ctx_per_seq }), 129 false); 130 ov::Output < ov::Node > after_seq_slice ; 131if (n_seq == 1 ) { 132after_seq_slice = src_reshaped ; 133 }else { 134after_seq_slice = 135 std::make_shared < ov::op::v8::Slice > (src_reshaped ,seq_active_start ,seq_active_end ,one ,zero ); 136 } 137auto slice2 = std::make_shared < ov::op::v8::Slice > (after_seq_slice ,zero ,attention_size ,one ,three ); 138res = slice2 ; 139 } 140 } 141return rename_outputs_with_suffix ({res },context .get_name ()); 142} 143 144}// namespace op 145}// namespace ggml 146}// namespace frontend 147}// namespace ov