← All courses ← Course home

Lesson 02 of 05

Embed the question on the device

Turn the question into a vector on the phone. Use Core AI or the documented Foundation Models helper. Do not send the text to a public embed API.

Agent brief (llms.md)

Environment setup

Use Xcode 27 on a Mac. Create an iOS 27 or macOS 27 SwiftUI App. Add Foundation Models and Core AI. Install the Metal Toolchain from Xcode Settings > Components.

xcode-select --install
xcodebuild -version
# File > New > Project > App, Interface: SwiftUI
# Deployment: iOS 27 or macOS 27
# Add FoundationModels and CoreAI to the target.

An embedding is a list of numbers that keeps meaning. Close questions sit close in that space. You need one embedding function and you must keep using it. Mixing two embedders breaks the cache.

TextUser question
EmbedOn-device vector
StoreVector plus answer

Honest API path

Apple does not document one forever name for "embed this string" across every SDK drop. Check these in the Xcode 27 docs, in this order:

  1. A Foundation Models embedding or representation API on the session or model, if present.
  2. A Core AI utility embedding from the official coreai-models catalog, loaded as an .aimodel.
  3. A CoreAILanguageModel only if that type is how your SDK exposes a custom embedder. Many embedders are not language models. Do not force chat APIs onto a vector model.

If none of those exist in your SDK, say so in the project README and stop. Do not call a hosted embed API "for convenience." That leaves the device.

import CoreAI
import FoundationModels

// Illustrative. Confirm the embedder type in the installed SDK.
struct QuestionEmbedder {
    let embed: @Sendable (String) async throws -> [Float]

    func vector(for question: String) async throws -> [Float] {
        let trimmed = question.trimmingCharacters(in: .whitespacesAndNewlines)
        return try await embed(trimmed)
    }
}

Prepare the embedder once at launch, the same way you prepare a Core AI function in the clothing course. First load is slower. Later questions should reuse the prepared model.

Fixed contract. Same embedder, same vector length, float32. Write the model name and dimension next to the cache file.

WWDC26 Core AI (session 326) shows custom models behind a session. Use that path for a catalog embedder. Next, compare two vectors.

Key concepts

  • Turn the question into an on-device vector with Core AI or a documented Foundation Models helper.
  • Keep the same embedder, vector length, and float32 type for the life of the cache.
  • Prepare the embedder once at launch. First load is slower.
  • Confirm embedder type names in the installed Xcode 27 SDK.

Takeaways

  • Never call a hosted embed API for the cache.
  • Write the model name and dimension next to the cache file.
  • Mixing embedders breaks similarity scores.