← 所有文章

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。裝置端的預算是4K token;Private Cloud Compute模型則把它提高到32K14。請預先規劃,否則會話會拋出例外。
  • 需要iOS 26與一台支援Apple Intelligence的裝置。低於這道門檻,這套框架根本不存在。iOS 27的beta版則在同一套API上加入了圖片輸入、逐請求的工具呼叫控制,以及Private Cloud Compute上的伺服器模型121314。

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

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、一個@Generable的Arguments型別,以及一個負責實際工作的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 Intent11,是形狀相同卻表面各異的東西:一項具名、有描述、有型別的能力。能力只設計一次,就能透過兩者同時對外開放。

可用性:不能省略的檢查

模型並非隨時都在。在不支援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。在使用者即將動作的畫面上值得這麼做,若只是臆測性地呼叫則是浪費。

動手做:一個檔案完成一項完整功能

上面這些零件,能用比多數網路層處理單一端點還少的程式碼,組成一項真實功能。下面的範例是一個完整、可編譯的SwiftUI畫面,把自由格式的會議筆記轉成結構化的待辦事項:可用性檢查、@Generable輸出型別、一次引導式生成呼叫,以及三種「不可用」分支的完整處理。當中每一個符號,都來自前文記錄過的框架介面2358。

import SwiftUI
import FoundationModels

@Generable
struct ActionItems {
    @Guide(description: "One-sentence summary of the meeting")
    let summary: String

    @Guide(description: "Concrete follow-up tasks, each starting with a verb")
    let tasks: [String]

    @Guide(description: "How urgent the follow-ups are overall", .anyOf(["low", "medium", "high"]))
    let urgency: String
}

struct MeetingNotesView: View {
    @State private var notes = ""
    @State private var result: ActionItems?
    @State private var errorMessage: String?

    var body: some View {
        Form {
            TextField("Paste meeting notes", text: $notes, axis: .vertical)
                .lineLimit(6...12)

            Button("Extract action items") {
                Task { await extract() }
            }
            .disabled(notes.isEmpty)

            if let result {
                Section(result.summary) {
                    ForEach(result.tasks, id: \.self) { Text($0) }
                    Text("Urgency: \(result.urgency)")
                }
            }

            if let errorMessage {
                Text(errorMessage).foregroundStyle(.secondary)
            }
        }
    }

    private func extract() async {
        switch SystemLanguageModel.default.availability {
        case .available:
            do {
                let session = LanguageModelSession()
                let response = try await session.respond(
                    to: "Extract the action items from these notes: \(notes)",
                    generating: ActionItems.self
                )
                result = response.content
            } catch {
                errorMessage = "The model could not process these notes."
            }
        case .unavailable(.appleIntelligenceNotEnabled):
            errorMessage = "Turn on Apple Intelligence in Settings to use this feature."
        case .unavailable(.modelNotReady):
            errorMessage = "The model is still downloading. Try again shortly."
        case .unavailable:
            errorMessage = "This feature needs an Apple Intelligence-capable device."
        }
    }
}

在這麼小的範例裡,有三個細節值得留意。輸出型別就是API:ActionItems精確定義了這項功能會產出什麼,而urgency上的@Guide約束意味著那個字串不可能回傳三個許可值以外的任何東西8。會話之所以每次呼叫都重新建立,是因為每一次抽取都彼此獨立;一個被保留下來的會話,會把先前的筆記一路拖進token預算裡2。至於那些不可用分支,產生的是三種不同的使用者體驗,而非一則籠統的錯誤訊息——這正是「誠實降級的功能」與「看起來就是壞了的功能」之間的分野。把這個檔案貼進一個iOS 26專案,在支援Apple Intelligence的裝置上執行,它就能運作。

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

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

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

對於這套框架真正攸關的那個決定——何時留在裝置端、何時該離開——上下文視窗是最乾淨俐落的訊號。數字如今已經公開:裝置端模型在4K token的預算內運作,而Private Cloud Compute上的伺服器模型把上限拉到32K14。前面關於切塊的一切建議,都請放在這兩個數字的脈絡下閱讀。

iOS 27的beta版帶來了什麼

以上描述的,都是iOS 26出貨時的框架樣貌,而這一切至今依然成立。iOS 27的beta版沿著四個方向擴充同一套介面,沒有任何一項會打破iOS 26的心智模型12。

提示可以放圖片了。 裝置端模型獲得了Vision能力:您在提示中與文字並列插入一份圖片附件,模型便會就兩者一起作答。新增的型別是Attachment、ImageAttachmentContent與ImageReference,而附件接受UIImage、NSImage、CGImage、Core Image型別、CoreVideo像素緩衝區,以及檔案URL1213。圖片不限尺寸與長寬比,但它們花的是與文字同一份token預算,因此裝置端那道4K視窗很快就會變成設計上的限制13。完整說明請見iOS 27的Foundation Models圖片輸入。

