Skip to content

Commit b29a627

Browse files
authored
Change default minimum_deployment_target to None and support CoreML models with no inputs (#13053)
This PR changes the default minimum_deployment_target in CoreML from the fixed iOS15 to None. This will automatically select the minimum deployment target required to export the model. A warning occurs after export telling the user the deploymnet target selected, and directing them to specify a specific target if that is what they need. This is more in line with how CoreML standalone works. In addition, this PR allows running CoreML models with no user inputs, which requires CoreML deployment target iOS18 or higher. This addresses: * #11719 * #12906
1 parent cbbbc3a commit b29a627

File tree

2 files changed

+26
-9
lines changed

2 files changed

+26
-9
lines changed

backends/apple/coreml/compiler/coreml_preprocess.py

Lines changed: 25 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -126,15 +126,18 @@ def model_compute_precision_from_compile_specs(
126126

127127
@staticmethod
128128
def generate_minimum_deployment_target_compile_spec(
129-
min_deployment_target: ct.target,
129+
min_deployment_target: Optional[ct.target],
130130
) -> CompileSpec:
131131
"""
132132
Returns the compile spec representing the minimum deployment target on which the model can run,
133133
for additional details please refer to the documentation for ``coremltools.target``.
134134
"""
135+
value = str("").encode("utf-8")
136+
if min_deployment_target is not None:
137+
value = str(min_deployment_target.value).encode("utf-8")
135138
return CompileSpec(
136139
COMPILE_SPEC_KEYS.MIN_DEPLOYMENT_TARGET.value,
137-
str(min_deployment_target.value).encode("utf-8"),
140+
value,
138141
)
139142

140143
@staticmethod
@@ -146,10 +149,13 @@ def min_deployment_target_from_compile_specs(
146149
"""
147150
for compile_spec in compile_specs:
148151
if compile_spec.key == COMPILE_SPEC_KEYS.MIN_DEPLOYMENT_TARGET.value:
149-
compile_spec_value: int = int(compile_spec.value.decode("utf-8"))
152+
value = compile_spec.value.decode("utf-8")
153+
if value == "":
154+
return None
155+
compile_spec_value: int = int(value)
150156
return ct.target(compile_spec_value)
151157

152-
return ct.target.iOS15
158+
return None
153159

154160
@staticmethod
155161
def compute_unit_from_compile_specs(
@@ -211,7 +217,7 @@ def op_linear_quantizer_config_from_compile_specs(
211217
@staticmethod
212218
def generate_compile_specs(
213219
compute_unit: ct.ComputeUnit = ct.ComputeUnit.ALL,
214-
minimum_deployment_target: ct.target = ct.target.iOS15,
220+
minimum_deployment_target: Optional[ct.target] = None,
215221
compute_precision: ct.precision = ct.precision.FLOAT16,
216222
model_type: MODEL_TYPE = MODEL_TYPE.MODEL,
217223
op_linear_quantizer_config: Optional[Dict] = None,
@@ -248,6 +254,13 @@ def model_metadata_from_spec(
248254
input_names: List[str] = [input.name for input in model_spec.description.input]
249255
output_names = [output.name for output in model_spec.description.output]
250256

257+
if len(output_names) == 0:
258+
raise ValueError("Cannot lower a model with no outputs in CoreML.")
259+
if len(input_names) == 0:
260+
assert (
261+
model_spec.specificationVersion >= 9
262+
), "Deploying a model with no inputs in CoreML requires you set minimum_deployment_target to iOS18 or later in the CoreMLPartitioner."
263+
251264
return ModelMetadata(
252265
inputNames=input_names, outputNames=output_names, identifier=identifier
253266
)
@@ -352,6 +365,12 @@ def preprocess_model(
352365
dir_path: Path = Path("tmp") / identifier
353366
model_dir_path: Path = dir_path / "lowered_module"
354367
model_spec: ct.proto.Model_pb2 = mlmodel.get_spec()
368+
logger.warning(
369+
f"The model with identifier {identifier} was exported with CoreML specification version {model_spec.specificationVersion}, and it will not run on all version of iOS/macOS."
370+
" See https://apple.github.io/coremltools/mlmodel/Format/Model.html#model for information on what OS versions are compatible with this specifcation version."
371+
" If you want to control the deployment target, please set the minimum_deployment_target compile spec in the CoreMLPartitioner."
372+
)
373+
355374
model_metadata: ModelMetadata = CoreMLBackend.model_metadata_from_spec(
356375
model_spec=model_spec,
357376
identifier=identifier,
@@ -418,7 +437,7 @@ def preprocess(
418437
model_compute_precision: ct.precision = (
419438
CoreMLBackend.model_compute_precision_from_compile_specs(compile_specs)
420439
)
421-
minimum_deployment_target: ct.target = (
440+
minimum_deployment_target: Optional[ct.target] = (
422441
CoreMLBackend.min_deployment_target_from_compile_specs(compile_specs)
423442
)
424443
compute_units: ct.ComputeUnit = CoreMLBackend.compute_unit_from_compile_specs(

backends/apple/coreml/runtime/delegate/model_metadata.h

Lines changed: 1 addition & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -29,9 +29,7 @@ struct ModelMetadata {
2929
inline ModelMetadata() noexcept { }
3030

3131
/// Returns `true` if the metadata is valid otherwise `false`.
32-
inline bool is_valid() const noexcept {
33-
return !identifier.empty() && !input_names.empty() && !output_names.empty();
34-
}
32+
inline bool is_valid() const noexcept { return !identifier.empty() && !output_names.empty(); }
3533

3634
inline std::string to_json_string() const noexcept { return executorchcoreml::serde::json::to_json_string(*this); }
3735

0 commit comments

Comments
 (0)