Foundation Models 自定义适配器:Apple 不推荐的生命周期
SystemLanguageModel.Adapter 类型允许应用将自定义训练的权重加载到 Apple 的设备端语言模型中。1 框架支持它。Apple 提供了训练工具包。还有一份文档化的权益声明、一种 .fmadapter 包格式,以及 Background Assets 集成,用于为正确的设备下载正确的适配器。
Apple 自己关于同一类型的文档却原话写道:”适配器消耗大量存储空间,不推荐用于大多数应用。”1 本系列的前一篇文章 Foundation Models 用例 介绍了大多数应用应当走的常规轨道。本文则是第三轨:训练、打包和发布自定义适配器的运营生命周期,以及 Apple 关于何时不应这样做的明确指引。
TL;DR
- 自定义适配器是一个经过 LoRA 训练的权重矩阵,叠加在设备端系统语言模型之上。2 Apple 的工具包按名称确认了该技术。
- 每个适配器都绑定到单一的系统模型版本。当 Apple 更新基础模型时,您需要重新训练适配器。3
- Apple 的建议原话:”对于大多数提示词工程、引导式生成和工具调用,请使用基础系统模型。如果您需要专门化模型,请训练一个自定义适配器……仅当您熟悉用 Python 训练基础模型时才使用自定义适配器。”1
- 适配器资源较大(约 160 MB),通过 Background Assets 打包,并由权益声明(
com.apple.developer.foundation-model-adapter)门控,需由 Apple Developer Program 会员资格的账户持有人申请以用于部署。3 - 此路径对一小部分应用而言是合理的:那些希望在设备端复制经过微调的服务端 LLM 的应用、对样式/格式/策略遵循有严格要求的应用,或在目标任务上有文档化提示词工程上限的应用。2
适配器到底是什么
SystemLanguageModel.Adapter 是一个 struct,可在 iOS、iPadOS、Mac Catalyst、macOS 和 visionOS 上使用,均为 26.0+。4 Apple 对该类型的描述:
“对于大多数提示词工程、引导式生成和工具调用,请使用基础系统模型。如果您需要专门化模型,请训练一个自定义适配器以更改系统模型权重,并针对您的自定义任务进行优化。仅当您熟悉用 Python 训练基础模型时才使用自定义适配器。”4
该机制有据可查。Apple 的适配器训练指南直截了当地说:2
“系统模型采用一种参数高效微调(PEFT)方法,称为 LoRA(低秩适应)。在 LoRA 中,原始模型权重被冻结,称为’适配器’的小型可训练权重矩阵被嵌入到模型网络中。在训练期间,仅更新适配器权重,从而显著减少需要训练的参数数量。”
LoRA 是一项公开技术,有已发表的论文历史。5 Apple 的贡献在于工具包、.fmadapter 包格式、加载适配器的设备端运行时,以及通过 Background Assets 发布它的生命周期管线。
该类型的 API 表面
Adapter 结构体公开了一个小型表面:4
init(fileURL: URL) throws:”从文件 URL 创建适配器。”用于本地 Xcode 测试。init(name: String) throws:”创建从 background assets 框架下载的适配器。”用于生产环境。func compile() async throws:”在与 LanguageModelSession 一起使用之前准备适配器。如果您的适配器有草稿模型,应当调用此方法。”var creatorDefinedMetadata: [String : Any]:来自元数据中创建者自定义字段的值。static func removeObsoleteAdapters() throws:清除不再匹配当前系统模型的适配器。static func compatibleAdapterIdentifiers(name: String) -> [String]:获取兼容适配器资源包的 ID。enum AssetError:与资源相关失败的错误类型。
SystemLanguageModel 有一个配套的适配器初始化器:convenience init(adapter: SystemLanguageModel.Adapter, guardrails: SystemLanguageModel.Guardrails),描述为”使用适配器创建模型的基础版本”。6
仅用于部署的权益声明键是 com.apple.developer.foundation-model-adapter:”一个布尔值,指示应用是否可以为 Foundation Models 框架启用自定义适配器。”6 训练或本地 Xcode 测试不需要它;但在向 App Store 发布之前需要。3
Apple 的”何时考虑使用适配器”准则
工具包页面列出了具体的采纳信号:2
- “您拥有适合 LLM 使用的数据集”,或者您已经使用经过微调的服务端 LLM,并希望在设备端获得对等表现。
- “您需要让模型成为某个领域的专家。”
- “您需要让模型遵循特定的样式、格式或策略。”
- “提示词工程未能为您的任务实现所需的准确度或一致性。”
- “您希望降低推理延迟。如果您的提示词工程方案要求每次调用都使用带示例的冗长提示词,那么针对该任务专门化的适配器只需极少的提示词。”
同一指南还列出了您要承担的代价:2
- 一个由提示词与响应配对组成的数据集,展示您的目标技能。
- 一个评估适配器质量的流程。
- 一个从服务器将适配器加载到应用中的流程。
以及存储税:”每个适配器在您的应用中将占用大约 160 MB 的存储空间。与其他大型资源一样,适配器不应成为应用主包的一部分,因为多个适配器版本会让您的应用变得过大,让用户难以安装。”2
框架的建议在 Apple 的两处分别重申:默认选择提示词工程加上工具调用,仅在上述准则达成时才转向适配器。
训练,按 Apple 的方式
训练管线是 Python。Apple 的工具包提供示例代码、与特定系统模型版本匹配的模型资源、数据集工具,以及生成 .fmadapter 包的导出步骤。2
硬件要求:”搭载 Apple 芯片且内存至少 32GB 的 Mac,或 Linux GPU 机器。”Python 3.11 或更高版本。2
数据集形式:2
- 格式为 jsonl,包含
role("user"或"assistant")和content字段。 - 基本任务 100 至 1,000 个样本。
- 复杂任务 5,000+ 样本。
- 工具包中的
Schema.md涵盖完整 schema,包括引导式生成和 AI 安全钩子的字段。
Apple 关于数据质量的备注值得引用:”注重质量而非数量。一个由清晰、一致、结构良好的样本组成的较小数据集,可能比由嘈杂、低质量样本组成的较大数据集更有效。”2
训练通过工具包的 train_adapter 入口点调用:
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/
可选地,在训练适配器之后,您可以训练一个匹配的草稿模型。2 草稿模型是系统基础模型的较小版本,启用了推测解码,这是一种已发表的推理加速技术。7 Apple 的表述:”如果您选择不训练草稿模型,则您的适配器用例将无法使用推测解码。”2
单一版本约束
关于适配器最具运营影响力的事实是它与特定系统模型版本的绑定:3
“每个适配器仅与一个特定的系统模型版本兼容。您必须为每个新的基础模型版本训练新的适配器。如果您的应用在没有兼容适配器的情况下运行在用户的设备上,将发生运行时错误。”
工具包随模型版本一同更新。截至撰写时,Apple 已发布两个 beta 工具包版本(Beta 0.1.0 和 Beta 0.2.0,均已移除)和一个完整版本:26.0.0。2 Apple 的发布节奏声明:”每次系统模型更新都会发布新的工具包。系统模型在 iOS、macOS 和 visionOS 之间共享,系统模型更新将作为这些平台 OS 更新的一部分进行(不过并非每次 OS 更新都会包含模型更新)。”2
运营层面的含义:发布适配器的应用团队订阅了一个按 Apple 节奏运行的模型更新生命周期。每次基础模型升级都是重新训练、重新评估和重新发布的强制因素。
作为资源包打包
适配器文件足够大,以至于在应用中捆绑它被明确地劝阻。Apple 通过 Background Assets 路由适配器交付。3
工具包生成 .fmadapter 包,工具包还会将其打包为 Background Assets 资源包。Xcode 16 或更高版本中的 ba-package 命令行工具完成打包工作;工具包调用它。3
托管选择:3
- Apple 托管,受管理。 Apple 托管资源;操作系统管理下载生命周期。
- 自托管,受管理。 您在自己的服务器上托管;操作系统管理下载生命周期。
- 自托管,不受管理。 您自行托管和管理生命周期。
所需的 Info.plist 键因托管选择而异:3 Apple 托管受管理需要 BAHasManagedAssetPacks、BAAppGroupID 和 BAUsesAppleHosting;自托管受管理需要前两项;自托管不受管理无需任何键。每条路径还有一个由 Xcode 生成的资源下载器扩展目标。
在运行时选择正确的适配器
当资源下载器扩展的 BackgroundDownloadHandler.swift 生成时,Xcode 会接通一个 shouldDownload(_:) 回调。Apple 给出的适配器资源示例主体:3
func shouldDownload(_ assetPack: AssetPack) -> Bool {
if assetPack.id.hasPrefix("mygameshader") {
return true
}
return SystemLanguageModel.Adapter.isCompatible(assetPack)
}
SystemLanguageModel.Adapter.isCompatible(_:) 对于其适配器与当前系统模型匹配的资源包返回 true。同一回调也可以放行您的应用所需的非适配器资源。
加载和跟踪下载
资源到达设备后,加载路径为:3
SystemLanguageModel.Adapter.removeObsoleteAdapters()
let adapter = try SystemLanguageModel.Adapter(name: "myAdapter")
如果设备没有缓存兼容的适配器,构造会启动下载。Apple 关于 UX 的备注:”因为适配器的数据规模较大,下载可能需要一些时间,特别是在用户使用 Wi-Fi 或蜂窝网络时。如果用户没有网络连接,他们无法立即使用您的适配器。”3
状态序列来自 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: ...
}
}
}
五个文档化的 DownloadStatusUpdate 案例:.began、.paused、.downloading、.finished、.failed。3 框架的 @unknown default 分支是强制的,因为 Apple 可能在未来的 SDK 版本中添加案例。
状态达到 .finished 之后,适配器就可以接入会话:
let adaptedModel = SystemLanguageModel(adapter: adapter)
let session = LanguageModelSession(model: adaptedModel)
草稿模型及其速率限制
如果您的适配器附带了草稿模型,调用 adapter.compile() 会准备它以供使用。Apple 的文档将其作为单独的、计算成本高昂的步骤标出:3
“设备首次下载新版本适配器时,对
compile()的调用会完整编译您的草稿模型并将其保存到设备。在后续启动应用时,对compile()的调用会检查是否存在已保存的已编译草稿模型,如果存在则立即返回它。”
存在已发布的速率限制:3
“速率限制保护所有应用和进程之间共享的设备资源。如果框架确定需要新的编译,它会在所有平台(macOS 除外)上限制编译过程,每个应用每天最多三次草稿模型编译。”
macOS 例外这一点很有意思;该限制适用于 iOS、iPadOS 和 visionOS。Apple 建议在由 Background Tasks 调度的任务内运行编译,这样工作就不会阻塞应用启动。3
一个开发陷阱:”每次通过 Xcode 启动应用时,完整的编译过程都会运行,因为 Xcode 为每次启动分配新的 UUID。如果在测试应用时收到速率限制错误,请在 Xcode 中停止应用并重新启动它,以重置速率计数器。”3
测试与模拟器约束
适配器测试需要物理设备。Apple 明确表示:”适配器测试需要物理设备,模拟器不支持。”3
在 Xcode 中本地测试时,您从文件 URL 而非名称初始化:3
let localURL = URL(filePath: "absolute/path/to/my_adapter.fmadapter")
let adapter = try SystemLanguageModel.Adapter(fileURL: localURL)
Apple 的模式:导入本地文件用于测试,然后在发布应用之前从项目中移除它,因为适配器文件太大无法捆绑。3
此路径在运营层面的代价
将生命周期串起来看,发布自定义适配器的应用需要承担:
- Python 训练基础设施。 至少一台搭载 Apple 芯片且具备 32 GB 内存的 Mac,或一台 Linux GPU 机器。2
- 按 Apple 节奏的重新训练周期。 每次系统模型更新都意味着新的适配器和新的工具包版本。3
- 一套服务栈。 通过 App Store Connect 的 Apple 托管资源包,或您自己运行资源下载器集成的服务器。3
- 存储中的版本特定适配器。 多个基础模型版本同时存在意味着托管多个适配器,由设备拉取匹配的那个。3
- 权益声明门控。 由您的 Apple Developer Program 会员资格的账户持有人申请;未经批准无法发布。2
- 每个适配器版本 160 MB 的代价。 不在应用主包中,但下载后会存在用户设备上。2
- 物理设备测试。 模拟器不运行适配器。3
这就是其运营成本的简单形态。当采纳信号达成时,收益是:设备端模型针对您的任务变得专门化,仅需极少提示词,延迟更低,无每次调用的 API 成本,并且数据完全本地化。对于已经为微调的服务端推理付费、并希望获得设备端对等性的应用而言,这是简明的权衡。
要点
- 适配器就是 LoRA,按 Apple 文档化的技术。 冻结的基础权重,模型网络中的小型可训练矩阵,训练期间仅更新适配器权重。2
- 每个系统模型版本对应一个适配器,无例外。 规划与 OS 发布挂钩的重新训练。3
.fmadapter流程是端到端的。 用 Python 训练,用工具包打包,作为 Background Assets 资源包托管,在应用中按名称加载,在后台任务中编译草稿模型。- Apple 自己建议大多数应用不要走这条路。 Apple 的两份独立文档页面对大多数用例劝阻使用。1 阅读工具包页面上的准则;默认答案是”否”。
- 在硬件上测试。 模拟器不运行适配器。围绕物理设备会话和
Background Tasks框架的编译时段构建测试方案。
完整的 Apple 生态系统系列:内置专门化的决策准则;框架核心的 Tool 协议;应用内与工具 LLM 之间的智能体工作流分割;用于更广泛路由问题的 App Intents 与 MCP。中心入口在 Apple 生态系统系列。关于更广泛的 iOS 与 AI 智能体上下文,请参阅 iOS 智能体开发指南。
FAQ
我如何知道我的应用是否真的需要自定义适配器?
阅读 Apple 工具包指南中的”何时考虑使用适配器”部分。2 信号包括:您希望在设备端镜像的现有微调服务端 LLM、文档化的提示词工程准确度上限、对特定样式/格式/策略遵循的硬性要求,或仅靠提示词工程无法满足的延迟目标。大多数应用都不满足任何一项,Apple 也是这么说的。
权益声明实际门控的是什么?
部署,而非训练。Apple 的文档明确表示:”您不需要此权益声明来训练或本地测试适配器。”3 您的 Apple Developer Program 会员资格的账户持有人从 Foundation Models Framework Adapter Entitlement 页面申请 com.apple.developer.foundation-model-adapter,该权益声明清除了向 App Store 发布的路径。2
适配器有多大,存放在哪里?
Apple 给出的数字:”每个适配器在您的应用中将占用大约 160 MB 的存储空间。”2 适配器不存放在应用主包中。Apple 通过 Background Assets 路由它们,托管在 Apple 服务器(受管理)或您自己的服务器(受管理或不受管理)上,设备下载与其当前系统模型匹配的版本。3
Apple 更新基础模型时会发生什么?
您需要重新训练。文档原文:”每个适配器仅与一个特定的系统模型版本兼容。您必须为每个新的基础模型版本训练新的适配器。如果您的应用在没有兼容适配器的情况下运行在用户的设备上,将发生运行时错误。”3 实际操作中,您的服务栈并发托管多个适配器版本,设备根据 isCompatible(_:) 拉取正确的那个。
适配器与 .contentTagging 是什么关系?
.contentTagging 是 Apple 提供的两个 SystemLanguageModel.UseCase 静态属性之一,配套文章 中已介绍。它是 Apple 管理的专门化,无权益声明门控,包含在框架中。自定义 Adapter 是针对 Apple 用例未涵盖任务的开发者管理的等价物。Apple 的文档在描述 .contentTagging 内部如何工作时使用了”适配的”一词,但这与正式的 Adapter 类型不同。本文涵盖的是正式类型。
我必须训练草稿模型吗?
不。Apple 的文档:”如果您选择不训练草稿模型,则您的适配器用例将无法使用推测解码。”2 适配器仍会加载和服务;您只是无法获得推测解码的推理加速。草稿模型是可选的第二轮训练。
参考
-
Apple Developer,“SystemLanguageModel.Adapter”。类型描述、不建议大多数应用使用的提示、”仅当您熟悉用 Python 训练基础模型时才使用自定义适配器”。检索于 2026-05-04。 ↩↩↩↩
-
Apple Developer,“Get started with Foundation Models adapter training”。工具包概述、LoRA 机制、硬件要求、数据集形式、训练 CLI、草稿模型选项、工具包版本表、权益申请流程。检索于 2026-05-04。 ↩↩↩↩↩↩↩↩↩↩↩↩↩↩↩↩↩↩↩↩↩↩
-
Apple Developer,“Loading and using a custom adapter with Foundation Models”。资源包托管、Info.plist 键、
shouldDownload(_:)示例、状态序列、速率限制、模拟器例外、单一版本兼容性约束。检索于 2026-05-04。 ↩↩↩↩↩↩↩↩↩↩↩↩↩↩↩↩↩↩↩↩↩↩↩↩↩↩↩↩ -
Apple Developer,“SystemLanguageModel.Adapter”。结构体 API 表面:
init(fileURL:)、init(name:)、compile()、creatorDefinedMetadata、removeObsoleteAdapters()、compatibleAdapterIdentifiers(name:)、AssetError。检索于 2026-05-04。 ↩↩↩ -
Hu 等,“LoRA: Low-Rank Adaptation of Large Language Models”,arXiv:2106.09685。Apple 所采用技术所引用的原始 LoRA 论文。 ↩
-
Apple Developer,“SystemLanguageModel”。
init(adapter:guardrails:)便捷初始化器和com.apple.developer.foundation-model-adapter权益声明描述。检索于 2026-05-04。 ↩↩ -
Leviathan 等,“Fast Inference from Transformers via Speculative Decoding”,arXiv:2211.17192,以及 Chen 等,“Accelerating Large Language Model Decoding with Speculative Sampling”,arXiv:2302.01318。Apple 草稿模型所采用的推测解码技术,由适配器训练指南直接引用。 ↩