Skip to content

About

A modern SwiftUI showcase app for macOS 27, built to demonstrate Apple’s Core AI framework in action.

Topics

Resources

Security policy

Stars

1 star

Watchers

0 watching

Forks

Repository files navigation

CoreAIChat app icon

CoreAIChat

Run your own exported language model with Apple Core AI.

A minimal macOS reference app for bundling a compatible model, loading it with Core AI, and chatting with it entirely on device.

MIT license Showcase project SwiftUI macOS 27 Xcode 27

At a Glance

CoreAIChat demonstrates the shortest path from a model exported with Apple's coreai-models tooling to a native, local chat experience on macOS. It focuses on the parts that are specific to bringing your own model: preserving the exported resource bundle, loading it through CoreAILanguageModels, and using it with the Foundation Models conversation APIs.

The project is model-agnostic. The included model/ directory is a generic resource placeholder; it can contain any compatible language model supported by Apple's coreai-models repository. Gemma 3 is used below only as an export example.

Highlights

  • Run inference on device: Load an exported Core AI model directly from the app bundle and generate responses locally.
  • Use native frameworks: Combine SwiftUI, Foundation Models, and CoreAILanguageModels in a compact reference implementation.
  • Swap compatible models: Follow a model-specific coreai-models recipe, then replace the contents of the generic model/ resource directory.
  • Keep the interface responsive: Model loading and response generation use Swift concurrency.
  • See the complete chat flow: The showcase covers loading, prewarming, prompt submission, progress feedback, conversation history, and errors.
  • Chat in neutral colors: White and gray message bubbles match the app icon and adapt to light and dark appearance. The model setup view uses matching neutral branding and a Liquid Glass load button.
  • Learn from documented behavior: Concise feature specifications describe the observable model-loading, conversation, and error states.

The implemented behavior is documented in docs/features/, including model loading, chat conversations, and error handling, plus starting a new conversation.

Project Status

Important

CoreAIChat is a showcase app, not an App Store product. It is intended for learning, experimentation, and demonstrating Apple Core AI integration. It is not production-ready and is not distributed through the App Store.

Generated output may be inaccurate, incomplete, or misleading. Model compatibility and setup requirements can vary between coreai-models releases.

Getting Started

You need macOS 27 and Xcode 27. Model export can require substantial disk space and memory; requirements vary by model.

1. Prepare the export tools

Install uv if it is not already available:

brew install uv

Alternatively, use the official installer:

curl -LsSf https://astral.sh/uv/install.sh | sh

Clone Apple's coreai-models repository and enter it:

git clone https://github.com/apple/coreai-models.git
cd coreai-models
git checkout 09ff139050d72e54dd8c073534c6ddd5927b5546

This revision matches the coreai-models runtime pinned in CoreAIChat.xcodeproj/project.xcworkspace/xcshareddata/swiftpm/Package.resolved. Use the same revision for exports and the app runtime so their resource formats stay compatible.

2. Choose and export a model

Choose one of the compatible model recipes in coreai-models and follow its requirements and license terms. For the Gemma 3 example, accept the Gemma license terms, install the Hugging Face CLI, and authenticate:

brew install hf
hf auth login --token <YOUR_TOKEN>

Then export the model from the coreai-models directory:

uv run coreai.llm.export google/gemma-3-4b-it

Exporting can take a few minutes because the source model may need to be downloaded before conversion. For Gemma 3, the result is written to exports/gemma_3_4b_it_4bit_dynamic and should have this structure:

gemma_3_4b_it_4bit_dynamic/
├── gemma_3_4b_it_4bit_dynamic.aimodel/
├── metadata.json
└── tokenizer/

Commands and prerequisites differ between models. Treat the matching recipe in coreai-models as the source of truth.

3. Add the model to Xcode

Open the project:

open CoreAIChat.xcodeproj

Copy the complete contents of the exported resource directory into the empty model/ placeholder. This generic directory is already included in the CoreAIChat app target and referenced by Core/Inference/InferenceService.swift.

