Foundation Models Swiftissä: Käytännön opas Apple Intelligence -malliin (2026)

Käytännön opas Applen Foundation Models -kehyksen käyttöön Swiftissä: istuntojen luonti, strukturoitu tuotos @Generable-makrolla, streaming, työkalukutsut ja saatavuuden tarkistus iOS 26:ssa.

Foundation Models Swift -opas 2026

Päivitetty: 3. kesäkuuta 2026

Foundation Models -kehys on Applen Swift-natiivi rajapinta, jonka kautta sovellukset voivat käyttää laitteessa suoritettavaa Apple Intelligence -kielimallia ilman verkkoyhteyttä tai palvelinkustannuksia. Kehys julkaistiin osana iOS 26:tta, iPadOS 26:tta ja macOS Tahoeta kesäkuussa 2025, ja se tarjoaa LanguageModelSession-tyypin promptaukseen, @Generable-makron strukturoituun tuotokseen sekä Tool-protokollan työkalukutsuihin. Olen pyörittänyt kehystä omissa sivuprojekteissani siitä lähtien, kun ensimmäiset Xcode 26 -betaversiot ilmestyivät, ja tämä artikkeli kokoaa ne asiat, jotka olisin halunnut tietää alussa.

  • Foundation Models -kehys vaatii Apple Intelligence -yhteensopivan laitteen: iPhone 15 Pro tai uudempi, iPad ja Mac M1-piiristä alkaen.
  • LanguageModelSession on rinnakkainen istunto-olio, joka säilyttää keskusteluhistorian automaattisesti.
  • @Generable-makro generoi malleille decoodausskeeman, joten respond(to:generating:) palauttaa tyypitetyn Swift-arvon ilman JSON-manuaalia.
  • Työkalukutsut toteutetaan Tool-protokollalla; malli päättää itse, milloin kutsuu työkalua argumenttien kanssa.
  • Tarkista aina SystemLanguageModel.default.availability ennen istunnon luontia, koska virheilmoitukset eivät paljasta syytä yhtä siististi.
  • Kehyksen on-device-malli on noin 3 miljardia parametria; älä yritä korvata sillä GPT-4-luokkaisia tehtäviä.

Mikä on Foundation Models -kehys?

Foundation Models on Applen ensimmäinen julkinen rajapinta omaan, laitteessa suoritettavaan suureen kielimalliin. Toisin kuin Core ML, joka on yleisen tason koneoppimisen ajoympäristö, Foundation Models on rakennettu nimenomaan tekstigeneroinnin, yhteenvedon, luokittelun ja työkalukutsujen ympärille. Malli itse ei ole sovelluksen niputtama tiedosto, vaan järjestelmäkomponentti, jonka käyttöjärjestelmä lataa ensimmäisellä Apple Intelligencen käyttökerralla ja päivittää itse.

Tämä on hieman samaa logiikkaa, mihin Apple totutti meidät jo Objective-C:n aikana NSLinguisticTaggerilla: sovellus ei kanna kielimallia mukanaan, vaan käyttää järjestelmän tarjoamaa. Erona on, että nyt taustalla on noin 3 miljardin parametrin transformer-malli LoRA-adaptereineen, ei sääntöpohjainen jäsentäjä. Kehyksen modulaarisuus tarkoittaa myös, että App Store -binäärin koko pysyy pienenä (kymmenien megatavujen mallitiedostoja ei kuljeteta mukana).

Kehyksen ytimessä ovat neljä tyyppiä: SystemLanguageModel kuvaa saatavilla olevaa mallia, LanguageModelSession on yksi keskustelu, Tool on protokolla mallin kutsumille funktioille, ja @Generable on makro, joka tekee omista Swift-tyypeistäsi mallin tuotoskelpoisia. Tarkka rajapinta on dokumentoitu osoitteessa Apple Developer: Foundation Models.

Mitkä laitteet tukevat Foundation Models -kehystä?

