← Todos os Posts

Adaptadores Customizados do Foundation Models: O Ciclo de Vida que a Apple Recomenda Evitar

O tipo SystemLanguageModel.Adapter permite que um app carregue pesos treinados de forma customizada no modelo de linguagem on-device da Apple.1 O framework dá suporte a isso. A Apple disponibiliza um kit de treinamento. Existe um entitlement documentado, um formato de pacote .fmadapter e uma integração com Background Assets para baixar o adaptador certo para o dispositivo certo.

A própria documentação da Apple sobre esse mesmo tipo também afirma, citando literalmente: “Adaptadores consomem uma grande quantidade de espaço de armazenamento e não são recomendados para a maioria dos apps.”1 O post anterior deste cluster, Casos de Uso do Foundation Models, abordou os trilhos pelos quais a maioria dos apps deveria seguir. Este post é o terceiro trilho: o ciclo de vida operacional de treinar, empacotar e distribuir um adaptador customizado, e a orientação explícita da Apple sobre quando não fazer isso.

TL;DR

  • Um adaptador customizado é uma matriz de pesos treinada com LoRA que se sobrepõe ao modelo de linguagem do sistema on-device.2 O kit de ferramentas da Apple confirma a técnica pelo nome.
  • Cada adaptador está vinculado a uma única versão do modelo do sistema. Quando a Apple atualiza o modelo base, você retreina o adaptador.3
  • A recomendação da Apple, em suas palavras: “Use o modelo do sistema base para a maior parte da prompt engineering, geração guiada e ferramentas. Se você precisar especializar o modelo, treine um Adapter customizado… Use adaptadores customizados apenas se você estiver confortável em treinar foundation models em Python.”1
  • Os assets dos adaptadores são grandes (~160 MB), empacotados via Background Assets e protegidos por um entitlement (com.apple.developer.foundation-model-adapter) que o Account Holder de uma assinatura do Apple Developer Program solicita para deployment.3
  • O caminho faz sentido para um conjunto restrito de apps: aqueles que replicam um LLM server-side com fine-tuning no dispositivo, aqueles com requisitos rigorosos de adesão a estilo/formato/política, ou aqueles com tetos documentados de prompt engineering em sua tarefa-alvo.2

O Que Um Adaptador Realmente É

SystemLanguageModel.Adapter é uma struct, disponível no iOS, iPadOS, Mac Catalyst, macOS e visionOS, todos 26.0+.4 A descrição da Apple sobre o tipo:

“Use o modelo do sistema base para a maior parte da prompt engineering, geração guiada e ferramentas. Se você precisar especializar o modelo, treine um Adapter customizado para alterar os pesos do modelo do sistema e otimizá-lo para sua tarefa customizada. Use adaptadores customizados apenas se você estiver confortável em treinar foundation models em Python.”4

O mecanismo está documentado. O guia de treinamento de adaptadores da Apple afirma diretamente:2

“O modelo do sistema usa uma abordagem de fine-tuning eficiente em parâmetros (PEFT) conhecida como LoRA (Low-Rank Adaptation). No LoRA, os pesos originais do modelo são congelados, e pequenas matrizes de pesos treináveis chamadas ‘adaptadores’ são incorporadas pela rede do modelo. Durante o treinamento, apenas os pesos do adaptador são atualizados, reduzindo significativamente o número de parâmetros a serem treinados.”

LoRA é uma técnica pública com um histórico de papers publicados.5 A contribuição da Apple é o kit de ferramentas, o formato de pacote .fmadapter, o runtime on-device que carrega o adaptador e a infraestrutura de ciclo de vida para distribuí-lo via Background Assets.

A Superfície de API do Tipo

