← 所有文章

Apple Foundation Models:裝置端LLM框架完全解析

Foundation Models框架讓應用程式得以直接、免費、離線地存取為Apple Intelligence提供動力的同一個裝置端大型語言模型1。不需要API金鑰,沒有按token計費,沒有網路往返,也沒有任何資料離開裝置。對於過去意味著一套雲端LLM加上一輪隱私審查的那類功能,如今成本幾乎歸零。代價在於能力:裝置端模型體積小、上下文視窗有限,而框架對自己願意與不願意做的事劃下了明確界線。摸清這些界線,就是這場遊戲的全部。

本文是這套框架本身的參考指南:您實際會呼叫的型別、讓它值得一用的那項關鍵功能,以及您應該就此打住、轉而尋求更大方案的那個臨界點。

太長不看

  • LanguageModelSession是進入點。建立一個會話,呼叫respond(to:),取回文字。多輪對話的上下文保存在會話中;單輪工作則每次取得一個全新會話2
  • 引導式生成正是使用這套框架的理由。 為Swift型別加上@Generable註記,模型便會回傳該型別本身——已填入內容且通過型別檢查——而非一段您還得自行解析的字串3
  • Tool協定讓模型得以在生成過程中呼叫您的程式碼,以取得資料或執行動作,再將結果摺回它的回答之中4
  • 動手之前,先檢查SystemLanguageModel.default.availability。在不符資格的裝置上、Apple Intelligence關閉時,或模型正在下載期間,該模型都不存在5
  • 上下文視窗是真實存在且偏小的。SystemLanguageModel.default.contextSize會回報提示與回應共用的token預算6。請預先規劃,否則會話會拋出例外。
  • 需要iOS 26與一台支援Apple Intelligence的裝置。低於這道門檻,這套框架根本不存在。

這套框架是什麼,又不是什麼

Foundation Models並非對雲端端點的一層包裝。模型就活在裝置上,隨作業系統一同出貨,並透過Neural Engine執行。這個單一事實,驅動了API中的每一項設計決策,以及您運用它時所做的每一個決定。

您能得到的:文字生成、摘要、分類、抽取、短篇改寫,以及結構化輸出,全都在裝置端完成,全都免費。您得不到的:一個前沿模型。Apple打造這個裝置端模型,是為了應用程式內聚焦的語言任務,而非開放式推理、長文件分析,也不是供您拿來測驗的世界知識。Apple自己也是這麼定位的,而這樣的定位之所以重要,是因為它設定了預期——否則這套API會放任您去違背它1

能讓您避開麻煩的心智模型是:把裝置端模型當成一位快速、私密、免費的實習生——他極擅長雕琢文字,卻極不擅長知道事實。交給他材料和一個明確的任務。別問他那些他根本無從回答的問題。

LanguageModelSession:進入點

每一次互動都從一個會話開始。

import FoundationModels

let session = LanguageModelSession()
let response = try await session.respond(to: "Summarize this review in one sentence: \(reviewText)")
print(response.content)

會話保存著對話狀態。每一次呼叫respond(to:)都會附加到持續累積的文字記錄上,因此一個您持續保留的會話會記得先前的內容。對於聊天功能,這正是您要的。但對於彼此獨立的一次性任務(摘要這個、分類那個),請為每次呼叫建立一個全新會話,免得陳舊的上下文滲入,白白吃掉您的token預算2

respond(to:)async throws。它在模型工作時暫停,並在請求超出上下文視窗、模型無法使用,或防護機制拒絕內容時拋出例外。上述每一種情況,都是您要處理的真實分支,而非可以忽略的邊角案例。

要打造反應靈敏的UI,請用串流取代等待。streamResponse(to:)會在模型產出時逐步交付部分輸出,將原本三秒的卡頓,化為隨著成形而逐漸浮現的文字7

引導式生成:讓這套框架值回票價的功能

接下來這部分,值回入場的票價。多數LLM整合工作,有三分之一的程式碼花在哄騙模型吐出有效的JSON,另外三分之二則用來防範它仍然失敗的那些時刻。Foundation Models刪掉了這份工作。

為Swift型別加上@Generable註記,要求會話生成它,模型便會回傳該型別的一個實例——已填入內容且型別安全3

@Generable
struct Recipe {
    @Guide(description: "The dish name")
    let title: String

