CapacitorアプリでApple Intelligenceを使うには、インストールしてください @capgo/capacitor-llm、呼び出し setModel({ path: 'Apple Intelligence' })、確認し getReadiness()、次にチャットを作成し、返信をストリーミングします。経由するのは textFromAi イベントです。内部的には、このプラグインはiOS 26で導入されたAppleのFoundation Models frameworkを使用しています。これにより、APIキー不要、リクエストごとの課金なし、データが端末外に出ない状態で、Appleのオンデバイス言語モデルを実行できます。
このガイドでは、フレームワークでできること、デバイス要件、TypeScript統合の完全な例、4,096トークンのコンテキストウィンドウ、エラーハンドリング、App Review向けの注意点、そして同じcodeがAndroidで動作する方法を解説します。
Apple Intelligenceがアプリ開発者に提供する機能
iOS 26で、Appleはオンデバイスの基盤モデルをサードパーティアプリに開放しました 基盤モデル framework。Swiftでは、次のものを扱います SystemLanguageModel と LanguageModelSession。このプラグインはそれらをラップしているため、Web側のcodeから利用できます:
| Foundation Modelsの概念 | プラグイン側の対応 |
|---|---|
SystemLanguageModel.default.availability |
getReadiness() |
LanguageModelSession |
createChat() IDを返します |
session.streamResponse(to:) |
sendMessage() と textFromAi イベント |
| 生成中に発生したエラー | generationError イベントと拒否された sendMessage |
このモデルは約30億パラメータで、要約、書き換え、抽出、分類、短文生成が得意です。オープンエンドな知識を問う質問では、大規模クラウドモデルの代替にはなりません。Apple自身もガイドラインでそう述べています。ユーザーがすでに持っているテキストを軸に機能を設計してください。
デバイスとOSの要件
| 要件 | 詳細 |
|---|---|
| iPhone | iPhone 15 Pro、15 Pro Max、iPhone 16 以降のモデル |
| iPad | iPad mini (A17 Pro)、M1 以降の iPad |
| Mac | Apple silicon 搭載 Mac(Simulator でのテストに関連) |
| OS | iOS 26 / iPadOS 26 以降 |
| 設定 | 設定 > Apple Intelligence & Siri で Apple Intelligence をオンにする |
| 言語 | デバイスと Siri の言語を、Apple Intelligence がサポートする言語に設定する |
| ストレージ | Apple Intelligenceモデルには約7GBの空き容量が必要です |
| ツールチェーン | 2026年4月以降、App Store Connectでのアップロードにも必須のXcode 26 |
古いXcodeでビルドできるプロジェクトについては、 Appleによる Capacitor アプリ向けのXcode 26要件を参照してください。アプリの最低デプロイターゲットを変更する必要はありません。このプラグインはiOS 15以降をサポートし、iOS 26ではFoundation Modelsにのみ影響します。
プラグインをインストール
bun add @capgo/capacitor-llm
bunx cap sync ios
Capacitor 8とプラグイン8.xを使用してください。Apple IntelligenceにはInfo.plistのキーやエンタイトルメントは不要です。まだCapacitor 7を使用している場合は、 Capacitor 8 アップグレードガイド が優先されます。参考ドキュメント: /docs/plugins/llm/.
ステップ1: モデルを選択し、利用可能性を確認
setModel({ path: 'Apple Intelligence' }) システムモデルを選択し、即座に解決します。実際の利用可能性は getReadiness()から取得され、Appleの利用可能性enumを可読な文字列にマッピングします:
readiness 値 |
意味 | 表示する内容 |
|---|---|---|
ready |
モデルが利用可能 | その機能 |
Device is not eligible for Apple Intelligence |
ハードウェアが非対応 | 機能を非表示にするか、クラウドフォールバックを使用 |
Apple Intelligence is not enabled |
ユーザーがオフに設定 | 設定で有効にするヒント |
Model is not ready |
モデルのダウンロードまたは準備中 | 「準備中」です。後で再試行してください |
Apple Intelligence requires iOS 26.0 or later |
旧バージョンのiOS | 機能を非表示にする |
import { Capacitor } from '@capacitor/core';
import { CapgoLLM } from '@capgo/capacitor-llm';
export type AIState = 'ready' | 'enable-in-settings' | 'preparing' | 'unsupported';
export async function initAppleIntelligence(): Promise<AIState> {
if (Capacitor.getPlatform() !== 'ios') return 'unsupported';
await CapgoLLM.setModel({ path: 'Apple Intelligence' });
const { readiness } = await CapgoLLM.getReadiness();
if (readiness === 'ready') return 'ready';
if (readiness.includes('not enabled')) return 'enable-in-settings';
if (readiness.includes('not ready')) return 'preparing';
return 'unsupported';
}
アプリがフォアグラウンドに戻った際に再確認してください。ユーザーはヒントを見てからApple Intelligenceを有効にすることが多く、アプリがバックグラウンドにある間にモデルのダウンロードが完了する場合があります。
import { App } from '@capacitor/app';
App.addListener('appStateChange', async ({ isActive }) => {
if (isActive) updateAIState(await initAppleIntelligence());
});
ステップ2: 指示を含むチャットを作成
チャットは1つの LanguageModelSessionに対応し、会話履歴を保持します。入力された createChat() はオプションを受け取らないため、最初のメッセージの先頭に指示を記述してください:
const INSTRUCTIONS =
'You summarize meeting notes. Reply with at most 5 bullet points. ' +
'Keep names and dates exactly as written. Do not add information.';
const { id: chatId } = await CapgoLLM.createChat();
タスクごとに1つのチャットを使用してください。チャットが成長し続けると、後述するコンテキスト制限に到達します。
ステップ3: 応答をUIにストリーミング
iOSでは、各 textFromAi イベントはそれまでのレスポンスのスナップショットを保持します。Foundation Models のストリーミングがそのように動作するためです。Android の Gemini Nano では、イベントは新しいテキストのみを保持します。このヘルパーは両方を処理し、最終的なテキストで解決します:
import { CapgoLLM } from '@capgo/capacitor-llm';
function mergeChunk(current: string, chunk: string) {
return chunk.startsWith(current) ? chunk : current + chunk;
}
export async function ask(chatId: string, message: string, onText: (t: string) => void) {
let text = '';
let finish!: (value: string) => void;
let fail!: (error: Error) => void;
const done = new Promise<string>((resolve, reject) => {
finish = resolve;
fail = reject;
});
const handles = await Promise.all([
CapgoLLM.addListener('textFromAi', (e) => {
if (e.chatId !== chatId) return;
text = mergeChunk(text, e.text);
onText(text);
}),
CapgoLLM.addListener('aiFinished', (e) => {
if (e.chatId === chatId) finish(text);
}),
CapgoLLM.addListener('generationError', (e) => {
if (!e.chatId || e.chatId === chatId) fail(new Error(e.error));
}),
]);
try {
await CapgoLLM.sendMessage({ chatId, message });
return await done;
} finally {
await Promise.all(handles.map((h) => h.remove()));
}
}
全体像: デバイス上でメモを要約する
export async function summarizeNotes(notes: string, render: (t: string) => void) {
const state = await initAppleIntelligence();
if (state !== 'ready') throw new Error(`AI unavailable: ${state}`);
const { id } = await CapgoLLM.createChat();
const prompt = `${INSTRUCTIONS}\n\nNotes:\n${notes.slice(0, 8000)}\n\nSummary:`;
return ask(id, prompt, render);
}
この slice は巨大な入力に対する簡易的なガードです。より良いアプローチは、長い文書をチャンクごとに要約し、その後、各要約を新しいチャットで要約することです。
フレームワークコンポーネントでは、 ask 実行中はボタンを無効にします。プラグインは同じチャットで2回目の sendMessage を「チャットが応答中です。新しい質問をする前に待ってください」というエラーで拒否します。
4,096トークンのコンテキストウィンドウ
オンデバイスモデルには4,096トークンのコンテキストウィンドウがあります。すべてがこれにカウントされます: 指示、チャット内のすべての以前のターン、新しいプロンプト、生成中のレスポンス。セッションがこれを超えると、Foundation Models は「コンテキストウィンドウサイズを超えました」エラーをスローし、それはあなたに generationError イベントと拒否された sendMessage.
実践的なルール:
- 1タスクにつき1チャット、1画面につき1チャットではありません。
- 指示は短く、具体的に。
- マルチターンチャットでは、長くなったら新しいチャットを開始し、以前の会話の短い要約を渡してください。
- 簡潔な出力を要求
出力の調整
Apple Intelligence パスでは、プラグインはシステムのデフォルト生成設定を使用します。 temperature, topkや maxTokens における setModel カスタム LiteRT-LM および MediaPipe モデルパスに適用されます。Apple のモデルを制御するには、プロンプトに頼ってください。回答の長さ、形式(箇条書き、JSON、1文)、形式が重要な場合は短い例を1つ含めてください。
Android での同じ code
モデルの選択のみが異なります:
const path = Capacitor.getPlatform() === 'ios' ? 'Apple Intelligence' : 'Gemini Nano';
await CapgoLLM.setModel({ path });
Androidの場合、 setModel Gemini Nano が利用できない場合は拒否され、同じプラグインを通じてダウンロード可能な Gemma モデルにフォールバックできます。詳細は Capacitor アプリで Gemini Nano を使う方法.
テスト
- 実機: 確実な方法です。Apple Intelligenceを有効にしたiOS 26の対応iPhoneを使ってください。
- シミュレーター: Apple silicon搭載のMacでmacOS 26を実行し、Apple Intelligenceを有効にしていれば、モデルを使用できます。挙動や速度は実機とは異なるため、必ず実機で確認してください。
- サポート対象外の状態: 「設定で有効にする」UIを確認するにはApple Intelligenceをオフにしてテストし、機能がきれいに非表示になるかは古いiPhoneやiOSバージョンでテストしてください。
App Reviewとプライバシー
プロンプトとレスポンスはデバイス上に留まるため、オンデバイス生成自体がプライバシーラベルにデータ収集を追加することはありません。ただし、ご自身で対応が必要な点が2つあります:
- AppleはFoundation Modelsフレームワークの利用要件を公開しています。特に他のユーザーに表示するコンテンツを生成する機能では、リリース前に必ず確認してください。
- モデルにはガードレールが組み込まれており、一部のプロンプトや出力を拒否することがあります。拒否は正常な結果として扱い、分かりやすいメッセージを表示してください。
プロンプトはWeb code 内のプレーンな文字列なので、リリース後も以下を使って改善できます: Capgo Live Updates 新しいApp Storeのビルドを待つ必要はありません。プラグインのアップグレードを含むネイティブ code への変更には、引き続きストアへのリリースが必要ですが、これは code を使ってクラウド上でビルド可能です。 Capgo のビルド.
よくあるエラーと解決策
| 症状 | 考えられる原因 | 解決策 |
|---|---|---|
readiness 「Device is not eligible」の場合 |
iPhone 15 Pro より前の機種、または非対応の iPad | 機能を非表示にするか、サーバーモデルを使用する |
readiness 「not enabled」の場合 |
ユーザーが Apple Intelligence をオフにした | 設定のヒントを表示し、再開時に再確認 |
readiness 「Model is not ready」の場合 |
モデルのダウンロード中 | 準備状態を表示し、後で再試行 |
sendMessage 「error deviceNotEligible error」を拒否 |
準備状態を確認せずに送信 | ゲート: getReadiness() 最初に |
| 「chat not found」 | 新しいチャット作成前に setModel 通話 |
呼び出しを setModel チャットをクリアして、新しいチャットを作成します |
| 「チャットが応答中」 | ストリーミング中に送信された2番目のメッセージ | 入力無効化は~まで aiFinished |
generationError コンテキストウィンドウの言及 |
チャットが長すぎます | サマリー付きで新しいチャットを開始 |
| Foundation Models に関するビルドエラー | Xcode が 26 より古い | Xcode を更新するか、クラウドでビルド |
まとめ
Apple Intelligenceは、iOS 26対応のすべてのiPhoneに、無料でプライベートかつオフラインで動作する言語モデルをもたらします。Capacitorアプリでは、TypeScript数行でこれを利用できます。モデルを選択し、UIを getReadiness()で制御し、各タスクを独立した短いチャットに保ち、スナップショットをUIにストリーミングし、拒否やコンテキストエラーを通常の結果として処理します。ハイブリッドアプリでのAI機能の提供についてより広く知りたい場合は、こちらを参照してください なぜ Capacitor はAIモバイルアプリに適しているのか.