1+ // Copyright (C) 2018-2026 Intel Corporation
2+ // SPDX-License-Identifier: Apache-2.0
3+ //
4+
15#pragma once
26
37#include < cstdint>
@@ -10,42 +14,73 @@ namespace ov {
1014namespace frontend {
1115namespace gguf {
1216
17+ // Typed RoPE configuration, replacing the raw gguf `op_params`/`rope_params` int32 array
18+ // the translators used to dereference by byte offset. A decoder is responsible for
19+ // producing this (the llama.cpp cgraph decoder by parsing ggml's layout, a future
20+ // gguf-file decoder by construction), so the op translators never need to know ggml's
21+ // memory layout.
22+ struct RopeConfig {
23+ int n_dims = 0 ;
24+ int n_ctx_orig = 0 ;
25+ float freq_base = 0 .0f ;
26+ float freq_scale = 0 .0f ;
27+ float ext_factor = 0 .0f ;
28+ float attn_factor = 0 .0f ;
29+ float beta_fast = 0 .0f ;
30+ float beta_slow = 0 .0f ;
31+ };
32+
33+ // Decoder interface consumed by the gguf frontend translators.
34+ //
35+ // This is a typed, ggml-free interface: operation parameters are exposed through
36+ // get_attribute(node_idx, name) / get_input_view_offset / RopeConfig rather than as raw
37+ // ggml `op_params` int32 arrays. A concrete decoder (e.g. the llama.cpp cgraph decoder)
38+ // only has to translate ggml's layout into these typed accessors -- the op translators
39+ // here never touch ggml memory directly.
1340class GgufDecoder : public DecoderBase {
1441public:
15- virtual ov::Any get_attribute (const std::string& name) const = 0;
42+ ov::Any get_attribute (const std::string& name) const override = 0;
43+
44+ // Per-node typed attribute access. This is the mechanism the op translators use to
45+ // read scalar operation parameters (e.g. "eps", "scale", "bias", "swapped",
46+ // "softmax_axis", "rope_config") without dereferencing ggml's raw op_params layout.
47+ virtual ov::Any get_attribute (int node_idx, const std::string& name) const = 0;
1648
1749 virtual PartialShape get_input_shape (int node_idx, const std::string& name) const = 0;
1850
1951 virtual std::vector<size_t > get_input_stride (int node_idx, const std::string& name) const = 0;
2052
53+ // Byte offset of an input that is a gguf VIEW into a larger tensor (0 when the input
54+ // is not a view). Replaces the raw `get_input_op_params(...)[0]` read: a view's start
55+ // offset is a single semantic scalar the decoder knows (by parsing ggml, or by
56+ // construction), so translators never touch ggml's op_params layout. Translators
57+ // convert bytes -> elements using get_input_stride as needed.
58+ virtual int64_t get_input_view_offset (int node_idx, const std::string& name) const = 0;
59+
2160 virtual element::Type get_input_type (int node_idx, const std::string& name) const = 0;
2261
23- virtual size_t get_input_size () const = 0;
62+ size_t get_input_size () const override = 0;
2463
2564 virtual size_t get_input_size (int node_idx) const = 0;
2665
27- virtual void get_input_node (size_t input_port_idx,
28- std::string& producer_name,
29- std::string& producer_output_port_name,
30- size_t & producer_output_port_index) const = 0;
66+ void get_input_node (size_t input_port_idx,
67+ std::string& producer_name,
68+ std::string& producer_output_port_name,
69+ size_t & producer_output_port_index) const override = 0;
3170
3271 virtual std::vector<std::string> get_input_names (int node_idx) const = 0;
3372
3473 virtual PartialShape get_output_shape (int node_idx) const = 0;
3574
3675 virtual element::Type get_output_type (const int node_idx) const = 0;
3776
38- virtual int32_t * get_input_op_params (int node_idx, const std::string& name) const = 0;
39-
40- virtual int32_t * get_output_op_params (int node_idx) const = 0;
41-
4277 virtual std::vector<std::string> get_output_names (int node_idx) const = 0;
4378
44- virtual const std::string& get_op_type () const = 0;
79+ const std::string& get_op_type () const override = 0;
4580
4681 virtual const std::string& get_op_type (int node_idx) const = 0;
4782
48- virtual const std::string& get_op_name () const = 0;
83+ const std::string& get_op_name () const override = 0;
4984
5085 virtual const std::string& get_op_name (int node_idx) const = 0;
5186
@@ -55,18 +90,33 @@ class GgufDecoder : public DecoderBase {
5590
5691 virtual const std::map<std::string, std::shared_ptr<ov::Node>>& get_model_inputs () const = 0;
5792 virtual const std::map<std::string, std::shared_ptr<ov::Node>>& get_model_extra_inputs () const = 0;
58- virtual const std::map<std::string, std::shared_ptr<ov::Node>>& get_model_weights () const = 0;
5993 virtual std::vector<std::string> get_model_output_names () const = 0;
6094
61- virtual int32_t * get_rope_params () const = 0;
95+ // NOTE: there is no get_model_weights(). A GGUF weight is surfaced as a regular node in
96+ // visit_subgraph with op type "GGML_OP_WEIGHT": the decoder exposes the raw weight bytes
97+ // via get_attribute<ov::Tensor>(node_idx, "data"), the ggml quant type name via
98+ // get_attribute<std::string>(node_idx, "quant_type") (e.g. "Q4_K", "F16") and the logical
99+ // [rows, cols] shape via get_output_shape(node_idx). The frontend's translate_weight does
100+ // the dequant / repacking / requantization, so the decoder never builds OV nodes itself.
101+
102+ // Model-level RoPE configuration, used by TranslateSession::preprocess to pre-build
103+ // the shared rope sin/cos. has_rope() == false means the model uses no RoPE.
104+ virtual bool has_rope () const = 0;
105+
106+ // When true, each ROPE op generates its own sin/cos from its per-op rope_config
107+ // (e.g. gemma4 where SWA and global layers have different n_dims). The shared
108+ // rope_cos/rope_sin tensor is NOT added to the tensor map.
109+ virtual bool use_per_op_rope () const = 0;
110+
111+ virtual RopeConfig get_rope_config () const = 0;
62112
63113 virtual std::map<std::string, std::string> get_kv_param_res_names () const = 0;
64114
65115 virtual bool is_static () const = 0;
66116
67117 virtual bool is_stateful () const = 0;
68118
69- virtual int is_swa_layer (int layer) const = 0;
119+ virtual bool is_swa_layer (int layer) const = 0;
70120};
71121
72122} // namespace gguf
0 commit comments