Skip to content

Commit d8294eb

Browse files
committed
granite-embedding-*-multilingual-r2 : add support SwiGLU FFN for Granite Embedding Multilingual R2
* added new GGUF key <arch>.hidden_activation (LLM_KV_HIDDEN_ACT) + writer * added a forward declaration of llm_ffn_op_type to llama-hparams.h * added llm_ffn_op in hparams * added LLM_FFN_NONE = 0 sentinel to llm_ffn_op_type (value-initialization), modern-bert: explicitly assigns LLM_FFN_GEGLU before reading GGUF (unchanged). * centralized hidden_act mapping in llama-model.cpp, added llm_ffn_op_type_from_string() helper, mirroring rope_scaling_type/llama_rope_scaling_type_from_string() * modern-bert reads the GGUF key (when present) and uses the resulting op in its FFN graph
1 parent ab2ed02 commit d8294eb

9 files changed

Lines changed: 55 additions & 2 deletions

File tree

gguf-py/gguf/constants.py

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -150,6 +150,7 @@ class LLM:
150150
EMBD_LENGTH_PER_LAYER_INP = "{arch}.embedding_length_per_layer_input"
151151
SWIGLU_CLAMP_EXP = "{arch}.swiglu_clamp_exp"
152152
SWIGLU_CLAMP_SHEXP = "{arch}.swiglu_clamp_shexp"
153+
HIDDEN_ACT = "{arch}.hidden_activation"
153154
DENSE_FEAT_IN_SIZE = "{arch}.{dense}_feat_in"
154155
DENSE_FEAT_OUT_SIZE = "{arch}.{dense}_feat_out"
155156

gguf-py/gguf/gguf_writer.py

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -853,6 +853,9 @@ def add_swiglu_clamp_exp(self, values: Sequence[float]) -> None:
853853
def add_swiglu_clamp_shexp(self, values: Sequence[float]) -> None:
854854
self.add_array(Keys.LLM.SWIGLU_CLAMP_SHEXP.format(arch=self.arch), values)
855855

856+
def add_hidden_act(self, value: str) -> None:
857+
self.add_string(Keys.LLM.HIDDEN_ACT.format(arch=self.arch), value)
858+
856859
def add_expert_group_scale(self, value: float) -> None:
857860
self.add_float32(Keys.LLM.EXPERT_GROUP_SCALE.format(arch=self.arch), value)
858861

