Foundation Models framework v Swifte: Apple on-device LLM v iOS 26 (2026)

Kompletný sprievodca Apple Foundation Models frameworkom v iOS 26. Naučte sa spúšťať on-device LLM v Swifte, používať @Generable makro a tool calling s reálnymi príkladmi.

Foundation Models Swift: iOS 26 Sprievodca

Aktualizované: 6. septembra 2026

Foundation Models framework je Apple on-device LLM SDK predstavený v iOS 26, ktorý dáva Swift aplikáciám priamy prístup k trojmiliardovému jazykovému modelu bežiacemu lokálne na zariadení. Model beží úplne offline, nespotrebúva API tokeny, a jeho odpovede sa vďaka makru @Generable a guided generation vracajú ako silne typované Swift štruktúry, bez parsovania JSON reťazcov. Prístup k modelu poskytuje trieda LanguageModelSession, ktorá funguje takmer identicky ako klasické async volanie sieťového API.

  • Foundation Models framework je on-device LLM od Apple, dostupný v iOS 26, iPadOS 26, macOS 26 a visionOS 26 na zariadeniach s Apple Intelligence.
  • Model má 3 miliardy parametrov s 2-bitovou kvantizáciou, beží na Apple Neural Engine a nikdy neposiela dáta na cloud.
  • Guided generation cez makro @Generable núti model vrátiť dáta v presnom Swift type, žiadny fragile JSON parsing.
  • Sessions podporujú tool calling: model môže volať vaše Swift funkcie s typovanými argumentmi cez protokol Tool.
  • Streaming cez streamResponse vracia AsyncSequence s partial snímkami, ideálne pre plynulé UI.
  • Použitie je zdarma, bez rate limitov a bez nutnosti platiť za tokeny. Jedinou cenou je energia batérie.

Čo je Foundation Models framework v iOS 26?

Foundation Models je framework predstavený na WWDC 2025 a rozšírený v iOS 26, ktorý ponúka priamy Swift interface k Apple on-device Large Language Model. Ide o ten istý model, ktorý poháňa Apple Intelligence funkcie ako Writing Tools, Notification Summarization a Genmoji. Model má približne 3 miliardy parametrov s 2-bitovou kvantizáciou a Apple ho ladil špecificky pre denné úlohy: sumarizácia, extrakcia, klasifikácia, konverzácia a generovanie štruktúrovaného obsahu.

Framework je súčasťou SDK, takže nemusíte pridávať žiadnu závislosť. Stačí import FoundationModels. V praxi som ho začal používať na Xcode 26 s iOS 26 SDK a rozdiel oproti volaniu cloud API je zásadný: žiadne API kľúče, žiadne rate limity, žiadne latencie voči serveru, a čo je pre mňa najdôležitejšie, nulový network payload s privátnymi dátami. Ak ste kedy museli riešiť odosielanie citlivých notiek do OpenAI, viete, o čom hovorím.

Framework nie je určený na to, aby nahradil GPT-4 alebo Claude Opus vo všetkom. Model je zámerne malý a špecializovaný. Apple ho pozicionuje pre on-device intelligence, teda funkcie, ktoré musia fungovať offline, bezpečne a s minimálnou latenciou. Pre agentické úlohy so zložitým reasoningom stále siahnete po cloud modeloch. Pre denné úlohy typu "sumarizuj tento email" alebo "extrahuj z tejto pozvánky dátum a miesto" je však lokálny 3B model úplne postačujúci a zväčša aj rýchlejší.

Ako skontrolovať dostupnosť Apple Intelligence?

Nie každé zariadenie podporuje Foundation Models. Apple Intelligence beží iba na iPhone 15 Pro a novších, iPad s M1 alebo novším a Mac s Apple Silicon. Používateľ musí mať navyše Apple Intelligence zapnutú v Nastaveniach a zariadenie musí byť v jednom z podporovaných jazykov. Framework preto ponúka SystemLanguageModel.default s vlastnosťou availability, ktorú musíte skontrolovať skôr, než sa pokúsite otvoriť reláciu.

import FoundationModels

func isModelAvailable() -> Bool {
    let model = SystemLanguageModel.default
    switch model.availability {
    case .available:
        return true
    case .unavailable(let reason):
        // .deviceNotEligible, .appleIntelligenceNotEnabled, .modelNotReady
        print("Model nedostupný: \(reason)")
        return false
    }
}

V SwiftUI si toto najčastejšie viažem na @State a používam task modifier na pre-check. Dôvod je jednoduchý: .modelNotReady je prechodný stav, model sa práve sťahuje alebo aktualizuje na pozadí. Ak zobrazíte trvalú chybu, používateľ ostane zmätený, keď mu funkcia po niekoľkých minútach začne fungovať. Vždy odlišujem trvalú nedostupnosť (napríklad Apple Intelligence nie je povolená) od dočasnej.