Foundation Models -kehys vaatii Apple Intelligence -yhteensopivuuden, joka rajoittaa käytön käytännössä uusimpiin laitteisiin. iPhonella tämä tarkoittaa iPhone 15 Prota, iPhone 15 Pro Maxia ja koko iPhone 16- ja 17-sarjaa. iPadeista mukana ovat M1-piirin tai uudemman sisältävät mallit, ja Maceista kaikki Apple silicon -koneet M1:stä alkaen. Tämän alle jäävillä laitteilla SystemLanguageModel.default.availability palauttaa .unavailable(.deviceNotEligible), jolloin sovelluksen on tarjottava vaihtoehtoinen reitti tai kerrottava käyttäjälle, että toiminto ei ole käytettävissä.

Lisäksi käyttäjän on kytkettävä Apple Intelligence päälle Asetuksista. Jos hän ei ole tehnyt niin, saat .unavailable(.appleIntelligenceNotEnabled). Tämä on todellisuudessa yleisempi virhe kuin laiterajoitus, koska ominaisuus on opt-in. Suositukseni: älä yritä avata Asetuksia automaattisesti. Selitä lyhyesti, miksi toiminto vaatii Apple Intelligencen, ja anna käyttäjän päättää.

watchOS- ja tvOS-tukea ei tällä hetkellä ole, eikä Apple ole sellaista vihjannut. visionOS 26 tukee kehystä Vision Pro -laitteissa, joissa on M2 tai uudempi.

Ensimmäinen LanguageModelSession

Yksinkertaisin mahdollinen käyttö näyttää tältä. Sessio luodaan, prompt lähetetään ja vastaus odotetaan. Koko rajapinta on async, joten se istuu luonnollisesti modernin Swift-rinnakkaisuuden päälle.

import FoundationModels

func summarize(_ text: String) async throws -> String {
    let session = LanguageModelSession()
    let response = try await session.respond(
        to: "Tiivistä seuraava teksti yhdellä virkkeellä:\n\n\(text)"
    )
    return response.content
}

Huomaa kaksi seikkaa. Ensinnäkin LanguageModelSession() ottaa oletuksena SystemLanguageModel.default-mallin, joten et tarvitse erillistä konfiguraatiota perustapauksissa. Toiseksi sessio säilyttää keskusteluhistorian: jos kutsut respond(to:) samalle sessiolle uudestaan, edellinen prompt ja vastaus ovat osa kontekstia. Tämä on harvoin haluttua eräajossa, joten luo uusi sessio per pyyntö, ellet rakenna varsinaista chat-näkymää.

Voit myös antaa konstruktorille instructions-parametrin, joka toimii kuten muiden LLM-rajapintojen system-viesti. Se annetaan kerran, ja malli kantaa sitä mukanaan koko session ajan:

let session = LanguageModelSession(
    instructions: """
    Olet kohtelias asiakaspalvelu-assistentti.
    Vastaa aina suomeksi ja korkeintaan kahdella virkkeellä.
    """
)

Strukturoitu tuotos @Generable-makrolla

Tämä on kehyksen mielenkiintoisin osa ja syy, miksi en henkilökohtaisesti enää kirjoita käsin JSON-jäsentäjiä LLM-vastauksille. @Generable-makro liittää omaan Swift-tyyppiisi mallin tarvitseman skeeman, ja kun pyydät vastausta tyyppiparametrin kanssa, saat takaisin tyypitetyn arvon.

import FoundationModels

@Generable
struct Recipe {
    @Guide(description: "Reseptin nimi suomeksi")
    let name: String

    @Guide(description: "Valmistusaika minuutteina", .range(5...240))
    let minutes: Int

    @Guide(description: "Ainesosat järjestyksessä")
    let ingredients: [String]

    let steps: [String]
}

