← Todos os Posts

Apple Foundation Models: o framework de LLM on-device, explicado

O framework Foundation Models dá a um app acesso direto, gratuito e offline ao mesmo modelo de linguagem grande no dispositivo que move o Apple Intelligence1. Sem chave de API, sem conta por token, sem ida e volta pela rede, sem dados saindo do dispositivo. Para uma categoria de recursos que antes significava uma LLM na nuvem e uma revisão de privacidade, o custo agora arredonda para zero. A troca é a capacidade: o modelo on-device é pequeno, a janela de contexto é finita e o framework traça linhas rígidas em torno do que ele faz e do que não faz. Conhecer essas linhas é o jogo inteiro.

Esta é a referência sobre o próprio framework: os tipos que você de fato chama, o único recurso que torna o uso dele valioso e o ponto em que você deveria parar e recorrer a algo maior.

TL;DR

  • LanguageModelSession é o ponto de entrada. Crie uma, chame respond(to:), receba o texto de volta. O contexto de múltiplos turnos vive na sessão; trabalho de turno único recebe uma sessão nova a cada vez2.
  • A geração guiada é a razão para usar este framework. Anote um tipo Swift com @Generable e o modelo retorna esse tipo, preenchido e com tipos verificados, em vez de uma string que você precisa parsear3.
  • O protocolo Tool permite que o modelo chame seu código no meio da geração para buscar dados ou executar uma ação e, em seguida, incorpore o resultado de volta à resposta4.
  • Verifique SystemLanguageModel.default.availability antes de fazer qualquer coisa. O modelo está ausente em dispositivos não elegíveis, com o Apple Intelligence desligado ou enquanto ele é baixado5.
  • A janela de contexto é real e pequena. SystemLanguageModel.default.contextSize informa o orçamento de tokens compartilhado entre o prompt e a resposta6. Planeje para isso, ou a sessão lança um erro.
  • Requer iOS 26 e um dispositivo compatível com Apple Intelligence. Abaixo desse piso, o framework não existe.

O que o framework é, e o que não é

O Foundation Models não é um invólucro em torno de um endpoint na nuvem. O modelo vive no dispositivo, é distribuído junto com o sistema operacional e roda sobre o Neural Engine. Esse único fato orienta cada decisão de design na API e cada decisão que você toma ao usá-la.

O que você ganha: geração de texto, sumarização, classificação, extração, reescrita de formato curto e saída estruturada, tudo on-device e tudo de graça. O que você não ganha: um modelo de fronteira. A Apple construiu o modelo on-device para tarefas de linguagem focadas dentro de um app, não para raciocínio aberto, não para análise de documentos longos, não para conhecimento de mundo que você possa sondar. A Apple diz exatamente isso, e o enquadramento importa porque define expectativas que a API, de outra forma, deixaria você violar1.

O modelo mental que mantém você longe de problemas: trate o modelo on-device como um estagiário rápido, privado e gratuito, excelente em moldar texto e péssimo em conhecer fatos. Entregue a ele material e uma tarefa clara. Não faça perguntas que ele não tem como responder.

LanguageModelSession: o ponto de entrada

Toda interação começa com uma sessão.

import FoundationModels

let session = LanguageModelSession()
let response = try await session.respond(to: "Summarize this review in one sentence: \(reviewText)")
print(response.content)

A sessão mantém o estado da conversa. Cada chamada a respond(to:) é acrescentada à transcrição em andamento, então uma sessão que você mantém por perto lembra do que veio antes. Para um recurso de chat, é isso que você quer. Para tarefas independentes de uma única passada (resumir isto, classificar aquilo), crie uma sessão nova por chamada para que contexto velho não vaze e consuma seu orçamento de tokens2.

respond(to:) é async throws. Ela suspende enquanto o modelo trabalha e lança um erro quando a requisição excede a janela de contexto, quando o modelo está indisponível ou quando as salvaguardas rejeitam o conteúdo. Cada um desses casos é um ramo real que você trata, não uma exceção que você ignora.

Para uma UI responsiva, faça streaming em vez de esperar. streamResponse(to:) entrega saída parcial conforme o modelo a produz, o que transforma um travamento de três segundos em texto que aparece à medida que se forma7.