A struct Adapter expõe uma superfície pequena:4

  • init(fileURL: URL) throws: “Cria um adaptador a partir do file URL.” Usado para testes locais no Xcode.
  • init(name: String) throws: “Cria um adaptador baixado pelo framework de background assets.” Usado em produção.
  • func compile() async throws: “Prepara um adaptador antes de ser usado com uma LanguageModelSession. Você deve chamar isso se seu adaptador tiver um draft model.”
  • var creatorDefinedMetadata: [String : Any]: valores do campo creator-defined dos metadados.
  • static func removeObsoleteAdapters() throws: limpa adaptadores que não correspondem mais a um modelo do sistema atual.
  • static func compatibleAdapterIdentifiers(name: String) -> [String]: busca os IDs dos asset packs de adaptadores compatíveis.
  • enum AssetError: tipo de erro para falhas relacionadas a assets.

SystemLanguageModel tem um inicializador pareado para adaptadores: convenience init(adapter: SystemLanguageModel.Adapter, guardrails: SystemLanguageModel.Guardrails), com a descrição “Cria a versão base do modelo com um adaptador.”6

A chave de entitlement exclusiva para deployment é com.apple.developer.foundation-model-adapter: “Um valor Boolean que indica se o app pode habilitar adaptadores customizados para o framework Foundation Models.”6 Você não precisa dela para treinamento ou para testes locais no Xcode; você precisa dela antes de publicar na App Store.3

A Régua “Quando Considerar um Adaptador” da Apple

A página do kit de ferramentas apresenta sinais concretos de adoção:2

  • “Você tem um dataset adequado para uso com um LLM” ou você já usa um LLM server-based com fine-tuning e quer paridade on-device.
  • “Você precisa que o modelo se torne um especialista no assunto.”
  • “Você precisa que o modelo siga um estilo, formato ou política específicos.”
  • “A prompt engineering não está atingindo a precisão ou consistência necessárias para sua tarefa.”
  • “Você quer menor latência na inferência. Se suas soluções baseadas em prompt engineering exigem prompts longos com exemplos para cada chamada, um adaptador especializado para essa tarefa oferece prompting mínimo.”

O mesmo guia também lista os custos que você assume:2

  • Um dataset de pares de prompt e resposta que demonstrem sua skill-alvo.
  • Um processo para avaliar a qualidade dos seus adaptadores.
  • Um processo para carregar seus adaptadores no seu app a partir de um servidor.

E o imposto de armazenamento: “Cada adaptador ocupará aproximadamente 160 MB de espaço de armazenamento no seu app. Como outros assets grandes, adaptadores não devem fazer parte do bundle principal do seu app porque, com várias versões de adaptadores, seu app ficará grande demais para que as pessoas o instalem.”2

A recomendação do framework, repetida pela Apple em dois lugares distintos, é seguir por padrão com prompt engineering e tool calling, e recorrer a adaptadores apenas quando a régua acima for atendida.

Treinamento, no Formato da Apple

O pipeline de treinamento é em Python. O kit de ferramentas da Apple traz código de exemplo, os assets do modelo correspondentes a uma versão específica do modelo do sistema, utilitários de dataset e o passo de export que produz um pacote .fmadapter.2

Requisitos de hardware: “Mac com Apple silicon e pelo menos 32GB de memória, ou máquinas Linux GPU.” Python 3.11 ou posterior.2

Formato do dataset:2

  • Formato é jsonl com campos role ("user" ou "assistant") e content.
  • 100 a 1.000 amostras para tarefas básicas.
  • 5.000+ amostras para tarefas complexas.
  • Um Schema.md no kit cobre o schema completo, incluindo campos para geração guiada e hooks de segurança de IA.

A nota da Apple sobre qualidade de dados merece ser citada: “Foque em qualidade em vez de quantidade. Um dataset menor com amostras claras, consistentes e bem estruturadas pode ser mais eficaz do que um dataset maior com amostras ruidosas e de baixa qualidade.”2

O treinamento é invocado a partir do entry point train_adapter do kit:

