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 <memory> 6#include <openvino/core/node_output.hpp> 7#include <openvino/op/clamp.hpp> 8#include <openvino/op/constant.hpp> 9#include <openvino/op/gelu.hpp> 10#include <openvino/op/multiply.hpp> 11#include <openvino/op/sigmoid.hpp> 12#include <openvino/op/slice.hpp> 13 14namespace ov { 15namespace frontend { 16namespace ggml { 17namespace op { 18 19OutputVector translate_glu_geglu (const NodeContext & context ) { 20num_inputs_check (context ,1 ,2 ); 21 22 ov::Output < ov::Node > src0 ; 23 ov::Output < ov::Node > src1 ; 24if (context .get_input_size ()== 2 ) { 25// Inputs may be VIEW slices of a combined gate_up tensor (MoE experts): 26// resolve them so each half has its real sliced shape, not the base tensor. 27src0 = process_view_input_new (context ,0 ); 28src1 = process_view_input_new (context ,1 ); 29 }else { 30// GGML splits along ne[0] (OV last axis) using floor division: nc = ne[0] / 2. 31// Both halves are nc elements; if the dimension is odd, the last element is dropped. 32// Use Slice instead of Split to handle odd dimensions correctly. 33// Resolve a VIEW input (e.g. non-contiguous slice) to its real shape first. 34auto combined = process_view_input_new (context ,0 ); 35auto combined_shape = combined .get_partial_shape (); 36int64_t last_dim_val = combined_shape [combined_shape .rank ().get_length ()- 1 ].get_length (); 37int64_t nc = last_dim_val /2 ; 38 39auto axis = ov::op::v0::Constant ::create (ov::element::i64 , {1 }, {-1 }); 40auto step = ov::op::v0::Constant ::create (ov::element::i64 , {1 }, {1 }); 41auto start0 = ov::op::v0::Constant ::create (ov::element::i64 , {1 }, {0 }); 42auto stop0 = ov::op::v0::Constant ::create (ov::element::i64 , {1 }, {nc }); 43auto start1 = ov::op::v0::Constant ::create (ov::element::i64 , {1 }, {nc }); 44auto stop1 = ov::op::v0::Constant ::create (ov::element::i64 , {1 }, {2 * nc }); 45 46src0 = std::make_shared < ov::op::v8::Slice > (combined ,start0 ,stop0 ,step ,axis ); 47src1 = std::make_shared < ov::op::v8::Slice > (combined ,start1 ,stop1 ,step ,axis ); 48 } 49 50int32_t * params = context .get_output_op_params (); 51const int32_t swapped = params [1 ]; 52if (swapped ) { 53 std::swap (src0 ,src1 ); 54 } 55 56if (context .is_static ()) { 57// TODO: Temporary solution for NPU accuracy issue due to fp16 overflow 58// To be removed once permanent solution is implemented 59// Justification: 60// For |x| > 5, GELU(x) ≈ max(x, 0) (behaves like ReLU) 61// So Clamp(-10, 10) only affects values where GELU would return ≈ x anyway. 62// The only loss: values > 10 get mapped to 10 instead of x. 63// In practice, FFN intermediates rarely exceed 10 after GEGLU gating. 64src0 = std::make_shared < ov::op::v0::Clamp > (src0 ,-10.0 ,10.0 ); 65 } 66auto gelu = std::make_shared < ov::op::v7::Gelu > (src0 ); 67auto res = std::make_shared < ov::op::v1::Multiply > (gelu ,src1 ); 68 69return rename_outputs_with_suffix ({res },context .get_name ()); 70} 71 72}// namespace op 73}// namespace ggml 74}// namespace frontend 75}// namespace ov