View in English

  • Apple Developer
    • 今すぐ始める

    「今すぐ始める」を詳しく見る

    • 概要
    • 学ぶ
    • Apple Developer Program

    最新情報

    • 最新ニュース
    • Hello Developer
    • プラットフォーム

    プラットフォームを詳しく見る

    • Appleプラットフォーム
    • iOS
    • iPadOS
    • macOS
    • tvOS
    • visionOS
    • watchOS
    • App Store

    特集

    • デザイン
    • 配信
    • ゲーム
    • アクセサリ
    • Web
    • Home
    • CarPlay
    • テクノロジー

    テクノロジーを詳しく見る

    • 概要
    • Xcode
    • Swift
    • SwiftUI

    特集

    • アクセシビリティ
    • App Intent
    • Apple Intelligence
    • ゲーム
    • 機械学習とAI
    • セキュリティ
    • Xcode Cloud
    • コミュニティ

    コミュニティを詳しく見る

    • 概要
    • 「Appleに相談」イベント
    • コミュニティによるイベント
    • デベロッパフォーラム
    • オープンソース

    特集

    • WWDC
    • Swift Student Challenge
    • デベロッパストーリー
    • App Store Awards
    • Apple Design Awards
    • Apple Developer Center
    • ドキュメント

    ドキュメントを詳しく見る

    • ドキュメントライブラリ
    • テクノロジー概要
    • サンプルコード
    • ヒューマンインターフェイスガイドライン
    • ビデオ

    リリースノート

    • 注目のアップデート
    • iOS
    • iPadOS
    • macOS
    • watchOS
    • visionOS
    • tvOS
    • Xcode
    • ダウンロード

    ダウンロードを詳しく見る

    • すべてのダウンロード
    • オペレーティングシステム
    • アプリ
    • デザインリソース

    特集

    • Xcode
    • TestFlight
    • フォント
    • SF Symbols
    • Icon Composer
    • サポート

    サポートを詳しく見る

    • 概要
    • ヘルプガイド
    • デベロッパフォーラム
    • フィードバックアシスタント
    • お問い合わせ

    特集

    • アカウントヘルプ
    • App Reviewガイドライン
    • App Store Connectヘルプ
    • 近日導入予定の要件
    • 契約およびガイドライン
    • システムステータス
  • クイックリンク

    • イベント
    • ニュース
    • Forum
    • サンプルコード
    • ビデオ
 

ビデオ

メニューを開く メニューを閉じる
  • コレクション
  • すべてのビデオ
  • 利用方法