python -m examples.train_adapter \
  --train-data /path/to/train.jsonl \
  --eval-data /path/to/valid.jsonl \
  --epochs 5 \
  --learning-rate 1e-3 \
  --batch-size 4 \
  --checkpoint-dir /path/to/my_checkpoints/

Opcionalmente, após treinar o adaptador, você pode treinar um draft model correspondente.2 Um draft model é uma versão menor do modelo base do sistema que habilita speculative decoding, uma técnica publicada de aceleração de inferência.7 O enquadramento da Apple: “Se você optar por não treinar o draft model, o speculative decoding não estará disponível para o caso de uso do seu adaptador.”2

A Restrição de Versão Única

O fato mais consequente operacionalmente sobre adaptadores é o vínculo a uma versão específica do modelo do sistema:3

“Cada adaptador é compatível com uma única versão específica do modelo do sistema. Você deve treinar um novo adaptador para cada nova versão do modelo base. Um runtime error ocorre se seu app rodar no dispositivo de uma pessoa sem um adaptador compatível.”

O kit é versionado junto com o modelo. Até o momento da escrita, a Apple lançou duas versões beta do kit (Beta 0.1.0 e Beta 0.2.0, ambas removidas) e um release completo: 26.0.0.2 A declaração da Apple sobre a cadência de releases: “Um novo kit será lançado para cada atualização do modelo do sistema. O modelo do sistema é compartilhado entre iOS, macOS e visionOS, e atualizações do modelo do sistema ocorrerão como parte das atualizações de OS dessas plataformas (embora nem toda atualização de OS tenha uma atualização de modelo).”2

A implicação operacional: equipes de apps que distribuem adaptadores se inscrevem em um ciclo de vida de atualização de modelo que segue a cadência da Apple. Cada bump do modelo base é uma função forçante para retreinamento, reavaliação e republicação.

Empacotamento Como Asset Packs

O arquivo do adaptador é grande o suficiente para que o bundling no app seja explicitamente desencorajado. A Apple roteia a entrega de adaptadores via Background Assets.3

O kit produz pacotes .fmadapter, que o kit também empacota como asset packs do Background Assets. A ferramenta de linha de comando ba-package, do Xcode 16 ou posterior, faz o trabalho de empacotamento; o kit a invoca.3

Opções de hospedagem:3

  • Apple-Hosted, Managed. A Apple hospeda o asset; o OS gerencia o ciclo de vida do download.
  • Self-Hosted, Managed. Você hospeda no seu servidor; o OS gerencia o ciclo de vida do download.
  • Self-Hosted, Unmanaged. Você hospeda e gerencia o ciclo de vida você mesmo.

As chaves de Info.plist necessárias variam conforme a opção de hospedagem:3 Apple-Hosted Managed precisa de BAHasManagedAssetPacks, BAAppGroupID e BAUsesAppleHosting; Self-Hosted Managed precisa das duas primeiras; Self-Hosted Unmanaged não precisa de nenhuma. Cada caminho também tem um target de extensão asset-downloader que o Xcode gera.

Escolhendo o Adaptador Certo em Runtime

Quando o BackgroundDownloadHandler.swift da extensão asset-downloader é gerado, o Xcode conecta um callback shouldDownload(_:). O exemplo da Apple para assets de adaptador:3

func shouldDownload(_ assetPack: AssetPack) -> Bool {
    if assetPack.id.hasPrefix("mygameshader") {
        return true
    }
    return SystemLanguageModel.Adapter.isCompatible(assetPack)
}

SystemLanguageModel.Adapter.isCompatible(_:) retorna true para asset packs cujo adaptador corresponde ao modelo do sistema atual. O mesmo callback também pode passar adiante assets que não sejam adaptadores e que seu app precise.

Carregando e Acompanhando Downloads

Uma vez que o asset esteja no dispositivo, o caminho de carregamento é:3

SystemLanguageModel.Adapter.removeObsoleteAdapters()

