关于 axiom-foundation-models-ref
为使用 Apple Foundation Models 框架的 Swift 开发者提供 API 参考,涵盖会话、结构化生成、流式输出和工具调用。内容还说明模型的设备端特性与适用任务。
主要功能
- 01LanguageModelSession 多轮会话
- 02@Generable 结构化输出
- 03流式生成与部分结果
- 04工具协议与会话集成
- 05Foundation Models 能力说明
适用场景
- 01实现设备端文本生成
- 02将模型输出映射为 Swift 类型
- 03让模型调用自定义工具
安装
复制下面的命令,在终端中运行。
npx skills add https:/ / github.com/ charleswiltgen/ axiom --skill axiom-foundation-models-ref安装后在 Claude Code 中输入/axiom-foundation-models-ref确认已加载。
详细介绍
Foundation Models 框架 — 完整 API 参考
概述
Foundation Models 框架通过 Swift API 提供对 Apple 端侧大模型的访问(30 亿参数,2 位量化)。本参考涵盖所有 API、WWDC 2025 的全部代码示例以及全面的实现模式。
模型规格
30 亿参数模型,2 位量化,上下文长度为 4096 个 token(输入和输出合计)。针对端侧摘要、提取、分类和生成进行优化。不适用于世界知识、复杂推理、数学或翻译。完全在设备端运行——无需网络、没有成本、数据不会离开设备。
何时使用本参考
在以下情况下使用本参考:
- 实现 Foundation Models 功能
- 了解 API 功能
- 查找特定代码示例
- 使用 Foundation Models 规划架构
- 从原型迁移到生产环境
- 调试实现问题
相关技能:
axiom-foundation-models— 规范技能,包含反模式、压力场景和决策树axiom-foundation-models-diag— 用于排查问题的诊断技能
LanguageModelSession
概述
LanguageModelSession 是与模型交互的核心类。它会维护对话历史记录(transcript)、处理多轮交互并管理模型状态。
创建会话
基本创建:
import FoundationModels
let session = LanguageModelSession()
使用自定义指令:
let session = LanguageModelSession(instructions: """
You are a friendly barista in a pixel art coffee shop.
Respond to the player's question concisely.
"""
)
来自 WWDC 301:1:05
使用工具:
let session = LanguageModelSession(
tools: [GetWeatherTool()],
instructions: "Help user with weather forecasts."
)
来自 WWDC 286:15:03
指定模型 / 使用场景:
let session = LanguageModelSession(
model: SystemLanguageModel(useCase: .contentTagging)
)
来自 WWDC 286:18:39
指令与提示词
指令:
- 来自开发者
- 定义模型的角色、风格和约束
- 大多是静态内容
- 是 transcript 中的第一项
- 模型经过训练,会优先遵循指令而非提示词(安全功能)
提示词:
- 来自用户(或动态应用状态)
- 针对生成的具体请求
- 动态输入
- 每次调用
respond(to:)都会向 transcript 添加提示词
安全注意事项:
- 绝不要将不可信的用户输入插入指令
- 用户输入只能放在提示词中
- 这样可防止提示词注入攻击
respond(to:) 方法
基本文本生成:
func respond(userInput: String) async throws -> String {
let session = LanguageModelSession(instructions: """
You are a friendly barista in a world full of pixels.
Respond to the player's question.
"""
)
let response = try await session.respond(to: userInput)
return response.content
}
来自 WWDC 301:1:05
返回类型:Response<String>,包含 .content 属性
respond(to:generating:) 方法
使用 @Generable 生成结构化输出:
@Generable
struct SearchSuggestions {
@Guide(description: "A list of suggested search terms", .count(4))
var searchTerms: [String]
}
let prompt = """
Generate a list of suggested search terms for an app about visiting famous landmarks.
"""
let response = try await session.respond(
to: prompt,
generating: SearchSuggestions.self
)
print(response.content) // SearchSuggestions instance
来自 WWDC 286:5:51
返回类型:Response<SearchSuggestions>,包含 .content 属性
生成选项
有关 GenerationOptions 的 sampling:、temperature: 和 includeSchemaInPrompt:,请参阅采样与生成选项。
多轮交互
保留上下文
let session = LanguageModelSession()
// First turn
let firstHaiku = try await session.respond(to: "Write a haiku about fishing")
print(firstHaiku.content)
// Silent waters gleam,
// Casting lines in morning mist—
// Hope in every cast.
// Second turn - model remembers context
let secondHaiku = try await session.respond(to: "Do another one about golf")
print(secondHaiku.content)
// Silent morning dew,
// Caddies guide with gentle words—
// Paths of patience tread.
print(session.transcript) // Shows full history
来自 WWDC 286:17:46
工作原理:
- 每次调用
respond()都会向 transcript 添加条目 - 模型会使用整个 transcript 作为上下文
- 支持对话式交互
Transcript 属性
let transcript = session.transcript
for entry in transcript.entries {
print("Entry: \(entry.content)")
}
使用场景:
- 调试生成问题
- 在 UI 中显示对话历史
- 导出聊天记录
- 精简内容以管理上下文
isResponding 属性
使用 session.isResponding 控制 UI,防止并发请求:
Button("Go!") {
Task { haiku = try await session.respond(to: prompt).content }
}
.disabled(session.isResponding)
来自 WWDC 286:18:22
@Generable 宏
概述
@Generable 可通过 Swift 类型启用模型结构化输出。该宏会在编译时生成 schema,并使用约束解码来确保结构正确。
基本用法
用于结构体:
@Generable
struct Person {
let name: String
let age: Int
}
let response = try await session.respond(
to: "Generate a person",
generating: Person.self
)
let person = response.content // Type-safe Person instance
来自 WWDC 301:8:14
用于枚举:
@Generable
struct NPC {
let name: String
let encounter: Encounter
@Generable
enum Encounter {
case orderCoffee(String)
case wantToTalkToManager(complaint: String)
}
}
来自 WWDC 301:10:49
支持的类型
基本类型:
StringInt、Float、Double、DecimalBool
集合:
[ElementType](数组)
组合类型:
@Generable
struct Itinerary {
var destination: String
var days: Int
var budget: Float
var rating: Double
var requiresVisa: Bool
var activities: [String]
var emergencyContact: Person
var relatedItineraries: [Itinerary] // Recursive!
}
来自 WWDC 286:6:18
@Guide 约束
@Guide 用于约束生成的属性。支持 description:(自然语言)、.range()(数值范围)、.count() / .maximumCount()(数组长度)和 Regex(模式匹配)。
@Generable
struct NPC {
@Guide(description: "A full name")
let name: String
@Guide(.range(1...10))
let level: Int
@Guide(.count(3))
let attributes: [String]
}
来自 WWDC 301:11:20
受约束解码
工作原理:
@Generable宏在编译时生成架构- 架构定义有效的词元序列
- 生成过程中,模型会为下一个词元创建概率分布
- 框架根据架构屏蔽无效词元
- 模型只能选择符合架构的词元
- 保证结构正确,不会出现幻觉键或无效 JSON
来自 WWDC 286:“受约束解码可以避免结构错误。模型无法生成无效字段名称或错误类型。”
优点:
- 无需编写解析代码
- 不会发生运行时解析错误
- 类型安全的 Swift 对象
- 编译时安全(结构体的更改会被编译器捕获)
属性声明顺序
生成的属性顺序与声明顺序一致:
@Generable
struct Itinerary {
var name: String // Generated FIRST
var days: [DayPlan] // Generated SECOND
var summary: String // Generated LAST
}
重要原因:
- 后续属性可以引用前面的属性
- 提升模型质量:在内容之后生成摘要
- 改善流式传输体验:优先生成重要属性
来自 WWDC 286:11:00
流式传输
概述
Foundation Models 使用快照流式传输(而非增量流式传输)。框架不会流式传输原始增量,而是流式传输带有可选属性的 PartiallyGenerated 类型,这些属性会逐步填充。
PartiallyGenerated 类型
@Generable 宏会自动创建一个嵌套的 PartiallyGenerated 类型:
@Generable
struct Itinerary {
var name: String
var days: [DayPlan]
}
// Compiler generates:
extension Itinerary {
struct PartiallyGenerated {
var name: String? // All properties optional!
var days: [DayPlan]?
}
}
来自 WWDC 286:9:20
streamResponse 方法
@Generable
struct Itinerary {
var name: String
var days: [Day]
}
let stream = session.streamResponse(
to: "Craft a 3-day itinerary to Mt. Fuji.",
generating: Itinerary.self
)
for try await partial in stream {
print(partial) // Incrementally updated Itinerary.PartiallyGenerated
}
来自 WWDC 286:9:40
返回类型:AsyncSequence<Itinerary.PartiallyGenerated>
SwiftUI 集成
struct ItineraryView: View {
let session: LanguageModelSession
let dayCount: Int
let landmarkName: String
@State
private var itinerary: Itinerary.PartiallyGenerated?
var body: some View {
VStack {
if let name = itinerary?.name {
Text(name).font(.title)
}
if let days = itinerary?.days {
ForEach(days, id: \.self) { day in
DayView(day: day)
}
}
Button("Start") {
Task {
do {
let prompt = """
Generate a \(dayCount) itinerary \
to \(landmarkName).
"""
let stream = session.streamResponse(
to: prompt,
generating: Itinerary.self
)
for try await partial in stream {
self.itinerary = partial
}
} catch {
print(error)
}
}
}
}
}
}
来自 WWDC 286:10:05
最佳实践
1. 使用 SwiftUI 动画:
if let name = itinerary?.name {
Text(name)
.transition(.opacity)
}
2. 数组的视图标识:
// ✅ GOOD - Stable identity
ForEach(days, id: \.id) { day in
DayView(day: day)
}
// ❌ BAD - Identity changes
ForEach(days.indices, id: \.self) { index in
DayView(day: days[index])
}
3. 优化属性顺序:
// ✅ GOOD - Title first for streaming
@Generable
struct Article {
var title: String // Shows immediately
var summary: String // Shows second
var fullText: String // Shows last
}
来自 WWDC 286:11:00
工具协议
概述
工具可让模型自主执行你的自定义代码,以获取外部数据或执行操作。工具可以与 MapKit、WeatherKit、Contacts、EventKit 或任何自定义 API 集成。
协议定义
protocol Tool {
var name: String { get }
var description: String { get }
associatedtype Arguments: Generable
func call(arguments: Arguments) async throws -> ToolOutput
}
示例:GetWeatherTool
import FoundationModels
import WeatherKit
import CoreLocation
struct GetWeatherTool: Tool {
let name = "getWeather"
let description = "Retrieve the latest weather information for a city"
@Generable
struct Arguments {
@Guide(description: "The city to fetch the weather for")
var city: String
}
func call(arguments: Arguments) async throws -> ToolOutput {
let places = try await CLGeocoder().geocodeAddressString(arguments.city)
let weather = try await WeatherService.shared.weather(for: places.first!.location!)
let temperature = weather.currentWeather.temperature.value
let content = GeneratedContent(properties: ["temperature": temperature])
let output = ToolOutput(content)
// Or if your tool's output is natural language:
// let output = ToolOutput("\(arguments.city)'s temperature is \(temperature) degrees.")
return output
}
}
来自 WWDC 286:13:42
将工具附加到会话
let session = LanguageModelSession(
tools: [GetWeatherTool()],
instructions: "Help the user with weather forecasts."
)
let response = try await session.respond(
to: "What is the temperature in Cupertino?"
)
print(response.content)
// It's 71˚F in Cupertino!
来自 WWDC 286:15:03
工作原理:
- 使用工具初始化会话
- 用户提示词:“东京的天气怎么样?”
- 模型分析提示词,判断需要天气数据
- 模型生成工具调用:
getWeather(city: "Tokyo") - 框架调用
call()方法 - 你的代码从 API 获取真实数据
- 工具输出插入对话记录
- 模型使用工具输出生成最终回答
来自 WWDC 301:“模型会自主决定何时以及调用工具的频率。每次请求可以调用多个工具,甚至并行调用。”
有状态工具
使用 class 而非 struct,即可在多次工具调用之间保留状态。工具实例会在整个会话生命周期内持续存在,因此可以实现追踪之前返回结果等模式:
class FindContactTool: Tool {
let name = "findContact"
let description = "Finds a contact from a specified age generation."
var pickedContacts = Set<String>()
@Generable
struct Arguments {
let generation: Generation
@Generable
enum Generation { case babyBoomers, genX, millennial, genZ }
}
func call(arguments: Arguments) async throws -> ToolOutput {
// Fetch, filter out already-picked, return new contact
pickedContacts.insert(pickedContact.givenName)
return ToolOutput(pickedContact.givenName)
}
}
来自 WWDC 301:18:47、301:21:55
ToolOutput
两种形式:
- 自然语言(String):
return ToolOutput("Temperature is 71°F")
- 结构化(GeneratedContent):
let content = GeneratedContent(properties: ["temperature": 71])
return ToolOutput(content)
工具命名最佳实践
推荐做法:
- 名称简短易读:
getWeather、findContact - 使用动词:
get、find、fetch、create - 描述用一句话概括
- 描述保持简洁(它们会包含在提示词中)
避免做法:
- 使用缩写:
gtWthr - 在描述中写入实现细节
- 描述过长(会增加词元数量)
来自 WWDC 301:“工具名称和描述会原样放入提示词。字符串越长,词元就越多,从而增加延迟。”
多个工具
let session = LanguageModelSession(
tools: [
GetWeatherTool(),
FindRestaurantTool(),
FindHotelTool()
],
instructions: "Plan travel itineraries."
)
// Model autonomously decides which tools to call and when
工具调用行为
关键事实:
- 每个请求可以调用工具多次
- 可以并行调用多个工具
- 由模型决定何时调用(不保证一定会调用)
- 通过 @Generable 保证参数有效
来自 WWDC 301:“并行调用工具时,你的调用方法可能会并发执行。访问数据时请牢记这一点。”
动态 Schema
概述
DynamicGenerationSchema 支持在运行时而非编译时创建 Schema。适用于用户定义的结构、关卡创建工具或动态表单。
创建和使用动态 Schema
使用 DynamicGenerationSchema.Property 构建属性,将其组合成 Schema,然后使用 GenerationSchema 进行验证:
// Build schema at runtime
let questionProp = DynamicGenerationSchema.Property(
name: "question", schema: DynamicGenerationSchema(type: String.self)
)
let answersProp = DynamicGenerationSchema.Property(
name: "answers", schema: DynamicGenerationSchema(
arrayOf: DynamicGenerationSchema(referenceTo: "Answer")
)
)
let riddleSchema = DynamicGenerationSchema(name: "Riddle", properties: [questionProp, answersProp])
let answerSchema = DynamicGenerationSchema(name: "Answer", properties: [/* text, isCorrect */])
// Validate and use
let schema = try GenerationSchema(root: riddleSchema, dependencies: [answerSchema])
let response = try await session.respond(to: "Generate a riddle", schema: schema)
let question = try response.content.value(String.self, forProperty: "question")
来自 WWDC 301:14:50、301:15:10
动态 Schema 与静态 @Generable
以下情况使用 @Generable:
- 结构在编译时已知
- 需要类型安全
- 需要自动解析
以下情况使用动态 Schema:
- 结构仅在运行时已知
- 用户定义的 Schema
- 需要最大灵活性
来自 WWDC 301:“编译时的 @Generable 提供类型安全。动态 Schema 提供运行时灵活性。两者都能保证使用受约束的解码。”
采样与生成选项
贪心(确定性)——用于测试和演示。仅在同一模型版本内具有确定性:
let response = try await session.respond(
to: prompt,
options: GenerationOptions(sampling: .greedy)
)
温度——控制变化程度。0.1-0.5 表示更聚焦,1.0 为默认值,1.5-2.0 更具创造性:
let response = try await session.respond(
to: prompt,
options: GenerationOptions(temperature: 0.5)
)
来自 WWDC 301:6:14
内置用例
内容标记适配器
专用适配器,适用于:
- 生成标签
- 提取实体
- 检测主题
@Generable
struct Result {
let topics: [String]
}
let session = LanguageModelSession(
model: SystemLanguageModel(useCase: .contentTagging)
)
let response = try await session.respond(
to: articleText,
generating: Result.self
)
来自 WWDC 286:19:19
自定义用例
使用自定义指令:
@Generable
struct Top3ActionEmotionResult {
@Guide(.maximumCount(3))
let actions: [String]
@Guide(.maximumCount(3))
let emotions: [String]
}
let session = LanguageModelSession(
model: SystemLanguageModel(useCase: .contentTagging),
instructions: "Tag the 3 most important actions and emotions in the given input text."
)
let response = try await session.respond(
to: text,
generating: Top3ActionEmotionResult.self
)
来自 WWDC 286:19:35
错误处理
GenerationError 类型
捕获 LanguageModelSession.GenerationError 的各种情况:
.exceededContextWindowSize— 超出上下文限制(4096 个 token)。精简对话记录或创建新会话。.guardrailViolation— 触发内容策略。显示合适的提示信息。.unsupportedLanguageOrLocale— 不支持该语言。检查supportedLanguages。
来自 WWDC 301:3:37、301:7:06
上下文窗口管理
策略 1:新建会话
var session = LanguageModelSession()
do {
let response = try await session.respond(to: prompt)
print(response.content)
} catch LanguageModelSession.GenerationError.exceededContextWindowSize {
// New session, no history
session = LanguageModelSession()
}
来自 WWDC 301:3:37
策略 2:精简会话
do {
let response = try await session.respond(to: prompt)
} catch LanguageModelSession.GenerationError.exceededContextWindowSize {
// New session with some history
session = newSession(previousSession: session)
}
private func newSession(previousSession: LanguageModelSession) -> LanguageModelSession {
let allEntries = previousSession.transcript.entries
var condensedEntries = [Transcript.Entry]()
if let firstEntry = allEntries.first {
condensedEntries.append(firstEntry) // Instructions
if allEntries.count > 1, let lastEntry = allEntries.last {
condensedEntries.append(lastEntry) // Recent context
}
}
let condensedTranscript = Transcript(entries: condensedEntries)
// Note: transcript includes instructions
return LanguageModelSession(transcript: condensedTranscript)
}
来自 WWDC 301:3:55
回退架构
当 Foundation Models 不可用时(设备较旧、用户选择退出或所在地区不受支持),应提供平稳降级方案:
func summarize(_ text: String) async throws -> String {
let model = SystemLanguageModel.default
switch model.availability {
case .available:
let session = LanguageModelSession()
let response = try await session.respond(to: "Summarize: \(text)")
return response.content
case .unavailable:
// Fallback: truncate with ellipsis, or call server API
return String(text.prefix(200)) + "..."
}
}
架构模式:在协议后封装 Foundation Models,以便切换实现:
protocol TextSummarizer {
func summarize(_ text: String) async throws -> String
}
struct OnDeviceSummarizer: TextSummarizer { /* Foundation Models */ }
struct ServerSummarizer: TextSummarizer { /* Server API fallback */ }
struct TruncationSummarizer: TextSummarizer { /* Simple truncation */ }
嵌套 @Generable 故障排查
嵌套的 @Generable 类型必须各自独立遵循 @Generable:
// ✅ Both types marked @Generable
@Generable struct Itinerary {
var days: [DayPlan]
}
@Generable struct DayPlan {
var activities: [String]
}
// ❌ Will fail — nested type not @Generable
@Generable struct Itinerary {
var days: [DayPlan] // DayPlan must also be @Generable
}
struct DayPlan { var activities: [String] }
常见问题:非 Generable 类型的数组可以通过编译,但在运行时会失败。请检查类型关系图中的所有类型。
可用性
检查可用性
struct AvailabilityExample: View {
private let model = SystemLanguageModel.default
var body: some View {
switch model.availability {
case .available:
Text("Model is available").foregroundStyle(.green)
case .unavailable(let reason):
Text("Model is unavailable").foregroundStyle(.red)
Text("Reason: \(reason)")
}
}
}
来自 WWDC 286:19:56
支持的语言
let supportedLanguages = SystemLanguageModel.default.supportedLanguages
guard supportedLanguages.contains(Locale.current.language) else {
// Show message
return
}
来自 WWDC 301:7:06
要求
设备要求:
- 支持 Apple Intelligence 的设备
- iPhone 15 Pro 或更新机型
- 配备 M1 或更新芯片的 iPad
- 搭载 Apple 芯片的 Mac
地区要求:
- 位于支持的地区(查看 Apple Intelligence 的可用性)
用户要求:
- 用户已在“设置”中选择启用 Apple Intelligence
性能与分析
Foundation Models Instruments
访问方式:Instruments 应用 → Foundation Models 模板
指标:
- 模型初始加载时间
- Token 数量(输入/输出)
- 每个请求的生成时间
- 延迟细分
- 优化机会
来自 WWDC 286:“新的 Instruments 性能分析模板可帮助你观察可优化之处并量化改进效果。”
优化:预热
问题:首次请求需要 1-2 秒加载模型
解决方案:在用户交互之前创建会话
class ViewModel: ObservableObject {
private var session: LanguageModelSession?
init() {
// Prewarm on init
Task {
self.session = LanguageModelSession(instructions: "...")
}
}
func generate(prompt: String) async throws -> String {
let response = try await session!.respond(to: prompt)
return response.content
}
}
来自 WWDC 259:“在用户交互之前预热会话,可降低初始延迟。”
节省时间:首次生成可节省 1-2 秒
优化:includeSchemaInPrompt
问题:大型 @Generable 架构会增加 token 数量
解决方案:后续请求跳过架构插入
// First request - schema inserted
let first = try await session.respond(
to: "Generate first person",
generating: Person.self
)
// Subsequent requests - skip schema
let second = try await session.respond(
to: "Generate another person",
generating: Person.self,
options: GenerationOptions(includeSchemaInPrompt: false)
)
摘自 WWDC 259:“将 includeSchemaInPrompt 设为 false,可减少后续请求的 token 数量并降低延迟。”
节省时间:每个请求可节省 10–20%
优化:属性顺序
在 @Generable 结构体中,优先声明重要属性。使用流式传输时,如果标题先于全文显示,感知到的延迟会从 2.5 秒降至 0.2 秒。示例请参阅流式传输最佳实践。
反馈与分析
LanguageModelFeedbackAttachment 可让你通过 Feedback Assistant 向 Apple 报告模型质量问题。使用 input、output、sentiment(.positive/.negative)、issues(类别 + 说明)和 desiredOutputExamples 创建附件。将其编码为 JSON,并附加到 Feedback Assistant 报告中。
摘自 WWDC 286:22:13
Xcode Playgrounds
概述
Xcode Playgrounds 可让你快速迭代提示词,而无需重新构建整个应用。
基本用法
import FoundationModels
import Playgrounds
#Playground {
let session = LanguageModelSession()
let response = try await session.respond(
to: "What's a good name for a trip to Japan? Respond only with a title"
)
}
摘自 WWDC 286:2:28
Playgrounds 还可以访问应用中定义的类型(例如 @Generable 结构体)。
API 快速参考
LanguageModelSession— 主要接口:respond(to:)→Response<String>、respond(to:generating:)→Response<T>、streamResponse(to:generating:)→AsyncSequence<T.PartiallyGenerated>。属性:transcript、isResponding。SystemLanguageModel—default.availability(.available/.unavailable(reason))、default.supportedLanguages、init(useCase:)GenerationOptions—sampling(.greedy/.random)、temperature、includeSchemaInPrompt@Generable— 启用结构化输出和受约束解码的宏@Guide— 属性约束:description:、.range()、.count()、.maximumCount()、RegexTool协议 —name、description、Arguments: Generable、call(arguments:) → ToolOutputDynamicGenerationSchema— 运行时架构定义,输出为GeneratedContentGenerationError—.exceededContextWindowSize、.guardrailViolation、.unsupportedLanguageOrLocale
迁移策略
从服务端大模型迁移
- 适合迁移的情况:需要隐私保护、需要离线使用、关注单次请求成本,且用例适用(摘要/提取/分类)
- 适合继续使用服务端的情况:需要世界知识、复杂推理,或超过 4096 token 的上下文
从手动 JSON 解析迁移
使用 @Generable 和 respond(to:generating:),而不是提示词要求输出 JSON 后再手动解析。完整迁移模式请参阅 axiom-foundation-models Scenario 2。
资源
WWDC:286、259、301
技能:axiom-foundation-models、axiom-foundation-models-diag
最后更新:2025-12-03 版本:1.0.0 技能类型:参考 内容:包含 WWDC 2025 的所有代码示例