Skip to content
Open
Show file tree
Hide file tree
Changes from 104 commits
Commits
Show all changes
150 commits
Select commit Hold shift + click to select a range
04cd682
Update nn.py
pctablet505 May 6, 2025
1a74465
Update nn.py
pctablet505 May 6, 2025
c11eb81
Update nn.py
pctablet505 May 6, 2025
c81e18c
Update nn.py
pctablet505 May 6, 2025
d938e20
Update nn.py
pctablet505 May 7, 2025
f60811e
Update nn.py
pctablet505 May 7, 2025
b3ae323
Merge branch 'master' of https://github.com/pctablet505/keras
pctablet505 May 12, 2025
28eeb24
Update random_grayscale.py
pctablet505 May 12, 2025
de81e5b
Update keras/src/layers/preprocessing/image_preprocessing/random_gray…
pctablet505 May 12, 2025
66661ac
Update random_grayscale_test.py
pctablet505 May 12, 2025
c37f2b5
code reformat
pctablet505 May 13, 2025
498dece
Update random_grayscale_test.py
pctablet505 May 13, 2025
b0b5f63
Merge branch 'master' of https://github.com/pctablet505/keras
pctablet505 May 21, 2025
653f5b1
changed compute_output_spec
pctablet505 May 21, 2025
e681e4c
Merge branch 'keras-team:master' into master
pctablet505 May 21, 2025
27ad80b
Update random_grayscale.py
pctablet505 May 26, 2025
50f6292
Merge branch 'master' of https://github.com/pctablet505/keras
pctablet505 May 29, 2025
579cc11
Reapply "Fixed issue with dot_product_attention when using TPU. (#21…
pctablet505 May 29, 2025
7a0c547
Improve error handling in _can_use_flash_attention for better debugging
pctablet505 May 29, 2025
f7a2290
Revert "Improve error handling in _can_use_flash_attention for better…
pctablet505 May 29, 2025
8bae892
Fix JAX API compatibility and improve error handling in `_can_use_fla…
pctablet505 May 29, 2025
ee196cd
Updated `dot_product_attention`
pctablet505 May 29, 2025
40583c8
Update nn.py
pctablet505 Jun 7, 2025
7c918ba
Update nn.py
pctablet505 Jun 7, 2025
a927e7e
Merge branch 'keras-team:master' into master
pctablet505 Jun 10, 2025
f04eafa
Merge branch 'keras-team:master' into master
pctablet505 Jul 7, 2025
bbc29a7
Merge branch 'keras-team:master' into master
pctablet505 Jul 14, 2025
bac3416
Merge branch 'keras-team:master' into master
pctablet505 Jul 15, 2025
98877eb
Created using Colab
pctablet505 Aug 18, 2025
39c559b
Merge branch 'keras-team:master' into master
pctablet505 Aug 20, 2025
417e4b1
Delete Model_Pruning.ipynb
pctablet505 Aug 20, 2025
14bfd9b
Merge branch 'master' of https://github.com/pctablet505/keras
pctablet505 Aug 20, 2025
9d34d0a
Merge branch 'keras-team:master' into master
pctablet505 Aug 26, 2025
837506d
Add LiteRT (TFLite) export support to Keras
pctablet505 Aug 28, 2025
631850e
Update lite_rt_exporter.py
pctablet505 Aug 28, 2025
f5aa72e
Update export_utils.py
pctablet505 Aug 28, 2025
2b952d6
Refactor LiteRTExporter to simplify TFLite conversion
pctablet505 Aug 28, 2025
8f81dd5
Refactor import structure to avoid circular dependencies
pctablet505 Aug 28, 2025
011f1d8
trying kerashub
pctablet505 Aug 28, 2025
9a99a32
Enhance LiteRT export for sequence models and large models
pctablet505 Aug 28, 2025
d0070c6
Update lite_rt_exporter.py
pctablet505 Aug 28, 2025
761793f
Update lite_rt_exporter.py
pctablet505 Aug 28, 2025
7bb0506
Prevent tensor overflow for large vocabulary models
pctablet505 Sep 1, 2025
c219eb1
Update export_utils.py
pctablet505 Sep 1, 2025
e26ff6b
Update lite_rt_exporter.py
pctablet505 Sep 1, 2025
4a32e04
Simplify TFLite export and sequence length safety checks
pctablet505 Sep 1, 2025
20d29a8
Merge branch 'keras-team:master' into master
pctablet505 Sep 2, 2025
3aca2f6
Merge branch 'keras-team:master' into export
pctablet505 Sep 2, 2025
926b0a8
Refactor TFLite export logic and add simple exporter
pctablet505 Sep 2, 2025
441a778
Merge branch 'export' of https://github.com/pctablet505/keras into ex…
pctablet505 Sep 2, 2025
4a8a9d5
Improve export robustness for large vocab and Keras-Hub models
pctablet505 Sep 2, 2025
f4b43b4
Update lite_rt_exporter.py
pctablet505 Sep 2, 2025
0fe4bd5
Update lite_rt_exporter.py
pctablet505 Sep 2, 2025
8c3faa3
Update lite_rt_exporter.py
pctablet505 Sep 2, 2025
88b6a6f
Update lite_rt_exporter.py
pctablet505 Sep 2, 2025
da13d04
Update lite_rt_exporter.py
pctablet505 Sep 3, 2025
f1f700c
Update lite_rt_exporter.py
pctablet505 Sep 8, 2025
5944780
Update lite_rt_exporter.py
pctablet505 Sep 9, 2025
4404c39
Update lite_rt_exporter.py
pctablet505 Sep 9, 2025
6a119fb
Update lite_rt_exporter.py
pctablet505 Sep 15, 2025
e469244
Merge branch 'keras-team:master' into master
pctablet505 Sep 16, 2025
4cec7cd
Merge branch 'keras-team:master' into export
pctablet505 Sep 16, 2025
3a7fcc4
Merge branch 'keras-team:master' into export
pctablet505 Sep 17, 2025
51a1c7f
Remove sequence length bounding from export utils
pctablet505 Sep 17, 2025
e1fca24
Delete test_keras_hub_export.py
pctablet505 Sep 17, 2025
fd197d9
Merge branch 'keras-team:master' into master
pctablet505 Sep 18, 2025
214558a
Merge branch 'keras-team:master' into export
pctablet505 Sep 22, 2025
73f00f1
Rename LiteRT exporter to Litert and update references
pctablet505 Sep 29, 2025
ebf11e2
Enhance LiteRT exporter and expand export tests
pctablet505 Sep 29, 2025
c6f0c70
Refactor LiteRT exporter to use module_utils.litert
pctablet505 Sep 30, 2025
a6746e1
Merge branch 'keras-team:master' into master
pctablet505 Sep 30, 2025
3c1d90a
Simplify export_litert return value and messaging
pctablet505 Oct 1, 2025
657a271
Merge branch 'keras-team:master' into export
pctablet505 Oct 1, 2025
8ce8bfa
Merge branch 'export' of https://github.com/pctablet505/keras into ex…
pctablet505 Oct 1, 2025
cd9d063
Update export_utils.py
pctablet505 Oct 1, 2025
fa3d3ed
Refactor input signature inference for export
pctablet505 Oct 3, 2025
e775ff2
simplified code
pctablet505 Oct 3, 2025
34b662d
Refactor LiteRT exporter and update import paths
pctablet505 Oct 6, 2025
33b0550
Merge branch 'keras-team:master' into export
pctablet505 Oct 6, 2025
cbe0229
Refactor import statements for export_utils functions
pctablet505 Oct 6, 2025
e52de85
Update saved_model.py
pctablet505 Oct 6, 2025
87af9ed
Update litert.py
pctablet505 Oct 6, 2025
c643772
Add conditional TensorFlow import for LiteRT export
pctablet505 Oct 6, 2025
f243a6e
reformat
pctablet505 Oct 6, 2025
d8236fa
Update litert_test.py
pctablet505 Oct 6, 2025
83577be
Update litert_test.py
pctablet505 Oct 6, 2025
c53b264
Update litert_test.py
pctablet505 Oct 6, 2025
487184d
Update litert_test.py
pctablet505 Oct 7, 2025
374d90b
Update requirements-tensorflow-cuda.txt
pctablet505 Oct 7, 2025
6a5597d
Merge branch 'keras-team:master' into master
pctablet505 Oct 13, 2025
e843f7e
Merge branch 'keras-team:master' into export
pctablet505 Oct 13, 2025
f99a103
Add litert_kwargs support to LiteRT export
pctablet505 Oct 13, 2025
d01a4cb
Update model.py
pctablet505 Oct 13, 2025
52440e1
Refactor LiteRT export wrapper and test setup
pctablet505 Oct 14, 2025
794d85d
Update export_utils.py
pctablet505 Oct 14, 2025
7a46f78
Replace print statements with io_utils.print_msg and logging
pctablet505 Oct 14, 2025
d2b90eb
typo fix
pctablet505 Oct 16, 2025
191f802
set verbose to True by default
pctablet505 Oct 16, 2025
b736ede
removed unnecessary variable
pctablet505 Oct 16, 2025
27f1d07
Rename LitertExporter to LiteRTExporter
pctablet505 Oct 21, 2025
17dccf2
Update litert.py
pctablet505 Oct 21, 2025
3e16ab3
Update export_utils.py
pctablet505 Oct 22, 2025
efbc6d3
Fix input signature inference and doc formatting
pctablet505 Oct 22, 2025
7825983
Update export_utils.py
pctablet505 Oct 22, 2025
676a53c
Update litert.py
pctablet505 Oct 22, 2025
4b6386e
Update litert.py
pctablet505 Oct 22, 2025
79f05c8
Update litert_test.py
pctablet505 Oct 22, 2025
a22eb65
Update litert.py
pctablet505 Oct 22, 2025
315f7f6
Merge branch 'keras-team:master' into master
pctablet505 Oct 25, 2025
4efae3e
Merge branch 'keras-team:master' into export
pctablet505 Oct 25, 2025
f019a0a
Add support for extra TFLite converter settings via kwargs
pctablet505 Oct 27, 2025
5067904
Merge branch 'export' of https://github.com/pctablet505/keras into ex…
pctablet505 Oct 27, 2025
1c8dbcd
Update litert.py
pctablet505 Oct 27, 2025
ff4a81e
Update .gitignore from master
pctablet505 Oct 27, 2025
bcd965b
Merge branch 'keras-team:master' into export
pctablet505 Oct 28, 2025
022cce8
Add LiteRT export optimization tests and update doc
pctablet505 Oct 29, 2025
820f73b
Merge branch 'export' of https://github.com/pctablet505/keras into ex…
pctablet505 Oct 29, 2025
85e878b
Add tests for LiteRT AOT compilation support
pctablet505 Oct 31, 2025
1005063
Update LiteRT export backend check in Model
pctablet505 Oct 31, 2025
c984a6b
Update litert_test.py
pctablet505 Oct 31, 2025
809f6bc
Merge branch 'keras-team:master' into export
pctablet505 Oct 31, 2025
30e4cdd
Merge branch 'keras-team:master' into master
pctablet505 Oct 31, 2025
65dc0f9
Update litert.py
pctablet505 Nov 2, 2025
dd1cfbd
Fix model call with multiple positional arguments
pctablet505 Nov 2, 2025
4bf2e80
Add comprehensive SignatureDef tests for LiteRT export
pctablet505 Nov 4, 2025
4773089
Improve error reporting for AOT compilation failure
pctablet505 Nov 5, 2025
d98cca1
Add support for dictionary model inputs in LiteRTExporter
pctablet505 Nov 12, 2025
11bb4be
Add tests for dict input adapter in LiteRT export
pctablet505 Nov 12, 2025
0f9f214
Update litert_test.py
pctablet505 Nov 12, 2025
ddf911f
Simplify LiteRT export error and remove verbose param
pctablet505 Nov 12, 2025
2a46ab3
Update litert.py
pctablet505 Nov 12, 2025
26ac160
Remove model build step from LiteRTExporter
pctablet505 Nov 13, 2025
7c5cb3f
Remove LiteRT AOT compilation support
pctablet505 Nov 13, 2025
537880f
Refactor import statements in litert.py
pctablet505 Nov 13, 2025
211b44d
Raise ValueError for invalid TFLite file extension
pctablet505 Nov 13, 2025
4199c69
Refactor tracked collection conversion and add _get_save_spec
pctablet505 Nov 17, 2025
d376afb
Refactor TFLite conversion fallback and add verbose option
pctablet505 Nov 17, 2025
66acb8f
Remove verbose argument from LiteRT export functions
pctablet505 Nov 17, 2025
3c2a4be
Enable resource variables for TFLite conversion
pctablet505 Nov 17, 2025
071c819
Remove unused _has_dict_inputs method from LiteRTExporter
pctablet505 Nov 17, 2025
f17422c
Refactor converter kwargs handling in LiteRTExporter
pctablet505 Nov 17, 2025
a550fcc
Update litert.py
pctablet505 Nov 17, 2025
b8267c6
Remove SavedModel fallback in TFLite conversion
pctablet505 Nov 18, 2025
46ead2f
Refactor to use local keras layers and models imports
pctablet505 Nov 18, 2025
b523552
Refactor input signature handling for TFLite export
pctablet505 Nov 27, 2025
ada71de
Add ai-edge-litert to requirements.txt
pctablet505 Nov 27, 2025
00088c9
Fix input signature handling in LiteRTExporter
pctablet505 Nov 27, 2025
42407e8
Merge master into export: Sync with upstream Keras changes
pctablet505 Nov 27, 2025
30deea8
Make batch dimension adjustment consistent in make_tf_tensor_spec
pctablet505 Dec 3, 2025
2f64e9a
Merge upstream/master: Sync with latest Keras changes
pctablet505 Dec 3, 2025
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
72 changes: 64 additions & 8 deletions keras/src/backend/tensorflow/layer.py
Original file line number Diff line number Diff line change
Expand Up @@ -62,17 +62,73 @@ def _trackable_children(self, save_type="checkpoint", **kwargs):
self.test_function = test_function
self.predict_function = predict_function

for tracked_attr in self._tracked:
tracked_item = getattr(self, tracked_attr)
if isinstance(tracked_item, tracking.TrackedList):
children[tracked_attr] = list(tracked_item)
if isinstance(tracked_item, tracking.TrackedDict):
children[tracked_attr] = dict(tracked_item)
if isinstance(tracked_item, tracking.TrackedSet):
children[tracked_attr] = list(tracked_item)
# Convert Keras tracked collections to plain Python structures
# without creating TensorFlow trackable dependencies
self._convert_tracked_collections(children)

return children

@tf.__internal__.tracking.no_automatic_dependency_tracking
def _convert_tracked_collections(self, children):
"""Convert TrackedList/Dict/Set to plain Python structures.

The decorator prevents TensorFlow from automatically wrapping
these conversions in _DictWrapper objects.
"""
for tracked_attr in self._tracked:
tracked_item = getattr(self, tracked_attr)
if isinstance(tracked_item, tracking.TrackedList):
children[tracked_attr] = list(tracked_item)
if isinstance(tracked_item, tracking.TrackedDict):
children[tracked_attr] = dict(tracked_item)
if isinstance(tracked_item, tracking.TrackedSet):
children[tracked_attr] = list(tracked_item)

def _get_save_spec(self, dynamic_batch=True):
"""Compatibility shim for TensorFlow saving utilities.

TensorFlow's SavedModel / TFLite export paths (e.g.,
tf.lite.TFLiteConverter.from_keras_model) expect a `_get_save_spec`
method on models. This method generates TensorSpec objects
describing the model's input signature.

Args:
dynamic_batch: whether to set the batch dimension to `None`.

Returns:
A TensorSpec, list or dict mirroring the model inputs, or
`None` when specs cannot be inferred.
"""
# Prefer the base implementation if available
try:
return super()._get_save_spec(dynamic_batch)
except AttributeError:
# Fall back to building specs from `self.inputs`
inputs = getattr(self, "inputs", None)
if inputs is None:
return None

def _make_spec(t):
# t is a tf.Tensor-like object
shape = list(t.shape)
if dynamic_batch and len(shape) > 0:
shape[0] = None
# Convert to tuple for TensorSpec
try:
name = getattr(t, "name", None)
return tf.TensorSpec(
shape=tuple(shape), dtype=t.dtype, name=name
)
except (ImportError, ModuleNotFoundError):
return None

# Handle dict/list/single tensor inputs
if isinstance(inputs, dict):
return {k: _make_spec(v) for k, v in inputs.items()}
if isinstance(inputs, (list, tuple)):
return [_make_spec(t) for t in inputs]
return _make_spec(inputs)

@property
def _default_save_signature(self):
"""For SavedModel support: returns the default serving signature."""
Expand Down
2 changes: 2 additions & 0 deletions keras/src/export/__init__.py
Original file line number Diff line number Diff line change
@@ -1,3 +1,5 @@
from keras.src.export.litert import LiteRTExporter
from keras.src.export.litert import export_litert
from keras.src.export.onnx import export_onnx
from keras.src.export.openvino import export_openvino
from keras.src.export.saved_model import ExportArchive
Expand Down
16 changes: 16 additions & 0 deletions keras/src/export/export_utils.py
Original file line number Diff line number Diff line change
Expand Up @@ -7,6 +7,14 @@


def get_input_signature(model):
"""Get input signature for model export.

Args:
model: A Keras Model instance.

Returns:
Input signature suitable for model export (always a tuple or list).
"""
if not isinstance(model, models.Model):
raise TypeError(
"The model must be a `keras.Model`. "
Expand All @@ -17,13 +25,20 @@ def get_input_signature(model):
"The model provided has not yet been built. It must be built "
"before export."
)

if isinstance(model, models.Functional):
# Functional models expect a single positional argument `inputs`
# containing the full nested input structure. We keep the
# original behavior of returning a single-element list that
# wraps the mapped structure so that downstream exporters
# build a tf.function with one positional argument.
input_signature = [
tree.map_structure(make_input_spec, model._inputs_struct)
]
elif isinstance(model, models.Sequential):
input_signature = tree.map_structure(make_input_spec, model.inputs)
else:
# Subclassed models: rely on recorded shapes from the first call.
input_signature = _infer_input_signature_from_model(model)
if not input_signature or not model._called:
raise ValueError(
Expand Down Expand Up @@ -60,6 +75,7 @@ def _make_input_spec(structure):
f"Unsupported type {type(structure)} for {structure}"
)

# Always return a flat list preserving the order of shapes_dict values
return [_make_input_spec(value) for value in shapes_dict.values()]


Expand Down
255 changes: 255 additions & 0 deletions keras/src/export/litert.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,255 @@
from keras.src import layers
from keras.src import models
from keras.src.export.export_utils import get_input_signature
from keras.src.export.export_utils import make_input_spec
from keras.src.utils import io_utils
from keras.src.utils.module_utils import tensorflow as tf


def export_litert(
model,
filepath,
input_signature=None,
**kwargs,
):
"""Export the model as a LiteRT artifact for inference.
Args:
model: The Keras model to export.
filepath: The path to save the exported artifact.
input_signature: Optional input signature specification. If
`None`, it will be inferred.
**kwargs: Additional keyword arguments passed to the exporter.
"""

exporter = LiteRTExporter(
model=model,
input_signature=input_signature,
**kwargs,
)
exporter.export(filepath)
io_utils.print_msg(f"Saved artifact at '{filepath}'.")


class LiteRTExporter:
"""Exporter for the LiteRT (TFLite) format.
This class handles the conversion of Keras models for LiteRT runtime and
generates a `.tflite` model file. For efficient inference on mobile and
embedded devices, it creates a single callable signature based on the
model's `call()` method.
"""

def __init__(
self,
model,
input_signature=None,
**kwargs,
):
"""Initialize the LiteRT exporter.
Args:
model: The Keras model to export
input_signature: Input signature specification (e.g., TensorFlow
TensorSpec or list of TensorSpec)
**kwargs: Additional export parameters
"""
self.model = model
self.input_signature = input_signature
self.kwargs = kwargs
Copy link
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Just for clarity, let's call it self.tf_lite_converter_kwargs.

Also, it's very unfortunate that it's not validated right here. If it fails later, you're no longer in __init__ and the connection between __init__ and the invalid kwarg is unclear.

Copy link
Collaborator Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

#21674 (comment)

We would be dealing with kwargs in a separate PR, for consistency across all formats we have left it as kwargs.
later it will be renamed as litert_kwargs.


def _infer_dict_input_signature(self):
"""Infer input signature from a model with dict inputs.
This reads the actual shapes and dtypes from model._inputs_struct.
Returns:
dict or None: Dictionary mapping input names to InputSpec, or None
"""
# Check _inputs_struct first (preserves dict structure)
if hasattr(self.model, "_inputs_struct") and isinstance(
self.model._inputs_struct, dict
):
return {
name: make_input_spec(inp)
for name, inp in self.model._inputs_struct.items()
}

# Fall back to model.inputs if it's a dict
if hasattr(self.model, "inputs") and isinstance(
self.model.inputs, dict
):
return {
name: make_input_spec(inp)
for name, inp in self.model.inputs.items()
}

return None

def export(self, filepath):
"""Exports the Keras model to a TFLite file.
Args:
filepath: Output path for the exported model
Returns:
Path to exported model
"""
# 1. Resolve / infer input signature
if self.input_signature is None:
# Try dict-specific inference first (for models with dict inputs)
dict_signature = self._infer_dict_input_signature()
if dict_signature is not None:
self.input_signature = dict_signature
else:
# Fall back to standard inference
self.input_signature = get_input_signature(self.model)

# 3. Handle dictionary inputs by creating an adapter
# Check if we have dict inputs that need adaptation
has_dict_inputs = isinstance(self.input_signature, dict)

if has_dict_inputs:
# Create adapter model that converts list to dict
adapted_model = self._create_dict_adapter(self.input_signature)

# Convert dict signature to list for TFLite conversion
# The adapter will handle the dict->list conversion
input_signature_list = list(self.input_signature.values())

# Use adapted model and list signature for conversion
model_to_convert = adapted_model
signature_for_conversion = input_signature_list
else:
# No dict inputs - use model as-is
model_to_convert = self.model
signature_for_conversion = self.input_signature

# Store original model reference for later use
original_model = self.model

# Temporarily replace self.model with the model to convert
self.model = model_to_convert

try:
# 4. Convert the model to TFLite.
tflite_model = self._convert_to_tflite(signature_for_conversion)
finally:
# Restore original model
self.model = original_model

# 4. Save the initial TFLite model to the specified file path.
if not filepath.endswith(".tflite"):
raise ValueError(
"The LiteRT export requires the filepath to end with "
"'.tflite'. Got: {filepath}"
)

with open(filepath, "wb") as f:
f.write(tflite_model)

return filepath

def _create_dict_adapter(self, input_signature_dict):
"""Create an adapter model that converts list inputs to dict inputs.
This adapter allows models expecting dictionary inputs to be exported
to TFLite format (which only supports positional/list inputs).
Args:
input_signature_dict: Dictionary mapping input names to InputSpec
Returns:
A Functional model that accepts list inputs and converts to dict
"""
io_utils.print_msg(
f"Creating adapter for dictionary inputs: "
f"{list(input_signature_dict.keys())}"
)

input_keys = list(input_signature_dict.keys())

# Create Input layers for TFLite (list-based)
input_layers = []
for name in input_keys:
spec = input_signature_dict[name]
input_layer = layers.Input(
shape=spec.shape[1:], # Remove batch dimension
dtype=spec.dtype,
name=name,
)
input_layers.append(input_layer)

# Create dict from list inputs
inputs_dict = {
name: layer for name, layer in zip(input_keys, input_layers)
}

# Call the original model with dict inputs
outputs = self.model(inputs_dict)

# Build as Functional model (list inputs -> dict -> model -> output)
adapted_model = models.Model(inputs=input_layers, outputs=outputs)

# Preserve the original model's variables
adapted_model._variables = self.model.variables
adapted_model._trainable_variables = self.model.trainable_variables
adapted_model._non_trainable_variables = (
self.model.non_trainable_variables
)

return adapted_model

def _convert_to_tflite(self, input_signature):
"""Converts the Keras model to TFLite format.
Returns:
A bytes object containing the serialized TFLite model.
"""
# Try direct conversion first for all models
try:
converter = tf.lite.TFLiteConverter.from_keras_model(self.model)
converter.target_spec.supported_ops = [
tf.lite.OpsSet.TFLITE_BUILTINS,
tf.lite.OpsSet.SELECT_TF_OPS,
]
# Keras 3 only supports resource variables
converter.experimental_enable_resource_variables = True

# Apply any additional converter settings from kwargs
self._apply_converter_kwargs(converter)

tflite_model = converter.convert()

return tflite_model

except Exception as e:
# If direct conversion fails, raise the error with helpful message
raise RuntimeError(
f"Direct TFLite conversion failed. This may be due to model "
f"complexity or unsupported operations. Error: {e}"
) from e

def _apply_converter_kwargs(self, converter):
"""Apply additional converter settings from kwargs.
Args:
converter: tf.lite.TFLiteConverter instance to configure
Raises:
ValueError: If any kwarg is not a valid converter attribute
"""
for attr, value in self.kwargs.items():
if attr == "target_spec" and isinstance(value, dict):
# Handle nested target_spec settings
for spec_key, spec_value in value.items():
if hasattr(converter.target_spec, spec_key):
setattr(converter.target_spec, spec_key, spec_value)
else:
raise ValueError(
f"Unknown target_spec attribute '{spec_key}'"
)
elif hasattr(converter, attr):
setattr(converter, attr, value)
else:
raise ValueError(f"Unknown converter attribute '{attr}'")
Loading