Зачем локальная ИИ в 2026 году? Потому что облака — это прошлый век
Представьте: вы пишете приложение для заметок с ИИ-помощником. Пользователь диктует мысль, а через секунду ИИ предлагает структуру. Но если это облачный ИИ, вы отправляете голос на сервер, ждёте ответ, платите за токены. И главное — приватность летит в трубу. В 2026 году это уже недопустимо.
Apple давно двигается в сторону on-device AI. Foundation Models — это их ответ. Модели работают прямо на iPhone или Mac, без интернета. Быстро, приватно, дёшево. И да, вы можете использовать это в своих приложениях.
1Готовим проект: минимальные требования на 2026 год
Сначала проверьте: Xcode 18+ (или какой актуальный на 2026), цель iOS 18+ или macOS 15+. Foundation Models доступны с iOS 17, но к 2026 лучше целиться на последние версии. Вам нужен Mac с Apple Silicon для симуляции, потому что модели жрут ресурсы.
// В Info.plist добавьте это:
<key>NSMicrophoneUsageDescription</key>
<string>Для голосового ввода ИИ</string>
// Если используете микрофон, но в этом примере мы фокусируемся на тексте.Создайте новый SwiftUI проект. Назовите его как угодно, например, "LocalAIApp".
2Импорты и модель: что грузим и как
Foundation Models — это фреймворк от Apple. Импортируем его. Модели нужно загрузить заранее. В 2026 году Apple предлагает несколько моделей, включая текстовые и мультимодальные. Мы используем текстовую, например, "Apple-Text-Large" (это вымышленное название, проверьте актуальные в документации).
import Foundation
import FoundationModels
import SwiftUI
// Загрузка модели
let modelURL = Bundle.main.url(forResource: "Apple-Text-Large", withExtension: "mlmodelc")!
let configuration = LanguageModelConfiguration(model: modelURL)Модели весят гигабайты. Не тащите их в bundle приложения — скачивайте по требованию с сервера. Или используйте on-demand resources. Иначе App Store отклонит.
3LanguageModelSession: сердце локальной ИИ
Сессия управляет состоянием модели. Создаётся один раз и используется для генерации. Не создавайте сессию заново для каждого запроса — это дорого.
class AIService: ObservableObject {
private var session: LanguageModelSession?
init() {
do {
let modelURL = Bundle.main.url(forResource: "Apple-Text-Large", withExtension: "mlmodelc")!
let configuration = LanguageModelConfiguration(model: modelURL)
session = try LanguageModelSession(configuration: configuration)
} catch {
print("Ошибка инициализации сессии: \(error)")
}
}
func generateResponse(prompt: String) async throws -> String {
guard let session = session else { throw NSError(domain: "AIService", code: 1) }
let response = try await session.prediction(for: prompt)
return response.text
}
}Это базовый пример. Но мы хотим потоковую передачу, чтобы слова появлялись по одному, как в ChatGPT. Для этого есть streamResponse(to:).
4Потоковая передача: магия streamResponse(to:)
Метод streamResponse(to:) отправляет токены в AsyncStream по мере генерации. Это ключ к интерактивному опыту.
extension AIService {
func streamResponse(prompt: String) -> AsyncStream {
AsyncStream { continuation in
Task {
guard let session = self.session else {
continuation.finish()
return
}
do {
try await session.streamResponse(to: prompt) { token in
continuation.yield(token.text)
}
continuation.finish()
} catch {
print("Ошибка потоковой передачи: \(error)")
continuation.finish()
}
}
}
}
} Обратите внимание: token.text может быть строкой или, возможно, другим типом в зависимости от API. В документации Foundation Models на 2026, проверьте точный тип.
5Интеграция с SwiftUI: делаем интерфейс живым
Теперь свяжем это с SwiftUI. Мы будем использовать @StateObject для сервиса и @State для текста.
struct ContentView: View {
@StateObject private var aiService = AIService()
@State private var prompt = ""
@State private var response = ""
@State private var isGenerating = false
var body: some View {
VStack {
TextField("Введите запрос", text: $prompt)
.textFieldStyle(RoundedBorderTextFieldStyle())
.padding()
Button("Сгенерировать") {
Task {
await generateResponse()
}
}
.disabled(isGenerating)
ScrollView {
Text(response)
.padding()
}
}
}
private func generateResponse() async {
isGenerating = true
response = ""
let stream = aiService.streamResponse(prompt: prompt)
for await token in stream {
response += token
}
isGenerating = false
}
}Это работает, но есть проблема: UI обновляется на каждый токен, что может тормозить. Используем @MainActor для обновлений.
private func generateResponse() async {
isGenerating = true
response = ""
let stream = aiService.streamResponse(prompt: prompt)
for await token in stream {
await MainActor.run {
response += token
}
}
await MainActor.run {
isGenerating = false
}
}6Ошибки, которые все совершают (и как их избежать)
- Не проверяют совместимость устройства: Старые iPhone без Neural Engine будут ползти. Используйте `MLHardwareService` чтобы проверить возможности.
- Забывают про память: Модели кушают RAM. Освобождайте сессию, когда не используется, особенно в фоне.
- Блокируют главный поток: Все операции с моделью — тяжёлые. Держите их в background.
- Игнорируют температуру и другие параметры: `LanguageModelConfiguration` позволяет настраивать креативность. Экспериментируйте.
Если ваше приложение похоже на локальный ИИ на llama.cpp, помните: Foundation Models оптимизированы для Apple железа. Не пытайтесь портировать сторонние модели без необходимости.
Что дальше? ИИ, который работает без интернета — это только начало
С Foundation Models вы можете делать не только чаты. Суммирование текста, генерация кода, анализ настроения — всё на устройстве. Например, в стенографисте для MacBook это используется для транскрипции и анализа встреч.
В 2026 году Apple, вероятно, расширила Foundation Models для видео и аудио. Следите за обновлениями. И не бойтесь экспериментировать. Локальная ИИ — это не будущее, это настоящее, которое уже в вашем iPhone.
Код из статьи — отправная точка. Кастомизируйте, оптимизируйте, тестируйте на реальных устройствах. И когда ваш конкурент шлёт данные в облако, вы уже ответили пользователю.