Prvá relácia s LanguageModelSession

Základný stavebný kameň je LanguageModelSession. Jedna inštancia predstavuje jednu konverzáciu, udržuje si kontext (transkript) a pri každom volaní respond(to:) pošle model celú históriu, čo znamená, že si nemusíte manuálne skladať prompt history. Takto vyzerá minimálne úplné volanie:

import FoundationModels

func summarize(_ text: String) async throws -> String {
    let session = LanguageModelSession(
        instructions: "Si asistent, ktorý stručne sumarizuje texty v slovenčine."
    )
    let response = try await session.respond(to: "Sumarizuj: \(text)")
    return response.content
}

Volanie je plne asynchrónne a integruje sa priamo do Swift concurrency modelu. Ak ste čítali môj skorší text o súbežnosti v Swifte 6.2, viete, že takéto await volanie sa dá pekne spojiť do TaskGroup a paralelizovať naprieč viacerými dokumentmi. Framework je thread-safe voči volaniam, ale samotná inštancia relácie je aktér, takže jedno volanie na reláciu naraz. Ak potrebujete konkurenciu, vytvorte viac relácií.

Pri opakovaných volaniach v tej istej relácii si model pamätá predchádzajúce správy. To znamená, že môžete klásť follow-up otázky bez opakovania kontextu. Reláciu si držte pri pohľade, ktorý s modelom konverzuje, a zahoďte ju, keď používateľ opustí obrazovku. Transkript rastie a s ním aj latencia každej ďalšej odpovede.

Guided generation cez @Generable

Toto je vlastnosť, ktorá Foundation Models odlišuje od väčšiny cloud LLM API. Namiesto toho, aby model vrátil voľný text, ktorý potom parsujete regexom alebo krehkým JSONDecoder-om, deklarujete cieľový typ ako Swift štruktúru s makrom @Generable, a framework vynúti, aby výstup zapadol presne do tohto typu.

import FoundationModels

@Generable
struct MeetingInvite {
    @Guide(description: "Názov stretnutia, maximálne 60 znakov.")
    let title: String

    @Guide(description: "Dátum a čas v ISO 8601, napr. 2026-09-15T14:30:00Z.")
    let startsAt: String

    @Guide(description: "Zoznam emailových adries pozvaných účastníkov.")
    let attendees: [String]

    let location: String?
}

func extractInvite(from email: String) async throws -> MeetingInvite {
    let session = LanguageModelSession(
        instructions: "Extrahuješ z emailu pozvánku na stretnutie."
    )
    let response = try await session.respond(
        to: "Email:\n\(email)",
        generating: MeetingInvite.self
    )
    return response.content
}

Makro @Generable je bratranec makier, ktorým som sa venoval v sprievodcovi Swift makrami. Za scénou vygeneruje schému, ktorú model dostane ako grammar constraint, takže tokeny mimo schémy sa jednoducho nesamplujú. Dôsledok je príjemný: nedostanete "skoro validný" JSON s chýbajúcou úvodzovkou. Buď dostanete presne MeetingInvite, alebo hodí framework typovanú chybu.

Popisky cez @Guide nie sú kozmetika. Model ich vidí a používa ich na rozhodovanie, čo do poľa vložiť. Investujem do nich rovnako, ako by som investoval do dobrého docstringu. Rovnako dôležité je pomenovanie polí: attendees funguje lepšie ako list, pretože model má z tréningu silnú koreláciu medzi anglickými menami polí a ich sémantikou.

Tool calling: rozšírenie modelu o Swift funkcie

Model sám nevidí do vášho kalendára, nevie zavolať sieť, nevie čítať súbory. Tool calling to rieši: definujete typ, ktorý splní protokol Tool, s vlastným @Generable argumentom, a framework model naučí volať ho. Keď model rozhodne, že tool je potrebný, framework ho zavolá, výstup pridá do transkriptu a modelu dá šancu odpovedať znova.

import FoundationModels

struct WeatherTool: Tool {
    let name = "getWeather"
    let description = "Vráti aktuálne počasie pre mesto."

    @Generable
    struct Arguments {
        @Guide(description: "Názov mesta v slovenčine.")
        let city: String
    }

    func call(arguments: Arguments) async throws -> ToolOutput {
        let temp = try await WeatherClient.currentTemperature(in: arguments.city)
        return ToolOutput("V meste \(arguments.city) je \(temp) °C.")
    }
}

let session = LanguageModelSession(
    tools: [WeatherTool()],
    instructions: "Odpovedáš na otázky o počasí."
)
let reply = try await session.respond(to: "Aké je počasie v Košiciach?")

