Core AI is Apple's new on-device AI inference framework for iOS 27, giving developers direct access to the same high-performance ML execution engine that powers Apple Intelligence. It enables loading and running custom .aimodel files across CPU, GPU, and Neural Engine with a modern Swift API.
โข Run your own custom AI/ML models on-device with no server costs or per-token fees, using the same inference stack that powers Apple Intelligence
โข Modern Swift API with non-escapable types (NDArray.MutableView) ensures memory safety without sacrificing throughput across CPU, GPU, and Neural Engine
โข Stateful inference support (key/value caching for transformers) and ahead-of-time compilation make production-quality LLM and vision model integration practical in a shipped app
Demonstrates loading a custom .aimodel file, preparing an NDArray input, running inference, and reading output logits โ the core loop for any Core AI-powered feature.
import CoreAI
import Foundation
// MARK: - Model Player using Core AI Framework
struct GameFeatures {
let wallDistances: [Float] // 4 values
let foodDelta: (x: Float, y: Float)
let currentDirection: [Float] // 4 one-hot values
let opponentDistance: Float
let opponentDirection: [Float] // 4 one-hot values
var featureVector: [Float] {
wallDistances + [foodDelta.x, foodDelta.y] + currentDirection + [opponentDistance] + opponentDirection
}
static let featureDim = 15
}
enum SnakeDirection: Int { case up = 0, down, left, right }
final class SnakeAIPlayer {
private let inferenceFunction: InferenceFunction
init(modelURL: URL) throws {
// Load the .aimodel file
let model = try AIModel(contentsOf: modelURL)
// Grab the single main inference function
self.inferenceFunction = try model.loadInferenceFunction()
}
func chooseDirection(history: [GameFeatures]) throws -> SnakeDirection {
let seqLen = history.count
let featureDim = GameFeatures.featureDim
// Create a 2D NDArray: [sequenceLength, featureDim] of Float32
var input = NDArray(
shape: [seqLen, featureDim],
dataType: .float32
)
// Populate features row by row using a MutableView (non-escapable, memory-safe)
input.withMutableView { view in
for (row, features) in history.enumerated() {
let vec = features.featureVector
for (col, value) in vec.enumerated() {
view[row, col] = value
}
}
}
// Run inference โ returns a dictionary of named output NDArrays
let outputs = try inferenceFunction.run(inputs: ["features": input])
// Read output logits NDArray [4] โ one logit per direction
guard let logitsArray = outputs["logits"] else {
throw InferenceError.missingOutput
}
// Find argmax over the 4 direction logits
let bestIndex = logitsArray.withView { view -> Int in
var maxIdx = 0
var maxVal: Float = view[0]
for i in 1..<4 {
let v: Float = view[i]
if v > maxVal { maxVal = v; maxIdx = i }
}
return maxIdx
}
return SnakeDirection(rawValue: bestIndex) ?? .up
}
}
enum InferenceError: Error {
case missingOutput
}Models must be converted to the .aimodel format using the Core AI Torch Python package before use. Dynamic shapes must be explicitly declared at conversion time with dynamic_shapes. InferenceFunction is not thread-safe by default โ create separate instances per concurrent call site. States (KV cache) require model-side changes during authoring, not just at inference time.
Requires Apple Silicon; Neural Engine acceleration requires devices with A-series or M-series chips. Performance scales with chip generation.
More iOS 27 APIs land every week.
Get notified when new capabilities are published โ no noise, just signal.