Niestandardowe adaptery Foundation Models: cykl życia, którego Apple odradza
Typ SystemLanguageModel.Adapter umożliwia aplikacji wczytanie niestandardowo wytrenowanych wag do modelu językowego Apple działającego na urządzeniu.1 Framework to obsługuje. Apple udostępnia zestaw narzędzi treningowych. Istnieje udokumentowane uprawnienie, format pakietu .fmadapter oraz integracja z Background Assets pozwalająca pobrać odpowiedni adapter dla odpowiedniego urządzenia.
Własna dokumentacja Apple dotycząca tego samego typu zawiera również, cytując dosłownie: „Adapters consume a large amount of storage space and isn’t recommended for most apps.”1 Wcześniejszy artykuł w tym klastrze, Foundation Models Use Cases, omawiał ścieżki, którymi powinna podążać większość aplikacji. Niniejszy artykuł to trzecia szyna: operacyjny cykl życia trenowania, pakowania i wdrażania niestandardowego adaptera oraz wyraźne wskazówki Apple, kiedy tego nie robić.
TL;DR
- Niestandardowy adapter to macierz wag wytrenowana metodą LoRA, która nakłada się na systemowy model językowy działający na urządzeniu.2 Zestaw narzędzi Apple potwierdza tę technikę z nazwy.
- Każdy adapter jest powiązany z konkretną wersją modelu systemowego. Gdy Apple aktualizuje model bazowy, należy ponownie wytrenować adapter.3
- Rekomendacja Apple, w ich własnych słowach: „Use the base system model for most prompt engineering, guided generation, and tools. If you need to specialize the model, train a custom Adapter… Use custom adapters only if you’re comfortable training foundation models in Python.”1
- Zasoby adapterów są duże (~160 MB), dystrybuowane przez Background Assets i ograniczone uprawnieniem (
com.apple.developer.foundation-model-adapter), o które Account Holder członkostwa Apple Developer Program wnioskuje na potrzeby wdrożenia.3 - Ścieżka ta ma sens dla wąskiego zbioru aplikacji: takich, które replikują dostrojony serwerowy LLM na urządzeniu, takich, które mają ścisłe wymagania zgodności ze stylem, formatem lub polityką, lub takich, które mają udokumentowane ograniczenia inżynierii promptów na docelowym zadaniu.2
Czym właściwie jest adapter
SystemLanguageModel.Adapter to struct dostępny na iOS, iPadOS, Mac Catalyst, macOS i visionOS, wszystkich w wersji 26.0+.4 Opis tego typu według Apple:
„Use the base system model for most prompt engineering, guided generation, and tools. If you need to specialize the model, train a custom Adapter to alter the system model weights and optimize it for your custom task. Use custom adapters only if you’re comfortable training foundation models in Python.”4
Mechanizm jest udokumentowany. Przewodnik Apple dotyczący trenowania adapterów stwierdza to wprost:2
„The system model uses a parameter-efficient fine-tuning (PEFT) approach known as LoRA (Low-Rank Adaptation). In LoRA, the original model weights are frozen, and small trainable weight matrices called ‘adapters’ are embedded through the model’s network. During training, only adapter weights are updated, significantly reducing the number of parameters to train.”
LoRA to publiczna technika z opublikowaną historią prac naukowych.5 Wkład Apple to zestaw narzędzi, format pakietu .fmadapter, środowisko uruchomieniowe na urządzeniu wczytujące adapter oraz infrastruktura cyklu życia umożliwiająca dostarczanie go przez Background Assets.
Powierzchnia API tego typu
Struktura Adapter udostępnia niewielką powierzchnię:4
init(fileURL: URL) throws: „Creates an adapter from the file URL.” Używane do lokalnego testowania w Xcode.init(name: String) throws: „Creates an adapter downloaded from the background assets framework.” Używane w środowisku produkcyjnym.func compile() async throws: „Prepares an adapter before being used with a LanguageModelSession. You should call this if your adapter has a draft model.”var creatorDefinedMetadata: [String : Any]: wartości z pola metadanych zdefiniowanego przez twórcę.static func removeObsoleteAdapters() throws: usuwa adaptery, które nie pasują już do bieżącego modelu systemowego.static func compatibleAdapterIdentifiers(name: String) -> [String]: pobiera identyfikatory kompatybilnych pakietów zasobów adapterów.enum AssetError: typ błędu dla niepowodzeń związanych z zasobami.
SystemLanguageModel ma sparowany inicjalizator dla adapterów: convenience init(adapter: SystemLanguageModel.Adapter, guardrails: SystemLanguageModel.Guardrails), z opisem „Creates the base version of the model with an adapter.”6
Klucz uprawnienia wymagany wyłącznie przy wdrożeniu to com.apple.developer.foundation-model-adapter: „A Boolean value that indicates whether the app can enable custom adapters for the Foundation Models framework.”6 Nie jest on potrzebny do trenowania ani do lokalnego testowania w Xcode; jest natomiast wymagany przed wysyłką do App Store.3
Kryteria Apple „kiedy rozważyć adapter”
Strona zestawu narzędzi przedstawia konkretne sygnały adopcji:2
- „You have a dataset suitable for use with an LLM” lub używają już Państwo dostrojonego serwerowego LLM i zależy Państwu na parytecie na urządzeniu.
- „You need the model to become a subject-matter expert.”
- „You need the model to adhere to a specific style, format, or policy.”
- „Prompt engineering isn’t achieving the required accuracy or consistency for your task.”
- „You want lower latency at inference. If your prompt-engineered solutions require lengthy prompts with examples for every call, an adapter specialized for that task offers minimal prompting.”
Ten sam przewodnik wymienia również koszty, które należy ponieść:2
- Zbiór danych par prompt-odpowiedź demonstrujących docelową umiejętność.
- Proces oceny jakości adapterów.
- Proces wczytywania adapterów do aplikacji z serwera.
Oraz podatek za przechowywanie: „Each adapter will take approximately 160 MB of storage space in your app. Like other big assets, adapters shouldn’t be part of your app’s main bundle because with multiple adapter versions your app will become too big for people to install.”2
Rekomendacja frameworka, powtórzona przez Apple w dwóch oddzielnych miejscach, brzmi: domyślnie należy stosować inżynierię promptów wraz z wywoływaniem narzędzi, a po adaptery sięgać tylko wtedy, gdy powyższe kryteria są spełnione.
Trenowanie w wydaniu Apple
Pipeline treningowy jest oparty na Python. Zestaw narzędzi Apple zawiera przykładowy kod, zasoby modelu pasujące do konkretnej wersji modelu systemowego, narzędzia do obsługi zbiorów danych oraz krok eksportu, który tworzy pakiet .fmadapter.2
Wymagania sprzętowe: „Mac with Apple silicon and at least 32GB memory, or Linux GPU machines.” Python 3.11 lub nowszy.2
Format zbioru danych:2
- Format jsonl z polami
role("user"lub"assistant") orazcontent. - Od 100 do 1 000 próbek dla podstawowych zadań.
- 5 000+ próbek dla złożonych zadań.
- Plik
Schema.mdw zestawie narzędzi obejmuje pełen schemat, łącznie z polami dla generowania kierowanego oraz haków bezpieczeństwa AI.
Uwaga Apple dotycząca jakości danych warta jest zacytowania: „Focus on quality over quantity. A smaller dataset of clear, consistent, and well-structured samples may be more effective than larger dataset of noisy, low-quality samples.”2
Trenowanie uruchamiane jest z punktu wejścia train_adapter zestawu narzędzi:
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/
Opcjonalnie, po wytrenowaniu adaptera, można wytrenować pasujący draft model.2 Draft model to mniejsza wersja systemowego modelu bazowego, która umożliwia speculative decoding — opublikowaną technikę przyspieszania wnioskowania.7 Sformułowanie Apple: „If you choose not to train the draft model, speculative decoding will not be available for your adapter’s use case.”2
Ograniczenie pojedynczej wersji
Najbardziej istotnym operacyjnie faktem dotyczącym adapterów jest powiązanie z konkretną wersją modelu systemowego:3
„Each adapter is compatible with a single specific system model version. You must train a new adapter for every new base model version. A runtime error occurs if your app runs on a person’s device without a compatible adapter.”
Zestaw narzędzi jest wersjonowany wraz z modelem. W chwili pisania tego artykułu Apple wydało dwie wersje beta zestawu narzędzi (Beta 0.1.0 i Beta 0.2.0, obie wycofane) oraz jedno pełne wydanie: 26.0.0.2 Stanowisko Apple dotyczące cykliczności wydań: „A new toolkit will be released for every system model update. The system model is shared across iOS, macOS, and visionOS, and system model updates will occur as part of those platforms’ OS updates (though not every OS update will have a model update).”2
Konsekwencja operacyjna: zespoły aplikacji wdrażające adaptery podpisują się pod cyklem życia aktualizacji modelu zgodnym z rytmem Apple. Każda aktualizacja modelu bazowego stanowi czynnik wymuszający ponowne trenowanie, ponowną ewaluację oraz ponowną publikację.
Pakowanie jako asset packs
Plik adaptera jest na tyle duży, że dołączanie go do aplikacji jest jawnie odradzane. Apple kieruje dostarczanie adapterów przez Background Assets.3
Zestaw narzędzi tworzy pakiety .fmadapter, które są przez niego również pakowane jako Background Assets asset packs. Narzędzie wiersza poleceń ba-package z Xcode 16 lub nowszego wykonuje pracę pakowania; zestaw narzędzi je wywołuje.3
Opcje hostingu:3
- Apple-Hosted, Managed. Apple hostuje zasób; system operacyjny zarządza cyklem życia pobierania.
- Self-Hosted, Managed. Zasób hostowany jest na własnym serwerze; system operacyjny zarządza cyklem życia pobierania.
- Self-Hosted, Unmanaged. Hosting i zarządzanie cyklem życia odbywa się we własnym zakresie.
Wymagane klucze Info.plist różnią się w zależności od opcji hostingu:3 Apple-Hosted Managed wymaga BAHasManagedAssetPacks, BAAppGroupID oraz BAUsesAppleHosting; Self-Hosted Managed wymaga pierwszych dwóch; Self-Hosted Unmanaged nie wymaga żadnego. Każda ścieżka posiada również cel rozszerzenia asset-downloader, który Xcode generuje automatycznie.
Wybór odpowiedniego adaptera w czasie wykonania
Gdy generowany jest plik BackgroundDownloadHandler.swift rozszerzenia asset-downloader, Xcode wpina callback shouldDownload(_:). Przykład Apple dla zasobów adapterów:3
func shouldDownload(_ assetPack: AssetPack) -> Bool {
if assetPack.id.hasPrefix("mygameshader") {
return true
}
return SystemLanguageModel.Adapter.isCompatible(assetPack)
}
SystemLanguageModel.Adapter.isCompatible(_:) zwraca true dla pakietów zasobów, których adapter pasuje do bieżącego modelu systemowego. Ten sam callback może również przepuszczać zasoby inne niż adaptery, których aplikacja potrzebuje.
Wczytywanie i śledzenie pobierania
Gdy zasób znajduje się już na urządzeniu, ścieżka wczytywania wygląda następująco:3
SystemLanguageModel.Adapter.removeObsoleteAdapters()
let adapter = try SystemLanguageModel.Adapter(name: "myAdapter")
Konstrukcja inicjuje pobieranie, jeśli urządzenie nie ma w pamięci podręcznej kompatybilnego adaptera. Uwaga Apple dotycząca UX: „Because adapters can have a large data size they can take some time to download, especially if a person is on Wi-Fi or a cell network. If a person doesn’t have a network connection, they aren’t able to use your adapter right away.”3
Sekwencja statusów pochodzi z 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: ...
}
}
}
Pięć udokumentowanych przypadków DownloadStatusUpdate: .began, .paused, .downloading, .finished, .failed.3 Gałąź @unknown default frameworka jest obowiązkowa, ponieważ Apple może dodać przypadki w przyszłych wersjach SDK.
Po osiągnięciu statusu .finished adapter jest gotowy do podpięcia do sesji:
let adaptedModel = SystemLanguageModel(adapter: adapter)
let session = LanguageModelSession(model: adaptedModel)
Draft model i jego ograniczenie częstotliwości
Jeśli adapter został dostarczony z draft model, wywołanie adapter.compile() przygotowuje go do użycia. Dokumentacja Apple wyodrębnia ten krok jako osobny i kosztowny obliczeniowo:3
„The first time a device downloads a new version of your adapter, a call to
compile()fully compiles your draft model and saves it to the device. During subsequent launches of your app, a call tocompile()checks for a saved compiled draft model and returns it immediately if it exists.”
Istnieje opublikowane ograniczenie częstotliwości:3
„Rate limiting protects device resources that are shared between all apps and processes. If the framework determines that a new compilation is necessary, it rate-limits the compilation process on all platforms, excluding macOS, to three draft model compilations per-app, per-day.”
Wyjątek dla macOS jest interesujący; limit obowiązuje na iOS, iPadOS i visionOS. Apple zaleca uruchamianie kompilacji w zadaniu zaplanowanym przez Background Tasks, aby praca nie blokowała uruchamiania aplikacji.3
Pułapka deweloperska: „The full compilation process runs every time you launch your app through Xcode because Xcode assigns your app a new UUID for every launch. If you receive a rate-limiting error while testing your app, stop your app in Xcode and re-launch it to reset the rate counter.”3
Testowanie i ograniczenie symulatora
Testowanie adapterów wymaga fizycznego urządzenia. Apple stwierdza to wprost: „Testing adapters requires a physical device and isn’t supported on Simulator.”3
Do lokalnego testowania w Xcode inicjalizacja odbywa się z URL pliku, a nie z nazwy:3
let localURL = URL(filePath: "absolute/path/to/my_adapter.fmadapter")
let adapter = try SystemLanguageModel.Adapter(fileURL: localURL)
Wzorzec Apple: zaimportować lokalny plik do testów, a następnie usunąć go z projektu przed publikacją aplikacji, ponieważ pliki adapterów są zbyt duże, aby je dołączać.3
Co ta ścieżka kosztuje w wymiarze operacyjnym
Składając razem cykl życia, aplikacja wdrażająca niestandardowy adapter zapisuje się na:
- Infrastrukturę treningową w Python. Mac z Apple silicon i co najmniej 32 GB pamięci jako minimum, ewentualnie maszyna GPU z systemem Linux.2
- Cykl ponownego trenowania zgodny z rytmem Apple. Każda aktualizacja modelu systemowego oznacza nowy adapter i nową wersję zestawu narzędzi.3
- Stos serwujący. Albo asset packs hostowane przez Apple poprzez App Store Connect, albo własny serwer z integracją asset-downloader.3
- Adaptery na każdą wersję w pamięci. Wiele wersji modelu bazowego w obiegu oznacza wiele hostowanych adapterów, a urządzenie pobiera ten pasujący.3
- Bramę uprawnień. Account Holder członkostwa Apple Developer Program wnioskuje o nie; nie da się wdrożyć bez zatwierdzenia.2
- Podatek 160 MB na wersję adaptera. Nie w pakiecie aplikacji, lecz na urządzeniu użytkownika po pobraniu.2
- Testowanie na fizycznym urządzeniu. Symulator nie uruchamia adapterów.3
Tak wygląda koszt operacyjny w prostej formie. Korzyść, gdy sygnały adopcji są jednoznaczne, jest następująca: model na urządzeniu staje się wyspecjalizowany pod dane zadanie przy minimalnej liczbie promptów, niższej latencji, bez kosztów API za wywołanie i z pełną lokalnością danych. Dla aplikacji, które już ponoszą koszty dostrojonego serwerowego wnioskowania i chcą uzyskać parytet na urządzeniu, jest to wymiana na takich właśnie warunkach.
Wnioski
- Adaptery to LoRA — zgodnie z udokumentowaną przez Apple techniką. Zamrożone wagi bazowe, małe trenowalne macierze przeplecione w sieci modelu, podczas trenowania aktualizowane są wyłącznie wagi adaptera.2
- Jeden adapter na wersję modelu systemowego — bez wyjątków. Należy planować ponowne trenowanie powiązane z wydaniami systemu operacyjnego.3
- Przepływ
.fmadapterjest kompletny. Trenowanie w Python, pakowanie zestawem narzędzi, hosting jako Background Assets asset pack, wczytanie po nazwie w aplikacji, kompilacja draft model w zadaniu w tle. - Apple samo zaleca, by większość aplikacji nie szła tą ścieżką. Dwie odrębne strony dokumentacji Apple odradzają to dla większości zastosowań.1 Warto przeczytać kryteria na stronie zestawu narzędzi; domyślną odpowiedzią jest „nie”.
- Testowanie odbywa się na sprzęcie. Symulator nie uruchamia adapterów. Plan testowy należy budować wokół sesji na fizycznych urządzeniach oraz slotu kompilacyjnego frameworka
Background Tasks.
Pełen klaster Apple Ecosystem: kryteria decyzyjne wbudowanej specjalizacji; protokół Tool w rdzeniu frameworka; podział agentowych przepływów pracy między LLMami w aplikacji a narzędziowymi; App Intents vs MCP w szerszym pytaniu o routing. Hub znajduje się w Apple Ecosystem Series. Szerszy kontekst iOS z agentami AI znajdą Państwo w iOS Agent Development guide.
FAQ
Skąd mam wiedzieć, czy moja aplikacja rzeczywiście potrzebuje niestandardowego adaptera?
Warto przeczytać sekcję „When to consider an adapter” w przewodniku zestawu narzędzi Apple.2 Sygnały: istniejący dostrojony serwerowy LLM, który chce się odzwierciedlić na urządzeniu, udokumentowany pułap inżynierii promptów dla dokładności, twarde wymaganie zgodności z konkretnym stylem, formatem lub polityką, lub cel latencji, którego sama inżynieria promptów nie osiąga. Większość aplikacji nie spełnia żadnego z nich i Apple to wprost stwierdza.
Co tak naprawdę kontroluje uprawnienie?
Wdrożenie, nie trenowanie. Dokumentacja Apple stwierdza wprost: „You don’t need this entitlement to train or locally test adapters.”3 Account Holder członkostwa Apple Developer Program wnioskuje o com.apple.developer.foundation-model-adapter ze strony Foundation Models Framework Adapter Entitlement, a uprawnienie odblokowuje ścieżkę wdrożenia do App Store.2
Jak duże są adaptery i gdzie się znajdują?
Liczba podana w dokumentacji Apple: „Each adapter will take approximately 160 MB of storage space in your app.”2 Adaptery nie znajdują się w pakiecie aplikacji. Apple kieruje je przez Background Assets, hostowane na serwerach Apple (managed) lub na własnym serwerze (managed lub unmanaged), a urządzenie pobiera wersję pasującą do swojego bieżącego modelu systemowego.3
Co się stanie, gdy Apple zaktualizuje model bazowy?
Należy ponownie wytrenować. Z dokumentacji: „Each adapter is compatible with a single specific system model version. You must train a new adapter for every new base model version. A runtime error occurs if your app runs on a person’s device without a compatible adapter.”3 W praktyce stos serwujący hostuje wiele wersji adapterów równocześnie, a urządzenie pobiera właściwą na podstawie isCompatible(_:).
Jaki jest związek między adapterami a .contentTagging?
.contentTagging to jedna z dwóch statycznych właściwości SystemLanguageModel.UseCase udostępnianych przez Apple, omówiona w artykule towarzyszącym. Jest to specjalizacja zarządzana przez Apple, niewymagająca żadnego uprawnienia, dołączona do frameworka. Niestandardowy Adapter to ekwiwalent zarządzany przez dewelopera dla zadań, których przypadki użycia Apple nie obejmują. Dokumentacja Apple używa słowa „adapted” przy opisie wewnętrznego działania .contentTagging, ale nie jest to to samo co formalny typ Adapter. Formalny typ jest tym, którym zajmuje się ten artykuł.
Czy muszę trenować draft model?
Nie. Dokumentacja Apple: „If you choose not to train the draft model, speculative decoding will not be available for your adapter’s use case.”2 Adapter nadal się wczytuje i obsługuje zapytania; po prostu nie uzyska się przyspieszenia wnioskowania dzięki speculative decoding. Draft model to opcjonalny drugi przebieg trenowania.
Odniesienia
-
Apple Developer, “SystemLanguageModel.Adapter”. Opis typu, rekomendacja przeciwko stosowaniu w większości aplikacji, „Use custom adapters only if you’re comfortable training foundation models in Python.” Pobrano 2026-05-04. ↩↩↩↩
-
Apple Developer, “Get started with Foundation Models adapter training”. Przegląd zestawu narzędzi, mechanizm LoRA, wymagania sprzętowe, format zbioru danych, CLI trenowania, opcja draft model, tabela wersji zestawu narzędzi, przepływ wnioskowania o uprawnienie. Pobrano 2026-05-04. ↩↩↩↩↩↩↩↩↩↩↩↩↩↩↩↩↩↩↩↩↩↩
-
Apple Developer, “Loading and using a custom adapter with Foundation Models”. Hosting asset pack, klucze Info.plist, przykład
shouldDownload(_:), sekwencja statusów, ograniczenie częstotliwości, wykluczenie symulatora, ograniczenie zgodności z pojedynczą wersją. Pobrano 2026-05-04. ↩↩↩↩↩↩↩↩↩↩↩↩↩↩↩↩↩↩↩↩↩↩↩↩↩↩↩↩ -
Apple Developer, “SystemLanguageModel.Adapter”. Powierzchnia API struktury:
init(fileURL:),init(name:),compile(),creatorDefinedMetadata,removeObsoleteAdapters(),compatibleAdapterIdentifiers(name:),AssetError. Pobrano 2026-05-04. ↩↩↩ -
Hu et al., “LoRA: Low-Rank Adaptation of Large Language Models”, arXiv:2106.09685. Oryginalna praca o LoRA, do której odwołuje się stosowana przez Apple technika. ↩
-
Apple Developer, “SystemLanguageModel”. Inicjalizator wygodny
init(adapter:guardrails:)oraz opis uprawnieniacom.apple.developer.foundation-model-adapter. Pobrano 2026-05-04. ↩↩ -
Leviathan et al., “Fast Inference from Transformers via Speculative Decoding”, arXiv:2211.17192, oraz Chen et al., “Accelerating Large Language Model Decoding with Speculative Sampling”, arXiv:2302.01318. Technika speculative decoding, której używa draft model Apple, cytowana bezpośrednio przez przewodnik trenowania adapterów. ↩