func recipe(for query: String) async throws -> Recipe {
    let session = LanguageModelSession()
    let response = try await session.respond(
        to: "Ehdota resepti hakusanalle: \(query)",
        generating: Recipe.self
    )
    return response.content
}

Makro generoi taustalla mallin ymmärtämän skeeman, joka pakottaa decoodausvaiheessa tuotoksen vastaamaan tyypin rakennetta. @Guide-attribuutilla annat kentälle kuvauksen ja valinnaisia rajoitteita, esimerkiksi .range, .count tai .enumeration. Tämä on samaa filosofiaa kuin SwiftDatan @Attribute-makroilla, joista kirjoitin SwiftData-oppaassa. Swift-makroista on tullut Applen ensisijainen tapa liimata tyyppisysteemiä ajonaikaiseen käyttäytymiseen.

Sisäkkäiset tyypit toimivat odotetusti, kunhan jokainen taso on merkitty @Generableiksi. enum-arvot ovat myös tuettuja, ja malli osaa valita oikean tapauksen kuvausten perusteella. Optionaaliset kentät tulkitaan niin, että malli voi jättää ne pois, jos kontekstista ei löydy arvoa. Tämä on usein parempi kuin pakottaa malli hallusinoimaan kenttiä.

Streaming-vastaukset reaaliajassa

Käyttöliittymässä on harvoin järkevää odottaa täyttä vastausta ennen näyttämistä. Foundation Models tukee streamingia respond(to:)-metodin streamResponse-variantilla, joka palauttaa AsyncSequencen osittaisista vastauksista.

import SwiftUI
import FoundationModels

@Observable
final class ChatViewModel {
    var partial: String = ""
    private let session = LanguageModelSession()

    func ask(_ prompt: String) async {
        partial = ""
        do {
            let stream = session.streamResponse(to: prompt)
            for try await chunk in stream {
                partial = chunk.content
            }
        } catch {
            partial = "Virhe: \(error.localizedDescription)"
        }
    }
}

Tärkeä yksityiskohta: chunk.content on koko kumulatiivinen vastaus tähän mennessä, ei pelkkä uusi pala. Tämä eroaa esimerkiksi OpenAI:n streaming-API:sta, jossa saat deltoja. Applen valinta on käytännöllinen, koska SwiftUI-näkymässä voit sitoa partial-merkkijonon suoraan Text-elementtiin ilman ylimääräistä konkatenointia.

Strukturoidulla tuotoksella streamaus toimii streamResponse(to:generating:)-variantilla ja palauttaa osittaisia, valinnaisia kenttiä sisältäviä arvoja. Tämä on hyödyllistä esimerkiksi silloin, kun haluat näyttää reseptin nimen heti, vaikka vaiheet ovat vielä kesken.

Työkalujen kutsuminen Tool-protokollalla

Yksi kehyksen aliarvioiduimmista ominaisuuksista on natiivi työkalukutsutuki. Toteutat Tool-protokollan, rekisteröit sen sessioon, ja malli päättää automaattisesti, milloin kutsua sitä. Kaikki Swiftissä, ilman erillistä funktiokuvausten JSON-skeemaa.

import FoundationModels
import CoreLocation

struct WeatherTool: Tool {
    let name = "currentWeather"
    let description = "Hakee säätiedot annetulle paikkakunnalle."

    @Generable
    struct Arguments {
        @Guide(description: "Kaupungin nimi suomeksi")
        let city: String
    }

    func call(arguments: Arguments) async throws -> ToolOutput {
        let temperature = try await WeatherService.shared.celsius(for: arguments.city)
        return ToolOutput("\(arguments.city): \(temperature) °C")
    }
}

let session = LanguageModelSession(tools: [WeatherTool()])
let response = try await session.respond(
    to: "Mitä mun pitää pukea Helsingissä tänään?"
)

