Voice et bot modif
This commit is contained in:
parent
189d56026b
commit
7333a22bcd
10774 changed files with 634644 additions and 933308 deletions
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
|
|
@ -3,7 +3,7 @@ import argparse
|
|||
from eole.config.run import PredictConfig
|
||||
from eole.constants import PositionEncodingType
|
||||
from eole.inputters.inputter import vocabs_to_dict
|
||||
from eole.models.model import BaseModel
|
||||
from eole.models.model import get_model_class
|
||||
|
||||
from ctranslate2.converters import utils
|
||||
from ctranslate2.converters.converter import Converter
|
||||
|
|
@ -164,7 +164,8 @@ class EoleConverter(Converter):
|
|||
|
||||
config = PredictConfig(model_path=self._model_path, src="dummy")
|
||||
|
||||
vocabs, model, model_config = BaseModel.load_test_model(config)
|
||||
model_class = get_model_class(config.model)
|
||||
model, vocabs, model_config = model_class.for_inference(config)
|
||||
vocabs_dict = vocabs_to_dict(vocabs)
|
||||
|
||||
config.model = model_config
|
||||
|
|
|
|||
|
|
@ -120,8 +120,14 @@ class TransformersConverter(Converter):
|
|||
)
|
||||
|
||||
model_class = getattr(transformers, loader.architecture_name)
|
||||
if hasattr(loader, "get_model_class"):
|
||||
model_class = loader.get_model_class(config, model_class)
|
||||
tokenizer_class = transformers.AutoTokenizer
|
||||
|
||||
extra_kwargs = {"config": config}
|
||||
if hasattr(loader, "get_model_kwargs"):
|
||||
extra_kwargs.update(loader.get_model_kwargs(config))
|
||||
|
||||
kwargs = {
|
||||
"dtype": (
|
||||
torch.float16
|
||||
|
|
@ -138,7 +144,9 @@ class TransformersConverter(Converter):
|
|||
if self._trust_remote_code:
|
||||
kwargs["trust_remote_code"] = self._trust_remote_code
|
||||
|
||||
model = self.load_model(model_class, self._model_name_or_path, **kwargs)
|
||||
model = self.load_model(
|
||||
model_class, self._model_name_or_path, **kwargs, **extra_kwargs
|
||||
)
|
||||
|
||||
tokenizer_kwargs = {}
|
||||
if self._trust_remote_code:
|
||||
|
|
@ -253,6 +261,30 @@ class ModelLoader(abc.ABC):
|
|||
"No activation smoothing logic is defined for this model"
|
||||
)
|
||||
|
||||
def get_rotary_params(self, config, default_rope_theta):
|
||||
rope_scaling = getattr(config, "rope_scaling", None)
|
||||
if rope_scaling:
|
||||
rope_type = rope_scaling.get("type") or rope_scaling.get("rope_type")
|
||||
|
||||
if rope_type == "default":
|
||||
rotary_scaling_type = None
|
||||
else:
|
||||
rotary_scaling_type = _SUPPORTED_ROPE_SCALING.get(rope_type)
|
||||
if rotary_scaling_type is None:
|
||||
raise NotImplementedError(
|
||||
"RoPE scaling type '%s' is not yet implemented. "
|
||||
"The following RoPE scaling types are currently supported: %s"
|
||||
% (rope_type, ", ".join(_SUPPORTED_ROPE_SCALING.keys()))
|
||||
)
|
||||
rotary_scaling_factor = rope_scaling.get("factor", 1)
|
||||
rope_theta = rope_scaling.get("rope_theta", default_rope_theta)
|
||||
else:
|
||||
rotary_scaling_type = None
|
||||
rotary_scaling_factor = 1
|
||||
rope_theta = getattr(config, "rope_theta", default_rope_theta)
|
||||
|
||||
return rotary_scaling_type, rotary_scaling_factor, rope_theta
|
||||
|
||||
|
||||
@register_loader("BartConfig")
|
||||
class BartLoader(ModelLoader):
|
||||
|
|
@ -463,7 +495,7 @@ class M2M100Loader(BartLoader):
|
|||
if tokens[-1] == tokenizer.unk_token:
|
||||
tokens.insert(tokenizer.unk_token_id, tokens.pop())
|
||||
|
||||
for token in tokenizer.additional_special_tokens:
|
||||
for token in tokenizer.special_tokens_map.get("additional_special_tokens", []):
|
||||
if token not in tokens:
|
||||
tokens.append(token)
|
||||
|
||||
|
|
@ -488,7 +520,7 @@ class MBartLoader(BartLoader):
|
|||
config.unk_token = tokenizer.unk_token
|
||||
|
||||
# MBart-25 passes the language code as the decoder start token.
|
||||
if model.config.tokenizer_class in ("MBartTokenizer", None):
|
||||
if getattr(model.config, "tokenizer_class", None) in ("MBartTokenizer", None):
|
||||
config.decoder_start_token = None
|
||||
else:
|
||||
config.decoder_start_token = tokenizer.eos_token
|
||||
|
|
@ -928,12 +960,14 @@ class WhisperLoader(BartLoader):
|
|||
"<|nocaptions|>",
|
||||
"<|notimestamps|>",
|
||||
]
|
||||
|
||||
additional_tokens = getattr(tokenizer, "additional_special_tokens", [])
|
||||
if not additional_tokens:
|
||||
return []
|
||||
|
||||
return [
|
||||
token_id
|
||||
for token_id, token in zip(
|
||||
tokenizer.additional_special_tokens_ids,
|
||||
tokenizer.additional_special_tokens,
|
||||
)
|
||||
tokenizer.convert_tokens_to_ids(token)
|
||||
for token in additional_tokens
|
||||
if token not in non_lang_special_tokens
|
||||
]
|
||||
|
||||
|
|
@ -1674,21 +1708,9 @@ class LlamaLoader(ModelLoader):
|
|||
if num_heads_kv == num_heads:
|
||||
num_heads_kv = None
|
||||
|
||||
rope_scaling = getattr(model.config, "rope_scaling", None)
|
||||
if rope_scaling:
|
||||
rope_type = rope_scaling.get("type") or rope_scaling["rope_type"]
|
||||
rotary_scaling_type = _SUPPORTED_ROPE_SCALING.get(rope_type)
|
||||
rotary_scaling_factor = rope_scaling["factor"]
|
||||
|
||||
if rotary_scaling_type is None:
|
||||
raise NotImplementedError(
|
||||
"RoPE scaling type '%s' is not yet implemented. "
|
||||
"The following RoPE scaling types are currently supported: %s"
|
||||
% (rope_scaling["type"], ", ".join(_SUPPORTED_ROPE_SCALING.keys()))
|
||||
)
|
||||
else:
|
||||
rotary_scaling_type = None
|
||||
rotary_scaling_factor = 1
|
||||
rotary_scaling_type, rotary_scaling_factor, rope_theta = self.get_rotary_params(
|
||||
model.config, 10_000
|
||||
)
|
||||
|
||||
quantization_config = getattr(model.config, "quantization_config", None)
|
||||
if quantization_config:
|
||||
|
|
@ -1722,7 +1744,7 @@ class LlamaLoader(ModelLoader):
|
|||
rotary_interleave=False,
|
||||
rotary_scaling_type=rotary_scaling_type,
|
||||
rotary_scaling_factor=rotary_scaling_factor,
|
||||
rotary_base=getattr(model.config, "rope_theta", 10000),
|
||||
rotary_base=rope_theta,
|
||||
num_heads_kv=num_heads_kv,
|
||||
quant_type=quant_type,
|
||||
quant_group_size=quant_group_size,
|
||||
|
|
@ -1733,6 +1755,7 @@ class LlamaLoader(ModelLoader):
|
|||
self.set_linear(spec.decoder.projection, model.lm_head)
|
||||
|
||||
# set extra RoPE parameters for Llama-3.1
|
||||
rope_scaling = getattr(model.config, "rope_scaling", None)
|
||||
if rotary_scaling_type == attention_spec.RotaryScalingType.Llama3:
|
||||
for layer in spec.decoder.layer:
|
||||
layer.self_attention.rotary_low_freq_factor = rope_scaling[
|
||||
|
|
@ -1827,30 +1850,49 @@ class Gemma3Loader(ModelLoader):
|
|||
def architecture_name(self):
|
||||
return "Gemma3ForCausalLM"
|
||||
|
||||
def get_model_class(self, config, default_class):
|
||||
# Gemma3Config (4b/12b/27b multimodal) needs ForConditionalGeneration to
|
||||
# load weights correctly. Gemma3TextConfig (1b text-only) uses ForCausalLM.
|
||||
if config.__class__.__name__ == "Gemma3Config":
|
||||
return transformers.Gemma3ForConditionalGeneration
|
||||
return default_class
|
||||
|
||||
def get_model_spec(self, model):
|
||||
num_layers = model.config.num_hidden_layers
|
||||
num_heads = model.config.num_attention_heads
|
||||
num_heads_kv = getattr(model.config, "num_key_value_heads", num_heads)
|
||||
text_config = getattr(model.config, "text_config", model.config)
|
||||
num_layers = text_config.num_hidden_layers
|
||||
num_heads = text_config.num_attention_heads
|
||||
num_heads_kv = getattr(text_config, "num_key_value_heads", num_heads)
|
||||
if num_heads_kv == num_heads:
|
||||
num_heads_kv = None
|
||||
|
||||
head_dim = model.config.head_dim
|
||||
head_dim = text_config.head_dim
|
||||
|
||||
activation_config = getattr(
|
||||
model.config, "hidden_activation", "gelu_pytorch_tanh"
|
||||
text_config, "hidden_activation", "gelu_pytorch_tanh"
|
||||
)
|
||||
|
||||
# Get RoPE parameters
|
||||
rope_theta = getattr(model.config, "rope_theta", 1_000_000) # Global: 1M
|
||||
rope_theta = getattr(text_config, "rope_theta", 1_000_000) # Global: 1M
|
||||
rope_local_base_freq = getattr(
|
||||
model.config, "rope_local_base_freq", 10_000
|
||||
text_config, "rope_local_base_freq", 10_000
|
||||
) # Local: 10k
|
||||
|
||||
# Get sliding window configuration
|
||||
sliding_window = getattr(model.config, "sliding_window", 1024)
|
||||
layer_types = getattr(model.config, "layer_types", None)
|
||||
sliding_window = getattr(text_config, "sliding_window", 1024)
|
||||
layer_types = getattr(text_config, "layer_types", None)
|
||||
if layer_types is None:
|
||||
sliding_window_pattern = getattr(
|
||||
text_config, "_sliding_window_pattern", None
|
||||
)
|
||||
if sliding_window_pattern is not None:
|
||||
layer_types = [
|
||||
"full_attention"
|
||||
if (i + 1) % sliding_window_pattern == 0
|
||||
else "sliding_attention"
|
||||
for i in range(num_layers)
|
||||
]
|
||||
|
||||
quantization_config = getattr(model.config, "quantization_config", None)
|
||||
quantization_config = getattr(text_config, "quantization_config", None)
|
||||
if quantization_config:
|
||||
if quantization_config.quant_method == "awq":
|
||||
quant_type = _SUPPORTED_QUANTIZATION.get(quantization_config.version)
|
||||
|
|
@ -1859,8 +1901,12 @@ class Gemma3Loader(ModelLoader):
|
|||
"Quantization type '%s' is not yet implemented."
|
||||
% quantization_config.quant_method
|
||||
)
|
||||
quant_group_size = quantization_config.group_size
|
||||
quant_bits = quantization_config.bits
|
||||
else:
|
||||
quant_type = common_spec.Quantization.CT2
|
||||
quant_group_size = None
|
||||
quant_bits = None
|
||||
|
||||
# Create base spec using from_config
|
||||
spec = transformer_spec.TransformerDecoderModelSpec.from_config(
|
||||
|
|
@ -1881,6 +1927,9 @@ class Gemma3Loader(ModelLoader):
|
|||
head_dim=head_dim,
|
||||
sliding_window=sliding_window, # Default to local sliding window
|
||||
pre_post_layer_norm=True,
|
||||
quant_type=quant_type,
|
||||
quant_group_size=quant_group_size,
|
||||
quant_bits=quant_bits,
|
||||
qk_norm=True,
|
||||
)
|
||||
|
||||
|
|
@ -1901,18 +1950,20 @@ class Gemma3Loader(ModelLoader):
|
|||
sliding_window
|
||||
)
|
||||
|
||||
self.set_decoder(spec.decoder, model.model, quant_type)
|
||||
text_model = getattr(model.model, "language_model", model.model)
|
||||
self.set_decoder(spec.decoder, text_model, quant_type)
|
||||
self.set_linear(spec.decoder.projection, model.lm_head)
|
||||
return spec
|
||||
|
||||
def get_vocabulary(self, model, tokenizer):
|
||||
tokens = super().get_vocabulary(model, tokenizer)
|
||||
|
||||
extra_ids = model.config.vocab_size - len(tokens)
|
||||
text_config = getattr(model.config, "text_config", model.config)
|
||||
extra_ids = text_config.vocab_size - len(tokens)
|
||||
for i in range(extra_ids):
|
||||
tokens.append("<extra_id_%d>" % i)
|
||||
if model.config.vocab_size < len(tokens):
|
||||
tokens = tokens[: model.config.vocab_size]
|
||||
if text_config.vocab_size < len(tokens):
|
||||
tokens = tokens[: text_config.vocab_size]
|
||||
|
||||
return tokens
|
||||
|
||||
|
|
@ -1933,7 +1984,8 @@ class Gemma3Loader(ModelLoader):
|
|||
config.eos_token = tokenizer.eos_token
|
||||
|
||||
def set_layer_norm(self, spec, layer_norm):
|
||||
spec.gamma = layer_norm.weight + 1.0
|
||||
spec.gamma = layer_norm.weight
|
||||
spec.layer_norm_use_residual = True
|
||||
|
||||
def set_decoder(self, spec, module, quant_type=common_spec.Quantization.CT2):
|
||||
spec.scale_embeddings = True
|
||||
|
|
@ -2006,6 +2058,267 @@ class Gemma3Loader(ModelLoader):
|
|||
gc.collect()
|
||||
|
||||
|
||||
@register_loader("Gemma4TextConfig")
|
||||
@register_loader("Gemma4Config")
|
||||
class Gemma4Loader(ModelLoader):
|
||||
@property
|
||||
def architecture_name(self):
|
||||
return "Gemma4ForCausalLM"
|
||||
|
||||
def get_model_class(self, config, default_class):
|
||||
if config.__class__.__name__ == "Gemma4Config":
|
||||
return transformers.Gemma4ForConditionalGeneration
|
||||
return default_class
|
||||
|
||||
def get_model_spec(self, model):
|
||||
text_config = getattr(model.config, "text_config", model.config)
|
||||
num_layers = text_config.num_hidden_layers
|
||||
num_heads = text_config.num_attention_heads
|
||||
num_heads_kv = getattr(text_config, "num_key_value_heads", num_heads)
|
||||
if num_heads_kv == num_heads:
|
||||
num_heads_kv = None
|
||||
|
||||
# KV-sharing is not yet supported (E2B/E4B)
|
||||
num_kv_shared_layers = getattr(text_config, "num_kv_shared_layers", 0)
|
||||
if num_kv_shared_layers > 0:
|
||||
raise NotImplementedError(
|
||||
"Gemma 4 KV-shared layers (num_kv_shared_layers=%d) are not yet "
|
||||
"supported. Use the 31B model which has no KV sharing."
|
||||
% num_kv_shared_layers
|
||||
)
|
||||
|
||||
# Sliding layers use head_dim, global (full) attention layers use global_head_dim
|
||||
head_dim = text_config.head_dim
|
||||
global_head_dim = getattr(text_config, "global_head_dim", head_dim)
|
||||
|
||||
# num_global_key_value_heads overrides num_key_value_heads for full-attention layers
|
||||
num_global_kv_heads = getattr(text_config, "num_global_key_value_heads", None)
|
||||
|
||||
# attention_k_eq_v: full-attention layers reuse key projection as value projection
|
||||
attention_k_eq_v = getattr(text_config, "attention_k_eq_v", False)
|
||||
|
||||
activation_config = getattr(
|
||||
text_config, "hidden_activation", "gelu_pytorch_tanh"
|
||||
)
|
||||
|
||||
# RoPE parameters are in a nested dict keyed by layer type
|
||||
rope_params = getattr(text_config, "rope_parameters", None) or {}
|
||||
sliding_rope = rope_params.get("sliding_attention", {})
|
||||
global_rope = rope_params.get("full_attention", {})
|
||||
|
||||
rope_local_base_freq = float(sliding_rope.get("rope_theta", 10_000))
|
||||
rope_theta = float(global_rope.get("rope_theta", 1_000_000))
|
||||
|
||||
# Proportional RoPE: only a fraction of global_head_dim uses RoPE
|
||||
global_partial_factor = float(global_rope.get("partial_rotary_factor", 1.0))
|
||||
global_rotary_dim = int(global_head_dim * global_partial_factor)
|
||||
|
||||
sliding_window = getattr(text_config, "sliding_window", 512)
|
||||
layer_types = getattr(text_config, "layer_types", None)
|
||||
if layer_types is None:
|
||||
sliding_window_pattern = 6
|
||||
layer_types = [
|
||||
"sliding_attention"
|
||||
if bool((i + 1) % sliding_window_pattern)
|
||||
else "full_attention"
|
||||
for i in range(num_layers)
|
||||
]
|
||||
|
||||
quantization_config = getattr(text_config, "quantization_config", None)
|
||||
if quantization_config:
|
||||
if quantization_config.quant_method == "awq":
|
||||
quant_type = _SUPPORTED_QUANTIZATION.get(quantization_config.version)
|
||||
if quant_type is None:
|
||||
raise NotImplementedError(
|
||||
"Quantization type '%s' is not yet implemented."
|
||||
% quantization_config.quant_method
|
||||
)
|
||||
quant_group_size = quantization_config.group_size
|
||||
quant_bits = quantization_config.bits
|
||||
else:
|
||||
quant_type = common_spec.Quantization.CT2
|
||||
quant_group_size = None
|
||||
quant_bits = None
|
||||
|
||||
# Build spec with sliding-attention defaults; global layers overridden per-layer below
|
||||
spec = transformer_spec.TransformerDecoderModelSpec.from_config(
|
||||
num_layers,
|
||||
num_heads,
|
||||
activation=(
|
||||
common_spec.Activation.GELU
|
||||
if activation_config == "gelu"
|
||||
else common_spec.Activation.GELUTanh
|
||||
),
|
||||
pre_norm=True,
|
||||
ffn_glu=True,
|
||||
rms_norm=True,
|
||||
rotary_dim=head_dim,
|
||||
rotary_interleave=False,
|
||||
rotary_base=rope_local_base_freq,
|
||||
num_heads_kv=num_heads_kv,
|
||||
head_dim=head_dim,
|
||||
sliding_window=sliding_window,
|
||||
pre_post_layer_norm=True,
|
||||
quant_type=quant_type,
|
||||
quant_group_size=quant_group_size,
|
||||
quant_bits=quant_bits,
|
||||
qk_norm=True,
|
||||
v_norm=True,
|
||||
)
|
||||
|
||||
self._layer_types = layer_types
|
||||
self._attention_k_eq_v = attention_k_eq_v
|
||||
|
||||
# Per-layer overrides for full-attention layers
|
||||
for i, layer_type in enumerate(layer_types):
|
||||
layer = spec.decoder.layer[i]
|
||||
# Gemma4 uses scaling=1.0 (no 1/sqrt(d_head) scaling)
|
||||
layer.self_attention.queries_scale = np.dtype("float32").type(1.0)
|
||||
if layer_type == "full_attention":
|
||||
layer.self_attention.rotary_dim = np.dtype("int32").type(
|
||||
global_rotary_dim
|
||||
)
|
||||
layer.self_attention.rotary_base = np.dtype("float32").type(rope_theta)
|
||||
layer.self_attention.sliding_window = np.dtype("int32").type(0)
|
||||
layer.self_attention.head_dim = np.dtype("int32").type(global_head_dim)
|
||||
if num_global_kv_heads is not None:
|
||||
layer.self_attention.num_heads_kv = np.dtype("int32").type(
|
||||
num_global_kv_heads
|
||||
)
|
||||
elif layer_type == "sliding_attention":
|
||||
layer.self_attention.rotary_base = np.dtype("float32").type(
|
||||
rope_local_base_freq
|
||||
)
|
||||
layer.self_attention.sliding_window = np.dtype("int32").type(
|
||||
sliding_window
|
||||
)
|
||||
|
||||
text_config = getattr(model.config, "text_config", model.config)
|
||||
final_softcap = getattr(text_config, "final_logit_softcapping", None)
|
||||
if final_softcap:
|
||||
spec.decoder.final_logit_softcapping = np.dtype("float32").type(
|
||||
final_softcap
|
||||
)
|
||||
|
||||
text_model = getattr(model.model, "language_model", model.model)
|
||||
self.set_decoder(spec.decoder, text_model, quant_type)
|
||||
self.set_linear(spec.decoder.projection, model.lm_head)
|
||||
return spec
|
||||
|
||||
def get_vocabulary(self, model, tokenizer):
|
||||
tokens = super().get_vocabulary(model, tokenizer)
|
||||
text_config = getattr(model.config, "text_config", model.config)
|
||||
extra_ids = text_config.vocab_size - len(tokens)
|
||||
for i in range(extra_ids):
|
||||
tokens.append("<extra_id_%d>" % i)
|
||||
if text_config.vocab_size < len(tokens):
|
||||
tokens = tokens[: text_config.vocab_size]
|
||||
return tokens
|
||||
|
||||
def set_vocabulary(self, spec, tokens):
|
||||
spec.register_vocabulary(tokens)
|
||||
|
||||
def set_config(self, config, model, tokenizer):
|
||||
config.bos_token = tokenizer.bos_token
|
||||
config.unk_token = tokenizer.unk_token
|
||||
if (
|
||||
hasattr(tokenizer, "chat_template")
|
||||
and isinstance(tokenizer.chat_template, str)
|
||||
and tokenizer.chat_template.strip()
|
||||
):
|
||||
config.eos_token = "<end_of_turn>"
|
||||
else:
|
||||
config.eos_token = tokenizer.eos_token
|
||||
|
||||
def set_layer_norm(self, spec, layer_norm):
|
||||
spec.gamma = layer_norm.weight
|
||||
# Gemma4 uses output * gamma (ones-initialized), not output * (1 + gamma)
|
||||
|
||||
def set_decoder(self, spec, module, quant_type=common_spec.Quantization.CT2):
|
||||
spec.scale_embeddings = True
|
||||
spec.start_from_zero_embedding = False
|
||||
self.set_embeddings(spec.embeddings, module.embed_tokens)
|
||||
self.set_layer_norm(spec.layer_norm, module.norm)
|
||||
|
||||
attention_k_eq_v = getattr(self, "_attention_k_eq_v", False)
|
||||
|
||||
for layer_spec, layer in zip(spec.layer, module.layers):
|
||||
self.set_layer_norm(layer_spec.input_layer_norm, layer.input_layernorm)
|
||||
self.set_layer_norm(
|
||||
layer_spec.post_attention_layer_norm, layer.post_attention_layernorm
|
||||
)
|
||||
self.set_layer_norm(
|
||||
layer_spec.pre_feedforward_layer_norm, layer.pre_feedforward_layernorm
|
||||
)
|
||||
self.set_layer_norm(
|
||||
layer_spec.post_feedforward_layer_norm, layer.post_feedforward_layernorm
|
||||
)
|
||||
self.set_layer_norm(
|
||||
layer_spec.self_attention.q_norm, layer.self_attn.q_norm
|
||||
)
|
||||
self.set_layer_norm(
|
||||
layer_spec.self_attention.k_norm, layer.self_attn.k_norm
|
||||
)
|
||||
|
||||
# v_norm has no learnable scale; supply all-ones gamma (pure RMS norm)
|
||||
layer_spec.self_attention.v_norm.gamma = (
|
||||
torch.ones_like(layer.self_attn.k_norm.weight).float().numpy()
|
||||
)
|
||||
|
||||
# When attention_k_eq_v is set, full-attention layers have no v_proj —
|
||||
# values are the same as keys, so we reuse k_proj weights.
|
||||
is_full_attn = layer.self_attn.layer_type == "full_attention"
|
||||
use_k_as_v = attention_k_eq_v and is_full_attn
|
||||
|
||||
split_layers = [common_spec.LinearSpec() for _ in range(3)]
|
||||
self.set_linear(
|
||||
split_layers[0], layer.self_attn.q_proj, quant_type=quant_type
|
||||
)
|
||||
self.set_linear(
|
||||
split_layers[1], layer.self_attn.k_proj, quant_type=quant_type
|
||||
)
|
||||
if use_k_as_v:
|
||||
self.set_linear(
|
||||
split_layers[2], layer.self_attn.k_proj, quant_type=quant_type
|
||||
)
|
||||
else:
|
||||
self.set_linear(
|
||||
split_layers[2], layer.self_attn.v_proj, quant_type=quant_type
|
||||
)
|
||||
|
||||
if quant_type == common_spec.Quantization.CT2:
|
||||
utils.fuse_linear(layer_spec.self_attention.linear[0], split_layers)
|
||||
else:
|
||||
cc_dim = 1 if quant_type == common_spec.Quantization.AWQ_GEMM else 0
|
||||
utils.fuse_linear_prequant(
|
||||
layer_spec.self_attention.linear[0], split_layers, cc_dim
|
||||
)
|
||||
|
||||
self.set_linear(
|
||||
layer_spec.self_attention.linear[1],
|
||||
layer.self_attn.o_proj,
|
||||
quant_type=quant_type,
|
||||
)
|
||||
|
||||
self.set_linear(
|
||||
layer_spec.ffn.linear_0, layer.mlp.gate_proj, quant_type=quant_type
|
||||
)
|
||||
self.set_linear(
|
||||
layer_spec.ffn.linear_0_noact, layer.mlp.up_proj, quant_type=quant_type
|
||||
)
|
||||
self.set_linear(
|
||||
layer_spec.ffn.linear_1, layer.mlp.down_proj, quant_type=quant_type
|
||||
)
|
||||
|
||||
ls = getattr(layer, "layer_scalar", None)
|
||||
if ls is not None:
|
||||
layer_spec.layer_scalar = np.dtype("float32").type(ls.float().item())
|
||||
|
||||
delattr(layer, "self_attn")
|
||||
delattr(layer, "mlp")
|
||||
gc.collect()
|
||||
|
||||
|
||||
@register_loader("MistralConfig")
|
||||
class MistralLoader(ModelLoader):
|
||||
@property
|
||||
|
|
@ -2022,20 +2335,9 @@ class MistralLoader(ModelLoader):
|
|||
|
||||
sliding_window = getattr(model.config, "sliding_window", 0)
|
||||
|
||||
rope_scaling = getattr(model.config, "rope_scaling", None)
|
||||
if rope_scaling:
|
||||
rotary_scaling_type = _SUPPORTED_ROPE_SCALING.get(rope_scaling["type"])
|
||||
rotary_scaling_factor = rope_scaling["factor"]
|
||||
|
||||
if rotary_scaling_type is None:
|
||||
raise NotImplementedError(
|
||||
"RoPE scaling type '%s' is not yet implemented. "
|
||||
"The following RoPE scaling types are currently supported: %s"
|
||||
% (rope_scaling["type"], ", ".join(_SUPPORTED_ROPE_SCALING.keys()))
|
||||
)
|
||||
else:
|
||||
rotary_scaling_type = None
|
||||
rotary_scaling_factor = 1
|
||||
rotary_scaling_type, rotary_scaling_factor, rope_theta = self.get_rotary_params(
|
||||
model.config, 10_000
|
||||
)
|
||||
|
||||
quantization_config = getattr(model.config, "quantization_config", None)
|
||||
if quantization_config:
|
||||
|
|
@ -2068,7 +2370,7 @@ class MistralLoader(ModelLoader):
|
|||
rotary_interleave=False,
|
||||
rotary_scaling_type=rotary_scaling_type,
|
||||
rotary_scaling_factor=rotary_scaling_factor,
|
||||
rotary_base=getattr(model.config, "rope_theta", 10000),
|
||||
rotary_base=rope_theta,
|
||||
num_heads_kv=num_heads_kv,
|
||||
sliding_window=sliding_window,
|
||||
quant_type=quant_type,
|
||||
|
|
@ -2167,21 +2469,9 @@ class Qwen2Loader(ModelLoader):
|
|||
if num_heads_kv == num_heads:
|
||||
num_heads_kv = None
|
||||
|
||||
rope_scaling = getattr(model.config, "rope_scaling", None)
|
||||
if rope_scaling:
|
||||
rope_type = rope_scaling.get("type") or rope_scaling["rope_type"]
|
||||
rotary_scaling_type = _SUPPORTED_ROPE_SCALING.get(rope_type)
|
||||
rotary_scaling_factor = rope_scaling["factor"]
|
||||
|
||||
if rotary_scaling_type is None:
|
||||
raise NotImplementedError(
|
||||
"RoPE scaling type '%s' is not yet implemented. "
|
||||
"The following RoPE scaling types are currently supported: %s"
|
||||
% (rope_scaling["type"], ", ".join(_SUPPORTED_ROPE_SCALING.keys()))
|
||||
)
|
||||
else:
|
||||
rotary_scaling_type = None
|
||||
rotary_scaling_factor = 1
|
||||
rotary_scaling_type, rotary_scaling_factor, rope_theta = self.get_rotary_params(
|
||||
model.config, 10_000
|
||||
)
|
||||
|
||||
# Check for AWQ quantization config
|
||||
quantization_config = getattr(model.config, "quantization_config", None)
|
||||
|
|
@ -2216,7 +2506,7 @@ class Qwen2Loader(ModelLoader):
|
|||
rotary_interleave=False,
|
||||
rotary_scaling_type=rotary_scaling_type,
|
||||
rotary_scaling_factor=rotary_scaling_factor,
|
||||
rotary_base=getattr(model.config, "rope_theta", 10000),
|
||||
rotary_base=rope_theta,
|
||||
num_heads_kv=num_heads_kv,
|
||||
quant_type=quant_type,
|
||||
quant_group_size=quant_group_size,
|
||||
|
|
@ -2323,21 +2613,9 @@ class Qwen3Loader(ModelLoader):
|
|||
if num_heads_kv == num_heads:
|
||||
num_heads_kv = None
|
||||
|
||||
rope_scaling = getattr(model.config, "rope_scaling", None)
|
||||
if rope_scaling:
|
||||
rope_type = rope_scaling.get("type") or rope_scaling["rope_type"]
|
||||
rotary_scaling_type = _SUPPORTED_ROPE_SCALING.get(rope_type)
|
||||
rotary_scaling_factor = rope_scaling["factor"]
|
||||
if rotary_scaling_type is None:
|
||||
raise NotImplementedError(
|
||||
"RoPE scaling type '%s' is not yet implemented. "
|
||||
"The following RoPE scaling types are currently supported: %s"
|
||||
% (rope_scaling["type"], ", ".join(_SUPPORTED_ROPE_SCALING.keys()))
|
||||
)
|
||||
else:
|
||||
rotary_scaling_type = None
|
||||
rotary_scaling_factor = 1
|
||||
|
||||
rotary_scaling_type, rotary_scaling_factor, rope_theta = self.get_rotary_params(
|
||||
model.config, 1_000_000
|
||||
)
|
||||
# Check for AWQ quantization config
|
||||
quantization_config = getattr(model.config, "quantization_config", None)
|
||||
if quantization_config:
|
||||
|
|
@ -2371,7 +2649,7 @@ class Qwen3Loader(ModelLoader):
|
|||
rotary_interleave=False,
|
||||
rotary_scaling_type=rotary_scaling_type,
|
||||
rotary_scaling_factor=rotary_scaling_factor,
|
||||
rotary_base=getattr(model.config, "rope_theta", 10000),
|
||||
rotary_base=rope_theta,
|
||||
num_heads_kv=num_heads_kv,
|
||||
head_dim=head_dim,
|
||||
qk_norm=True,
|
||||
|
|
@ -3478,7 +3756,7 @@ class T5GemmaLoader(ModelLoader):
|
|||
return "T5GemmaForConditionalGeneration"
|
||||
|
||||
def set_layer_norm(self, spec, layer_norm):
|
||||
spec.gamma = layer_norm.weight.data + 1.0
|
||||
spec.gamma = (layer_norm.weight.data + 1.0).float()
|
||||
|
||||
def get_model_spec(self, model):
|
||||
encoder_config = model.config.encoder
|
||||
|
|
@ -3731,3 +4009,202 @@ class T5GemmaLoader(ModelLoader):
|
|||
delattr(layer, "cross_attn")
|
||||
delattr(layer, "mlp")
|
||||
gc.collect()
|
||||
|
||||
|
||||
@register_loader("T5Gemma2Config")
|
||||
class T5Gemma2Loader(ModelLoader):
|
||||
@property
|
||||
def architecture_name(self):
|
||||
return "T5Gemma2ForConditionalGeneration"
|
||||
|
||||
def _side_kwargs(self, side_config):
|
||||
num_heads = side_config.num_attention_heads
|
||||
num_heads_kv = getattr(side_config, "num_key_value_heads", num_heads)
|
||||
if num_heads_kv == num_heads:
|
||||
num_heads_kv = None
|
||||
head_dim = side_config.head_dim
|
||||
rope_params = getattr(side_config, "rope_parameters", {}) or {}
|
||||
global_theta = rope_params.get("full_attention", {}).get(
|
||||
"rope_theta", getattr(side_config, "rope_theta", 1_000_000)
|
||||
)
|
||||
return dict(
|
||||
num_layers=side_config.num_hidden_layers,
|
||||
num_heads=num_heads,
|
||||
pre_norm=True,
|
||||
activation=_SUPPORTED_ACTIVATIONS[side_config.hidden_activation],
|
||||
ffn_glu=True,
|
||||
rms_norm=True,
|
||||
rotary_dim=head_dim,
|
||||
rotary_interleave=False,
|
||||
rotary_scaling_type=attention_spec.RotaryScalingType.Linear,
|
||||
rotary_scaling_factor=1,
|
||||
rotary_base=global_theta,
|
||||
sliding_window=getattr(side_config, "sliding_window", 0),
|
||||
num_heads_kv=num_heads_kv,
|
||||
head_dim=head_dim,
|
||||
qk_norm=True,
|
||||
pre_post_layer_norm=True,
|
||||
)
|
||||
|
||||
def _apply_layer_types(self, side_config, spec_layers):
|
||||
layer_types = getattr(side_config, "layer_types", None)
|
||||
if not layer_types:
|
||||
return
|
||||
rope_params = getattr(side_config, "rope_parameters", {}) or {}
|
||||
global_theta = rope_params.get("full_attention", {}).get(
|
||||
"rope_theta", 1_000_000
|
||||
)
|
||||
local_theta = rope_params.get("sliding_attention", {}).get("rope_theta", 10_000)
|
||||
sliding_window = getattr(side_config, "sliding_window", 0)
|
||||
full_attn_params = rope_params.get("full_attention", {})
|
||||
full_rope_type = full_attn_params.get("rope_type", "default")
|
||||
full_rope_factor = full_attn_params.get("factor", 1.0)
|
||||
for layer_type, layer_spec in zip(layer_types, spec_layers):
|
||||
attn = layer_spec.self_attention
|
||||
if layer_type == "full_attention":
|
||||
attn.rotary_base = np.dtype("float32").type(global_theta)
|
||||
attn.sliding_window = np.dtype("int32").type(0)
|
||||
if full_rope_type == "linear":
|
||||
attn.rotary_scaling_factor = np.dtype("float32").type(
|
||||
full_rope_factor
|
||||
)
|
||||
else:
|
||||
attn.rotary_base = np.dtype("float32").type(local_theta)
|
||||
attn.sliding_window = np.dtype("int32").type(sliding_window)
|
||||
|
||||
def get_model_spec(self, model):
|
||||
encoder_config = model.config.encoder.text_config
|
||||
decoder_config = model.config.decoder
|
||||
|
||||
encoder = transformer_spec.TransformerEncoderSpec(
|
||||
**self._side_kwargs(encoder_config)
|
||||
)
|
||||
decoder = transformer_spec.TransformerDecoderSpec(
|
||||
**self._side_kwargs(decoder_config),
|
||||
with_encoder_attention=True,
|
||||
merged_encoder_attention=True,
|
||||
)
|
||||
spec = transformer_spec.TransformerSpec(encoder, decoder)
|
||||
|
||||
self.set_encoder(spec.encoder, model.model.encoder.text_model)
|
||||
self._apply_layer_types(encoder_config, spec.encoder.layer)
|
||||
|
||||
self.set_decoder(spec.decoder, model.model.decoder)
|
||||
self._apply_layer_types(decoder_config, spec.decoder.layer)
|
||||
|
||||
if hasattr(model.lm_head, "weight"):
|
||||
self.set_linear(spec.decoder.projection, model.lm_head)
|
||||
else:
|
||||
self.set_linear(spec.decoder.projection, model.model.decoder.embed_tokens)
|
||||
return spec
|
||||
|
||||
def set_vocabulary(self, spec, tokens):
|
||||
spec.register_source_vocabulary(tokens)
|
||||
spec.register_target_vocabulary(tokens)
|
||||
|
||||
def get_vocabulary(self, model, tokenizer):
|
||||
tokens = super().get_vocabulary(model, tokenizer)
|
||||
extra_ids = model.config.vocab_size - len(tokens)
|
||||
for i in range(extra_ids):
|
||||
tokens.append("<extra_id_%d>" % i)
|
||||
return tokens
|
||||
|
||||
def set_config(self, config, model, tokenizer):
|
||||
config.bos_token = getattr(tokenizer, "bos_token", None)
|
||||
config.eos_token = getattr(tokenizer, "eos_token", None)
|
||||
config.unk_token = getattr(tokenizer, "unk_token", None)
|
||||
config.decoder_start_token = getattr(tokenizer, "bos_token", None)
|
||||
config.layer_norm_epsilon = model.config.encoder.text_config.rms_norm_eps
|
||||
|
||||
def set_encoder(self, spec, encoder):
|
||||
encoder_emb_spec = (
|
||||
spec.embeddings[0] if isinstance(spec.embeddings, list) else spec.embeddings
|
||||
)
|
||||
self.set_embeddings(encoder_emb_spec, encoder.embed_tokens)
|
||||
self.set_layer_norm(spec.layer_norm, encoder.norm)
|
||||
embed_scale = getattr(encoder.embed_tokens, "embed_scale", None)
|
||||
spec.scale_embeddings = float(embed_scale) if embed_scale is not None else False
|
||||
|
||||
for layer_spec, layer in zip(spec.layer, encoder.layers):
|
||||
self.set_layer_norm(
|
||||
layer_spec.input_layer_norm, layer.pre_self_attn_layernorm
|
||||
)
|
||||
self.set_layer_norm(
|
||||
layer_spec.post_attention_layer_norm, layer.post_self_attn_layernorm
|
||||
)
|
||||
self._set_self_attention(layer_spec.self_attention, layer)
|
||||
self.set_layer_norm(
|
||||
layer_spec.pre_feedforward_layer_norm, layer.pre_feedforward_layernorm
|
||||
)
|
||||
self.set_layer_norm(
|
||||
layer_spec.post_feedforward_layer_norm, layer.post_feedforward_layernorm
|
||||
)
|
||||
self.set_linear(layer_spec.ffn.linear_0, layer.mlp.gate_proj)
|
||||
self.set_linear(layer_spec.ffn.linear_0_noact, layer.mlp.up_proj)
|
||||
self.set_linear(layer_spec.ffn.linear_1, layer.mlp.down_proj)
|
||||
delattr(layer, "self_attn")
|
||||
delattr(layer, "mlp")
|
||||
gc.collect()
|
||||
|
||||
def set_decoder(self, spec, module, quant_type=common_spec.Quantization.CT2):
|
||||
embed_scale = getattr(module.embed_tokens, "embed_scale", None)
|
||||
spec.scale_embeddings = float(embed_scale) if embed_scale is not None else False
|
||||
spec.start_from_zero_embedding = False
|
||||
self.set_embeddings(spec.embeddings, module.embed_tokens)
|
||||
self.set_layer_norm(spec.layer_norm, module.norm)
|
||||
|
||||
for layer_spec, layer in zip(spec.layer, module.layers):
|
||||
attn_spec = layer_spec.self_attention
|
||||
self.set_layer_norm(
|
||||
layer_spec.input_layer_norm, layer.pre_self_attn_layernorm
|
||||
)
|
||||
self.set_layer_norm(
|
||||
layer_spec.post_attention_layer_norm, layer.post_self_attn_layernorm
|
||||
)
|
||||
# Merged attention: same K/V projections feed both self-attn and cross-attn.
|
||||
# Save them again as a fused memory_kv linear so the runtime can project
|
||||
# encoder memory through them at inference time.
|
||||
kv_split = [common_spec.LinearSpec() for _ in range(2)]
|
||||
self.set_linear(kv_split[0], layer.self_attn.k_proj, quant_type=quant_type)
|
||||
self.set_linear(kv_split[1], layer.self_attn.v_proj, quant_type=quant_type)
|
||||
utils.fuse_linear(attn_spec.memory_kv, kv_split)
|
||||
|
||||
self._set_self_attention(attn_spec, layer, quant_type=quant_type)
|
||||
|
||||
self.set_layer_norm(
|
||||
layer_spec.pre_feedforward_layer_norm, layer.pre_feedforward_layernorm
|
||||
)
|
||||
self.set_layer_norm(
|
||||
layer_spec.post_feedforward_layer_norm, layer.post_feedforward_layernorm
|
||||
)
|
||||
self.set_linear(
|
||||
layer_spec.ffn.linear_0, layer.mlp.gate_proj, quant_type=quant_type
|
||||
)
|
||||
self.set_linear(
|
||||
layer_spec.ffn.linear_0_noact, layer.mlp.up_proj, quant_type=quant_type
|
||||
)
|
||||
self.set_linear(
|
||||
layer_spec.ffn.linear_1, layer.mlp.down_proj, quant_type=quant_type
|
||||
)
|
||||
delattr(layer, "self_attn")
|
||||
delattr(layer, "mlp")
|
||||
gc.collect()
|
||||
|
||||
def _set_self_attention(
|
||||
self, attn_spec, layer, quant_type=common_spec.Quantization.CT2
|
||||
):
|
||||
# T5Gemma2 wraps self-attn pre/post norms on the layer (not inside attention).
|
||||
# We map them via input_layer_norm/post_attention_layer_norm on the layer spec.
|
||||
qkv_split = [common_spec.LinearSpec() for _ in range(3)]
|
||||
self.set_linear(qkv_split[0], layer.self_attn.q_proj, quant_type=quant_type)
|
||||
self.set_linear(qkv_split[1], layer.self_attn.k_proj, quant_type=quant_type)
|
||||
self.set_linear(qkv_split[2], layer.self_attn.v_proj, quant_type=quant_type)
|
||||
utils.fuse_linear(attn_spec.linear[0], qkv_split)
|
||||
self.set_linear(
|
||||
attn_spec.linear[1], layer.self_attn.o_proj, quant_type=quant_type
|
||||
)
|
||||
self.set_layer_norm(attn_spec.q_norm, layer.self_attn.q_norm)
|
||||
self.set_layer_norm(attn_spec.k_norm, layer.self_attn.k_norm)
|
||||
|
||||
def set_layer_norm(self, spec, layer_norm):
|
||||
spec.gamma = (layer_norm.weight.data + 1.0).float()
|
||||
|
|
|
|||
Loading…
Add table
Add a link
Reference in a new issue