axiom-foundation-models-diag by charleswiltgen/axiom
npx skills add https://github.com/charleswiltgen/axiom --skill axiom-foundation-models-diag基础模型问题表现为上下文窗口超出错误、护栏违规、生成缓慢、可用性故障和意外输出。核心原则 80% 的基础模型问题源于对模型能力(30亿参数的设备级模型,不具备世界知识)、上下文限制(4096个令牌)或可用性要求的误解——而非框架错误。
如果您看到以下任何情况,请怀疑是基础模型理解问题,而非框架故障:
exceededContextWindowSizeguardrailViolationunsupportedLanguageOrLocale关键区别 基础模型是一个设备级模型(30亿参数),专为摘要、提取、分类优化——不具备世界知识或复杂推理能力。将其用于错误的任务必然导致糟糕的结果。
始终首先运行这些(在更改代码之前):
广告位招租
在这里展示您的产品或服务
触达数万 AI 开发者,精准高效
// 1. 检查可用性
let availability = SystemLanguageModel.default.availability
switch availability {
case .available:
print("✅ 可用")
case .unavailable(let reason):
print("❌ 不可用: \(reason)")
// 可能的原因:
// - 设备不支持 Apple Intelligence
// - 区域不受支持
// - 用户未选择加入
}
// 记录:"可用?是/否,如果不可用请说明原因"
// 2. 检查支持的语言
let supported = SystemLanguageModel.default.supportedLanguages
print("支持的语言: \(supported)")
print("当前区域设置: \(Locale.current.language)")
if !supported.contains(Locale.current.language) {
print("⚠️ 当前语言不受支持!")
}
// 记录:"语言支持?是/否"
// 3. 检查上下文使用情况
let session = LanguageModelSession()
// 经过一些交互后:
print("转录条目数: \(session.transcript.entries.count)")
// 粗略估计(不精确):
let transcriptText = session.transcript.entries
.map { $0.content }
.joined()
print("近似字符数: \(transcriptText.count)")
print("粗略令牌估计: \(transcriptText.count / 3)")
// 4096 令牌限制 ≈ 12,000 字符
// 记录:"接近上下文限制?是/否"
// 4. 使用 Instruments 分析
// 使用基础模型 Instrument 模板运行
// 检查:
// - 初始模型加载时间
// - 令牌计数(输入/输出)
// - 每个请求的生成时间
// - 优化领域
// 记录:"延迟分析:[来自 Instruments 的数字]"
// 5. 检查转录以进行调试
print("完整转录:")
for entry in session.transcript.entries {
print("条目: \(entry.content.prefix(100))...")
}
// 记录:"任何异常条目?重复内容?"
在更改任何代码之前,识别以下一项:
availability = .unavailable → 设备/区域/选择加入问题(非代码错误)exceededContextWindowSize → 令牌过多(压缩转录)guardrailViolation → 内容策略触发(非模型故障)unsupportedLanguageOrLocale → 语言不受支持(检查支持列表)respond() 调用添加详细日志记录基础模型问题?
│
├─ 无法启动?
│ ├─ .unavailable → 可用性问题
│ │ ├─ 设备不支持? → 模式 1a(设备要求)
│ │ ├─ 区域限制? → 模式 1b(区域可用性)
│ │ └─ 用户未选择加入? → 模式 1c(设置检查)
│ │
├─ 生成失败?
│ ├─ exceededContextWindowSize → 上下文限制
│ │ └─ 长对话或冗长提示? → 模式 2a(压缩)
│ │
│ ├─ guardrailViolation → 内容策略
│ │ └─ 敏感或不适当内容? → 模式 2b(优雅处理)
│ │
│ ├─ unsupportedLanguageOrLocale → 语言问题
│ │ └─ 非英语或不受支持的语言? → 模式 2c(语言检查)
│ │
│ └─ 其他错误 → 通用错误处理
│ └─ 未知错误类型? → 模式 2d(兜底处理)
│
├─ 输出错误?
│ ├─ 幻觉事实 → 错误模型使用
│ │ └─ 询问世界知识? → 模式 3a(用例不匹配)
│ │
│ ├─ 错误结构 → 解析问题
│ │ └─ 手动 JSON 解析? → 模式 3b(使用 @Generable)
│ │
│ ├─ 缺少数据 → 需要工具
│ │ └─ 需要外部信息? → 模式 3c(工具调用)
│ │
│ └─ 输出不一致 → 采样问题
│ └─ 每次结果不同? → 模式 3d(温度/贪婪)
│
├─ 太慢?
│ ├─ 初始延迟 (1-2s) → 模型加载
│ │ └─ 第一个请求慢? → 模式 4a(预热)
│ │
│ ├─ 结果等待时间长 → 未流式传输
│ │ └─ 用户等待 3-5s? → 模式 4b(流式传输)
│ │
│ ├─ 冗长模式 → 令牌开销
│ │ └─ 大型 @Generable 类型? → 模式 4c(includeSchemaInPrompt)
│ │
│ └─ 复杂提示 → 处理过多
│ └─ 大量提示或任务? → 模式 4d(分解)
│
└─ UI 冻结?
└─ 主线程阻塞 → 异步问题
└─ 生成期间应用无响应? → 模式 5a(Task {})
症状:
SystemLanguageModel.default.availability = .unavailable诊断:
let availability = SystemLanguageModel.default.availability
switch availability {
case .available:
print("✅ 可用")
case .unavailable(let reason):
print("❌ 原因: \(reason)")
// 检查是否与设备相关
}
修复:
// ❌ 错误 - 无可用性 UI
let session = LanguageModelSession() // 在不支持的设备上崩溃
// ✅ 正确 - 优雅的 UI
struct AIFeatureView: View {
@State private var availability = SystemLanguageModel.default.availability
var body: some View {
switch availability {
case .available:
AIContentView()
case .unavailable:
VStack {
Image(systemName: "cpu")
Text("AI 功能需要 Apple Intelligence")
.font(.headline)
Text("适用于 iPhone 15 Pro 及更高版本")
.font(.caption)
.foregroundColor(.secondary)
}
}
}
}
时间成本:5-10 分钟添加 UI
症状:
诊断:基础模型要求:
修复:
// ✅ 正确 - 清晰的消息
switch SystemLanguageModel.default.availability {
case .available:
// 继续
case .unavailable(let reason):
// 显示特定区域消息
Text("AI 功能在您所在的区域尚不可用")
Text("检查 设置 → Apple Intelligence 了解可用性")
}
时间成本:5 分钟
症状:
诊断:用户必须在设置中选择加入 Apple Intelligence
修复:
// ✅ 正确 - 引导用户前往设置
switch SystemLanguageModel.default.availability {
case .available:
// 继续
case .unavailable:
VStack {
Text("启用 Apple Intelligence")
Text("设置 → Apple Intelligence → 启用")
Button("打开设置") {
if let url = URL(string: UIApplication.openSettingsURLString) {
UIApplication.shared.open(url)
}
}
}
}
时间成本:10 分钟
症状:
Error: LanguageModelSession.GenerationError.exceededContextWindowSize
诊断:
修复:
// ❌ 错误 - 未处理的错误
let response = try await session.respond(to: prompt)
// 大约 10-15 轮后崩溃
// ✅ 正确 - 压缩转录
var session = LanguageModelSession()
do {
let response = try await session.respond(to: prompt)
} catch LanguageModelSession.GenerationError.exceededContextWindowSize {
// 压缩并继续
session = condensedSession(from: session)
let response = try await session.respond(to: prompt)
}
func condensedSession(from previous: LanguageModelSession) -> LanguageModelSession {
let entries = previous.transcript.entries
guard entries.count > 2 else {
return LanguageModelSession(transcript: previous.transcript)
}
// 保留:第一个(指令)+ 最后一个(最近上下文)
var condensed = [entries.first!, entries.last!]
let transcript = Transcript(entries: condensed)
return LanguageModelSession(transcript: transcript)
}
时间成本:15-20 分钟实现压缩
症状:
Error: LanguageModelSession.GenerationError.guardrailViolation
诊断:
修复:
// ✅ 正确 - 优雅处理
do {
let response = try await session.respond(to: userInput)
print(response.content)
} catch LanguageModelSession.GenerationError.guardrailViolation {
// 显示用户友好消息
print("我无法帮助处理该请求")
// 记录以供审查(但不要显示用户输入以避免存储有害内容)
}
时间成本:5-10 分钟
症状:
Error: LanguageModelSession.GenerationError.unsupportedLanguageOrLocale
诊断:用户输入的语言模型不支持
修复:
// ❌ 错误 - 无语言检查
let response = try await session.respond(to: userInput)
// 如果语言不受支持则崩溃
// ✅ 正确 - 首先检查
let supported = SystemLanguageModel.default.supportedLanguages
guard supported.contains(Locale.current.language) else {
// 显示免责声明
print("语言不受支持。当前支持:\(supported)")
return
}
// 同时处理错误
do {
let response = try await session.respond(to: userInput)
} catch LanguageModelSession.GenerationError.unsupportedLanguageOrLocale {
print("请使用英语或其他支持的语言")
}
时间成本:10 分钟
症状:未知错误类型
修复:
// ✅ 正确 - 全面的错误处理
do {
let response = try await session.respond(to: prompt)
print(response.content)
} catch LanguageModelSession.GenerationError.exceededContextWindowSize {
// 处理上下文溢出
session = condensedSession(from: session)
} catch LanguageModelSession.GenerationError.guardrailViolation {
// 处理内容策略
showMessage("无法生成该内容")
} catch LanguageModelSession.GenerationError.unsupportedLanguageOrLocale {
// 处理语言问题
showMessage("语言不受支持")
} catch {
// 兜底处理意外错误
print("意外错误: \(error)")
showMessage("出错了。请重试。")
}
时间成本:10-15 分钟
症状:
诊断:将模型用于世界知识(错误用例)
修复:
// ❌ 错误 - 错误用例
let prompt = "法国总统是谁?"
let response = try await session.respond(to: prompt)
// 将产生幻觉或给出过时信息
// ✅ 正确 - 使用服务器 LLM 获取世界知识
// 基础模型适用于:
// - 摘要
// - 提取
// - 分类
// - 内容生成
// 或者:使用工具调用外部数据源
struct GetFactTool: Tool {
let name = "getFact"
let description = "从已验证来源获取事实信息"
@Generable
struct Arguments {
let query: String
}
func call(arguments: Arguments) async throws -> ToolOutput {
// 从维基百科 API、新闻 API 等获取
let fact = await fetchFactFromAPI(arguments.query)
return ToolOutput(fact)
}
}
时间成本:20-30 分钟实现工具或切换到适当的 AI
症状:
诊断:手动 JSON 解析而非使用 @Generable
修复:
// ❌ 错误 - 手动解析
let prompt = "以 JSON 格式生成人员信息"
let response = try await session.respond(to: prompt)
let data = response.content.data(using: .utf8)!
let person = try JSONDecoder().decode(Person.self, from: data) // 崩溃
// ✅ 正确 - @Generable
@Generable
struct Person {
let name: String
let age: Int
}
let response = try await session.respond(
to: "生成一个人",
generating: Person.self
)
// response.content 是类型安全的 Person,保证结构
时间成本:10 分钟转换为 @Generable
症状:
诊断:需要外部数据(天气、位置、联系人)
修复:
// ❌ 错误 - 无外部数据
let response = try await session.respond(
to: "东京天气如何?"
)
// 将编造天气数据
// ✅ 正确 - 工具调用
import WeatherKit
struct GetWeatherTool: Tool {
let name = "getWeather"
let description = "获取城市的当前天气"
@Generable
struct Arguments {
let city: String
}
func call(arguments: Arguments) async throws -> ToolOutput {
// 获取真实天气
let weather = await WeatherService.shared.weather(for: arguments.city)
return ToolOutput("温度: \(weather.temperature)°F")
}
}
let session = LanguageModelSession(tools: [GetWeatherTool()])
let response = try await session.respond(to: "东京天气如何?")
// 使用真实天气数据
时间成本:20-30 分钟实现工具
症状:
诊断:随机采样(默认行为)
修复:
// 默认:随机采样
let response1 = try await session.respond(to: "写一首俳句")
let response2 = try await session.respond(to: "写一首俳句")
// 每次不同
// ✅ 用于确定性输出(测试/演示)
let response = try await session.respond(
to: "写一首俳句",
options: GenerationOptions(sampling: .greedy)
)
// 相同提示输出相同(给定相同模型版本)
// ✅ 用于低方差
let response = try await session.respond(
to: "分类这篇文章",
options: GenerationOptions(temperature: 0.5)
)
// 略有变化但集中
// ✅ 用于高创造力
let response = try await session.respond(
to: "写一个创意故事",
options: GenerationOptions(temperature: 2.0)
)
// 输出非常多样化
时间成本:2-5 分钟
症状:
诊断:模型加载时间
修复:
// ❌ 错误 - 用户交互时加载
Button("生成") {
Task {
let session = LanguageModelSession() // 此处有 1-2 秒延迟
let response = try await session.respond(to: prompt)
}
}
// ✅ 正确 - 初始化时预热
class ViewModel: ObservableObject {
private var session: LanguageModelSession?
init() {
// 用户交互前预热
Task {
self.session = LanguageModelSession(instructions: "...")
}
}
func generate(prompt: String) async throws -> String {
guard let session = session else {
// 如果未准备好则回退
self.session = LanguageModelSession()
return try await self.session!.respond(to: prompt).content
}
return try await session.respond(to: prompt).content
}
}
时间成本:10 分钟 节省的延迟:首次请求 1-2 秒
症状:
诊断:未流式传输长生成
修复:
// ❌ 错误 - 无流式传输
let response = try await session.respond(
to: "生成 5 天行程",
generating: Itinerary.self
)
// 用户等待 4 秒,什么也看不到
// ✅ 正确 - 流式传输
@Generable
struct Itinerary {
var destination: String
var days: [DayPlan]
}
let stream = session.streamResponse(
to: "生成前往东京的 5 天行程",
generating: Itinerary.self
)
for try await partial in stream {
// 增量更新 UI
self.itinerary = partial
}
// 用户在 0.5 秒内看到目的地,然后逐步看到天数
时间成本:15-20 分钟 感知延迟:0.5 秒 vs 4 秒
症状:
诊断:每次都将模式重新插入提示
修复:
// 第一个请求 - 自动插入模式
let first = try await session.respond(
to: "生成第一个人",
generating: Person.self
)
// ✅ 后续请求 - 跳过模式插入
let second = try await session.respond(
to: "生成另一个人",
generating: Person.self,
options: GenerationOptions(includeSchemaInPrompt: false)
)
时间成本:2 分钟 节省的延迟:每个请求 10-20%
症状:
诊断:提示对单次生成过于复杂
修复:
// ❌ 错误 - 一个巨大的提示
let prompt = """
生成包含酒店、餐厅、
活动、交通、预算、提示和当地习俗的完整 7 天行程
"""
// 5-8 秒,质量差
// ✅ 正确 - 分解为步骤
let overview = try await session.respond(
to: "为东京生成高级 7 天计划"
)
var dayDetails: [DayPlan] = []
for day in 1...7 {
let detail = try await session.respond(
to: "详细说明东京第 \(day) 天的活动和餐厅",
generating: DayPlan.self
)
dayDetails.append(detail.content)
}
// 总时间相似,但质量更好且结果逐步呈现
时间成本:20-30 分钟 质量改进:显著更好
症状:
诊断:在主线程上同步调用 respond()
修复:
// ❌ 错误 - 阻塞主线程
Button("生成") {
let response = try await session.respond(to: prompt)
// UI 冻结 2-5 秒!
}
// ✅ 正确 - 异步任务
Button("生成") {
Task {
do {
let response = try await session.respond(to: prompt)
// 在主线程上更新 UI
await MainActor.run {
self.result = response.content
}
} catch {
print("错误: \(error)")
}
}
}
时间成本:5 分钟 用户体验改进:巨大(无冻结 UI)
情况:您刚刚推出了一个使用基础模型的 AI 驱动功能。2 小时内:
压力信号:
不要陷入这些陷阱:
// 检查错误分布
// 看到每种错误的百分比是多少?
// 在测试设备上运行:
let availability = SystemLanguageModel.default.availability
switch availability {
case .available:
print("✅ 可用")
case .unavailable(let reason):
print("❌ 不可用: \(reason)")
}
// 假设:
// - 如果 20% 不可用 → 可用性问题(设备/区域/选择加入)
// - 如果 20% 遇到错误 → 代码错误
// - 如果 20% 看到错误结果 → 用例不匹配
结果:发现 20% 的用户设备不支持 Apple Intelligence。
// 检查哪些设备受影响
// iPhone 15 Pro+ = ✅ 可用
// iPhone 15 = ❌ 不可用
// iPhone 14 = ❌ 不可用
// 结论:可用性问题,非代码错误
根本原因:功能假设所有用户都有 Apple Intelligence。20% 的用户没有。
验证:
// ✅ 添加可用性检查 + 优雅的 UI
struct AIFeatureView: View {
@State private var availability = SystemLanguageModel.default.availability
var body: some View {
switch availability {
case .available:
// 显示 AI 功能
AIContentView()
case .unavailable:
// 优雅降级
VStack {
Image(systemName: "sparkles")
.font(.largeTitle)
.foregroundColor(.secondary)
Text("AI 驱动功能")
.font(.headline)
Text("适用于 iPhone 15 Pro 及更高版本")
.font(.subheadline)
.foregroundColor(.secondary)
.multilineTextAlignment(.center)
// 提供替代方案
Button("使用标准模式") {
// 显示非 AI 降级方案
}
}
}
}
}
致产品副总裁(立即):
已识别根本原因:
AI 功能需要 Apple Intelligence(iPhone 15 Pro+)。
20% 的用户使用旧设备。我们未检查可用性。
修复:添加了可用性检查并带有优雅降级 UI。
时间线:
- 热修复就绪:现在
- TestFlight:10 分钟
- App Store 提交:30 分钟
- 审核:24-48 小时(请求加急)
影响缓解:
- 80% 的用户看到正常工作的 AI 功能
- 20% 的用户看到清晰消息 + 标准模式降级
- 功能未丢失,只是优雅降级
致工程团队:
事后分析项目:
1. 将可用性检查添加到启动清单
2. 在非 Apple Intelligence 设备上测试
3. 清晰记录设备要求
4. 为可用性状态添加分析
| 症状 | 原因 | 检查 | 模式 | 时间 |
|---|---|---|---|---|
| 无法启动 | .unavailable | SystemLanguageModel.default.availability | 1a | 5 分钟 |
| 区域问题 | 不受支持的区域 | 检查支持的区域 | 1b | 5 分钟 |
| 未选择加入 | Apple Intelligence 已禁用 | 设置检查 | 1c | 10 分钟 |
| 上下文超出 | >4096 令牌 | 转录长度 | 2a | 15 分钟 |
| 护栏错误 | 内容策略 | 用户输入类型 | 2b | 10 分钟 |
| 语言错误 | 不支持的语言 | supportedLanguages | 2c | 10 分钟 |
| 幻觉输出 | 错误用例 | 任务类型检查 | 3a | 20 分钟 |
| 错误结构 | 无 @Generable | 手动解析? | 3b | 10 分钟 |
| 缺少数据 | 无工具 | 需要外部数据? | 3c | 30 分钟 |
| 不一致 | 随机采样 | 需要确定性? | 3d | 5 分钟 |
| 初始延迟 | 模型加载 | 第一个请求慢? | 4a | 10 分钟 |
| 等待时间长 | 无流式传输 | >1 秒生成? | 4b | 20 分钟 |
| 模式开销 | 重新插入模式 | 后续请求? | 4c | 2 分钟 |
| 复杂提示 | 一次处理过多 | >5 秒生成? | 4d | 30 分钟 |
| UI 冻结 | 主线程 | 线程检查 | 5a | 5 分钟 |
相关 Axiom Skills:
axiom-foundation-models — 反模式、正确使用模式、压力场景的学科技能axiom-foundation-models-ref — 包含所有 WWDC 2025 代码示例的完整 API 参考Apple 资源:
最后更新:2025-12-03 版本:1.0.0 技能类型:诊断
每周安装
100
仓库
GitHub 星标
606
首次出现
2026 年 1 月 21 日
安全审计
安装于
opencode85
codex79
claude-code79
gemini-cli78
cursor77
github-copilot73
Foundation Models issues manifest as context window exceeded errors, guardrail violations, slow generation, availability failures, and unexpected output. Core principle 80% of Foundation Models problems stem from misunderstanding model capabilities (3B parameter device-scale model, not world knowledge), context limits (4096 tokens), or availability requirements—not framework bugs.
If you see ANY of these, suspect a Foundation Models misunderstanding, not framework breakage:
exceededContextWindowSizeguardrailViolationunsupportedLanguageOrLocaleCritical distinction Foundation Models is a device-scale model (3B parameters) optimized for summarization, extraction, classification—NOT world knowledge or complex reasoning. Using it for the wrong task guarantees poor results.
ALWAYS run these FIRST (before changing code):
// 1. Check availability
let availability = SystemLanguageModel.default.availability
switch availability {
case .available:
print("✅ Available")
case .unavailable(let reason):
print("❌ Unavailable: \(reason)")
// Possible reasons:
// - Device not Apple Intelligence-capable
// - Region not supported
// - User not opted in
}
// Record: "Available? Yes/no, reason if not"
// 2. Check supported languages
let supported = SystemLanguageModel.default.supportedLanguages
print("Supported languages: \(supported)")
print("Current locale: \(Locale.current.language)")
if !supported.contains(Locale.current.language) {
print("⚠️ Current language not supported!")
}
// Record: "Language supported? Yes/no"
// 3. Check context usage
let session = LanguageModelSession()
// After some interactions:
print("Transcript entries: \(session.transcript.entries.count)")
// Rough estimation (not exact):
let transcriptText = session.transcript.entries
.map { $0.content }
.joined()
print("Approximate chars: \(transcriptText.count)")
print("Rough token estimate: \(transcriptText.count / 3)")
// 4096 token limit ≈ 12,000 characters
// Record: "Approaching context limit? Yes/no"
// 4. Profile with Instruments
// Run with Foundation Models Instrument template
// Check:
// - Initial model load time
// - Token counts (input/output)
// - Generation time per request
// - Areas for optimization
// Record: "Latency profile: [numbers from Instruments]"
// 5. Inspect transcript for debugging
print("Full transcript:")
for entry in session.transcript.entries {
print("Entry: \(entry.content.prefix(100))...")
}
// Record: "Any unusual entries? Repeated content?"
Before changing ANY code, identify ONE of these:
availability = .unavailable → Device/region/opt-in issue (not code bug)exceededContextWindowSize → Too many tokens (condense transcript)guardrailViolation → Content policy triggered (not model failure)unsupportedLanguageOrLocale → Language not supported (check supported list)respond() callFoundation Models problem?
│
├─ Won't start?
│ ├─ .unavailable → Availability issue
│ │ ├─ Device not capable? → Pattern 1a (device requirement)
│ │ ├─ Region restriction? → Pattern 1b (regional availability)
│ │ └─ User not opted in? → Pattern 1c (Settings check)
│ │
├─ Generation fails?
│ ├─ exceededContextWindowSize → Context limit
│ │ └─ Long conversation or verbose prompts? → Pattern 2a (condense)
│ │
│ ├─ guardrailViolation → Content policy
│ │ └─ Sensitive or inappropriate content? → Pattern 2b (handle gracefully)
│ │
│ ├─ unsupportedLanguageOrLocale → Language issue
│ │ └─ Non-English or unsupported language? → Pattern 2c (language check)
│ │
│ └─ Other error → General error handling
│ └─ Unknown error type? → Pattern 2d (catch-all)
│
├─ Output wrong?
│ ├─ Hallucinated facts → Wrong model use
│ │ └─ Asking for world knowledge? → Pattern 3a (use case mismatch)
│ │
│ ├─ Wrong structure → Parsing issue
│ │ └─ Manual JSON parsing? → Pattern 3b (use @Generable)
│ │
│ ├─ Missing data → Tool needed
│ │ └─ Need external information? → Pattern 3c (tool calling)
│ │
│ └─ Inconsistent output → Sampling issue
│ └─ Different results each time? → Pattern 3d (temperature/greedy)
│
├─ Too slow?
│ ├─ Initial delay (1-2s) → Model loading
│ │ └─ First request slow? → Pattern 4a (prewarm)
│ │
│ ├─ Long wait for results → Not streaming
│ │ └─ User waits 3-5s? → Pattern 4b (streaming)
│ │
│ ├─ Verbose schema → Token overhead
│ │ └─ Large @Generable type? → Pattern 4c (includeSchemaInPrompt)
│ │
│ └─ Complex prompt → Too much processing
│ └─ Massive prompt or task? → Pattern 4d (break down)
│
└─ UI frozen?
└─ Main thread blocked → Async issue
└─ App unresponsive during generation? → Pattern 5a (Task {})
Symptom :
SystemLanguageModel.default.availability = .unavailableDiagnosis :
let availability = SystemLanguageModel.default.availability
switch availability {
case .available:
print("✅ Available")
case .unavailable(let reason):
print("❌ Reason: \(reason)")
// Check if device-related
}
Fix :
// ❌ BAD - No availability UI
let session = LanguageModelSession() // Crashes on unsupported devices
// ✅ GOOD - Graceful UI
struct AIFeatureView: View {
@State private var availability = SystemLanguageModel.default.availability
var body: some View {
switch availability {
case .available:
AIContentView()
case .unavailable:
VStack {
Image(systemName: "cpu")
Text("AI features require Apple Intelligence")
.font(.headline)
Text("Available on iPhone 15 Pro and later")
.font(.caption)
.foregroundColor(.secondary)
}
}
}
}
Time cost : 5-10 minutes to add UI
Symptom :
Diagnosis : Foundation Models requires:
Fix :
// ✅ GOOD - Clear messaging
switch SystemLanguageModel.default.availability {
case .available:
// proceed
case .unavailable(let reason):
// Show region-specific message
Text("AI features not yet available in your region")
Text("Check Settings → Apple Intelligence for availability")
}
Time cost : 5 minutes
Symptom :
Diagnosis : User must opt in to Apple Intelligence in Settings
Fix :
// ✅ GOOD - Direct user to settings
switch SystemLanguageModel.default.availability {
case .available:
// proceed
case .unavailable:
VStack {
Text("Enable Apple Intelligence")
Text("Settings → Apple Intelligence → Enable")
Button("Open Settings") {
if let url = URL(string: UIApplication.openSettingsURLString) {
UIApplication.shared.open(url)
}
}
}
}
Time cost : 10 minutes
Symptom :
Error: LanguageModelSession.GenerationError.exceededContextWindowSize
Diagnosis :
Fix :
// ❌ BAD - Unhandled error
let response = try await session.respond(to: prompt)
// Crashes after ~10-15 turns
// ✅ GOOD - Condense transcript
var session = LanguageModelSession()
do {
let response = try await session.respond(to: prompt)
} catch LanguageModelSession.GenerationError.exceededContextWindowSize {
// Condense and continue
session = condensedSession(from: session)
let response = try await session.respond(to: prompt)
}
func condensedSession(from previous: LanguageModelSession) -> LanguageModelSession {
let entries = previous.transcript.entries
guard entries.count > 2 else {
return LanguageModelSession(transcript: previous.transcript)
}
// Keep: first (instructions) + last (recent context)
var condensed = [entries.first!, entries.last!]
let transcript = Transcript(entries: condensed)
return LanguageModelSession(transcript: transcript)
}
Time cost : 15-20 minutes to implement condensing
Symptom :
Error: LanguageModelSession.GenerationError.guardrailViolation
Diagnosis :
Fix :
// ✅ GOOD - Graceful handling
do {
let response = try await session.respond(to: userInput)
print(response.content)
} catch LanguageModelSession.GenerationError.guardrailViolation {
// Show user-friendly message
print("I can't help with that request")
// Log for review (but don't show user input to avoid storing harmful content)
}
Time cost : 5-10 minutes
Symptom :
Error: LanguageModelSession.GenerationError.unsupportedLanguageOrLocale
Diagnosis : User input in language model doesn't support
Fix :
// ❌ BAD - No language check
let response = try await session.respond(to: userInput)
// Crashes if unsupported language
// ✅ GOOD - Check first
let supported = SystemLanguageModel.default.supportedLanguages
guard supported.contains(Locale.current.language) else {
// Show disclaimer
print("Language not supported. Currently supports: \(supported)")
return
}
// Also handle errors
do {
let response = try await session.respond(to: userInput)
} catch LanguageModelSession.GenerationError.unsupportedLanguageOrLocale {
print("Please use English or another supported language")
}
Time cost : 10 minutes
Symptom : Unknown error types
Fix :
// ✅ GOOD - Comprehensive error handling
do {
let response = try await session.respond(to: prompt)
print(response.content)
} catch LanguageModelSession.GenerationError.exceededContextWindowSize {
// Handle context overflow
session = condensedSession(from: session)
} catch LanguageModelSession.GenerationError.guardrailViolation {
// Handle content policy
showMessage("Cannot generate that content")
} catch LanguageModelSession.GenerationError.unsupportedLanguageOrLocale {
// Handle language issue
showMessage("Language not supported")
} catch {
// Catch-all for unexpected errors
print("Unexpected error: \(error)")
showMessage("Something went wrong. Please try again.")
}
Time cost : 10-15 minutes
Symptom :
Diagnosis : Using model for world knowledge (wrong use case)
Fix :
// ❌ BAD - Wrong use case
let prompt = "Who is the president of France?"
let response = try await session.respond(to: prompt)
// Will hallucinate or give outdated info
// ✅ GOOD - Use server LLM for world knowledge
// Foundation Models is for:
// - Summarization
// - Extraction
// - Classification
// - Content generation
// OR: Use Tool calling with external data source
struct GetFactTool: Tool {
let name = "getFact"
let description = "Fetch factual information from verified source"
@Generable
struct Arguments {
let query: String
}
func call(arguments: Arguments) async throws -> ToolOutput {
// Fetch from Wikipedia API, news API, etc.
let fact = await fetchFactFromAPI(arguments.query)
return ToolOutput(fact)
}
}
Time cost : 20-30 minutes to implement tool OR switch to appropriate AI
Symptom :
Diagnosis : Manual JSON parsing instead of @Generable
Fix :
// ❌ BAD - Manual parsing
let prompt = "Generate person as JSON"
let response = try await session.respond(to: prompt)
let data = response.content.data(using: .utf8)!
let person = try JSONDecoder().decode(Person.self, from: data) // CRASHES
// ✅ GOOD - @Generable
@Generable
struct Person {
let name: String
let age: Int
}
let response = try await session.respond(
to: "Generate a person",
generating: Person.self
)
// response.content is type-safe Person, guaranteed structure
Time cost : 10 minutes to convert to @Generable
Symptom :
Diagnosis : Need external data (weather, locations, contacts)
Fix :
// ❌ BAD - No external data
let response = try await session.respond(
to: "What's the weather in Tokyo?"
)
// Will make up weather data
// ✅ GOOD - Tool calling
import WeatherKit
struct GetWeatherTool: Tool {
let name = "getWeather"
let description = "Get current weather for a city"
@Generable
struct Arguments {
let city: String
}
func call(arguments: Arguments) async throws -> ToolOutput {
// Fetch real weather
let weather = await WeatherService.shared.weather(for: arguments.city)
return ToolOutput("Temperature: \(weather.temperature)°F")
}
}
let session = LanguageModelSession(tools: [GetWeatherTool()])
let response = try await session.respond(to: "What's the weather in Tokyo?")
// Uses real weather data
Time cost : 20-30 minutes to implement tool
Symptom :
Diagnosis : Random sampling (default behavior)
Fix :
// Default: Random sampling
let response1 = try await session.respond(to: "Write a haiku")
let response2 = try await session.respond(to: "Write a haiku")
// Different every time
// ✅ For deterministic output (testing/demos)
let response = try await session.respond(
to: "Write a haiku",
options: GenerationOptions(sampling: .greedy)
)
// Same output for same prompt (given same model version)
// ✅ For low variance
let response = try await session.respond(
to: "Classify this article",
options: GenerationOptions(temperature: 0.5)
)
// Slightly varied but focused
// ✅ For high creativity
let response = try await session.respond(
to: "Write a creative story",
options: GenerationOptions(temperature: 2.0)
)
// Very diverse output
Time cost : 2-5 minutes
Symptom :
Diagnosis : Model loading time
Fix :
// ❌ BAD - Load on user interaction
Button("Generate") {
Task {
let session = LanguageModelSession() // 1-2s delay here
let response = try await session.respond(to: prompt)
}
}
// ✅ GOOD - Prewarm on init
class ViewModel: ObservableObject {
private var session: LanguageModelSession?
init() {
// Prewarm before user interaction
Task {
self.session = LanguageModelSession(instructions: "...")
}
}
func generate(prompt: String) async throws -> String {
guard let session = session else {
// Fallback if not ready
self.session = LanguageModelSession()
return try await self.session!.respond(to: prompt).content
}
return try await session.respond(to: prompt).content
}
}
Time cost : 10 minutes Latency saved : 1-2 seconds on first request
Symptom :
Diagnosis : Not streaming long generations
Fix :
// ❌ BAD - No streaming
let response = try await session.respond(
to: "Generate 5-day itinerary",
generating: Itinerary.self
)
// User waits 4 seconds seeing nothing
// ✅ GOOD - Streaming
@Generable
struct Itinerary {
var destination: String
var days: [DayPlan]
}
let stream = session.streamResponse(
to: "Generate 5-day itinerary to Tokyo",
generating: Itinerary.self
)
for try await partial in stream {
// Update UI incrementally
self.itinerary = partial
}
// User sees destination in 0.5s, then days progressively
Time cost : 15-20 minutes Perceived latency : 0.5s vs 4s
Symptom :
Diagnosis : Schema re-inserted into prompt every time
Fix :
// First request - schema inserted automatically
let first = try await session.respond(
to: "Generate first person",
generating: Person.self
)
// ✅ Subsequent requests - skip schema insertion
let second = try await session.respond(
to: "Generate another person",
generating: Person.self,
options: GenerationOptions(includeSchemaInPrompt: false)
)
Time cost : 2 minutes Latency saved : 10-20% per request
Symptom :
Diagnosis : Prompt too complex for single generation
Fix :
// ❌ BAD - One massive prompt
let prompt = """
Generate complete 7-day itinerary with hotels, restaurants,
activities, transportation, budget, tips, and local customs
"""
// 5-8 seconds, poor quality
// ✅ GOOD - Break into steps
let overview = try await session.respond(
to: "Generate high-level 7-day plan for Tokyo"
)
var dayDetails: [DayPlan] = []
for day in 1...7 {
let detail = try await session.respond(
to: "Detail activities and restaurants for day \(day) in Tokyo",
generating: DayPlan.self
)
dayDetails.append(detail.content)
}
// Total time similar, but better quality and progressive results
Time cost : 20-30 minutes Quality improvement : Significantly better
Symptom :
Diagnosis : Calling respond() on main thread synchronously
Fix :
// ❌ BAD - Blocking main thread
Button("Generate") {
let response = try await session.respond(to: prompt)
// UI frozen for 2-5 seconds!
}
// ✅ GOOD - Async task
Button("Generate") {
Task {
do {
let response = try await session.respond(to: prompt)
// Update UI on main thread
await MainActor.run {
self.result = response.content
}
} catch {
print("Error: \(error)")
}
}
}
Time cost : 5 minutes UX improvement : Massive (no frozen UI)
Situation : You just launched an AI-powered feature using Foundation Models. Within 2 hours:
Pressure Signals :
DO NOT fall into these traps:
"Disable the feature"
"Roll back to previous version"
"It works for me"
"Switch to ChatGPT API"
// Check error distribution
// What percentage seeing what error?
// Run this on test devices:
let availability = SystemLanguageModel.default.availability
switch availability {
case .available:
print("✅ Available")
case .unavailable(let reason):
print("❌ Unavailable: \(reason)")
}
// Hypothesis:
// - If 20% unavailable → Availability issue (device/region/opt-in)
// - If 20% getting errors → Code bug
// - If 20% seeing wrong results → Use case mismatch
Results : Discover that 20% of users have devices without Apple Intelligence support.
// Check which devices affected
// iPhone 15 Pro+ = ✅ Available
// iPhone 15 = ❌ Unavailable
// iPhone 14 = ❌ Unavailable
// Conclusion: Availability issue, not code bug
Root cause : Feature assumes all users have Apple Intelligence. 20% don't.
Verify:
// ✅ Add availability check + graceful UI
struct AIFeatureView: View {
@State private var availability = SystemLanguageModel.default.availability
var body: some View {
switch availability {
case .available:
// Show AI feature
AIContentView()
case .unavailable:
// Graceful fallback
VStack {
Image(systemName: "sparkles")
.font(.largeTitle)
.foregroundColor(.secondary)
Text("AI-Powered Features")
.font(.headline)
Text("Available on iPhone 15 Pro and later")
.font(.subheadline)
.foregroundColor(.secondary)
.multilineTextAlignment(.center)
// Offer alternative
Button("Use Standard Mode") {
// Show non-AI fallback
}
}
}
}
}
Test on multiple devices (15 min)
Submit hotfix build (5 min)
To VP of Product (immediate) :
Root cause identified:
The AI feature requires Apple Intelligence (iPhone 15 Pro+).
20% of our users have older devices. We didn't check availability.
Fix: Added availability check with graceful fallback UI.
Timeline:
- Hotfix ready: Now
- TestFlight: 10 minutes
- App Store submission: 30 minutes
- Review: 24-48 hours (requesting expedited)
Impact mitigation:
- 80% of users see working AI feature
- 20% see clear message + standard mode fallback
- No functionality lost, just graceful degradation
To Engineering Team :
Post-mortem items:
1. Add availability check to launch checklist
2. Test on non-Apple-Intelligence devices
3. Document device requirements clearly
4. Add analytics for availability status
| Symptom | Cause | Check | Pattern | Time |
|---|---|---|---|---|
| Won't start | .unavailable | SystemLanguageModel.default.availability | 1a | 5 min |
| Region issue | Not supported region | Check supported regions | 1b | 5 min |
| Not opted in | Apple Intelligence disabled | Settings check | 1c | 10 min |
| Context exceeded | >4096 tokens | Transcript length | 2a | 15 min |
| Guardrail error | Content policy | User input type | 2b | 10 min |
| Language error | Unsupported language |
Related Axiom Skills :
axiom-foundation-models — Discipline skill for anti-patterns, proper usage patterns, pressure scenariosaxiom-foundation-models-ref — Complete API reference with all WWDC 2025 code examplesApple Resources :
Last Updated : 2025-12-03 Version : 1.0.0 Skill Type : Diagnostic
Weekly Installs
100
Repository
GitHub Stars
606
First Seen
Jan 21, 2026
Security Audits
Gen Agent Trust HubPassSocketPassSnykPass
Installed on
opencode85
codex79
claude-code79
gemini-cli78
cursor77
github-copilot73
AI 代码实施计划编写技能 | 自动化开发任务分解与 TDD 流程规划工具
50,900 周安装
化合物信息检索工具:跨数据库验证,获取全面化学数据与生物活性信息
184 周安装
AI代理管理工具 - 统一CLI创建、管理和编排多个AI代理,支持生命周期管理和插件扩展
188 周安装
AI智能错误诊断与调试指南:自动化根因分析、可观测性平台集成与生产环境安全调试
188 周安装
前端设计技能:创建独特、生产级UI界面,突破AI生成美学,实现创意前端开发
194 周安装
Attio CRM API 集成指南:Python脚本管理公司、联系人、笔记和交易
187 周安装
iOS无障碍功能开发指南:VoiceOver、动态字体、WCAG合规性检查与App Store审核
187 周安装
| supportedLanguages |
| 2c |
| 10 min |
| Hallucinated output | Wrong use case | Task type check | 3a | 20 min |
| Wrong structure | No @Generable | Manual parsing? | 3b | 10 min |
| Missing data | No tool | External data needed? | 3c | 30 min |
| Inconsistent | Random sampling | Need deterministic? | 3d | 5 min |
| Initial delay | Model loading | First request slow? | 4a | 10 min |
| Long wait | No streaming | >1s generation? | 4b | 20 min |
| Schema overhead | Re-inserting schema | Subsequent requests? | 4c | 2 min |
| Complex prompt | Too much at once | >5s generation? | 4d | 30 min |
| UI frozen | Main thread | Thread check | 5a | 5 min |