Localight is a simple SwiftUI chatbot app for iOS 26 and iOS 27, powered entirely by Apple’s on-device Foundation Models. Designed for demonstration purposes, Localight offers fast, private, and completely offline AI chat — no internet connection or server required.
Localight showcases how to integrate Apple's local LLM into a native iOS experience using SwiftUI and the new Foundation Models framework.
Apple’s third-generation model family contains five models: two on-device models and three server-based models running on Private Cloud Compute. The local models are AFM 3 Core, a dense 3-billion-parameter model, and AFM 3 Core Advanced, a multimodal 20-billion-parameter sparse model that activates 1–4 billion parameters depending on the request. The server models are AFM 3 Cloud, ADM 3 Cloud (Image), and AFM 3 Cloud Pro.
Localight accesses the system-provided on-device model through SystemLanguageModel.
Availability depends on the device and operating system.
See Introducing the Third Generation of Apple’s Foundation Models for details.
- 🧠 On-device LLM: Uses Apple’s local Foundation Models for text generation.
- 🔐 Privacy-first: All conversations stay on your device. No data is sent to the cloud.
- ⚡ Fast & Offline: No internet needed. Responses are generated locally.
- 💬 Minimalist Chat UI: Clean SwiftUI interface for interacting with the model.
- 🗑️ No history: Conversation is not saved after closing the app.
| Feature | iOS 26 | iOS 27 |
|---|---|---|
| On-device responses | ✅ | ✅ |
| Response streaming | ✅ | ✅ |
| Editable model instructions | ✅ | ✅ |
| Current context usage | ❌ | ✅ |
| Per-message token usage | ❌ | ✅ |
| Model availability fallback | ✅ | ✅ |
| Clear chat session | ✅ | ✅ |
| Local-only, non-persistent chat | ✅ | ✅ |
Localight keeps separate implementations for each supported iOS version:
Localight/
├── ContentView_26.swift
├── ContentView_27.swift
├── iOS_26/ # iOS 26 chat, model, settings, and components
├── iOS_27/ # iOS 27 chat, model, settings, and components
└── LocalightApp.swift # Selects the implementation for the current iOS version
Version-specific files and types use the _26 or _27 suffix.
-
Import the Library: To work with Foundation Models, you must import the library in every file where you intend to use them. Go with:
import FoundationModels -
Check Availability: The key object is the SystemLanguageModel. This can indicate whether the model is
.availableor.unavailable. In case of unavailability, a reason is also provided. -
Create a LanguageModelSession: To start prompting, create a LanguageModelSession. Its instructions define the model’s role and response behavior:
let session = LanguageModelSession(instructions: "You are the best friend.")
-
Generate a Response: Finally, call the method to receive a result as a String by using:
let response = try await session.respond(to: promptAsString).content
-
Stream a Response: Otherwise, you can call the method to receive a result as a String that is streamed by using:
let stream = session.streamResponse(to: promptAsString) do { for try await chunk in stream { self.streamingResponse = chunk.content } let response = try await stream.collect().content } catch {}
Apple’s on-device Foundation Models operate with a limited context window per session.
The context window defines how many tokens the model can process within a single LanguageModelSession.
On iOS 27, the displayed usage includes the system instructions.
- A token is a unit of text processed by the model.
- In Western languages (e.g. English or German), 1 token ≈ 3–4 characters.
- In East Asian languages (e.g. Japanese or Chinese), 1 token ≈ 1 character.
- The system model currently supports up to 4,096 tokens per session.
If this limit is exceeded, the framework throws the following error: LanguageModelError.contextSizeExceeded(_:)
For more details, see Apple’s official documentation: TN3193 – Managing the on-device foundation model’s context window
Localight is available under the MIT License. See LICENSE for the full license text.