Geração guiada: o recurso que justifica o framework

Aqui está a parte que vale o preço da entrada. A maioria das integrações de LLM gasta um terço do código convencendo o modelo a cuspir JSON válido e os outros dois terços se defendendo das vezes em que ele falha mesmo assim. O Foundation Models elimina esse trabalho.

Anote um tipo Swift com @Generable, peça à sessão para gerá-lo, e o modelo retorna uma instância desse tipo, preenchida e com tipos seguros3:

@Generable
struct Recipe {
    @Guide(description: "The dish name")
    let title: String

    @Guide(description: "Ingredients, each as 'quantity item'")
    let ingredients: [String]

    @Guide(description: "Total minutes, start to finish", .range(5...240))
    let minutes: Int
}

let session = LanguageModelSession()
let response = try await session.respond(
    to: "A weeknight pasta for two.",
    generating: Recipe.self
)
let recipe = response.content   // a Recipe, not a String

Sem parsing. Sem JSONDecoder. Sem laço de retentativa para saída malformada. A macro @Guide restringe campos individuais: uma descrição que o modelo lê como instrução, e limites opcionais como uma faixa numérica ou uma expressão regular que a saída precisa satisfazer8. O framework não pede educadamente ao modelo um número entre 5 e 240; ele restringe a decodificação para que o campo não possa vir de outra forma.

A disciplina que isso impõe é o valor de verdade. Você projeta o tipo de saída primeiro, em Swift, com o compilador conferindo. O modelo preenche um contrato que você definiu em vez de retornar prosa que você decifra por engenharia reversa. Para extração, preenchimento de formulários e qualquer recurso que transforme linguagem em dados, a geração guiada é a diferença entre uma demonstração e código que vai para produção.

Vale conhecer um controle: respond(to:generating:) deixa includeSchemaInPrompt com o padrão true, o que injeta a forma do seu tipo no prompt para inclinar o modelo em direção a ela. Deixe ligado, a menos que o modelo já conheça o formato do treinamento ou de turnos anteriores na sessão; desligar para economizar tokens em um formato que o modelo nunca viu é como você recebe lixo de volta9.

Chamada de ferramentas: deixando o modelo alcançar seu código

A geração guiada molda o que sai. A chamada de ferramentas muda o que entra. Uma ferramenta é um trecho do seu código que o modelo pode invocar no meio da geração para buscar uma informação que não tem ou executar uma ação e, então, continuar sua resposta usando o resultado4.

Uma ferramenta segue o protocolo Tool: um name, uma description que o modelo lê para decidir quando chamá-la, um tipo Arguments marcado com @Generable e um método call(arguments:) que faz o trabalho4:

struct FindContacts: Tool {
    let name = "findContacts"
    let description = "Find a specific number of contacts from the address book"

    @Generable
    struct Arguments {
        @Guide(description: "How many contacts to return", .range(1...10))
        let count: Int
    }

    func call(arguments: Arguments) async throws -> [String] {
        // Fetch contacts, return formatted names.
    }
}

let session = LanguageModelSession(tools: [FindContacts()])
let response = try await session.respond(to: "Draft a dinner invite to three of my contacts.")

O fluxo: o modelo decide que precisa de contatos, chama sua ferramenta com um count validado, você retorna dados e o modelo escreve o convite usando nomes reais. Os argumentos chegam com os tipos verificados pela mesma maquinaria de geração guiada, então você nunca extrai a intenção do modelo de texto livre. A descrição da ferramenta é sua única alavanca sobre quando o modelo decide recorrer a ela, então escreva-a como a documentação de uma função que outro engenheiro (sem nenhum outro contexto) precisa ler e usar corretamente.

Esta é também a costura onde o Foundation Models encontra o restante da história do agente. Uma ferramenta que o modelo on-device chama e um App Intent que o Apple Intelligence chama são superfícies diferentes com a mesma forma: uma capacidade nomeada, descrita e tipada. Projete a capacidade uma vez e você poderá expô-la pelas duas.

Disponibilidade: a verificação que você não pode pular