    @Guide(description: "Ingredients, each as 'quantity item'")
    let ingredients: [String]

    @Guide(description: "Total minutes, start to finish", .range(5...240))
    let minutes: Int
}

let session = LanguageModelSession()
let response = try await session.respond(
    to: "A weeknight pasta for two.",
    generating: Recipe.self
)
let recipe = response.content   // a Recipe, not a String

不必解析。沒有JSONDecoder。不必為了畸形輸出而設重試迴圈。@Guide巨集約束個別欄位:一段模型會當成指示來讀的描述,以及可選的限制,例如數值範圍,或輸出必須符合的正規表示式8。框架不是客客氣氣地請模型給一個介於5到240之間的數字;它約束的是解碼過程,讓這個欄位根本不可能以其他形式回傳。

它所強制建立的這份紀律,才是真正的價值所在。您先在Swift裡設計輸出型別,由編譯器替您把關。模型填的是一份您所定義的契約,而非一段您得逆向工程的散文。對於抽取、表單填寫,以及任何把語言轉成資料的功能,引導式生成正是「示範品」與「可出貨程式碼」之間的分野。

有一個值得知道的控制項:respond(to:generating:)會把includeSchemaInPrompt預設為true,將您型別的結構注入提示之中,使模型偏向它。除非模型已經從訓練、或從會話中較早的對話得知該格式,否則請保持開啟;為了在一個模型沒見過的格式上省token而把它關掉,正是讓您收到一堆垃圾的方式9

工具呼叫:讓模型觸及您的程式碼

引導式生成形塑的是輸出的內容。工具呼叫改變的則是輸入的內容。所謂工具,是一段您的程式碼,模型可以在生成過程中加以呼叫,以取得它沒有的資訊或執行某個動作,再運用結果繼續它的回答4

工具須符合Tool協定:一個name、一段模型用來判斷何時呼叫它的description、一個@GenerableArguments型別,以及一個負責實際工作的call(arguments:)方法4

struct FindContacts: Tool {
    let name = "findContacts"
    let description = "Find a specific number of contacts from the address book"

    @Generable
    struct Arguments {
        @Guide(description: "How many contacts to return", .range(1...10))
        let count: Int
    }

    func call(arguments: Arguments) async throws -> [String] {
        // Fetch contacts, return formatted names.
    }
}

let session = LanguageModelSession(tools: [FindContacts()])
let response = try await session.respond(to: "Draft a dinner invite to three of my contacts.")

流程是這樣的:模型判定它需要聯絡人,以一個經過驗證的count呼叫您的工具,您回傳資料,模型再用真實姓名寫出邀請函。引數透過同一套引導式生成機制,以通過型別檢查的形式抵達,因此您永遠不必從自由文字中去解析模型的意圖。工具的描述,是您唯一能左右「模型何時伸手取用它」的槓桿,所以請把它寫得像一份函式文件——要讓另一位毫無背景脈絡的工程師讀完後就能正確使用。

這也是Foundation Models與其餘代理故事接合的縫合處。裝置端模型呼叫的工具,與Apple Intelligence呼叫的App Intent,是形狀相同卻表面各異的東西:一項具名、有描述、有型別的能力。能力只設計一次,就能透過兩者同時對外開放。

可用性:不能省略的檢查

模型並非隨時都在。在不支援Apple Intelligence的裝置上、使用者已將其關閉時,以及作業系統仍在下載模型資產的那段期間,它都不存在。若您出貨的程式碼假設模型一定在,它就會當機、悄悄降級,或對著一群您從未測試過的使用者卡住不動。

請檢查SystemLanguageModel.default.availability,並依其原因分支處理5

switch SystemLanguageModel.default.availability {
case .available:
    // Show the intelligence feature.
case .unavailable(.deviceNotEligible):
    // Hide it. This device will never have the model.
case .unavailable(.appleIntelligenceNotEnabled):
    // Prompt the user to turn on Apple Intelligence.
case .unavailable(.modelNotReady):
    // Downloading or otherwise not ready yet. Try again later.
case .unavailable(let other):
    // Unknown reason. Fail closed.
}