Malli näkee promptin, tunnistaa tarvitsevansa säätiedon, kutsuu WeatherToolia city: "Helsinki"-argumentilla, saa tuloksen takaisin ja muotoilee vastauksen sen pohjalta. Voit rekisteröidä useita työkaluja samaan sessioon, ja malli valitsee tarvittavat itse. Tämän rakentaminen pilvi-LLM:llä vaatisi tyypillisesti oman funktiokutsuvälikerroksen, joten Applen ratkaisu säästää huomattavasti liimakoodia.

Pidä työkalut nopeina ja idempotentteina. Malli voi kutsua samaa työkalua useita kertoja saman vastauksen aikana, jos prompt sitä vihjaa, ja jos työkalu tekee verkkopyyntöjä, käyttäjä huomaa viiveen heti.

Saatavuuden tarkistus ja virheenkäsittely

Sovelluksesi käynnistyy aina laitteilla, joilla Foundation Models ei ole saatavilla. Tarkista tilanne ennen istunnon luontia ja näytä sopiva käyttöliittymä:

import FoundationModels

enum FoundationModelsState {
    case ready
    case needsAppleIntelligence
    case downloadingModel
    case unsupportedDevice
    case other(String)
}

func currentState() -> FoundationModelsState {
    switch SystemLanguageModel.default.availability {
    case .available:
        return .ready
    case .unavailable(.appleIntelligenceNotEnabled):
        return .needsAppleIntelligence
    case .unavailable(.modelNotReady):
        return .downloadingModel
    case .unavailable(.deviceNotEligible):
        return .unsupportedDevice
    case .unavailable(let reason):
        return .other(String(describing: reason))
    }
}

Tähän modelNotReady-tilaan törmää erityisesti laitteen ensimmäisellä käynnistyskerralla iOS 26 -päivityksen jälkeen. Malli latautuu taustalla, ja saatavuus muuttuu itsestään muutaman minuutin kuluessa. Hyvä käyttäjäkokemus näyttää tämän tilan ja tarjoaa pull-to-refresh-tyyppisen tavan tarkistaa uudelleen. Älä polla saatavuutta sekunneittain, koska se on energiasyöppö.

Itse istuntopyynnöt voivat heittää LanguageModelSession.GenerationError-tyyppisiä virheitä, joista yleisimmät ovat .guardrailViolation (sisältösuodattimet estivät vastauksen), .exceededContextWindow (prompt + historia ylittävät kontekstin) ja .cancelled (kutsuja perui Tehtävän). Käsittele ainakin nämä kolme erikseen, koska yleinen "jokin meni pieleen" -viesti ei auta käyttäjää.

Foundation Models vs. Core ML vs. pilvi-LLM

Foundation Models ei ole kaikkien ongelmien ratkaisu. Tässä yhteenveto, milloin valita mitäkin:

OminaisuusFoundation ModelsCore MLPilvi-LLM (esim. Claude)
VerkkoyhteysEi tarvitaEi tarvitaPakollinen
Mallin koko~3 mrd parametriaVapaa, sovelluksen mukana100+ mrd parametria
TehtävätTeksti, työkalutYleinen ML (kuva, ääni, teksti)Mikä tahansa teksti
Strukturoitu tuotos@Generable, sisäänrakennettuManuaalinenVaihtelee tarjoajan mukaan
YksityisyysTäysin laitteessaTäysin laitteessaTiedot lähtevät palvelimelle
KustannuksetIlmainenIlmainenTokeniperustainen lasku
LaiterajoitteetApple Intelligence -laitteetKaikki Apple-laitteetEi rajoitteita

Käytännössä Foundation Models on oikea valinta, kun kyseessä on lyhyt tekstin muokkaus, luokittelu, yhteenveto tai työkalupohjainen aktio paikallisilla tiedoilla. Pilvi-LLM voittaa, kun tarvitset pitkän kontekstin (100k+ tokenia), korkeampaa päättelykykyä tai monimutkaisten suomalaisten lakitekstien analyysiä. Core ML on yhä paras valinta omilla, kapeisilla malleilla, esimerkiksi kuvanluokittelu, tai jos sovelluksesi pitää toimia myös iPhone 12:lla.

