keras-hub-nightly 0.22.0.dev202508190411__py3-none-any.whl → 0.23.0.dev202508200409__py3-none-any.whl
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- keras_hub/src/models/backbone.py +16 -0
- keras_hub/src/models/causal_lm.py +21 -0
- keras_hub/src/models/causal_lm_preprocessor.py +14 -0
- keras_hub/src/tokenizers/tokenizer.py +15 -0
- keras_hub/src/utils/transformers/export/gemma.py +49 -4
- keras_hub/src/utils/transformers/export/hf_exporter.py +71 -25
- keras_hub/src/version.py +1 -1
- {keras_hub_nightly-0.22.0.dev202508190411.dist-info → keras_hub_nightly-0.23.0.dev202508200409.dist-info}/METADATA +1 -1
- {keras_hub_nightly-0.22.0.dev202508190411.dist-info → keras_hub_nightly-0.23.0.dev202508200409.dist-info}/RECORD +11 -11
- {keras_hub_nightly-0.22.0.dev202508190411.dist-info → keras_hub_nightly-0.23.0.dev202508200409.dist-info}/WHEEL +0 -0
- {keras_hub_nightly-0.22.0.dev202508190411.dist-info → keras_hub_nightly-0.23.0.dev202508200409.dist-info}/top_level.txt +0 -0
keras_hub/src/models/backbone.py
CHANGED
@@ -277,3 +277,19 @@ class Backbone(keras.Model):
|
|
277
277
|
layer.lora_kernel_a.assign(lora_kernel_a)
|
278
278
|
layer.lora_kernel_b.assign(lora_kernel_b)
|
279
279
|
store.close()
|
280
|
+
|
281
|
+
def export_to_transformers(self, path):
|
282
|
+
"""Export the backbone model to HuggingFace Transformers format.
|
283
|
+
|
284
|
+
This saves the backbone's configuration and weights in a format
|
285
|
+
compatible with HuggingFace Transformers. For unsupported model
|
286
|
+
architectures, a ValueError is raised.
|
287
|
+
|
288
|
+
Args:
|
289
|
+
path: str. Path to save the exported model.
|
290
|
+
"""
|
291
|
+
from keras_hub.src.utils.transformers.export.hf_exporter import (
|
292
|
+
export_backbone,
|
293
|
+
)
|
294
|
+
|
295
|
+
export_backbone(self, path)
|
@@ -392,3 +392,24 @@ class CausalLM(Task):
|
|
392
392
|
outputs = [postprocess(x) for x in outputs]
|
393
393
|
|
394
394
|
return self._normalize_generate_outputs(outputs, input_is_scalar)
|
395
|
+
|
396
|
+
def export_to_transformers(self, path):
|
397
|
+
"""Export the full CausalLM model to HuggingFace Transformers format.
|
398
|
+
|
399
|
+
This exports the trainable model, tokenizer, and configurations in a
|
400
|
+
format compatible with HuggingFace Transformers. For unsupported model
|
401
|
+
architectures, a ValueError is raised.
|
402
|
+
|
403
|
+
If the preprocessor is attached (default), both the trainable model and
|
404
|
+
tokenizer are exported. To export only the trainable model, set
|
405
|
+
`self.preprocessor = None` before calling this method, then export the
|
406
|
+
preprocessor separately via `preprocessor.export_to_transformers(path)`.
|
407
|
+
|
408
|
+
Args:
|
409
|
+
path: str. Path to save the exported model.
|
410
|
+
"""
|
411
|
+
from keras_hub.src.utils.transformers.export.hf_exporter import (
|
412
|
+
export_to_safetensors,
|
413
|
+
)
|
414
|
+
|
415
|
+
export_to_safetensors(self, path)
|
@@ -180,3 +180,17 @@ class CausalLMPreprocessor(Preprocessor):
|
|
180
180
|
self._sequence_length = value
|
181
181
|
if self.packer is not None:
|
182
182
|
self.packer.sequence_length = value
|
183
|
+
|
184
|
+
def export_to_transformers(self, path):
|
185
|
+
"""Export the preprocessor to HuggingFace Transformers format.
|
186
|
+
|
187
|
+
Args:
|
188
|
+
path: str. Path to save the exported preprocessor/tokenizer.
|
189
|
+
"""
|
190
|
+
if self.tokenizer is None:
|
191
|
+
raise ValueError("Preprocessor must have a tokenizer for export.")
|
192
|
+
from keras_hub.src.utils.transformers.export.hf_exporter import (
|
193
|
+
export_tokenizer,
|
194
|
+
)
|
195
|
+
|
196
|
+
export_tokenizer(self.tokenizer, path)
|
@@ -261,3 +261,18 @@ class Tokenizer(PreprocessingLayer):
|
|
261
261
|
if cls.backbone_cls != backbone_cls:
|
262
262
|
cls = find_subclass(preset, cls, backbone_cls)
|
263
263
|
return loader.load_tokenizer(cls, config_file, **kwargs)
|
264
|
+
|
265
|
+
def export_to_transformers(self, path):
|
266
|
+
"""Export the tokenizer to HuggingFace Transformers format.
|
267
|
+
|
268
|
+
This saves tokenizer assets in a format compatible with HuggingFace
|
269
|
+
Transformers.
|
270
|
+
|
271
|
+
Args:
|
272
|
+
path: str. Path to save the exported tokenizer.
|
273
|
+
"""
|
274
|
+
from keras_hub.src.utils.transformers.export.hf_exporter import (
|
275
|
+
export_tokenizer,
|
276
|
+
)
|
277
|
+
|
278
|
+
export_tokenizer(self, path)
|
@@ -2,6 +2,7 @@ import keras.ops as ops
|
|
2
2
|
|
3
3
|
|
4
4
|
def get_gemma_config(backbone):
|
5
|
+
token_embedding_layer = backbone.get_layer("token_embedding")
|
5
6
|
hf_config = {
|
6
7
|
"vocab_size": backbone.vocabulary_size,
|
7
8
|
"num_hidden_layers": backbone.num_layers,
|
@@ -11,11 +12,16 @@ def get_gemma_config(backbone):
|
|
11
12
|
"intermediate_size": backbone.intermediate_dim // 2,
|
12
13
|
"head_dim": backbone.head_dim,
|
13
14
|
"max_position_embeddings": 8192,
|
15
|
+
"tie_word_embeddings": token_embedding_layer.tie_weights,
|
16
|
+
"pad_token_id": 0,
|
17
|
+
"bos_token_id": 2,
|
18
|
+
"eos_token_id": 1,
|
19
|
+
"model_type": "gemma",
|
14
20
|
}
|
15
21
|
return hf_config
|
16
22
|
|
17
23
|
|
18
|
-
def get_gemma_weights_map(backbone):
|
24
|
+
def get_gemma_weights_map(backbone, include_lm_head=False):
|
19
25
|
weights_dict = {}
|
20
26
|
|
21
27
|
# Map token embedding
|
@@ -83,7 +89,46 @@ def get_gemma_weights_map(backbone):
|
|
83
89
|
"final_normalization"
|
84
90
|
).weights[0]
|
85
91
|
|
86
|
-
#
|
87
|
-
|
88
|
-
|
92
|
+
# Map lm_head if embeddings are not tied
|
93
|
+
if include_lm_head and not token_embedding_layer.tie_weights:
|
94
|
+
weights_dict["lm_head.weight"] = ops.transpose(
|
95
|
+
token_embedding_layer.reverse_embeddings
|
96
|
+
)
|
89
97
|
return weights_dict
|
98
|
+
|
99
|
+
|
100
|
+
def get_gemma_tokenizer_config(tokenizer):
|
101
|
+
tokenizer_config = {
|
102
|
+
"tokenizer_class": "GemmaTokenizer",
|
103
|
+
"clean_up_tokenization_spaces": False,
|
104
|
+
"bos_token": "<bos>",
|
105
|
+
"eos_token": "<eos>",
|
106
|
+
"pad_token": "<pad>",
|
107
|
+
"unk_token": "<unk>",
|
108
|
+
"add_bos_token": True,
|
109
|
+
"add_eos_token": False,
|
110
|
+
"model_max_length": 8192,
|
111
|
+
}
|
112
|
+
# Add added_tokens_decoder
|
113
|
+
added_tokens_decoder = {}
|
114
|
+
special_tokens = [
|
115
|
+
"<pad>",
|
116
|
+
"<bos>",
|
117
|
+
"<eos>",
|
118
|
+
"<unk>",
|
119
|
+
"<start_of_turn>",
|
120
|
+
"<end_of_turn>",
|
121
|
+
]
|
122
|
+
for token in special_tokens:
|
123
|
+
token_id = tokenizer.token_to_id(token)
|
124
|
+
if token_id is not None:
|
125
|
+
added_tokens_decoder[str(token_id)] = {
|
126
|
+
"content": token,
|
127
|
+
"special": True,
|
128
|
+
"single_word": False,
|
129
|
+
"lstrip": False,
|
130
|
+
"rstrip": False,
|
131
|
+
"normalized": False,
|
132
|
+
}
|
133
|
+
tokenizer_config["added_tokens_decoder"] = added_tokens_decoder
|
134
|
+
return tokenizer_config
|
@@ -6,58 +6,59 @@ import warnings
|
|
6
6
|
import keras
|
7
7
|
|
8
8
|
from keras_hub.src.utils.transformers.export.gemma import get_gemma_config
|
9
|
+
from keras_hub.src.utils.transformers.export.gemma import (
|
10
|
+
get_gemma_tokenizer_config,
|
11
|
+
)
|
9
12
|
from keras_hub.src.utils.transformers.export.gemma import get_gemma_weights_map
|
10
13
|
|
11
14
|
MODEL_CONFIGS = {
|
12
15
|
"GemmaBackbone": get_gemma_config,
|
13
|
-
# Add future models
|
16
|
+
# Add for future models, e.g., "MistralBackbone": get_mistral_config
|
14
17
|
}
|
15
18
|
|
16
19
|
MODEL_EXPORTERS = {
|
17
20
|
"GemmaBackbone": get_gemma_weights_map,
|
18
|
-
# Add future models
|
21
|
+
# Add for future models, e.g., "MistralBackbone": get_mistral_weights_map
|
19
22
|
}
|
20
23
|
|
24
|
+
MODEL_TOKENIZER_CONFIGS = {
|
25
|
+
"GemmaTokenizer": get_gemma_tokenizer_config,
|
26
|
+
# Add for future models, e.g., "MistralTokenizer":
|
27
|
+
# get_mistral_tokenizer_config
|
28
|
+
}
|
21
29
|
|
22
|
-
def export_to_safetensors(keras_model, path):
|
23
|
-
"""Converts a Keras model to Hugging Face safetensor format.
|
24
30
|
|
25
|
-
|
26
|
-
|
27
|
-
- Saves the configuration as 'config.json'.
|
28
|
-
- Saves weights in 'model.safetensors'.
|
29
|
-
- Saves tokenizer assets.
|
31
|
+
def export_backbone(backbone, path, include_lm_head=False):
|
32
|
+
"""Export the backbone model to HuggingFace format.
|
30
33
|
|
31
34
|
Args:
|
32
|
-
|
33
|
-
path: str. Path
|
34
|
-
|
35
|
+
backbone: The Keras backbone model to convert.
|
36
|
+
path: str. Path to save the exported model.
|
37
|
+
include_lm_head: bool. If True, include lm_head weights if applicable.
|
35
38
|
"""
|
36
39
|
backend = keras.config.backend()
|
37
|
-
backbone = keras_model.backbone
|
38
40
|
model_type = backbone.__class__.__name__
|
39
|
-
|
40
41
|
if model_type not in MODEL_CONFIGS:
|
41
|
-
raise ValueError(
|
42
|
-
|
42
|
+
raise ValueError(
|
43
|
+
f"Export to Transformers format not implemented for {model_type}"
|
44
|
+
)
|
43
45
|
if model_type not in MODEL_EXPORTERS:
|
44
|
-
raise ValueError(
|
45
|
-
|
46
|
+
raise ValueError(
|
47
|
+
f"Export to Transformers format not implemented for {model_type}"
|
48
|
+
)
|
49
|
+
# Get config
|
46
50
|
get_config_fn = MODEL_CONFIGS[model_type]
|
47
51
|
hf_config = get_config_fn(backbone)
|
48
|
-
|
52
|
+
# Get weights
|
49
53
|
get_weights_fn = MODEL_EXPORTERS[model_type]
|
50
|
-
weights_dict = get_weights_fn(backbone)
|
51
|
-
|
54
|
+
weights_dict = get_weights_fn(backbone, include_lm_head=include_lm_head)
|
52
55
|
if not weights_dict:
|
53
56
|
raise ValueError("No weights to save.")
|
54
|
-
|
55
57
|
# Save config
|
56
58
|
os.makedirs(path, exist_ok=True)
|
57
59
|
config_path = os.path.join(path, "config.json")
|
58
60
|
with open(config_path, "w") as f:
|
59
61
|
json.dump(hf_config, f)
|
60
|
-
|
61
62
|
# Save weights based on backend
|
62
63
|
weights_path = os.path.join(path, "model.safetensors")
|
63
64
|
if backend == "torch":
|
@@ -81,9 +82,28 @@ def export_to_safetensors(keras_model, path):
|
|
81
82
|
else:
|
82
83
|
raise ValueError(f"Unsupported backend: {backend}")
|
83
84
|
|
84
|
-
# Save tokenizer assets
|
85
|
-
keras_model.preprocessor.tokenizer.save_assets(path)
|
86
85
|
|
86
|
+
def export_tokenizer(tokenizer, path):
|
87
|
+
"""Export only the tokenizer to HuggingFace Transformers format.
|
88
|
+
|
89
|
+
Args:
|
90
|
+
tokenizer: The Keras tokenizer to convert.
|
91
|
+
path: str. Path to save the exported tokenizer.
|
92
|
+
"""
|
93
|
+
os.makedirs(path, exist_ok=True)
|
94
|
+
# Save tokenizer assets
|
95
|
+
tokenizer.save_assets(path)
|
96
|
+
# Export tokenizer config
|
97
|
+
tokenizer_type = tokenizer.__class__.__name__
|
98
|
+
if tokenizer_type not in MODEL_TOKENIZER_CONFIGS:
|
99
|
+
raise ValueError(
|
100
|
+
"Export to Transformers format not implemented for {tokenizer_type}"
|
101
|
+
)
|
102
|
+
get_tokenizer_config_fn = MODEL_TOKENIZER_CONFIGS[tokenizer_type]
|
103
|
+
tokenizer_config = get_tokenizer_config_fn(tokenizer)
|
104
|
+
tokenizer_config_path = os.path.join(path, "tokenizer_config.json")
|
105
|
+
with open(tokenizer_config_path, "w") as f:
|
106
|
+
json.dump(tokenizer_config, f, indent=4)
|
87
107
|
# Rename vocabulary file
|
88
108
|
vocab_spm_path = os.path.join(path, "vocabulary.spm")
|
89
109
|
tokenizer_model_path = os.path.join(path, "tokenizer.model")
|
@@ -96,3 +116,29 @@ def export_to_safetensors(keras_model, path):
|
|
96
116
|
"is correct and that the vocabulary file is present "
|
97
117
|
"in the original model."
|
98
118
|
)
|
119
|
+
|
120
|
+
|
121
|
+
def export_to_safetensors(keras_model, path):
|
122
|
+
"""Converts a Keras model to Hugging Face Transformers format.
|
123
|
+
|
124
|
+
It does the following:
|
125
|
+
- Exports the backbone (config and weights).
|
126
|
+
- Exports the tokenizer assets.
|
127
|
+
|
128
|
+
Args:
|
129
|
+
keras_model: The Keras model to convert.
|
130
|
+
path: str. Path of the directory to which the safetensors file,
|
131
|
+
config and tokenizer will be saved.
|
132
|
+
"""
|
133
|
+
backbone = keras_model.backbone
|
134
|
+
export_backbone(backbone, path, include_lm_head=True)
|
135
|
+
if (
|
136
|
+
keras_model.preprocessor is not None
|
137
|
+
and keras_model.preprocessor.tokenizer is None
|
138
|
+
):
|
139
|
+
raise ValueError(
|
140
|
+
"CausalLM preprocessor must have a tokenizer for export "
|
141
|
+
"if attached."
|
142
|
+
)
|
143
|
+
if keras_model.preprocessor is not None:
|
144
|
+
export_tokenizer(keras_model.preprocessor.tokenizer, path)
|
keras_hub/src/version.py
CHANGED
@@ -5,7 +5,7 @@ keras_hub/models/__init__.py,sha256=UXMwKVZ7bg-AOrq2xsl8M0idUAS89pkdCvQKhzL-D3I,
|
|
5
5
|
keras_hub/samplers/__init__.py,sha256=aFQIkiqbZpi8vjrPp2MVII4QUfE-eQjra5fMeHsoy7k,886
|
6
6
|
keras_hub/src/__init__.py,sha256=47DEQpj8HBSa-_TImW-5JCeuQeRkm5NMpJWZG3hSuFU,0
|
7
7
|
keras_hub/src/api_export.py,sha256=9pQZK27JObxWZ96QPLBp1OBsjWigh1iuV6RglPGMRk0,1499
|
8
|
-
keras_hub/src/version.py,sha256=
|
8
|
+
keras_hub/src/version.py,sha256=PDBU1UqKx4PB-kMmTU1MRLk90YLp6I_7y6FpUU9xYA4,222
|
9
9
|
keras_hub/src/layers/__init__.py,sha256=47DEQpj8HBSa-_TImW-5JCeuQeRkm5NMpJWZG3hSuFU,0
|
10
10
|
keras_hub/src/layers/modeling/__init__.py,sha256=47DEQpj8HBSa-_TImW-5JCeuQeRkm5NMpJWZG3hSuFU,0
|
11
11
|
keras_hub/src/layers/modeling/alibi_bias.py,sha256=1XBTHI52L_iJDhN_w5ydu_iMhCuTgQAxEPwcLA6BPuk,4411
|
@@ -43,9 +43,9 @@ keras_hub/src/metrics/rouge_n.py,sha256=JoFtmgjF4Ic263ny6bfD6vMHKreH9le3HnOOxemu
|
|
43
43
|
keras_hub/src/models/__init__.py,sha256=47DEQpj8HBSa-_TImW-5JCeuQeRkm5NMpJWZG3hSuFU,0
|
44
44
|
keras_hub/src/models/audio_to_text.py,sha256=XoOjXtKBX6K1fz-zOXcdVo3FpjuxCMnJZh2LQcYXb_0,2726
|
45
45
|
keras_hub/src/models/audio_to_text_preprocessor.py,sha256=GS-WWyJ6aSsPRxi_0bxvxA00h2mT2FEwSdAoQXAUYVI,3249
|
46
|
-
keras_hub/src/models/backbone.py,sha256=
|
47
|
-
keras_hub/src/models/causal_lm.py,sha256=
|
48
|
-
keras_hub/src/models/causal_lm_preprocessor.py,sha256=
|
46
|
+
keras_hub/src/models/backbone.py,sha256=MYc9rJbFRM1q3asI3ORb1sFakV9nBACSQFHnkZBc75M,12323
|
47
|
+
keras_hub/src/models/causal_lm.py,sha256=iyPfYhfvM9Rqyc-SZg132KsCYA3Poy-9RRQXN9U8lpE,17671
|
48
|
+
keras_hub/src/models/causal_lm_preprocessor.py,sha256=nxl-sfmCfkfl6JmVRASa878QbaZUgWSA6Jdu48x4-dY,7155
|
49
49
|
keras_hub/src/models/feature_pyramid_backbone.py,sha256=clEW-TTQSVJ_5qFNdDF0iABkin1p_xlBUFjJrC7T0IA,2247
|
50
50
|
keras_hub/src/models/image_classifier.py,sha256=yt6cjhPfqs8A_eWXBsXdXFzn-aRgH2rVHUq7Zu7CyK8,7804
|
51
51
|
keras_hub/src/models/image_classifier_preprocessor.py,sha256=Bf7jSqHB1hX2ZWoWQS4GcXNOY_EjeoJi-_vtzCAqw4o,2690
|
@@ -500,7 +500,7 @@ keras_hub/src/tokenizers/byte_pair_tokenizer.py,sha256=WeUlHMAf5y_MUjFIfVhEcFoOZ
|
|
500
500
|
keras_hub/src/tokenizers/byte_tokenizer.py,sha256=GPIKaddXugbfckfhodADsBpaYb72DgFMs_xfXHnK4qU,10418
|
501
501
|
keras_hub/src/tokenizers/sentence_piece_tokenizer.py,sha256=nOqkpa2nHitITpdowPHdwxiN87e8huLW8Dt2gozVnhI,9350
|
502
502
|
keras_hub/src/tokenizers/sentence_piece_tokenizer_trainer.py,sha256=caqgV9N4lH97zBviFPdpwo_O95AaJBEJLQv6Icq3Hs8,4774
|
503
|
-
keras_hub/src/tokenizers/tokenizer.py,sha256=
|
503
|
+
keras_hub/src/tokenizers/tokenizer.py,sha256=dk7ZY08k-YMb25FmeK6SQouLKXOvHQjOww2Z30KRyt0,10173
|
504
504
|
keras_hub/src/tokenizers/unicode_codepoint_tokenizer.py,sha256=hRv_XxoPIPDpHfO0ZttSOv_M89sMaFpvmllojvKz_ac,13553
|
505
505
|
keras_hub/src/tokenizers/word_piece_tokenizer.py,sha256=vP6AZgbzsRiuPCt3W_n94nsF7XiERnagWcH_rqJHtVU,19943
|
506
506
|
keras_hub/src/tokenizers/word_piece_tokenizer_trainer.py,sha256=cylrs02ZrYQ1TuZr9oyS3NrVbDwGctA3VXbIh1pFJMQ,6743
|
@@ -542,11 +542,11 @@ keras_hub/src/utils/transformers/convert_qwen_moe.py,sha256=a7R28aln-PdAcNuKAXdr
|
|
542
542
|
keras_hub/src/utils/transformers/convert_vit.py,sha256=9SUZ9utNJhW_5cj3acMn9cRy47u2eIcDsrhmzj77o9k,5187
|
543
543
|
keras_hub/src/utils/transformers/preset_loader.py,sha256=YZVpeNhFITHdauY3MWESrZLNUIJt9ilHJ1jUhvITNT8,4781
|
544
544
|
keras_hub/src/utils/transformers/safetensor_utils.py,sha256=CYUHyA4y-B61r7NDnCsFb4t_UmSwZ1k9L-8gzEd6KRg,3339
|
545
|
-
keras_hub/src/utils/transformers/export/gemma.py,sha256=
|
546
|
-
keras_hub/src/utils/transformers/export/hf_exporter.py,sha256=
|
545
|
+
keras_hub/src/utils/transformers/export/gemma.py,sha256=xX_vfQwvFZ_-lQX4kgMNOGKL7fL_1yk7QyGYV2Qyly4,4699
|
546
|
+
keras_hub/src/utils/transformers/export/hf_exporter.py,sha256=Qk52c6LIA2eMHUNY9Vy4STJSpnhLMdJ_t-3ljqhSr4k,5081
|
547
547
|
keras_hub/tokenizers/__init__.py,sha256=gQIESc4erRLuwxHyxtYy_Z0ePQXw_uhXAa4GVHMffYk,4244
|
548
548
|
keras_hub/utils/__init__.py,sha256=jXPqVGBpJr_PpYmqD8aDG-fRMlxH-ulqCR2SZMn288Y,646
|
549
|
-
keras_hub_nightly-0.
|
550
|
-
keras_hub_nightly-0.
|
551
|
-
keras_hub_nightly-0.
|
552
|
-
keras_hub_nightly-0.
|
549
|
+
keras_hub_nightly-0.23.0.dev202508200409.dist-info/METADATA,sha256=vaEex836rRGrO23Lmx6CugNTCP20DYdh6QbntxEIEWg,7395
|
550
|
+
keras_hub_nightly-0.23.0.dev202508200409.dist-info/WHEEL,sha256=_zCd3N1l69ArxyTb8rzEoP9TpbYXkqRFSNOD5OuxnTs,91
|
551
|
+
keras_hub_nightly-0.23.0.dev202508200409.dist-info/top_level.txt,sha256=N4J6piIWBKa38A4uV-CnIopnOEf8mHAbkNXafXm_CuA,10
|
552
|
+
keras_hub_nightly-0.23.0.dev202508200409.dist-info/RECORD,,
|
File without changes
|