let adapter = try SystemLanguageModel.Adapter(name: "myAdapter")

A construção dispara um download se o dispositivo não tiver um adaptador compatível em cache. Nota da Apple sobre UX: “Como adaptadores podem ter um tamanho de dados grande, eles podem demorar algum tempo para baixar, especialmente se a pessoa estiver em uma rede Wi-Fi ou celular. Se a pessoa não tiver conexão de rede, ela não poderá usar seu adaptador imediatamente.”3

A sequência de status vem do AssetPackManager:3

let assetpackIDList = SystemLanguageModel.Adapter.compatibleAdapterIdentifiers(name: name)
if let assetPackID = assetpackIDList.first {
    let statusUpdates = AssetPackManager.shared.statusUpdates(forAssetPackWithID: assetPackID)
    for await status in statusUpdates {
        switch status {
        case .began(let assetPack): ...
        case .paused(let assetPack): ...
        case .downloading(let assetPack, let progress): ...
        case .finished(let assetPack): ...
        case .failed(let assetPack, let error): ...
        @unknown default: ...
        }
    }
}

Os cinco casos documentados de DownloadStatusUpdate: .began, .paused, .downloading, .finished, .failed.3 O ramo @unknown default do framework é obrigatório porque a Apple pode adicionar casos em versões futuras do SDK.

Após o status atingir .finished, o adaptador está pronto para ser plugado em uma sessão:

let adaptedModel = SystemLanguageModel(adapter: adapter)
let session = LanguageModelSession(model: adaptedModel)

O Draft Model e seu Rate Limit

Se seu adaptador foi distribuído com um draft model, chamar adapter.compile() o prepara para uso. A documentação da Apple chama atenção para isso como um passo separado e computacionalmente caro:3

“Na primeira vez que um dispositivo baixa uma nova versão do seu adaptador, uma chamada a compile() compila completamente seu draft model e o salva no dispositivo. Em launches subsequentes do seu app, uma chamada a compile() verifica se há um draft model compilado salvo e o retorna imediatamente se ele existir.”

Há um rate limit publicado:3

“O rate limiting protege os recursos do dispositivo que são compartilhados entre todos os apps e processos. Se o framework determinar que uma nova compilação é necessária, ele aplica rate-limit ao processo de compilação em todas as plataformas, exceto macOS, em três compilações de draft model por app, por dia.”

A exclusão do macOS é interessante; o limite se aplica em iOS, iPadOS e visionOS. A Apple recomenda rodar a compilação dentro de uma task agendada via Background Tasks, para que o trabalho não bloqueie o launch do app.3

Uma pegadinha de desenvolvimento: “O processo de compilação completo roda toda vez que você inicia seu app pelo Xcode, porque o Xcode atribui ao seu app um novo UUID a cada launch. Se você receber um erro de rate-limiting enquanto testa seu app, pare seu app no Xcode e o reinicie para resetar o contador de rate.”3

Testes e a Restrição do Simulator

Testar adaptadores requer um dispositivo físico. A Apple é explícita: “Testar adaptadores requer um dispositivo físico e não é suportado no Simulator.”3

Para testes locais no Xcode, você inicializa a partir de um file URL em vez de um nome:3

let localURL = URL(filePath: "absolute/path/to/my_adapter.fmadapter")
let adapter = try SystemLanguageModel.Adapter(fileURL: localURL)

Padrão da Apple: importe o arquivo local para testes, depois remova-o do projeto antes de publicar o app, já que arquivos de adaptador são grandes demais para serem incluídos no bundle.3

O Que Esse Caminho Custa em Termos Operacionais