這三種原因要求三種不同的產品回應,而把它們混為一談,正是這類功能讓人覺得「壞了」的最常見原因。deviceNotEligible是永久性的:隱藏該功能,別再嘮叨。appleIntelligenceNotEnabled是使用者自己掌控的一項設定:出現一次性提示是合理的。modelNotReady則是暫時性的:重試即可,別顯示錯誤。請以對待順利路徑同等的用心去打造「不可用」的路徑,因為對於相當一部分裝置而言,它是唯一的路徑。

當模型可用、且您已知有一個請求即將到來時,對會話呼叫prewarm()會預先暖機,讓第一次真正的回應更快落地10。在使用者即將動作的畫面上值得這麼做,若只是臆測性地呼叫則是浪費。

上下文視窗,以及它不再夠用的那個界點

SystemLanguageModel.default.contextSize會回報模型運作所在的token預算,而這份預算是共用的:提示加回應合起來必須塞得進去6。相對於雲端模型,這個數字偏小,在真實輸入上您很快就會感受到。一份長文件、一整段聊天歷史、一個臃腫的工具結果:任何一個都可能撐爆預算,讓respond拋出例外。

隨之而來的有兩種失敗模式,而兩者都該由您來預防。第一種是緩慢的蔓延:一個多輪會話不斷累積文字記錄,直到再多一輪就溢位。處理方式是為不相關的工作另起全新會話,並讓每一輪的輸入保持精簡。第二種是單一過大的請求:一份20頁的PDF就是塞不下,沒得商量。請把它切塊、對各塊做摘要,再對這些摘要進行推理(LLM工程師熟知的map-reduce),或者接受這個任務的形狀本就不適合裝置端模型。

對於這套框架真正攸關的那個決定——何時留在裝置端、何時該離開——上下文視窗是最乾淨俐落的訊號。

何時不該使用Foundation Models

這套框架免費、私密又離線,讓人忍不住到處都想用它。請克制。當以下情況出現時,跳過它、伸手去拿更大的方案:

  • 您需要真正的推理,或廣度足夠的世界知識。 裝置端模型在設計上就是小的。開放式推理、程式碼生成,以及深度分析,都屬於前沿雲端模型的範疇。拿這些去問裝置端模型,得到的會是自信滿滿卻錯誤的答案。
  • 輸入塞不進上下文視窗,而切塊又會摧毀其語意。有些任務需要一次看到全貌。
  • 您需要一個自己掌控的模型: 特定的檢查點、一個微調版本、自訂權重,或跨作業系統更新仍維持確定性的版本控管。Apple是按自己的時程出貨並更新模型,而不是您的。
  • 您低於iOS 26,或身處不符資格的裝置上。 框架根本就不在那兒,而可用性檢查會在每一次執行時這麼告訴您。

對於這套框架未涵蓋的裝置端情境(自訂模型、您自己的權重、在裝置上訓練),底下那一層是Core ML與Apple的MLX。對於那些確實需要規模的情境,隱私邊界後方的一套雲端LLM,仍然是誠實的答案。Foundation Models並不能取代兩者中的任何一個。對於您手邊既有文字上的聚焦語言工作,它是正確的第一選擇;對於其他一切,它則是錯誤的選擇。

這套框架所獎賞的本事,不是提示工程的巧手,而是對範疇的品味:餵給模型它擅長的任務、設計出恰好捕捉您所需內容的@Generable型別,並認出工作量已超出裝置負荷的那一刻。帶著這些直覺去打造,裝置端模型就會免費地完成出乎意料大量的真實工作。忽略它們,您出貨的功能就會對每一個輸入恰好多出一個token的使用者壞掉。

常見問題

Apple的Foundation Models框架可以免費使用嗎?

可以。這套框架讓應用程式得以直接、免費、離線地存取為Apple Intelligence提供動力的同一個裝置端模型。沒有API金鑰、沒有按token計費,也沒有網路往返1

Foundation Models需要哪些裝置與iOS版本?

它需要iOS 26與一台支援Apple Intelligence的裝置。低於這道門檻,框架根本不存在;而即使在受支援的作業系統上,在不符資格的裝置上、Apple Intelligence關閉時,或模型下載期間,該模型仍會缺席。使用前請務必檢查SystemLanguageModel.default.availability5

我要如何取得結構化、型別安全的輸出,而非一段字串?

為Swift型別加上@Generable註記,模型便會回傳該型別本身——已填入內容且通過型別檢查——而非一段您還得自行解析的字串。這項引導式生成,正是讓這套框架值得一用的那唯一一項功能3

