Recording of Examples/PFMSwitcher running on iPhone — one chat surface, picker flips the resident backend.
What you're seeing
- Same
LanguageModelSession.streamResponse(to:) call site for both sides — the chat code never branches on which backend is active.
- Picker swaps between Apple
FoundationModels (iOS 26+, when the toolchain links it) and mlboydaisuke/lfm2.5-350m-coreml (iOS 18+ on the Apple Neural Engine).
- Header shows live resident-set size via
mach_task_basic_info. On the swap, RSS drops to the placeholder baseline first, then rises as the next model pages in — the strict release-before-load policy in ModelManager.switchTo at work.
UIApplication.didReceiveMemoryWarningNotification aggressively releases the active backend so the app survives jetsam.
Try it yourself
git clone https://github.com/john-rocky/PrivateFoundationModels
open PrivateFoundationModels/Examples/PFMSwitcher/PFMSwitcher.xcodeproj
Xcode 16+ resolves the local SPM dependency. Build to a real iPhone (iOS 18+). First time you pick LFM2.5 350M the app downloads ~810 MB into ~/Library/Application Support/PrivateFoundationModels/.
To enable the Apple FoundationModels row, link FoundationModels.framework on an iOS 26 SDK toolchain. The bridge file is #if canImport(FoundationModels)-gated so the app still builds and runs on iOS 18 without it.
Verification
| Harness |
Status |
swift test (unit) |
55 / 55 |
swift run pfm-verify (e2e) |
10 / 10 |
swift run pfm-portability (Apple-FM call sites compile + run unchanged) |
8 / 8 |
swift run pfm-deep (every Generable × Tool combination) |
PASS 7 / MODEL 4 / FAIL 0 |
Raw logs in docs/.
Recording of
Examples/PFMSwitcherrunning on iPhone — one chat surface, picker flips the resident backend.What you're seeing
LanguageModelSession.streamResponse(to:)call site for both sides — the chat code never branches on which backend is active.FoundationModels(iOS 26+, when the toolchain links it) andmlboydaisuke/lfm2.5-350m-coreml(iOS 18+ on the Apple Neural Engine).mach_task_basic_info. On the swap, RSS drops to the placeholder baseline first, then rises as the next model pages in — the strict release-before-load policy inModelManager.switchToat work.UIApplication.didReceiveMemoryWarningNotificationaggressively releases the active backend so the app survives jetsam.Try it yourself
Xcode 16+ resolves the local SPM dependency. Build to a real iPhone (iOS 18+). First time you pick LFM2.5 350M the app downloads ~810 MB into
~/Library/Application Support/PrivateFoundationModels/.To enable the Apple FoundationModels row, link
FoundationModels.frameworkon an iOS 26 SDK toolchain. The bridge file is#if canImport(FoundationModels)-gated so the app still builds and runs on iOS 18 without it.Verification
swift test(unit)swift run pfm-verify(e2e)swift run pfm-portability(Apple-FM call sites compile + run unchanged)swift run pfm-deep(every Generable × Tool combination)Raw logs in
docs/.