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!