Hi everyone,
I've been struggling for a few weeks to integrate my Core ML Image Classifier model into my .swiftpm project, and I’m hoping someone can help.
Here’s what I’ve done so far:
- I converted my .mlmodel file to .mlmodelc manually via the terminal.
- In my Package.swift file, I tried both "copy" and "process" options for the resource.
The issues I’m facing:
- When using "process", Xcode gives me the error:
"multiple resources named 'coremldata.bin' in target 'AppModule'."
- When using "copy", the app runs, but the model doesn’t work, and the terminal shows:
"A valid manifest does not exist at path: .../Manifest.json."
I even tried creating a Manifest.json manually to test, but this led to more errors, such as:
- "File format version must be in the form of major.minor.patch."
- "Failed to look up root model."
To check if the problem was specific to my model, I tested other Core ML models in the same setup, but none of them worked either.
I feel stuck and unsure of how to resolve these issues. Any guidance or suggestions would be greatly appreciated. Thanks in advance! :)
You are on the right track that you precompiled a source model (.mlpackage
or .mlmodel
) to .mlmodelc
manually before adding it to Swift Package. Currently SPM doesn't support compiling the source model in .process(:)
rule.
Let's say, you have a source model named model.mlpackage
. The first step is to compile it to .mlmodelc
.
xcrun coremlcompiler compile model.mlpackage /tmp/
Then, copy the compiled model to your Swift Package.
cp -r /tmp/model.mlmodelc /path/to/ModelInSwiftPackage/Sources/ModelInSwiftPackage/
In my test, the resultant directory structure is something like this.
. ├── Package.swift ├── Sources │ └── ModelInSwiftPackage │ ├── ModelInSwiftPackage.swift │ └── model.mlmodelc │ ├── analytics │ │ └── coremldata.bin │ ├── coremldata.bin │ └── model.mil └── Tests └── ModelInSwiftPackageTests └── ModelInSwiftPackageTests.swift
Now, edit Package.swift
as follows, using copy
rule.
import PackageDescription let package = Package( : targets: [ .target( name: "ModelInSwiftPackage", resources: [ .copy("model.mlmodelc")] ), )
Now, you should be able to build the package with the model.
To access the model, you can use Bundle.module.url()
.
public func loadModel() throws -> MLModel? { guard let modelURL = Bundle.module.url(forResource: "model", withExtension: "mlmodelc") else { return nil } return try MLModel(contentsOf: modelURL) }
Hope it works!