Using Core ML in a .swiftpm file

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:

  1. I converted my .mlmodel file to .mlmodelc manually via the terminal.
  2. 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!

Using Core ML in a .swiftpm file
 
 
Q