How to Integrate OpenMedKit Swift Library in iOS Apps: MLX and CoreML Setup
Add OpenMedKit via Swift Package Manager, initialize it with either the MLX backend for Apple Silicon devices or the CoreML backend for bundled models, then call extractPII(_:) to perform on-device clinical entity extraction.
OpenMedKit is a Swift package from the maziyarpanahi/openmed repository that brings HIPAA-compliant clinical NLP—specifically named entity recognition (NER) and PII de-identification—directly to iOS, iPadOS, and macOS applications. To integrate OpenMedKit Swift library in iOS apps, you import the package, configure a backend, and invoke the high-level API on user text.
Installation via Swift Package Manager
You can add the dependency using Xcode's GUI or by editing your Package.swift directly.
Via Xcode
- Choose File > Add Packages…
- Enter the repository URL:
https://github.com/maziyarpanahi/openmed - Select the OpenMedKit product and add it to your app target
Via Package.swift
// swift-tools-version:5.9
import PackageDescription
let package = Package(
name: "YourApp",
dependencies: [
.package(url: "https://github.com/maziyarpanahi/openmed.git", from: "1.5.5")
],
targets: [
.executableTarget(
name: "YourApp",
dependencies: [
.product(name: "OpenMedKit", package: "openmed")
]
)
]
)
The package manifest is defined in swift/OpenMedKit/Package.swift and includes dependencies for MLX, Transformers, and ZIPFoundation.
Choosing Your Inference Backend
OpenMedKit abstracts the model runtime behind the OpenMedBackend enum defined in OpenMedBackend.swift. You must choose between two execution paths:
- MLX: Downloads Apple Silicon-optimized models from Hugging Face and runs inference locally using the MLX framework. Best for production iPhones and iPads.
- CoreML: Loads a pre-converted
.mlmodelcbundle shipped with your app. Required for iOS simulator testing or when you have existing CoreML assets.
MLX Backend Setup (Recommended for Devices)
The MLX backend requires downloading the model artifact on first launch. Use OpenMedModelStore.downloadMLXModel(repoID:) defined in OpenMedModelStore.swift to handle caching and file management.
import OpenMedKit
// Download and cache the model (async, runs once)
let modelDirectory = try await OpenMedModelStore.downloadMLXModel(
repoID: "OpenMed/OpenMed-PII-ClinicalE5-Small-33M-v1-mlx"
)
// Initialize with MLX backend
let openmed = try OpenMed(
backend: .mlx(modelDirectoryURL: modelDirectory)
)
// Extract PII entities
let entities = try openmed.extractPII(
"Patient John Doe, DOB 1990-05-15, SSN 123-45-6789"
)
// entities is [EntityPrediction] containing label, text, confidence, and spans
CoreML Backend Setup (For Simulator or Bundled Models)
Use the CoreML backend when testing on simulators or when you prefer to bundle a converted model with your app binary. You need both the .mlmodelc directory and an id2label.json mapping file.
import OpenMedKit
// Locate bundled resources
let modelURL = Bundle.main.url(
forResource: "OpenMedPII",
withExtension: "mlmodelc"
)!
let labelURL = Bundle.main.url(
forResource: "id2label",
withExtension: "json"
)!
// Initialize with CoreML backend
let openmed = try OpenMed(
backend: .coreML(
modelURL: modelURL,
id2labelURL: labelURL,
tokenizerName: "OpenMed/OpenMed-PII-ClinicalE5-Small-33M-v1"
)
)
// Run inference
let entities = try openmed.extractPII("Patient Jane Doe, MRN 123456")
The convenience initializer for the CoreML backend resides in OpenMedKit.swift.
Implementing Clinical NLP in SwiftUI
The following example mirrors the implementation in swift/OpenMedScanDemo/OpenMedScanDemo/ContentView.swift, demonstrating async model loading and entity display.
import SwiftUI
import OpenMedKit
struct ClinicalDocumentView: View {
@State private var text = "Patient: Jane Doe, DOB: 01/15/1970, SSN: 000-00-0000"
@State private var entities: [EntityPrediction] = []
@State private var isLoading = false
@State private var errorMessage: String?
var body: some View {
VStack(spacing: 16) {
TextEditor(text: $text)
.frame(height: 120)
.border(Color.gray.opacity(0.5))
Button(action: detectPII) {
if isLoading {
ProgressView()
} else {
Text("Detect PII")
}
}
.disabled(isLoading)
if let error = errorMessage {
Text(error).foregroundColor(.red)
}
List(entities) { entity in
VStack(alignment: .leading) {
Text("[\(entity.label)] \(entity.text)")
.font(.headline)
Text("Confidence: \(entity.confidence, specifier: "%.3f")")
.font(.caption)
.foregroundColor(.secondary)
}
}
}
.padding()
}
private func detectPII() {
isLoading = true
errorMessage = nil
Task {
do {
// Switch to .coreML if running on simulator
let modelDir = try await OpenMedModelStore.downloadMLXModel(
repoID: "OpenMed/OpenMed-PII-ClinicalE5-Small-33M-v1-mlx"
)
let openmed = try OpenMed(backend: .mlx(modelDirectoryURL: modelDir))
entities = try openmed.extractPII(text)
} catch {
errorMessage = error.localizedDescription
}
isLoading = false
}
}
}
Key Source Files and Architecture
Understanding these files helps when debugging or extending functionality:
swift/OpenMedKit/Package.swift: Defines the Swift package structure and external dependencies (MLX, Transformers).OpenMedBackend.swift: Contains theOpenMedBackendenum with.mlx(modelDirectoryURL:)and.coreML(modelURL:id2labelURL:tokenizerName:)cases.OpenMedModelStore.swift: ImplementsdownloadMLXModel(repoID:)for Hugging Face artifact management and local caching.OpenMedKit.swift: Houses theOpenMedclass public API, includingextractPII(_:confidenceThreshold:)andanalyzeText(_:confidenceThreshold:).PostProcessing.swift: Smart post-processing logic for entity span repair and merging.ContentView.swift: Reference SwiftUI implementation in the demo app showing end-to-end integration.
Summary
- Add dependency: Use Swift Package Manager with
https://github.com/maziyarpanahi/openmed - Choose backend: MLX for Apple Silicon performance on real devices; CoreML for simulator or bundled models
- Download MLX models: Call
OpenMedModelStore.downloadMLXModel(repoID:)to cache Hugging Face artifacts locally - Bundle CoreML models: Include
.mlmodelcdirectories andid2label.jsonfiles in your app target - Initialize: Create an
OpenMedinstance usingOpenMed(backend: .mlx(...))orOpenMed(backend: .coreML(...)) - Extract entities: Invoke
extractPII(_:confidenceThreshold:)to receive[EntityPrediction]results with labels, confidence scores, and character spans
Frequently Asked Questions
Can I use OpenMedKit on the iOS simulator?
Yes, but only with the CoreML backend. The MLX backend requires Apple Silicon hardware and will not run on Intel-based simulators. For simulator testing, bundle a converted CoreML model (.mlmodelc) and initialize with OpenMed(backend: .coreML(modelURL:id2labelURL:tokenizerName:)).
What is the difference between extractPII and analyzeText?
Both methods perform named entity recognition defined in OpenMedKit.swift. extractPII(_:confidenceThreshold:) specifically targets personally identifiable information in clinical text (names, dates, SSNs, medical record numbers), while analyzeText(_:confidenceThreshold:) provides general clinical entity analysis. Both return arrays of EntityPrediction objects containing the entity text, label, confidence score, and character positions.
How does OpenMedKit handle model caching?
The OpenMedModelStore.downloadMLXModel(repoID:) method in OpenMedModelStore.swift automatically caches downloaded MLX artifacts in the application's local filesystem. Subsequent calls return the cached path immediately, avoiding redundant network requests across app launches.
Which backend offers better performance on modern iPhones?
The MLX backend delivers superior performance on iPhone 12, iPad Air/Pro, and Apple Silicon Macs by leveraging the Neural Engine and GPU acceleration. CoreML provides broader compatibility, particularly for older devices or when you require simulator support, but may have higher latency for complex clinical documents.
Have a question about this repo?
These articles cover the highlights, but your codebase questions are specific. Give your agent direct access to the source. Share this with your agent to get started:
curl -s "https://instagit.com/install.md" Maintain an open-source project? Get it listed too →