Juntando o ciclo de vida, um app que distribui um adaptador customizado se inscreve para:

  1. Infraestrutura de treinamento em Python. Um Mac com Apple silicon e 32 GB de memória no mínimo, ou uma máquina Linux GPU.2
  2. Uma cadência de retreinamento no relógio da Apple. Toda atualização do modelo do sistema significa um adaptador novo e uma versão nova do kit.3
  3. Uma stack de serving. Ou asset packs hospedados pela Apple via App Store Connect, ou seu próprio servidor rodando uma integração de asset-downloader.3
  4. Adaptadores por versão em armazenamento. Múltiplas versões do modelo base no campo significam múltiplos adaptadores hospedados, com o dispositivo puxando o que corresponde.3
  5. Um portão de entitlement. O Account Holder da sua assinatura do Apple Developer Program o solicita; você não pode publicar sem aprovação.2
  6. O imposto de 160 MB por versão de adaptador. Não no app bundle, mas no dispositivo do usuário após o download.2
  7. Testes em dispositivo físico. O Simulator não roda adaptadores.3

Esse é o custo operacional em forma direta. O benefício, quando os sinais de adoção estão alinhados, é: o modelo on-device se torna especializado para sua tarefa com prompting mínimo, menor latência, sem custo de API por chamada e localidade total dos dados. Para apps que já pagam por inferência server-side com fine-tuning e querem paridade on-device, esse é o trade-off em termos diretos.

Conclusões

  1. Adaptadores são LoRA, pela técnica documentada da Apple. Pesos base congelados, pequenas matrizes treináveis pela rede do modelo, apenas os pesos do adaptador são atualizados durante o treinamento.2
  2. Um adaptador por versão do modelo do sistema, sem exceções. Planeje retreinamento atrelado a releases do OS.3
  3. O fluxo .fmadapter é end-to-end. Treine em Python, empacote com o kit, hospede como asset pack do Background Assets, carregue por nome no seu app, compile o draft model em uma background task.
  4. A própria Apple recomenda que a maioria dos apps não siga esse caminho. Duas páginas distintas da documentação da Apple desencorajam isso para a maioria dos casos de uso.1 Leia a régua na página do kit; a resposta é “não” por padrão.
  5. Teste em hardware. O Simulator não roda adaptadores. Construa o plano de testes em torno de sessões em dispositivo físico e do slot de compilação do framework Background Tasks.

O cluster completo do Ecossistema Apple: a régua de decisão para especialização built-in; o Tool protocol no centro do framework; a divisão de workflow agêntico entre LLMs in-app e de tooling; App Intents vs MCP para a questão mais ampla de roteamento. O hub está na Série Apple Ecosystem. Para contexto mais amplo de iOS com agentes de IA, veja o guia de iOS Agent Development.

FAQ

Como sei se meu app realmente precisa de um adaptador customizado?

Leia a seção “When to consider an adapter” da Apple no guia do kit.2 Os sinais: um LLM server-side já existente com fine-tuning que você quer espelhar on-device, um teto documentado de prompt engineering em precisão, um requisito firme de adesão a estilo/formato/política específicos, ou uma meta de latência que prompt engineering sozinho não atinge. A maioria dos apps não atende a nenhum desses, e a Apple diz isso.

O que o entitlement de fato controla?

Deployment, não treinamento. A documentação da Apple afirma explicitamente: “Você não precisa desse entitlement para treinar ou testar localmente adaptadores.”3 O Account Holder da sua assinatura do Apple Developer Program solicita com.apple.developer.foundation-model-adapter na página Foundation Models Framework Adapter Entitlement, e o entitlement libera o caminho para publicar na App Store.2

Qual o tamanho dos adaptadores e onde eles ficam?

O número documentado pela Apple: “Cada adaptador ocupará aproximadamente 160 MB de espaço de armazenamento no seu app.”2 Adaptadores não ficam no app bundle. A Apple os roteia via Background Assets, hospedados nos servidores da Apple (managed) ou no seu próprio servidor (managed ou unmanaged), e o dispositivo baixa a versão que corresponde ao modelo do sistema atual.3

O que acontece quando a Apple atualiza o modelo base?