その他のビデオ

  • 概要
  • Summary
  • トランスクリプト
  • コード
  • Foundation ModelフレームワークへのLLMプロバイダーの導入

    新しいモデル用にLanguageModelExecutorを実装することで、Foundation Modelフレームワークを拡張できます。LanguageModelSessionのトランスクリプトとの接続、セッション状態の効果的な管理、KVキャッシュの利用の最適化を行うための方法を紹介します。カスタムのセグメントタイプをサポートし、生成AIの高度な機能を活用する方法も確認しましょう。

    関連する章

    • 0:00 - Introduction
    • 3:37 - Packaging
    • 4:48 - Protocol
    • 14:50 - Authentication
    • 15:51 - Customization
    • 19:47 - Next steps

    リソース

    • Foundation Models
    • Core AI Models
    • MLX Swift LM on GitHub
      • HDビデオ
      • SDビデオ

    関連ビデオ

    WWDC26

    • プライベートクラウドコンピューティングによるApple Foundation Model の活用
    • fm CLIとPython SDKによるAI活用型スクリプトの作成
    • Foundation Modelフレームワークによる、エージェントを活用したアプリ体験の構築
    • Foundation Modelフレームワークの新機能
  • このビデオを検索

    こんにちは! Christopher Webbです Machine Learning Research チームのエンジニアです 今日はお話しできることを うれしく思います Foundation Modelフレームワークの 新しい使い方についてです Foundation Modelフレームワークは 以前にご紹介しました Appleのオンデバイス言語モデルへの アクセスを提供するためのものです このframeworkをほぼすべてのLLMで 使えるよう拡張しました ローカルでもサーバーベースでも 大企業から個人デベロッパまで 誰でも利用できます frameworkを使って独自の モデル連携を簡単に構築できます

    オンデバイスSystem Language Modelは ゼロから作り直しました より賢く 指示への追従性も向上し プロンプトに画像を 直接含めることもできます システムモデルに加えて 3つの新しいオプションを追加しました Private Cloud Computeは多くの Apple Intelligence機能を支えるモデルです 推論機能を備え 32Kトークンのコンテキストウィンドウと プライバシー保証も提供します Core AIを使えばローカルモデルを 効率的に実行でき ANEも活用できます MLXはHugging Face上で利用可能な 数千ものモデルを MLX-Community経由で 使えるようにします

    これらはすべて新しいパブリック プロトコル上に構築されているため デベロッパは最先端のAIモデルを 同じframeworkを使って アプリに組み込めます AnthropicとGoogleはまもなく Foundation Modelフレームワークを 独自のSwiftパッケージで拡張します 最先端のClaudeとGeminiのモデルを すべてのSwiftデベロッパが 使えるようになります どのモデルを使う場合でも Appleのもの、独自のもの、 コミュニティのものであっても 呼び出し方は同じです すべてのモデルがLanguage Model プロトコルに準拠しているからです アプリデベロッパの方には これらのモデルを呼び出す方法を おなじみのAPIでご紹介します モデルプロバイダの方には 独自のLanguage Model パッケージの 作成方法をご説明します まずは使いやすさを プレビューでご覧ください オンデバイスのFoundation Modelです 作成して セッションに渡し respond関数を呼び出します さらに多くのモデルオプションもあります より高い性能が必要なら Private Cloud Computeを試してください モデルを切り替えるだけです 独自モデルを配布したい場合は CoreAIをリソースに 指定するだけです 最新のオープンソースモデルを 試したい場合は モデルIDを渡すだけで frameworkが残りを処理します

    Language Modelプロトコル上に 構築されたモデルを使うと Foundation Modelの優れた 機能をすべて利用できます Dynamic Profilesなどです 追加内容の概要については 「What's new in the Foundation Models framework」をご覧ください

    モデルを簡単に 切り替えられる理由は すべてのLanguageModelが 同じプロトコルに従っているからです System Language Model PCC Core AI MLX そしてコミュニティ製のものも同様です モデルプロバイダの方は ぜひ参加してください! 方法をご説明します モデルをframeworkに組み込む 4つのステップがあります まずパッケージングから始めます 丁寧に作られたSwiftパッケージは デベロッパの導入を容易にします 次にプロトコルを実装します モデルを記述する型と それを実行するExecutorを定義します 次に実装方法についてお話しします サーバーベースモデルの認証 ベストプラクティスを含めてご紹介します 最後はカスタマイズです 調整が必要なら プロトコルの構成要素を ニーズに合わせて変更できます それが可能です レスポンスメタデータの添付から まったく新しいモダリティの 定義まで対応できます まずはパッケージングです Swift Package Managerの 使用をお勧めします デベロッパがパッケージを 簡単に追加できるように アプリの依存関係として設定できます Package.swiftの設定方法と リリースの公開方法をご説明します 重要な考慮事項として サポートするプラットフォームがあります Foundation ModelはiOS macOS visionOS watchOSをサポートし デベロッパがさまざまな 体験を作れるようにしています 同様のサポートをお勧めします Foundation Modelフレームワークは オープンソースとして公開されるため パッケージはデベロッパにとっても 役立つ可能性があります サーバーにSwiftをデプロイする Linuxのサポートもご検討ください 3つ目は依存関係です 依存関係はすべてバイト数に換算され デベロッパがユーザーに配布します パッケージにリンクされる 依存関係を慎重に検討してください

    パッケージの公開はgitタグの 作成と同じくらい簡単です Swift Package Managerは分散型なので リポジトリのURLが 配布チャネルになります デベロッパはURLを貼り付けて Xcodeでモデルの組み込みを始め アプリに統合できます 詳細は「Creating Swift Packages」をご覧ください パッケージの準備ができたら プロトコルに移ります プロトコルはモデルと Foundation Modelフレームワークを つなぐ橋です プロトコルには2つの重要な要素があります 1つ目はLanguageModelです frameworkにモデルを記述します モデルの機能を宣言し capabilitiesを通じて frameworkがモデルのExecutorを 設定するために必要な configurationを提供します

    2つ目はLanguageModelExecutorで 実際の処理が行われます Configurationを受け取る initializerがあり 最初のリクエスト前に リソースを準備する prewarm関数と respond関数があります セッションにストリーミングで 生成結果を返します

    Configurationは2つの型を つなぐものです Modelが提供し frameworkがそれを使って Executorを構築します コードでプロトコルを確認したので モデルのconfigurationが どのようにExecutorと 連携するかを理解しましょう 各セッションはExecutorストアを持ちます Model1が到着すると frameworkはモデルのconfigurationで ストアを検索しますが 一致するExecutorが見つかりません そのためLanguageModelSessionが 新しいExecutorを作成して保存します Model2は同じconfigurationを生成し ConfigurationはHashableなので frameworkは一致することを認識し 同じExecutorを返します ルックアップキーはモデルではなく configurationです Model3は異なるconfigurationを 生成するため 独自のExecutorが割り当てられます ユニークなconfigurationは ストア内の1つのExecutorに対応します

    コードではどのように見えるでしょうか LanguageModelの実装例です capabilitiesを宣言し frameworkがExecutorを見つけるために使う configurationを返します

    Executorが実際の処理を担います ウェイトの読み込み リソース管理 セッションへのトークンのストリーミングです frameworkはモデルが提供する configurationから構築し リクエストのたびにモデルを渡します この分離によりModelの構築が シンプルに保たれます セッションが解放されると ストアも解放されます 保存されたすべてのExecutorが解放され deinitが実行され ウェイトが解放され 接続がクローズされます すべて自動的に行われます クリーンアップコードを 自分で書く必要はありません そのライフサイクル内で Executorにはもうひとつのfunctionが あります prewarmです リクエストが届く前に デベロッパはframeworkに prewarmを依頼できます コストのかかるセットアップを 事前に行うチャンスです ウェイトの読み込みや接続のオープンなど 最初のレスポンスを遅くする 可能性のある処理です 使い方を見てみましょう 1つのアプローチはそのセットアップを プライベートヘルパーに入れて ウェイトを一度だけ読み込んで キャッシュすることです prewarmはヘルパーをすぐに呼び出し 最初のリクエストが届く前に ウェイトを準備します ただしprewarmの実行は保証されません

    いずれにしても ウェイトは一度だけ読み込まれ Executorにコストのかかる セットアップがない場合 サーバーバックモデルのような場合 prewarmは何もしなくて構いません respond functionが呼ばれると Executorが動作を開始します 会話のトランスクリプトを モデルが期待する形式に変換します デベロッパが設定したオプションを適用し 生成イベントをセッションに ストリーミングします

    デベロッパの側から見ると セッションがインタラクションの すべての窓口です モデルを初期化し セッションを作成して respondを呼んで待ちます ExecutorとパッケージのすべてはS セッションの内側にあり 見えません デベロッパはその仕組みを 見ることはありませんが 裏側で起きていることはこうです frameworkはトランスクリプトの エントリを渡しますが 推論エンジンは ネイティブ型しか処理できません そのためExecutorが中間に入り エントリを推論エンジンが理解できる メッセージに変換して 推論のために渡します 推論エンジンが応答すると 同じ変換が逆向きに実行されます メッセージをトランスクリプトエントリに戻し セッションにストリーミングします

    まずトランスクリプトに注目しましょう Executorとの間を流れるものです

    トランスクリプトはこれまでの会話で エントリのシーケンスとして表されます 各エントリにはロールがあります デベロッパが設定するInstructions ユーザーからのPrompts モデルが行ったtool calls それらが返したoutputs そしてモデルが生成したResponsesです

    俯瞰して見ると Executorの役割は 各トランスクリプトエントリを 推論エンジンが読める メッセージに変換することです トランスクリプトの中身はどうなっているか Foundation Modelは 6つのエントリ型を定義しています

    モデルは独自のロールを定義します Executorの役割は その2つをマッピングすることです モデルの形式がどうであっても この例ではInstructions、 Prompt、Responseが system、user、assistantに マッピングされます tool calls、tool outputs そしてreasoningもassistantに マッピングされます これらはモデルのターン中に 行ったことの一部であり このモデルにはこれらの 専用ロールがないため assistantにマッピングします モデルが専用のtoolロールを 定義している場合は そちらにルーティングできます いずれにしても Executorがコントロールできます Executorは会話を読み取ります しかし各リクエストは履歴以上のものを 含んでいます モデルがどのように応答すべきかという デベロッパの意図が込められており 2つの追加プロパティで 表現されています

    すべてのrequestオブジェクトには ContextOptionsを含めることができます そしてGenerationOptionsも ContextOptionsはプロンプトの 内容を制御します モデルに使わせたい 推論レベルや レスポンスのスキーマなどです GenerationOptionsはデコーダループを 制御します サンプリング戦略 temperature 最大レスポンス長などです

    respondの内側での 見え方はこうです 両方のオプションが リクエストで届き Executorがそれを取り出し モデル呼び出し時に 渡します 以上が受け取る側のすべてです トランスクリプト、オプション、 すべて解析済みです 次はデベロッパが目にする レスポンスです レスポンス側では いくつか送るものがあります 推論エンジンが生成するテキスト tool callsやreasoningも それに付随するメタデータも すべてチャネルのイベントとして送られます 推論エンジンが出力する各チャンク トークンやtool-callのフラグメントが イベントになります textDelta、toolCallDeltaなどです frameworkはそれらを トランスクリプトに書き込みます Foundation Modelはワンショットと ストリーミングの両方のレスポンスを提供しますが 実装は常にストリーミングで ワンショットAPIは 内部でデルタを収集します

    ここまでモデル側から見てきました モデルが生成するにつれて イベントが送られます 少しデベロッパの立場に なってみましょう respondを呼んで 待っています 最初に何が必要でしょうか

    デベロッパとのExecutorのハンドシェイクです 意図的な順序があります まずメタデータの更新 デベロッパがログやデバッグに使える モデルIDとリクエストIDです 次に使用量の更新 課金のためのプロンプトトークン数です これらを最初に送ることで デベロッパはストリーム全体を待たずに 各リクエストのコストを把握できます 最後に、モデルが生成する 各トークンに対して 到着した瞬間にtext deltaを送ります frameworkはそれらのデルタを 到着次第 セッションにストリーミングするため ユーザーはレスポンスを一度にではなく 単語ごとに見ることができます 先ほどframeworkがconfigurationで Executorをキャッシュする仕組みを説明しました ステートフルな連携の場合 呼び出し間でKVキャッシュや 永続セッションを保持する場合 そのキャッシュによってネットワーク負荷を 最小化し作業の重複を避けられます それを活用するための設計と Executorが呼び出し間で 作業を保持する方法を見ていきます Executorはrespondの呼び出しごとに 完全なトランスクリプトを受け取ります 前回処理した内容です instruction prompt そして生成したresponseです 次の呼び出しが来ると 新しいトランスクリプトを 前回保存したものと比較します ほとんどの場合 新しいエントリが追加されているだけで 最後のresponseの後に 新しいpromptが来ています その場合は 既存の状態を保持して 新しい部分だけを処理できます しかし比較でエントリが削除または 変更されていることがわかる場合もあります 例えばデベロッパがコンテキストを 節約するために古いエントリを削除した場合です その場合 トランスクリプトが分岐した 箇所まで無効化が必要です frameworkはすべての呼び出しで 完全なトランスクリプトを提供します Executorが何を一致とみなすか 変更の扱い方を決めます モデルがデベロッパの 要求に完全に応えられない場合もあります その場合Executorには 2つの選択肢が あります 近似するかthrowするかです できる限り柔軟に対応して デベロッパの意図を尊重してください しかし正直な近似が できない場合もあります デベロッパがトークン上限を設定しつつ 必須フィールドのある スキーマを指定した場合 両方を満たす方法が ない場合があります その場合はthrowします Foundation ModelはLanguageModel Errorをまさにこのために提供しています コンテキストウィンドウのオーバーフロー レート制限、拒否などです これらをthrowすれば frameworkを使ったことのある デベロッパなら すでに対処法を知っています

    組み込みのLanguageModelErrorの ケースが状況をカバーしない場合は 独自のエラー型を定義します サービス固有の状況でしか 意味をなさない失敗があります サブスクリプション階層、機能、 アカウントの状態などです 意図を込めたケース名があれば それをcatchするデベロッパは 何が起きたか正確に理解できます カスタムエラーは強力で 必要な場面もあります しかし各エラーはデベロッパが 新たに学ぶべきケースになります catchしてアプリで処理する必要があります 適合する場合は 組み込みのLanguageModelErrorを使い 独自サービスでしか発生しない失敗に カスタムを残してください プロトコル要件の実装が完了しました 次に認証の 扱い方を説明します パッケージ作者としての役割はデベロッパ が正しいことをしやすくすることです initializerがAPI keyを 文字列で受け取る場合 デベロッパは最も簡単な方法に 流れがちです 代わりに、デベロッパが 正しいことをできるように トークンプロバイダまたは サインインフローを提供してください パッケージがデベロッパのために アクセストークンを取得する場合は Keychainを使って 安全に保存してください 認証情報の扱いは 話の半分です デバイスの認証はもう半分です クラウドベースの LanguageModelパッケージを 配布する場合は 詳しく調べる価値があります この関連セッションではデバイスの 検証について説明しています 改ざんされたビルドの検出 ペイロードの署名 Appleの不正シグナルを使って 不正な トラフィックからサービスを守る方法です 「Secure your apps with App Attest」でご確認ください モデルをパッケージ化し プロトコルを実装して 認証を処理しました LanguageModelの しっかりとしたパッケージが完成し 基本的な要素がすべて揃いました 次は差別化の時間です プロトコルはLanguageModelSessionを 形作る余地を提供します あなたのモデルだけが 持つ機能に合わせてです レスポンスメタデータは 軽量なオプションで レスポンスに追加情報を 添付できます デベロッパが明確に アクセスできる方法を提供します

    レスポンスに独自の カスタムメタデータを添付できます ここではストリーミング完了後に ExecutorがtokensPerSecondを送信し timeToFirstTokenを チャネルに送ります メタデータの扱いを 容易にするユーティリティや ドキュメントをデベロッパに 提供することをお勧めします 明確なキー 型付きアクセサ 合理的なものであれば何でも メタデータの内部は 辞書にすぎません 文字列、数値、 その他の組み込み型を含められます しかしより柔軟性が 必要な場合もあります

    カスタムセグメントがその答えです 新しいセグメント型を定義して Executorで受け取り 同じチャネルを通じて 結果をストリーミングします デベロッパはLanguageModelSessionを 離れずに使えます カスタムセグメント型は プロトコルを拡張できます 新しいモダリティが登場したとき 音声、映像、その先のものも デベロッパはモデルにそのデータを 型付きで構造的に送れます 仕組みはこうです まずcustom segmentに準拠する 型を定義します カスタムセグメントは PromptRepresentableが必要なため デベロッパはプロンプトに 直接渡すことができます テキストと同様にです Executorではトランスクリプトの customSegmentとして受け取ります すでに処理しているテキストエントリと 並んで届きます モデルが応答するとき チャネルを通じて 結果を返します custom segment updateとしてです セグメントIDは新しいセグメントを 追加するのか すでにストリーミング中のものを 更新するのかを制御します アプリへの結果のストリーミング方法を 完全にコントロールできます カスタムセグメントを使えば もうひとつ取り上げる価値があります サーバーサイドツールの推奨事項です サーバーサイドツールはモデルが 自律的に実行する機能です Web検索 コード実行 画像生成などです モデルがそれらを呼び出し サーバーが実行し Executorが結果のストリームを 監視します 3つの詳細レベルを 説明します ツールの処理をより多く 表面化するものです Web検索を例として使います サーバーサイドツールはモデルの 名前付き型付き値です デベロッパは使いたいツールで モデルを構築します Executorはリクエストごとに モデルを通じてそれらを受け取ります モデルが宣言する他のすべての capabilityと同じ方法で まず最もシンプルなパターンです ツールをプライベートに実行して 答えだけをストリーミングします ツールはモデルの レスポンスを根拠づけますが 処理はExecutorの内側に 留まります

    追加するテキストデルタはframeworkが トランスクリプトにストリーミングし ツールの痕跡は 残りません ツールの出力でレスポンスを 根拠づけることに加えて レスポンスに追加の メタデータを添付できます テキストデルタがメタデータを 持っている場合 引用文などです 両方をチャネルに転送すると frameworkがトランスクリプトの テキストセグメントにメタデータを添付します

    最後に ツールの処理自体を 表面化することもできます カスタムセグメントで ツールの構造化出力を チャネルに転送します テキストやメタデータと並べて モデルが生成したすべてを アプリに提供します 1つのチャネルを通じて 転送するイベント 添付するメタデータ 設計するカスタムセグメントにより サーバーサイドツールはパッケージを 使うアプリが ユーザーに何を表示できるかを決めます もう1つ覚えておいてほしいことがあります パッケージを選ぶ側でも 配布する側でも チェーン内の全員が 背後にあるモデルのプライバシーへの影響を 理解する必要があります オンデバイスとクラウドベースのモデルでは プライバシーの特性が大きく異なります ユーザーはどちらを利用するか 知る権利があります モデルをframeworkに 組み込む方法を見てきました これらのセッションでは デベロッパが何を作るかを紹介します 「Integrate On-Device AI Models into Your App Using Core AI」では ローカルモデルをアプリに 直接バンドルする方法を説明します 「Build with the new Apple Foundation Model on Private Cloud Compute」では Appleのプライバシー保証による サーバースケールの推論を詳しく説明します 「Build agentic app experiences with the Foundation Models framework」では デベロッパがdynamic profilesを使って マルチステップの ツールを使うワークフローを あなたのようなモデルの上に 構築する方法を示します これからが楽しみです LanguageModelパッケージの 活発なエコシステムが育つことを期待しています Swiftデベロッパがアプリに最適な モデルを自由に選べる環境です 皆さんの作品を楽しみにしています

    • 2:00 - Choose a language model

      import FoundationModels
      import MLXFoundationModels
      
      // On-device Apple Foundation Model
      let model = SystemLanguageModel()
      
      // Private Cloud Compute model
      // let model = PrivateCloudComputeLanguageModel()
      
      // Custom Core AI model
      // let model = try await CoreAILanguageModel(resourcesAt: modelURL)
      
      // Open-source MLX model from HuggingFace
      // let model = MLXLanguageModel(modelID: "mlx-community/my-model")
      
      let session = LanguageModelSession(model: model)
      let response = try await session.respond(to: "...")
      print(response.content)
    • 3:46 - Configure Package.swift for your model package

      // Package.swift
      
      let package = Package(
          name: "MyModel",
          platforms: [
              .macOS(.v27), .iOS(.v27), .visionOS(.v27), .watchOS(.v27)
          ],
          products: [
              .library(name: "MyModel", targets: ["MyModel"])
          ],
          dependencies: [
              .package(url: "...", .upToNextMinor(from: "1.0.0"))
          ],
          targets: [
              .target(name: "MyModelRuntime"),
              // public: LanguageModel conformance
              .target(name: "MyModel", dependencies: ["MyModelRuntime"]),
              .testTarget(name: "MyModelTests", dependencies: ["MyModel"])
          ]
      )
    • 4:56 - LanguageModel and LanguageModelExecutor protocols

      // LanguageModel protocol
      
      public protocol LanguageModel: Sendable {
          var capabilities: LanguageModelCapabilities { get }
          var executorConfiguration: Executor.Configuration { get }
      }
      
      // LanguageModelExecutor protocol
      
      public protocol LanguageModelExecutor: Sendable {
          init(configuration: Configuration) throws
          func prewarm(model: Model, transcript: Transcript)
          func respond(
              to request: LanguageModelExecutorGenerationRequest,
              model: Model,
              streamingInto channel: LanguageModelExecutorGenerationChannel
          ) async throws
      }
    • 6:25 - Implement LanguageModel and Executor conformances

      // LanguageModel conformance
      public struct MyLanguageModel: LanguageModel {
          typealias Executor = MyLanguageModelExecutor
      
          public var capabilities: LanguageModelCapabilities {
              LanguageModelCapabilities(capabilities: [
                  .toolCalling, .guidedGeneration, .reasoning
              ])
          }
      
          public var executorConfiguration: Executor.Configuration {
              Executor.Configuration(/* ... */)
          }
      }
      
      // Executor conformance
      public struct MyLanguageModelExecutor: LanguageModelExecutor {
          public typealias Model = MyLanguageModel
      
          public struct Configuration: Hashable, Sendable { /* ... */ }
      
          public init(configuration: Configuration) throws { /* ... */ }
      
          public func respond(
              to request: LanguageModelExecutorGenerationRequest,
              model: MyLanguageModel,
              streamingInto channel: LanguageModelExecutorGenerationChannel
          ) async throws { /* ... */ }
      }
    • 7:28 - Manage model resources with prewarm and respond

      // One approach to managing resources
      
      struct MyLanguageModelExecutor: LanguageModelExecutor {
      
          private mutating func loadModelIfNeeded() throws -> LoadedWeights {
              let weights = try loadedModel ?? loadWeights()
              loadedModel = weights
              return weights
          }
      
          func prewarm(transcript: Transcript) {
              loadedModel = try? loadModelIfNeeded()
          }
      
          func respond( ... ) async throws {
              let weights = try loadModelIfNeeded()
              // ...generate with 'weights'...
          }
      }
    • 9:00 - Map Transcript entries to model messages

      // Transcript entries
      
      let transcript = Transcript(entries: [
          .instructions( ... ),  // "You are a helpful assistant"
      
          .prompt( ... ),        // "What's the weather in Pittsburgh?"
          .toolCalls( ... ),     // getWeather(location: "Pittsburgh")
          .toolOutput( ... ),    // 65°F, sunny
          .response( ... ),      // "It's 65°F and sunny in Pittsburgh"
      
          .prompt( ... ),        // "What's the address of Apple Park?"
          .response( ... ),      // "One Apple Park Way, Cupertino, CA 95014"
      ])
    • 10:42 - Read generation and context options from the request

      // Parse generation and context options
      
      func respond(
          to request: LanguageModelExecutorGenerationRequest,
          model: MyLanguageModel,
          streamingInto channel: LanguageModelExecutorGenerationChannel
      ) async throws {
          let reasoningLevel = request.contextOptions.reasoningLevel
          let temperature = request.generationOptions.temperature
          let maxTokens = request.generationOptions.maximumResponseTokens
      }
    • 11:47 - Stream tokens and metadata through the channel

      // Streaming text tokens
      
      func respond( ... ) async throws {
          // 1. Report metadata
          await channel.send(.response(action: .updateMetadata([
              "modelID": "my-model-2026-06-08",
              "requestID": request.id.uuidString
          ])))
          // 2. Report prompt token usage before generating
          await channel.send(.response(action: .updateUsage(
              input: .init(totalTokenCount: promptTokens, cachedTokenCount: cachedTokens),
              output: .init(totalTokenCount: 0, reasoningTokenCount: 0)
          )))
          // 3. Stream text deltas as the model generates
          for try await token in tokens {
              await channel.send(.response(action: .appendText(token)))
          }
      }
    • 13:33 - Honor the developer's intent or throw

      // Honor the developer's intention where possible
      
      // The developer set sampling: .greedy, but our service only takes temperature
      if request.generationOptions.sampling?.kind == .greedy {
          serviceRequest.temperature = 0
      }
      
      // Otherwise, throw an error
      
      // The token budget is too small to satisfy the schema
      if let schema = request.schema,
         let budget = request.generationOptions.maximumResponseTokens,
         budget < minimumTokens(for: schema) {
          throw LanguageModelError.unsupportedCapability(
              .init(
                  capability: .guidedGeneration,
                  debugDescription: "Token budget too small to satisfy this schema."
              )
          )
      }
    • 13:57 - Built-in errors that any model can throw

      // Built-in errors that any model can throw
      
      public enum LanguageModelError: LocalizedError, CustomDebugStringConvertible {
          // Transcript grew past the model's context window. Trim entries and retry.
          case contextSizeExceeded(     )
          // Too many requests in a short window. Space them out or reduce load.
          case rateLimited(     )
          // Model declined to answer. Fall back to a message of your choosing.
          case refusal(     )
          // Safety guardrails tripped on the prompt or the response.
          case guardrailViolation(     )
          // Model lacks a feature you used, such as guided generation or tools.
          case unsupportedCapability(     )
          // Prompt contains content the model can't process (bad files, unknown formats).
          case unsupportedTranscriptContent(     )
          // A generation guide (e.g., a regex pattern) isn't supported by this model.
          case unsupportedGenerationGuide(     )
          // Prompt asked for output in a language or locale the model doesn't support.
          case unsupportedLanguageOrLocale(     )
          // Request timed out before the model produced a response.
          case timeout(     )
      }
    • 14:14 - Handle errors from your model executor

      // Custom errors
      
      public enum MyModelError: Error, LocalizedError {
          // User hit monthly token limit. Prompt upgrade or wait for reset.
          case exceededSubscriptionTierLimit
          // Model variant isn't enabled on this account.
          case modelNotProvisioned
          // Billing or policy review locked this account.
          case accountSuspended
      
          public var errorDescription: String? {
              switch self {
              case .exceededSubscriptionTierLimit:
                  String(localized: "Your plan limit has been reached.")
              // ...
              }
          }
      }
    • 16:08 - Attach custom metadata to responses

      // Attach service-specific performance metadata
      
      let elapsed = Date().timeIntervalSince(startTime)
      let tokensPerSecond = Double(tokenCount) / elapsed
      let timeToFirstToken = firstTokenTime?.timeIntervalSince(startTime) ?? 0
      
      await channel.send(.metadataUpdate([
          "tokensPerSecond": tokensPerSecond,
          "timeToFirstToken": timeToFirstToken
      ]))
    • 17:05 - Define and use custom Transcript segments

      // Define a custom segment
      public struct AudioSegment: Transcript.CustomSegment {
          public var id: String
          public var content: URL
      }
      
      // Pass it in a prompt
      let recording = AudioSegment(id: UUID().uuidString, content: URL(filePath: "/path/to/recording.m4a"))
      let response = try await session.respond {
          "Where was Frank Lloyd Wright's original architecture school located?"
          recording
      }
      
      // Emit a custom segment from the executor
      for try await event in stream {
          switch event {
          case .audioFileGenerated(let file):
              await channel.send(.response(action: .updateCustomSegment(
                  AudioSegment(id: file.id, content: file.url)
              )))
          }
      }
    • 18:09 - Implement server-side tools in your model

      // Configure server-side tools
      public struct MyLanguageModel: LanguageModel {
          public struct ServerTool: Sendable {
              public static let webSearch: ServerTool = ...
          }
          public init(serverTools: [ServerTool] = []) { }
      }
      
      // Surface tool results through the channel
      let client = MyServerClient(serverTools: model.serverTools)
      let response = try await client.send(prompt: .init(request))
      for try await chunk in response {
          switch chunk {
          case .webSearch(let webSearch):
              await channel.send(.response(action: .updateCustomSegment(
                  WebSearchSegment(url: webSearch.url, content: webSearch.html)
              )))
          case .textDelta(let textDelta):
              await channel.send(.response(action: .appendText(
                  textDelta.text, tokenCount: textDelta.tokenCount
              )))
          }
      }
    • 0:00 - Introduction
    • Overview of the Foundation Models framework opening to nearly any LLM. Covers improvements to the on-device System Language Model, three new model options (Private Cloud Compute, Core AI, and MLX), upcoming Anthropic and Google partner integrations, and a code preview showing how any model can be swapped into a LanguageModelSession using the same Swift API.

    • 3:37 - Packaging
    • How to package your LLM provider as a Swift package — configuring Package.swift with the right platform targets (iOS, macOS, visionOS, watchOS, and Linux), being deliberate about dependencies to minimize shipped bytes, and publishing a release via a git tag that developers can paste directly into Xcode.

    • 4:48 - Protocol
    • The two core protocol types bridging your model to the framework: LanguageModel (declares capabilities and provides a Configuration) and LanguageModelExecutor (handles prewarm, translates Transcript entries to your inference engine's native format, applies ContextOptions and GenerationOptions, and streams responses with metadata-first ordering). Covers executor caching by configuration and KV cache state reuse across calls, plus how to approximate unsupported options or throw LanguageModelError when needed.

    • 14:50 - Authentication
    • Best practices for credential handling — designing initializers that guide developers toward secure usage rather than plain API key strings, persisting tokens securely via Keychain, and using App Attest for device attestation to verify devices, catch tampered builds, and protect cloud-based language model services.

    • 15:51 - Customization
    • How to differentiate your model package beyond the protocol fundamentals — attaching custom response metadata (e.g., tokensPerSecond, timeToFirstToken), defining custom segment types for new input and output modalities (audio, video, and beyond), and implementing server-side tools (web search, code execution, image generation) at three levels of visibility: privately grounded, metadata-enriched, or fully surfaced through custom segments.

    • 19:47 - Next steps
    • Privacy considerations when choosing or shipping a model package — on-device versus cloud-based models have very different characteristics and users deserve to know which they're getting. Pointers to companion sessions on Core AI model integration, Private Cloud Compute, and building agentic app experiences on top of the new model ecosystem.

Developer Footer

  • ビデオ
  • WWDC26
  • Foundation ModelフレームワークへのLLMプロバイダーの導入
  • メニューを開く メニューを閉じる
    • iOS
    • iPadOS
    • macOS
    • tvOS
    • visionOS
    • watchOS
    Open Menu Close Menu
    • Swift
    • SwiftUI
    • Swift Playground
    • TestFlight
    • Xcode
    • Xcode Cloud
    • SF Symbols
    メニューを開く メニューを閉じる
    • アクセシビリティ
    • アクセサリ
    • Apple Intelligence
    • App Extension
    • App Store
    • オーディオとビデオ(英語)
    • 拡張現実
    • デザイン
    • 配信
    • 教育
    • フォント(英語)
    • ゲーム
    • ヘルスケアとフィットネス
    • アプリ内課金
    • ローカリゼーション
    • マップと位置情報
    • 機械学習とAI
    • オープンソース(英語)
    • セキュリティ
    • SafariとWeb(英語)
    メニューを開く メニューを閉じる
    • 英語ドキュメント(完全版)
    • 日本語ドキュメント(一部トピック)
    • チュートリアル
    • ダウンロード
    • フォーラム(英語)
    • ビデオ
    Open Menu Close Menu
    • サポートドキュメント
    • お問い合わせ
    • バグ報告
    • システム状況(英語)
    メニューを開く メニューを閉じる
    • Apple Developer
    • App Store Connect
    • Certificates, IDs, & Profiles(英語)
    • フィードバックアシスタント
    メニューを開く メニューを閉じる
    • Apple Developer Program
    • Apple Developer Enterprise Program
    • App Store Small Business Program
    • MFi Program(英語)
    • Mini Apps Partner Program
    • News Partner Program(英語)
    • Video Partner Program(英語)
    • セキュリティ報奨金プログラム(英語)
    • Security Research Device Program(英語)
    Open Menu Close Menu
    • Appleに相談
    • Apple Developer Center
    • App Store Awards(英語)
    • Apple Design Awards
    • Apple Developer Academy(英語)
    • WWDC
    最新ニュースを読む。
    Apple Developerアプリを入手する。
    Copyright © 2026 Apple Inc. All rights reserved.
    利用規約 プライバシーポリシー 契約とガイドライン