src/llama-arch.cpp

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -194,6 +194,7 @@ static const std::map<llm_kv, const char *> LLM_KV_NAMES = {
194194
{ LLM_KV_MOE_LATENT_SIZE, "%s.moe_latent_size" },
195195
{ LLM_KV_NEXTN_PREDICT_LAYERS, "%s.nextn_predict_layers" },
196196
{ LLM_KV_NUM_DEEPSTACK_LAYERS, "%s.n_deepstack_layers" },
197+
{ LLM_KV_HIDDEN_ACT, "%s.hidden_activation" },
197198
{ LLM_KV_POOLING_TYPE, "%s.pooling_type" },
198199
{ LLM_KV_LOGIT_SCALE, "%s.logit_scale" },
199200
{ LLM_KV_DECODER_START_TOKEN_ID, "%s.decoder_start_token_id" },

src/llama-arch.h

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -198,6 +198,7 @@ enum llm_kv {
198198
LLM_KV_MOE_LATENT_SIZE,
199199
LLM_KV_NEXTN_PREDICT_LAYERS,
200200
LLM_KV_NUM_DEEPSTACK_LAYERS,
201+
LLM_KV_HIDDEN_ACT,
201202
LLM_KV_POOLING_TYPE,
202203
LLM_KV_LOGIT_SCALE,
203204
LLM_KV_DECODER_START_TOKEN_ID,

src/llama-graph.h

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -35,7 +35,8 @@ enum llm_graph_type {
3535
LLM_GRAPH_TYPE_DECODER_MTP,
3636
};
3737

38-
enum llm_ffn_op_type {
38+
enum llm_ffn_op_type : int {
39+
LLM_FFN_NONE = 0, // sentinel: unset; archs must assign before use
3940
LLM_FFN_SILU,
4041
LLM_FFN_GELU,
4142
LLM_FFN_RELU,

src/llama-hparams.h

Lines changed: 11 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -23,6 +23,9 @@ enum llama_swa_type {
2323
LLAMA_SWA_TYPE_SYMMETRIC = 3,
2424
};
2525

26+
// forward declaration; full definition in llama-graph.h
27+
enum llm_ffn_op_type : int;
28+
2629
struct llama_hparams_posnet {
2730
uint32_t n_embd;
2831
uint32_t n_layer;
@@ -227,6 +230,14 @@ struct llama_hparams {
227230
enum llama_rope_scaling_type rope_scaling_type_train = LLAMA_ROPE_SCALING_TYPE_NONE;
228231

229232

233+
// Resolved FFN gated activation flavor for archs that read
234+
// `<arch>.hidden_activation` from the GGUF (e.g. ModernBert derivatives).
235+
// Defaults to LLM_FFN_NONE (sentinel = 0); the mapping from the GGUF
236+
// string to a real op is done at hparam-load time via
237+
// llm_ffn_op_type_from_string() in llama-model.cpp, mirroring how
238+
// rope_scaling_type_train is handled.
239+
enum llm_ffn_op_type llm_ffn_op;
240+
230241
// Step35: optional per-layer clamps for (Swi)GLU
231242
std::array<float, LLAMA_MAX_LAYERS> swiglu_clamp_exp; // clamping for expert FFN
232243
std::array<float, LLAMA_MAX_LAYERS> swiglu_clamp_shexp; // shared expert

src/llama-model.cpp

Lines changed: 22 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -815,6 +815,28 @@ static llama_rope_scaling_type llama_rope_scaling_type_from_string(const std::st
815815
return LLAMA_ROPE_SCALING_TYPE_UNSPECIFIED;
816816
}
817817

818+
// Maps the GGUF `<arch>.hidden_activation` string to the FFN op type used by the
819+
// graph builders. Only gated activations that map cleanly to llm_ffn_op_type are
820+
// listed; unrecognized values fall back to GeGLU, which matches the historical
821+
// default for ModernBert-style architectures.
822+
static const std::map<std::string, llm_ffn_op_type> LLM_FFN_OP_TYPES_FROM_STRING = {
823+
{ "gelu", LLM_FFN_GEGLU },
824+
{ "geglu", LLM_FFN_GEGLU },
825+
{ "silu", LLM_FFN_SWIGLU },
826+
{ "swish", LLM_FFN_SWIGLU },
827+
{ "swiglu", LLM_FFN_SWIGLU },
828+
{ "relu", LLM_FFN_RELU },
829+
{ "reglu", LLM_FFN_REGLU },
830+
};
831+
832+
llm_ffn_op_type llm_ffn_op_type_from_string(const std::string & name, llm_ffn_op_type fallback) {
833+
const auto it = LLM_FFN_OP_TYPES_FROM_STRING.find(name);
834+
if (it != LLM_FFN_OP_TYPES_FROM_STRING.end()) {
835+
return it->second;
836+
}
837+
return fallback;
838+
}
839+
818840
// CPU: ACCEL -> GPU host -> CPU extra -> CPU
819841
static buft_list_t make_cpu_buft_list(const std::vector<llama_device> & devices, bool use_extra_bufts, bool no_host) {
820842
buft_list_t buft_list;

src/llama-model.h

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -144,6 +144,10 @@ enum llm_type {
144144

145145
std::string llama_rope_scaling_type_name(llama_rope_scaling_type rope_scaling_type);
146146

147+
// Map a GGUF activation-name string to llm_ffn_op_type. Returns `fallback` if
148+
// the string is empty or not recognized.
149+
llm_ffn_op_type llm_ffn_op_type_from_string(const std::string & name, llm_ffn_op_type fallback);
150+
147151
struct llama_layer_posnet {
148152
// resnet
149153
struct ggml_tensor * norm1 = nullptr;

src/models/modern-bert.cpp

Lines changed: 10 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -14,6 +14,14 @@ void llama_model_modern_bert::load_arch_hparams(llama_model_loader & ml) {
1414

1515
ml.get_key(LLM_KV_ATTENTION_LAYERNORM_EPS, hparams.f_norm_eps);
1616

17+
// Some ModernBert derivatives (e.g. IBM Granite Embedding 97m R2) use
18+
// SiLU/SwiGLU in the FFN instead of the default GELU/GeGLU.
19+
hparams.llm_ffn_op = LLM_FFN_GEGLU;
20+
std::string hidden_act;
21+
if (ml.get_key(LLM_KV_HIDDEN_ACT, hidden_act, false)) {
22+
hparams.llm_ffn_op = llm_ffn_op_type_from_string(hidden_act, LLM_FFN_GEGLU);
23+
}
24+
1725
switch (hparams.n_layer) {
1826
case 12:
1927
type = LLM_TYPE_47M; break; // granite-embedding-small
@@ -144,7 +152,8 @@ llama_model_modern_bert::graph::graph(const llama_model & model, const llm_graph
144152
NULL, NULL, NULL,
145153
model.layers[il].ffn_down, NULL, NULL,
146154
NULL,
147-
LLM_FFN_GEGLU, LLM_FFN_SEQ, il);
155+
hparams.llm_ffn_op,
156+
LLM_FFN_SEQ, il);
148157

149158
// attentions bypass the intermediate layer
150159
cur = ggml_add(ctx0, cur, ffn_inp);

0 commit comments

Comments
 (0)