V produkcii držím tools malé a jednoznačne pomenované. Model rozhoduje o volaní tool na základe mena a popisu, takže getWeather je jasnejšie ako fetchData. Argumenty musia byť @Generable, čo znamená, že platí to isté, čo pri guided generation: dobré popisy, výstižné názvy polí, minimum voliteľných hodnôt.

Streaming odpovedí do SwiftUI

Pri dlhších odpovediach používateľ nechce čakať 4 sekundy na "hotovo". Session preto ponúka streamResponse(to:), ktorý vráti AsyncSequence partial snímok. Každá snímka obsahuje priebežný obsah. Pre String pribúda text token po tokene, pre @Generable typy pribúdajú polia podľa toho, ako sa model rozhodne generovať.

import SwiftUI
import FoundationModels

struct ChatView: View {
    @State private var reply = ""
    let session = LanguageModelSession()

    var body: some View {
        Text(reply)
            .task {
                do {
                    let stream = session.streamResponse(to: "Napíš krátku báseň o Bratislave.")
                    for try await partial in stream {
                        reply = partial
                    }
                } catch {
                    reply = "Chyba: \(error.localizedDescription)"
                }
            }
    }
}

Pri guided generation na typových výstupoch má stream ešte jednu peknú vlastnosť: postupne dopĺňa polia štruktúry, takže môžete zobraziť čiastočný stav bez toho, aby ste čakali na kompletnú odpoveď. Pre komplexnejšie UI (typicky forma alebo tabuľka) je to rozdiel medzi tým, či používateľ vidí prázdny skeleton alebo živý stream vypĺňaných hodnôt. Ak plánujete stream používať v kombinácii s @Observable a Observation frameworkom, väzba na view state je prakticky triviálna.

Playground makro pre iteráciu promptov

Xcode 26 pridal #Playground makro, ktoré je pre prácu s Foundation Models nenahraditeľné. Umožňuje spúšťať kód priamo v editore bez buildu aplikácie a vidieť výsledky vedľa v canvas paneli. Pri ladení promptov to znamená smyčku "uprav prompt, stlač Run, vidím odpoveď" za sekundy, nie za minúty.

import FoundationModels
import Playgrounds

#Playground {
    let session = LanguageModelSession(
        instructions: "Klasifikuješ text ako 'positive', 'neutral' alebo 'negative'."
    )
    let result = try await session.respond(to: "Bolo to zbytočne zdĺhavé.")
    result.content
}

Playground makro nie je viazané výhradne na Foundation Models, ale práve tu ho oceníte najviac. Iterujem tak systém instructions, testujem edge case-y (prázdny vstup, cudzí jazyk, agresívny obsah) a kontrolujem, ako sa mení odpoveď s teplotou. Keď je prompt hotový, presuniem ho do produkčného kódu.

Instructions vs. Prompt: dva rôzne kanály

Framework rozlišuje dva vstupy: instructions pri vytvorení relácie a prompt pri každom volaní respond(to:). Toto rozdelenie som si spočiatku podceňoval, čo bola chyba. Instructions definujú perzistentnú rolu a pravidlá, sú "cachované" pre celú reláciu a model ich chápe ako systémový kontext. Prompt je jednotlivá otázka, ktorá sa mení pri každom volaní.

V praxi: do instructions patrí "Odpovedáš v slovenčine, formálne, maximálne dve vety" alebo "Nikdy nevymýšľaj fakty, ktoré nie sú v poskytnutom kontexte". Do promptu patrí konkrétny obsah, ktorý má model spracovať. Ak toto poplacete, model bude na každé nové vlákno zabúdať rolu, alebo naopak "prilepí" jednorázový obsah do reťaza konverzácie a bude ho opakovať v ďalších odpovediach.

Dobré instructions sú krátke, konkrétne a v druhej osobe. Zlé instructions sú dlhé eseje s "shall" a "must" na každom riadku (malý model to nepobral vždy tak, ako by ste chceli). Ak potrebujete štruktúrovaný výstup, kombinujte krátke instructions s guided generation cez @Generable. Je to podstatne robustnejšie než popisovať schému slovami.

Error handling a bezpečnostné guardraily

Foundation Models chybí typovaným spôsobom, s ktorým sa dobre pracuje. Volanie respond(to:) hádže LanguageModelSession.GenerationError, ktorá pokrýva prípady ako guardrailViolation (model odmietol prompt kvôli safety filtru), unsupportedLanguageOrLocale, rateLimited (áno, aj on-device model má thermal rate limity) a assetsUnavailable. Ak by ste chceli pochopiť, prečo je typed throws pre podobný framework tak pekný, mrknite môj text o Typed Throws v Swifte 6.2.

