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.
@@ -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
- # Tie weights, but clone to avoid sharing memory issues
87
- weights_dict["lm_head.weight"] = ops.copy(token_embedding_layer.weights[0])
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 here, e.g., "LlamaBackbone": get_llama_config,
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 here, e.g., "LlamaBackbone": get_llama_weights_map,
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
- It does the following:
26
- - Extracts and maps weights from the Keras backbone to safetensors.
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
- keras_model: The Keras model to convert.
33
- path: str. Path of the directory to which the safetensors file,
34
- config and tokenizer will be saved.
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(f"Config not implemented for {model_type}")
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(f"Exporter not implemented for {model_type}")
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
@@ -1,7 +1,7 @@
1
1
  from keras_hub.src.api_export import keras_hub_export
2
2
 
3
3
  # Unique source of truth for the version number.
4
- __version__ = "0.22.0.dev202508190411"
4
+ __version__ = "0.23.0.dev202508200409"
5
5
 
6
6
 
7
7
  @keras_hub_export("keras_hub.version")
@@ -1,6 +1,6 @@
1
1
  Metadata-Version: 2.4
2
2
  Name: keras-hub-nightly
3
- Version: 0.22.0.dev202508190411
3
+ Version: 0.23.0.dev202508200409
4
4
  Summary: Pretrained models for Keras.
5
5
  Author-email: Keras team <keras-users@googlegroups.com>
6
6
  License-Expression: Apache-2.0
@@ -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=Ey-gc5DdV3BKvC-FIM1hDevCrbEYvV5XQgYnIzimtds,222
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=utZP09_u5FpMGiq8jl3W98TCW8CysndwLw2VCs3BHz8,11780
47
- keras_hub/src/models/causal_lm.py,sha256=ReaF-i3SHsCkHh4c28jM72QjMQ8x7yiCwG39FRb-7KE,16786
48
- keras_hub/src/models/causal_lm_preprocessor.py,sha256=YY7VJZicdmnjDSWi9g4_pEpd5bdJK166GlWcapvokF0,6663
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=v0Ka5ayrBwpsGBlkIadXK-b4RsMTbhV6BZrvKullbxY,9722
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=NpTSgRUSWp3WXQil1CjYUVFVyyVhpO-4-3q2en2Wxwg,3264
546
- keras_hub/src/utils/transformers/export/hf_exporter.py,sha256=oTdRS8SalPCbi_cZPC55aZUBc-1_pdviUIp0XysA4cI,3234
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.22.0.dev202508190411.dist-info/METADATA,sha256=Rzvs3Xi8nPtcH71ZHF18q0x0yqSuotTblSrBfMjypmg,7395
550
- keras_hub_nightly-0.22.0.dev202508190411.dist-info/WHEEL,sha256=_zCd3N1l69ArxyTb8rzEoP9TpbYXkqRFSNOD5OuxnTs,91
551
- keras_hub_nightly-0.22.0.dev202508190411.dist-info/top_level.txt,sha256=N4J6piIWBKa38A4uV-CnIopnOEf8mHAbkNXafXm_CuA,10
552
- keras_hub_nightly-0.22.0.dev202508190411.dist-info/RECORD,,
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,,