O modelo nem sempre está lá. Ele está ausente em dispositivos que não suportam o Apple Intelligence, quando o usuário o desligou e durante a janela em que o sistema operacional ainda está baixando os ativos do modelo. Distribua código que assume que o modelo existe e ele vai travar, degradar em silêncio ou congelar para uma parcela dos seus usuários que você nunca testou.

Verifique SystemLanguageModel.default.availability e ramifique conforme o motivo5:

switch SystemLanguageModel.default.availability {
case .available:
    // Show the intelligence feature.
case .unavailable(.deviceNotEligible):
    // Hide it. This device will never have the model.
case .unavailable(.appleIntelligenceNotEnabled):
    // Prompt the user to turn on Apple Intelligence.
case .unavailable(.modelNotReady):
    // Downloading or otherwise not ready yet. Try again later.
case .unavailable(let other):
    // Unknown reason. Fail closed.
}

Os três motivos exigem três respostas de produto diferentes, e confundi-los é a forma mais comum de esses recursos parecerem quebrados. deviceNotEligible é permanente: esconda o recurso, não fique insistindo. appleIntelligenceNotEnabled é uma configuração que o usuário controla: um aviso único é justo. modelNotReady é temporário: tente de novo, não mostre um erro. Construa o caminho do indisponível com o mesmo cuidado que o caminho feliz, porque para uma fatia real de dispositivos ele é o único caminho.

Quando o modelo está disponível e você sabe que uma requisição está chegando, prewarm() na sessão aquece o modelo para que a primeira resposta real chegue mais rápido10. Vale a pena numa tela em que o usuário está prestes a agir, desperdício se você o chamar especulativamente.

A janela de contexto, e onde ela deixa de ser suficiente

SystemLanguageModel.default.contextSize informa o orçamento de tokens dentro do qual o modelo trabalha, e esse orçamento é compartilhado: prompt mais resposta, juntos, precisam caber6. O número é pequeno em relação a um modelo na nuvem, e você sente isso rápido em entradas reais. Um documento longo, um histórico de chat completo, um resultado de ferramenta gordo: qualquer um deles pode estourar o orçamento e fazer respond lançar um erro.

Daí decorrem dois modos de falha, e ambos cabem a você prevenir. Primeiro, o acúmulo lento: uma sessão de múltiplos turnos acumula transcrição até que mais um turno transborde. Administre isso iniciando sessões novas para trabalhos não relacionados e mantendo enxuta a entrada por turno. Segundo, a requisição única grande demais: um PDF de 20 páginas não cabe, ponto-final. Fatie-o, resuma os pedaços e então raciocine sobre os resumos (o map-reduce que engenheiros de LLM conhecem bem), ou aceite que a tarefa tem a forma errada para um modelo on-device.

A janela de contexto é o sinal mais limpo para a decisão que de fato importa com este framework: quando ficar no dispositivo e quando partir.

Quando não usar o Foundation Models

O framework é gratuito, privado e offline, o que torna tentador recorrer a ele em todo lugar. Resista. Vá além dele quando:

  • Você precisa de raciocínio de verdade ou amplitude de conhecimento de mundo. O modelo on-device é pequeno por design. Raciocínio aberto, geração de código e análise profunda pertencem a um modelo de fronteira na nuvem. Pedir isso ao modelo on-device produz respostas confiantes e erradas.
  • A entrada não cabe na janela de contexto e fatiar destruiria o significado. Algumas tarefas precisam enxergar tudo de uma vez.
  • Você precisa de um modelo que você controla: um checkpoint específico, um fine-tune, pesos personalizados, versionamento determinístico ao longo das atualizações do sistema. A Apple distribui e atualiza o modelo no cronograma dela, não no seu.
  • Você está abaixo do iOS 26 ou em um dispositivo não elegível. O framework simplesmente não está lá, e a verificação de disponibilidade vai dizer isso a cada execução.

Para os casos on-device que o framework não cobre (um modelo personalizado, seus próprios pesos, treinamento no dispositivo), a camada abaixo é o Core ML e o MLX da Apple. Para os casos que genuinamente precisam de escala, uma LLM na nuvem por trás de uma fronteira de privacidade ainda é a resposta honesta. O Foundation Models não substitui nenhum dos dois. Ele é a primeira escolha certa para trabalho de linguagem focado sobre texto que você já tem em mãos, e a escolha errada para todo o resto.