Apple裝置端模型的上下文視窗有多大?

SystemLanguageModel.default.contextSize會回報token預算,而它由提示與生成的回應共用6。它在設計上就偏小,因此長文件與長篇多輪歷史都會超出它。請為這個上限預作規劃,否則會話會拋出例外。

Foundation Models能離線運作嗎?它會把資料送給Apple嗎?

它完全在裝置端、透過Neural Engine執行。沒有資料離開裝置,也不需要網路往返——這正是它適合用在過去需要雲端LLM加上隱私審查的那類功能上的原因1

裝置端模型能在生成過程中呼叫我自己的程式碼嗎?

可以。Tool協定讓模型得以在生成期間呼叫您的程式碼,以取得資料或執行動作,再將結果摺回它的回答之中4

我什麼時候不該使用Foundation Models?

當您需要一個前沿模型時,跳過它、伸手去拿更大的方案:開放式推理、程式碼生成、長文件分析,或世界知識。Apple打造這個裝置端模型,是為了應用程式內聚焦的語言任務,所以拿它去要求通用智慧,得到的會是自信滿滿卻錯誤的答案1



  1. Apple Developer, “Foundation Models” framework overview. Apple describes the framework as access to the on-device model that powers Apple Intelligence, suited to focused language tasks such as text generation, summarization, classification, and structured output rather than open-ended reasoning or world knowledge. 

  2. Apple Developer, “LanguageModelSession” and “Generating content and performing tasks with Foundation Models”. A session holds multi-turn context; Apple’s guidance is to create a new session for each distinct single-turn interaction. 

  3. Apple Developer, “Generable” and “Prompting an on-device foundation model”. The @Generable macro lets the framework return a populated, type-checked Swift value rather than a string. 

  4. Apple Developer, “Tool” protocol. Defines protocol Tool<Arguments, Output>: Sendable with required name, description, and parameters: GenerationSchema, plus call(arguments:) async throws -> Output. The Arguments type conforms to ConvertibleFromGeneratedContent and is typically declared @Generable

  5. Apple Developer, “SystemLanguageModel.Availability” and its UnavailableReason. Cases: .available and .unavailable(...) with reasons deviceNotEligible, appleIntelligenceNotEnabled, and modelNotReady. SystemLanguageModel.default.isAvailable is the convenience boolean. 

  6. Apple Developer, “SystemLanguageModel.contextSize”. An instance property (reached through SystemLanguageModel.default) documented as the maximum context size, representing the total tokens across input prompt and generated response. 

  7. Apple Developer, “LanguageModelSession.streamResponse(to:)”. Streams partial generated output as the model produces it, for incremental UI updates. 

  8. Apple Developer, “Guide(description:_:)”. A peer macro that attaches a natural-language description and optional constraints (numeric ranges, regular-expression guides) to a @Generable property. Requires iOS 26.0+. 

  9. Apple Developer, “respond(to:schema:includeSchemaInPrompt:options:)”. includeSchemaInPrompt defaults to true; Apple’s discussion recommends keeping the default unless the model already knows the expected format. 

  10. Apple Developer, “LanguageModelSession.prewarm()”. Asks the framework to load model resources ahead of a known upcoming request to reduce first-response latency. 

  11. Author’s related analysis: On-Device LLMs with Apple’s Foundation Models, Custom Adapters for Foundation Models, Foundation Models Use Cases, and Agentic Workflows on Foundation Models. The App Intents and tool-surface argument is developed in App Intents Are Apple’s New API to Your App

相關文章

Foundation Models 使用案例:通用模型與內容標記

iOS 26 Foundation Models 提供 .general 與 .contentTagging 兩種使用案例。運用 Apple 的規則,判斷何時提示工程勝過專業化模型。

3 分鐘閱讀

Foundation Models 自訂 Adapter:何時應該訓練一個

iOS 26 Foundation Models 自訂 adapter 訓練 LoRA 權重、匯出 .fmadapter 套件、透過 Background Assets 配送,並需要 Apple 的權限授權。

4 分鐘閱讀

The Robots Are Taking Exams in My Search Console

First-party GSC data: 91% of 3.8M impressions fail a human-query filter. Exam questions, pasted errors, and agent sweeps…

10 分鐘閱讀