Você retreina. Da documentação: “Cada adaptador é compatível com uma única versão específica do modelo do sistema. Você deve treinar um novo adaptador para cada nova versão do modelo base. Um runtime error ocorre se seu app rodar no dispositivo de uma pessoa sem um adaptador compatível.”3 Na prática, sua stack de serving hospeda múltiplas versões de adaptador concorrentemente, e o dispositivo puxa a certa com base em isCompatible(_:).

Qual a relação entre adaptadores e .contentTagging?

.contentTagging é uma das duas propriedades estáticas de SystemLanguageModel.UseCase que a Apple disponibiliza, abordadas no post complementar. É uma especialização gerenciada pela Apple, sem entitlement, incluída no framework. Um Adapter customizado é o equivalente gerenciado pelo desenvolvedor para tarefas que os use cases da Apple não cobrem. A documentação da Apple usa a palavra “adapted” ao descrever como .contentTagging funciona internamente, mas isso não é o mesmo que o tipo formal Adapter. O tipo formal é o que este post cobre.

Tenho que treinar um draft model?

Não. Documentação da Apple: “Se você optar por não treinar o draft model, o speculative decoding não estará disponível para o caso de uso do seu adaptador.”2 O adaptador ainda carrega e serve; você simplesmente não recebe o speedup de inferência do speculative decoding. O draft model é um segundo passo opcional de treinamento.

Referências


  1. Apple Developer, “SystemLanguageModel.Adapter”. Descrição do tipo, recomendação contra uso para a maioria dos apps, “Use adaptadores customizados apenas se você estiver confortável em treinar foundation models em Python.” Acessado em 04-05-2026. 

  2. Apple Developer, “Get started with Foundation Models adapter training”. Visão geral do kit, mecanismo do LoRA, requisitos de hardware, formato do dataset, CLI de treinamento, opção de draft model, tabela de versões do kit, fluxo de solicitação de entitlement. Acessado em 04-05-2026. 

  3. Apple Developer, “Loading and using a custom adapter with Foundation Models”. Hospedagem de asset pack, chaves de Info.plist, exemplo de shouldDownload(_:), sequência de status, rate limiting, exclusão do Simulator, restrição de compatibilidade de versão única. Acessado em 04-05-2026. 

  4. Apple Developer, “SystemLanguageModel.Adapter”. Superfície de API da struct: init(fileURL:), init(name:), compile(), creatorDefinedMetadata, removeObsoleteAdapters(), compatibleAdapterIdentifiers(name:), AssetError. Acessado em 04-05-2026. 

  5. Hu et al., “LoRA: Low-Rank Adaptation of Large Language Models”, arXiv:2106.09685. O paper original do LoRA que a técnica usada pela Apple referencia. 

  6. Apple Developer, “SystemLanguageModel”. O inicializador de conveniência init(adapter:guardrails:) e a descrição do entitlement com.apple.developer.foundation-model-adapter. Acessado em 04-05-2026. 

  7. Leviathan et al., “Fast Inference from Transformers via Speculative Decoding”, arXiv:2211.17192, e Chen et al., “Accelerating Large Language Model Decoding with Speculative Sampling”, arXiv:2302.01318. A técnica de speculative decoding que o draft model da Apple usa, citada diretamente pelo guia de treinamento de adaptadores. 

Artigos relacionados

Foundation Models Use Cases: General vs Content Tagging

iOS 26 Foundation Models has .general and .contentTagging use cases. Use Apple's rules to decide when prompting beats sp…

9 min de leitura

Foundation Models On-Device LLM: The Tool Protocol

iOS 26's Foundation Models framework puts a 3B-parameter LLM on every Apple Intelligence device. The Tool protocol is th…

15 min de leitura

The Cleanup Layer Is the Real AI Agent Market

Charlie Labs pivoted from building agents to cleaning up after them. The AI agent market is moving from generation to pr…

15 min de leitura