do {
    let response = try await session.respond(to: userInput, generating: Summary.self)
    return response.content
} catch let error as LanguageModelSession.GenerationError {
    switch error {
    case .guardrailViolation:
        throw AppError.safeFallback("Nepodarilo sa spracovať vstup.")
    case .rateLimited:
        try await Task.sleep(for: .seconds(1))
        return try await session.respond(to: userInput, generating: Summary.self).content
    default:
        throw error
    }
}

Apple zabudoval do modelu safety layer, ktorý odmieta nebezpečné výstupy (self-harm, malware, sexuálny obsah týkajúci sa maloletých, a tak ďalej) a rovnako aj vstupy, ktoré sa o toto pokúšajú. Vaša aplikácia musí guardrail violations elegantne pokryť, ideálne miestom, kde ukážete používateľovi neutrálny fallback, nie stacktrace. Honestly, v mojich projektoch mám na tento účel jednu safeFallback pomocnú funkciu, ktorá loguje incident do Sentry a používateľovi ukáže univerzálne "Skúste to prosím preformulovať".

Kedy zvoliť Foundation Models a kedy cloud LLM?

Rozhodovací strom, ktorý používam pri každom novom feature, sa dá zhrnúť do tabuľky:

KritériumFoundation Models (on-device)Cloud LLM (GPT-5, Claude Opus)
Cena za dopytZdarma (batéria)Účtované za tokeny
Latencia~50-200 ms na tokenSieťová round-trip + generovanie
SúkromieNikdy neopustí zariadenieOdchádza k poskytovateľovi
Offline režimÁnoNie
Kvalita pri komplexnom reasoninguPostačujúca pre bežné úlohyVýrazne lepšia
Veľkosť kontextu~4 tisíc tokenov200 tisíc+
Podpora zariadeníIba Apple Intelligence-eligibleKtorýkoľvek platform

V praxi ide model rozdeliť tak, že Foundation Models robí prvú vrstvu (rýchlu klasifikáciu, extrakciu, sumár) a iba pri prípadoch, ktoré vyžadujú hlbšie uvažovanie, aplikácia siahne po cloud modele. Toto hybrid routing šetrí náklady a zároveň drží väčšinu operácií offline. Odporúčam si prečítať aj oficiálnu dokumentáciu Foundation Models a WWDC 2025 session "Meet the Foundation Models framework", kde Apple ukazuje ďalšie vzorce použitia. Pre kontext ohľadom modelu samotného stojí za pozretie aj Apple Machine Learning Research: Introducing Apple's On-Device and Server Foundation Models.

Často kladené otázky

Je Foundation Models framework zadarmo?

Áno. Použitie modelu nie je nijak spoplatnené a nemá rate limity vo forme tokenov. Jedinou "cenou" je spotreba batérie a mierne teplo pri dlhších sériách volaní. Neplatíte Apple ani inému poskytovateľovi za dopyt.

Aký model Foundation Models používa pod kapotou?

Ide o Apple on-device jazykový model s približne 3 miliardami parametrov a 2-bitovou kvantizáciou, ladený na denné produktivitné úlohy. Beží na Apple Neural Engine, prípadne CPU/GPU pri starších čipoch podporujúcich Apple Intelligence.

Ktoré zariadenia podporujú Foundation Models?

Framework beží na zariadeniach, ktoré podporujú Apple Intelligence: iPhone 15 Pro a novší, iPady s M1 a novším čipom, Macy s Apple Silicon a Apple Vision Pro. Používateľ musí mať Apple Intelligence zapnutú v Nastaveniach a jazyk zariadenia musí byť medzi podporovanými lokalizáciami.

Ako vyzerá kontextové okno modelu?

Model má obmedzený kontext v ráde niekoľkých tisíc tokenov (Apple oficiálne uvádza okolo 4 tisíc). To znamená, že pri dlhých dokumentoch musíte urobiť chunking alebo priebežné sumarizácie. Pri opakovanom používaní tej istej relácie sa kontext plní históriou konverzácie, takže dlhé relácie pravidelne resetujem.

Môžem model doladiť (fine-tune) na svoje dáta?

V iOS 26 nie priamo cez framework. Apple ponúka adapters mechanizmus cez Apple Intelligence Training v macOS, kde môžete vlastný LoRA adapter pripraviť a distribuovať s aplikáciou. Nie je to však plnohodnotný fine-tuning, pre custom modely stále siahnete po Core ML alebo cloud tréningu.

Lukas Müller
O Autorovi Lukas Müller

iOS developer and Swift author since the Objective-C days. Spends his evenings on side projects and his mornings on SwiftUI internals.