Yksityisyys, suorituskyky ja akkukulutus

Kaikki Foundation Models -pyynnöt suoritetaan laitteessa. Tämä ei ole vain markkinointiväite vaan rajapinnan suunnitteluperiaate: kehys ei sisällä tapaa pyytää pilviversiota mallista. Applen Apple Foundation Models -tekninen raportti kannattaa lukea, jos haluat ymmärtää, miten Private Cloud Compute eroaa tästä rajapinnasta. Se on eri kerros, johon sovelluskehittäjillä ei ole suoraa pääsyä.

Suorituskykynäkökulmasta odota noin 30–60 tokenia sekunnissa iPhone 16 Prossa, hieman vähemmän iPhone 15 Prossa, ja noin 100 tokenia sekunnissa M4 Macissa. Tämä riittää sujuvaan streamattuun tekstigenerointiin, mutta ei reaaliaikaiseen puheeseen. Akkukulutus on huomattava: pitkä 1000 tokenin generointi vastaa karkeasti 30 sekunnin videontoistoa. Älä siis aja mallia taustalla jatkuvasti.

Jos sovelluksesi käyttöliittymä rakentuu uuden Liquid Glass -suunnittelukielen päälle, varaa generoinnin ajaksi selkeä latausindikaattori. Käyttäjät ovat tottuneet pilvi-LLM:ien latenssiin, mutta on-device-mallin lämpenemisviive ensimmäisellä pyynnöllä voi tuntua erikoiselta.

Usein kysytyt kysymykset

Voinko käyttää Foundation Models -kehystä ilman internetiä?

Kyllä. Koko inferenssi tapahtuu laitteessa, eikä kehys lähetä yhtään tavua verkkoon. Ainoa verkkoa vaativa vaihe on mallin alkulataus, joka tapahtuu kerran iOS 26 -päivityksen yhteydessä järjestelmätasolla.

Miten päivitän olemassa olevan Core ML -projektin Foundation Modelsiin?

Et kirjaimellisesti päivitä, sillä kyseessä ovat eri kehykset eri käyttötarkoituksiin. Jos Core ML -mallisi tekee tekstigenerointia tai luokittelua yleisellä kielimallilla, voit korvata sen Foundation Models -istunnolla. Jos malli on oma erikoistunut luokittelija, pidä se Core ML:ssä, koska Foundation Models on yleismalli eikä korvaa erikoismalleja.

Voiko Foundation Models -mallia hienosäätää omalla datalla?

Suoraa fine-tuning-rajapintaa ei kehittäjille ole, mutta Apple tukee LoRA-adaptereita rajoitetuilla yrityskumppanuusohjelmilla. Useimmissa tapauksissa instructions-parametri ja muutaman esimerkin few-shot-prompting riittävät. Yhden hengen sivuprojekteissa et tarvitse fine-tuningia.

Mikä on Foundation Models -mallin kontekstin enimmäispituus?

Konteksti-ikkuna on 4096 tokenia (prompt + ohjeet + tuotos yhteensä) Xcode 26.0 -beetan aikaan. Tämä on huomattavasti pienempi kuin pilvi-LLM:issä, joten älä syötä mallille kokonaisia PDF-dokumentteja. Käytä esikäsittelyä, pilkkomista tai yhteenvetokierroksia.

Tukeeko Foundation Models suomen kieltä?

Kyllä, mutta laatu on parhainta englanniksi. Suomen ja muiden Pohjoismaiden kielten tuki lisättiin iOS 26.1:ssä, ja se riittää hyvin yhteenvetoihin, luokitteluun ja yksinkertaiseen generointiin. Monimutkaisemmissa luovissa tehtävissä huomaat eron, ja siinä tilanteessa harkitse pilvi-LLM:ää.

Lukas Müller
Tietoa Kirjoittajasta 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.