When using another compatible model:

  1. Remove the previous generated contents from model/.
  2. Copy all contents of the newly exported resource directory into model/.
  3. Keep the .aimodel, metadata.json, and tokenizer/ resources together.

The exported directory name does not need to match model; the model identity and asset paths are read from its metadata.json.

Exported model files are intentionally not committed to this repository.

4. Run the showcase

For a signed local build, create your personal build configuration once:

cp Config/Local.xcconfig.example Config/Local.xcconfig

Then replace YOUR_TEAM_ID and the example bundle identifier in Config/Local.xcconfig. The local file is ignored by Git, so developer-specific signing values do not end up in project.pbxproj. Unsigned command-line builds do not require this file.

If the bundled model/ directory or its metadata.json is missing, the app shows Model Resources Missing with setup instructions. Copy the complete exported resources into model/, then rebuild and run the app.

Select the CoreAIChat scheme in Xcode and run it. Choose Load Model, wait for the local model to load and prewarm, then start a conversation. The first load can take a little longer.

The chat opens only after the model engine has loaded successfully. If loading fails, the app shows the error with a Try Again button.

Use New Conversation in the chat toolbar to clear all messages, the draft, and the model's conversation context while keeping the model loaded. This action takes effect immediately and is disabled while a response is running.

For a signing-independent compile check, use Xcode 27:

DEVELOPER_DIR=/Applications/Xcode.app/Contents/Developer \
xcodebuild -project CoreAIChat.xcodeproj \
  -scheme CoreAIChat \
  -sdk macosx \
  -destination 'platform=macOS' \
  -derivedDataPath /tmp/coreaichat-derived-data \
  CODE_SIGNING_ALLOWED=NO build

Minimal Core AI Example

The central integration is deliberately small. The stable model resource name points to whichever compatible exported model is currently placed in the generic resource directory.

import Foundation
import FoundationModels
import CoreAILanguageModels

func respond(to prompt: String) async throws -> String {
    guard let modelURL = Bundle.main.url(
        forResource: "model",
        withExtension: nil
    ) else {
        throw URLError(.fileDoesNotExist)
    }

    let model = try await CoreAILanguageModel(resourcesAt: modelURL)
    try await model.load()
    let session = LanguageModelSession(model: model)
    let response = try await session.respond(to: prompt)

    return response.content
}

Repository Layout

CoreAIChat/
├── CoreAIChat/
│   ├── App/                         App entry point and root composition
│   ├── Features/
│   │   ├── Chat/                    Conversation state, views, and components
│   │   └── ModelManagement/         Bundled-model setup view
│   ├── Core/Inference/              Model loading, session, and runtime state
│   ├── Models/                      Shared conversation data types
│   ├── Shared/Components/           Reusable error presentation
│   └── Assets.xcassets/             App assets
├── CoreAIChat.xcodeproj/             Xcode project and package resolution
├── Config/                           Shared and local build settings
├── docs/features/                    Feature behavior and acceptance criteria
├── docs/assets/                      README assets
├── model/                            Generic untracked model-resource placeholder
└── Icon.icon/                        App icon source

The root ContentView owns an InferenceService and a ChatViewModel per window and injects that same service into the chat model. InferenceService owns the LanguageModelSession, loads and prewarms the bundled model, and returns generated text. ChatViewModel manages the draft, visible messages, and response progress. Both keep observable state on the main actor.

Future conversation storage and inspector features can be added when implemented; the current app remains a single target without additional dependencies. Conversation history is kept only in memory for each window and is not saved between app launches.

License

CoreAIChat is available under the MIT License. Model weights and related resources remain subject to their respective licenses.

About

A modern SwiftUI showcase app for macOS 27, built to demonstrate Apple’s Core AI framework in action.

Topics

Resources

Security policy

Stars

1 star

Watchers

0 watching

Forks

Used by

Contributors

Languages