Pour utiliser Apple Intelligence dans une application Capacitor, installez @capgo/capacitor-llm, appelez setModel({ path: 'Apple Intelligence' }), vérifiez getReadiness(), puis créez un chat et diffusez les réponses via l'événement textFromAi Sous le capot, le plugin utilise le framework Foundation Models d'Apple, introduit avec iOS 26, qui exécute le modèle de langage embarqué d'Apple sans clé API, sans coût par requête et sans que les données quittent le téléphone.
Ce guide couvre ce que le framework propose, les prérequis d'appareil, une intégration TypeScript complète, la fenêtre de contexte de 4 096 tokens, la gestion des erreurs, les notes pour l'App Review et comment le même code fonctionne sur Android.
Ce qu'Apple Intelligence offre aux développeurs d'applications
Avec iOS 26, Apple a ouvert son modèle de fondation embarqué aux applications tierces via le Modèles de fondation framework. En Swift, vous travaillez avec SystemLanguageModel et LanguageModelSession. The plugin wraps those so your web code can use them:
| Concept des Foundation Models | Équivalent du plugin |
|---|---|
SystemLanguageModel.default.availability |
getReadiness() |
LanguageModelSession |
createChat() retourne un id |
session.streamResponse(to:) |
sendMessage() , ce qui textFromAi événements |
| Erreurs levées pendant la génération | generationError événement et d'un sendMessage |
Le modèle compte environ 3 milliards de paramètres. Il excelle dans la synthèse, la réécriture, l’extraction, la classification et la génération de textes courts. Il ne remplace pas un grand modèle cloud pour les questions de connaissance ouvertes, et Apple le précise dans ses propres recommandations. Concevez vos fonctionnalités autour des textes que l’utilisateur possède déjà.
Exigences matérielles et système d’exploitation
| Exigence | Détail |
|---|---|
| iPhone | iPhone 15 Pro, 15 Pro Max et modèles iPhone 16 et ultérieurs |
| iPad | iPad mini (A17 Pro), iPad avec puce M1 et versions ultérieures |
| Mac | Mac Apple silicon (utile pour les tests dans le Simulateur) |
| OS | iOS 26 / iPadOS 26 ou version ultérieure |
| Paramètre | Apple Intelligence activé dans Réglages > Apple Intelligence & Siri |
| Langue | Appareil et Siri configurés sur une langue prise en charge par Apple Intelligence |
| Stockage | Apple réserve environ 7 Go d’espace libre pour les modèles Apple Intelligence |
| Chaîne d’outils | Xcode 26, également requis par App Store Connect pour les uploads depuis avril 2026 |
Si votre projet est encore compilé avec une version antérieure de Xcode, voir Xcode 26 désormais exigé par Apple pour les apps Capacitor. La cible de déploiement minimale de votre application n’a pas besoin d’être modifiée. Le plugin prend en charge iOS 15 et ultérieur et n’interagit avec Foundation Models que sur iOS 26.
Installer le plugin
bun add @capgo/capacitor-llm
bunx cap sync ios
Utilisez le plugin 8.x avec Capacitor 8. Aucune clé Info.plist ni entitlement n’est nécessaire pour Apple Intelligence. Si vous êtes encore sur Capacitor 7, le Capacitor guide de mise à niveau vient en premier. Documentation de référence : /docs/plugins/llm/.
Étape 1 : Sélectionner le modèl’et vérifier la disponibilité
setModel({ path: 'Apple Intelligence' }) sélectionne le modèle système et se résout immédiatement. La disponibilité réelle provient de getReadiness(), qui convertit l'enum de disponibilité d'Apple en chaînes lisibles :
readiness valeur |
Signification | Ce qu'il faut afficher |
|---|---|---|
ready |
Modèle disponible | La fonctionnalité |
Device is not eligible for Apple Intelligence |
Matériel non pris en charge | Masquer la fonctionnalité ou utiliser un fallback cloud |
Apple Intelligence is not enabled |
L'utilisateur l'a désactivée | Une indication pour l'activer dans les Réglages |
Model is not ready |
Model still downloading or preparing | « Préparation », réessayez plus tard |
Apple Intelligence requires iOS 26.0 or later |
Older iOS | Masquer la fonctionnalité |
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';
}
Vérifiez à nouveau lorsque l’application revient au premier plan. Les utilisateurs activent souvent Apple Intelligence après avoir vu votre indication, et le téléchargement du modèle peut se terminer pendant que votre application est en arrière-plan.
import { App } from '@capacitor/app';
App.addListener('appStateChange', async ({ isActive }) => {
if (isActive) updateAIState(await initAppleIntelligence());
});
Étape 2 : créer un chat avec des instructions
Un chat correspond à un LanguageModelSession, qui conserve l’historique de la conversation. Le texte saisi createChat() ne prend aucune option, placez donc vos instructions au début du premier message :
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();
Utilisez un chat par tâche. Un chat qui ne cesse de grandir finira par atteindre la limite de contexte décrite ci-dessous.
Étape 3 : streamer la réponse dans l’UI
Sur iOS, chaque textFromAi l'événement contient un instantané de la réponse jusqu'ici, car c'est ainsi que Foundation Models fonctionne en streaming. Sur Android avec Gemini Nano, les événements ne contiennent que le nouveau texte. Ce helper gère les deux cas et résout la promesse avec le texte final :
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()));
}
}
Assembler le tout : résumer les notes sur l’appareil
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);
}
Le slice est un garde-fou rudimentaire contre les entrées volumineuses. Une meilleure approche consiste à résumer les longs documents en plusieurs morceaux, puis à résumer les résumés, chacun dans un nouveau chat.
Dans un composant de framework, désactivez le bouton pendant que ask s'exécute. Le plugin rejette un second sendMessage sur le même chat avec le message « chat is responding, please wait before asking new questions ».
La fenêtre de contexte de 4 096 tokens
Le modèl’on-device dispose d'une fenêtre de contexte de 4 096 tokens. Tout y compte : les instructions, chaque tour précédent du chat, le nouveau prompt et la réponse en cours de génération. Lorsqu'une session dépasse cette limite, Foundation Models lève une erreur « exceeded context window size », qui vous parvient sous forme d'un generationError événement et d'un sendMessage.
Règles pratiques :
- Un chat par tâche, pas un chat par écran.
- Gardez les instructions courtes et précises.
- Pour un chat multi-tours, démarrez une nouvelle conversation quand elle devient longue et transmettez un résumé court de l’échange précédent.
- Demandez une réponse concise. Les réponses longues utilisent le même budget.
Ajuster la sortie
Sur le chemin Apple Intelligence, le plugin utilise les paramètres de génération par défaut du système. temperature, topk, et maxTokens dans setModel s’appliquent aux chemins personnalisés des modèles LiteRT-LM et MediaPipe. Pour orienter le modèle d’Apple, fiez-vous au prompt : précisez la longueur attendue de la réponse, indiquez le format (puces, JSON, une phrase) et incluez un exemple court si le format est important.
Le même code sur Android
Seule la sélection du modèle change :
const path = Capacitor.getPlatform() === 'ios' ? 'Apple Intelligence' : 'Gemini Nano';
await CapgoLLM.setModel({ path });
Sur Android, setModel rejette la requête si Gemini Nano n’est pas disponible, et vous pouvez basculer sur un modèle Gemma téléchargeable via le même plugin. Les détails sont dans comment utiliser Gemini Nano dans une app Capacitor.
En test
- Appareil réel : la voie la plus fiable. Utilisez un iPhone compatible sous iOS 26 avec Apple Intelligence activé.
- Simulateur : il peut utiliser le modèle si le Mac hôte exécute macOS 26 sur Apple silicon avec Apple Intelligence activé. Le comportement et la vitesse diffèrent de ceux d'un téléphone : validez donc sur un appareil physique.
- États non pris en charge : testez avec Apple Intelligence désactivé pour vérifier votre interface « Activer dans les Réglages », et sur un iPhone ou une version d'iOS plus ancienne pour vérifier que la fonctionnalité se masque correctement.
App Review et confidentialité
Les prompts et les réponses restent sur l'appareil : la génération on-device n'ajoute donc en soi aucune collecte de données à votre étiquette de confidentialité. Deux points restent toutefois à votre charge :
- Apple publie des exigences d'utilisation acceptable pour le framework Foundation Models. Lisez-les avant de déployer, surtout pour les fonctionnalités qui génèrent du contenu affiché à d'autres utilisateurs.
- Le modèle dispose de garde-fous intégrés et peut refuser certains prompts ou sorties. Considérez un refus comme un résultat normal et affichez un message clair.
Comme les prompts sont de simples chaînes de caractères dans votre web code, vous pouvez les améliorer après le lancement avec les live updates Capgo au lieu d’attendre un nouveau build App Store. Les modifications du code natif, y compris les mises à niveau de plugins, nécessitent toujours une release store, que vous pouvez compiler dans le cloud avec Build Capgo.
Erreurs courantes et solutions
| Symptôme | Cause probable | Corriger |
|---|---|---|
readiness est « L'appareil n'est pas éligible » |
iPhone antérieur au 15 Pro ou iPad non pris en charge | Masquer la fonctionnalité ou utiliser un modèle serveur |
readiness est « non activé » |
L'utilisateur a désactivé Apple Intelligence | Show a Settings hint, recheck on resume |
readiness est « Model is not ready » |
Téléchargement du modèl’en cours | Afficher un état de préparation, réessayer plus tard |
sendMessage rejette « error deviceNotEligible error » |
Envoi sans vérifier la disponibilité | Activer getReadiness() d'abord |
| « chat not found » | Chat créé avant un nouveau setModel Appelez |
Appeler setModel efface les discussions, en crée une nouvelle |
| « la discussion répond » | Deuxième message envoyé pendant le streaming | Désactiver la saisie jusqu'à aiFinished |
generationError en mentionnant la fenêtre de contexte |
Discussion trop longue | Démarrer une nouvelle conversation avec un résumé |
| Erreur de build concernant Foundation Models | Xcode antérieur à la version 26 | Mettre à jour Xcode ou compiler dans le cloud |
Récapitulatif
Apple Intelligence apporte un modèle de langage gratuit, privé et hors ligne à chaque iPhone éligible sous iOS 26, et une app Capacitor peut l’utiliser en quelques lignes de TypeScript. Sélectionnez le modèle, conditionnez l’UI sur getReadiness(), gardez chaque tâche dans sa propre conversation courte, diffusez les instantanés dans l’UI et gérez les refus et les erreurs de contexte comme des résultats normaux. Pour une vue d’ensemble sur la publication de fonctionnalités IA dans les apps hybrides, lisez pourquoi Capacitor convient bien aux apps mobiles d'IA.