工具呼叫多了一道節流閥。 GenerationOptions新增了可逐請求設定的toolCallingMode,用來控制模型如何與您掛上的工具互動;Vision框架也直接提供現成的OCRTool與BarcodeReaderTool實作,掛到會話上即可,不必自己寫辨識程式碼15。行為細節請見iOS 27的工具呼叫控制。

更大的模型,只差一行。 PrivateCloudComputeLanguageModel讓同一套API去跑Apple在Private Cloud Compute上的伺服器模型,需要一項權限(entitlement),換來的是32K上下文視窗,以及裝置端模型所沒有的推理能力1214。引導式生成與工具的用法完全不變;切換模型就只是會話的model引數。

會話有了更多控制面。 beta版新增了ContextOptions、TranscriptErrorHandlingPolicy、動態設定檔(DynamicInstructions、LanguageModelSession.DynamicProfile),以及一套自訂語言模型供應者協定(LanguageModel、LanguageModelExecutor),讓會話得以驅動您自備的模型,而非系統內建的那一個12。watchOS也在27.0加入了支援平台名單12。

值得記住的定位是:iOS 26的程式碼在iOS 27上編譯與行為完全一致。beta版拓寬的是提示能承載什麼、模型能在哪裡執行;它們並未改變這套框架的本質。

何時不該使用Foundation Models

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

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

對於這套框架未涵蓋的裝置端情境(自訂模型、您自己的權重、在裝置上訓練),底下那幾層分別是:固定的轉換後模型交給Core ML,開放權重模型與您自己擁有的微調版本交給MLX,而當您需要對特化與排程有明確掌控時,則是iOS 27的Core AI。對於那些確實需要規模的情境,Private Cloud Compute,或隱私邊界後方的一套雲端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。裝置端模型提供4K token;Private Cloud Compute模型則提供32K14。長文件與長篇多輪歷史都會超出裝置端的預算,因此請為這個上限預作規劃,否則會話會拋出例外。

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

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

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

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

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

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

iOS 27為Foundation Models增加了什麼?

iOS 27的beta版加入了圖片輸入(提示中的附件,可由UIImage、CGImage、像素緩衝區等建立)、透過GenerationOptions逐請求控制工具呼叫、現成的OCRTool與BarcodeReaderTool兩項Vision工具,以及讓同一套API去跑Apple 32K上下文伺服器模型的PrivateCloudComputeLanguageModel12131415。iOS 26的程式碼原封不動即可執行。



  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. ↩

  12. Apple Developer, “Foundation Models” framework topics as of July 2026. The types marked beta for the 27.0 releases include Attachment, ImageAttachmentContent, and ImageReference (prompt attachments); ContextOptions and TranscriptErrorHandlingPolicy; DynamicInstructions and LanguageModelSession.DynamicProfile (dynamic profiles); PrivateCloudComputeLanguageModel with the com.apple.developer.private-cloud-compute entitlement; and the custom provider surface LanguageModel, LanguageModelCapabilities, and LanguageModelExecutor. The framework’s platform list adds watchOS 27.0 (beta). ↩↩↩↩↩↩↩

  13. Apple, WWDC26 session 241, “What’s new in the Foundation Models framework”. Image attachments “can be created from a variety of types including UIImage, NSImage, CGImage, Core Image types, CoreVideo Pixel Buffers, and file URLs”; “the model supports images in any size and aspect ratio,” and “larger images will consume more tokens and incur more latency.” ↩↩↩↩

  14. Apple, WWDC26 session 319, “Build with the new Apple Foundation Model on Private Cloud Compute”. “The on-device model offers 4k, and with PCC you get 32K”; the session demonstrates switching from the on-device model to the PCC server model by changing one line, with guided generation and tool calling working the same on both. ↩↩↩↩↩↩

  15. Apple Developer, “GenerationOptions.ToolCallingMode” (iOS 27 beta; the toolCallingMode property and the init(samplingMode:temperature:maximumResponseTokens:toolCallingMode:) initializer), and the Vision framework’s “OCRTool” and “BarcodeReaderTool” (iOS 27 beta), which conform to the Foundation Models Tool protocol. ↩↩

相關文章

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

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

7 分鐘閱讀

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

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

9 分鐘閱讀

安裝與更新 Codex CLI:Mac、Linux、Windows

codex update 可升級以安裝指令碼、npm 與 Homebrew 安裝的版本;以 winget 安裝的則用 winget upgrade OpenAI.Codex 升級。本文說明如何在任何作業系統上安裝、更新、鎖定版本與解除安裝 …

18 分鐘閱讀