A habilidade que este framework recompensa não é o artesanato de prompts. É o bom gosto quanto ao escopo: alimentar o modelo com tarefas em que ele é bom, projetar tipos @Generable que capturam exatamente o que você precisa e reconhecer o momento em que o trabalho ultrapassa o tamanho do dispositivo. Construa com esses instintos e o modelo on-device faz uma quantidade surpreendente de trabalho real de graça. Ignore-os e você entrega um recurso que quebra para todo usuário cuja entrada passou um token do limite.



  1. Apple Developer, visão geral do framework “Foundation Models”. A Apple descreve o framework como acesso ao modelo on-device que move o Apple Intelligence, adequado a tarefas de linguagem focadas como geração de texto, sumarização, classificação e saída estruturada, em vez de raciocínio aberto ou conhecimento de mundo. 

  2. Apple Developer, “LanguageModelSession” e “Generating content and performing tasks with Foundation Models”. Uma sessão mantém o contexto de múltiplos turnos; a orientação da Apple é criar uma nova sessão para cada interação distinta de turno único. 

  3. Apple Developer, “Generable” e “Prompting an on-device foundation model”. A macro @Generable permite que o framework retorne um valor Swift preenchido e com tipos verificados, em vez de uma string. 

  4. Apple Developer, protocolo “Tool”. Define protocol Tool<Arguments, Output>: Sendable com name, description e parameters: GenerationSchema obrigatórios, além de call(arguments:) async throws -> Output. O tipo Arguments segue ConvertibleFromGeneratedContent e normalmente é declarado @Generable

  5. Apple Developer, “SystemLanguageModel.Availability” e seu UnavailableReason. Casos: .available e .unavailable(...) com os motivos deviceNotEligible, appleIntelligenceNotEnabled e modelNotReady. SystemLanguageModel.default.isAvailable é o booleano de conveniência. 

  6. Apple Developer, “SystemLanguageModel.contextSize”. Uma propriedade de instância (acessada por SystemLanguageModel.default) documentada como o tamanho máximo de contexto, representando o total de tokens entre o prompt de entrada e a resposta gerada. 

  7. Apple Developer, “LanguageModelSession.streamResponse(to:)”. Faz streaming da saída parcial gerada conforme o modelo a produz, para atualizações incrementais de UI. 

  8. Apple Developer, “Guide(description:_:)”. Uma macro de mesmo nível que anexa uma descrição em linguagem natural e restrições opcionais (faixas numéricas, guias de expressão regular) a uma propriedade @Generable. Requer iOS 26.0+. 

  9. Apple Developer, “respond(to:schema:includeSchemaInPrompt:options:)”. includeSchemaInPrompt tem true como padrão; a discussão da Apple recomenda manter o padrão a menos que o modelo já conheça o formato esperado. 

  10. Apple Developer, “LanguageModelSession.prewarm()”. Pede ao framework para carregar os recursos do modelo antes de uma requisição conhecida que está por vir, para reduzir a latência da primeira resposta. 

  11. Análise relacionada do autor: LLMs on-device com o Foundation Models da Apple, Adaptadores personalizados para o Foundation Models, Casos de uso do Foundation Models e Fluxos de trabalho agênticos no Foundation Models. O argumento sobre App Intents e a superfície de ferramentas é desenvolvido em App Intents são a nova API da Apple para o seu app

Artigos relacionados

Casos de uso do Foundation Models: General vs Content Tagging

O Foundation Models do iOS 26 tem os casos de uso .general e .contentTagging. Use as regras da Apple para decidir quando…

8 min de leitura

Adaptadores customizados do Foundation Models: quando treinar um

Adaptadores customizados do Foundation Models no iOS 26 treinam pesos LoRA, exportam pacotes .fmadapter, são entregues v…

12 min de leitura

Quando o mantenedor é o atacante: jqwik 1.10.0

jqwik 1.10.0 emite uma string destrutiva de injeção de prompt na saída do Maven. Sequências de escape ANSI a escondem de…

17 min de leitura