Salta al contenuto principale

Come usare Apple Intelligence in un'app Capacitor

Usa Apple Intelligence in un'app Capacitor tramite il framework Foundation Models su iOS 26: controlli sul dispositivo, streaming, limiti di contesto ed errori.

Illustrazione delle funzionalità di AI on-device all'interno di un'app Capacitor su iPhone

Per usare Apple Intelligence in un'app Capacitor, installa @capgo/capacitor-llm, chiama setModel({ path: 'Apple Intelligence' }), controlla getReadiness(), poi crea una chat e ricevi le risposte in streaming tramite l' textFromAi event. Sotto il cofano, il plugin usa il framework Foundation Models di Apple, introdotto con iOS 26, che esegue il modello linguistico on-device di Apple senza chiave API, senza costi per richiesta e senza che i dati lascino il telefono.

Questa guida copre cosa offre il framework, i requisiti del dispositivo, un'integrazione TypeScript completa, la context window da 4.096 token, la gestione degli errori, le note per l'App Review e come lo stesso code funziona su Android.

Cosa offre Apple Intelligence agli sviluppatori di app

Con iOS 26, Apple ha aperto il suo foundation model on-device alle app di terze parti tramite il Modelli di base framework. In Swift lavori con SystemLanguageModel e LanguageModelSession. Il plugin li incapsula in modo che il tuo code web possa usarli:

Concetto Foundation Models Equivalente del plugin
SystemLanguageModel.default.availability getReadiness()
LanguageModelSession createChat() restituisce un ID
session.streamResponse(to:) sendMessage() più textFromAi eventi
Errori lanciati durante la generazione generationError evento e una promessa rifiutata sendMessage

Il modello ha circa 3 miliardi di parametri. È ottimo per riassumere, riscrivere, estrarre, classificare e generare testi brevi. Non sostituisce un modello cloud di grandi dimensioni per domande aperte su conoscenze generali, e Apple lo dice chiaramente nelle proprie linee guida. Progetta le funzionalità intorno al testo che l'utente ha già.

Requisiti di dispositivo e OS

Requisito Dettaglio
iPhone iPhone 15 Pro, 15 Pro Max e modelli iPhone 16 e successivi
iPad iPad mini (A17 Pro), iPad con chip M1 o successivi
Mac Mac con Apple silicon (rilevanti per i test nel Simulator)
OS iOS 26 / iPadOS 26 o versioni successive
Impostazione Apple Intelligence attivata in Impostazioni > Apple Intelligence & Siri
Lingua Lingua del dispositivo e di Siri impostata su una lingua supportata da Apple Intelligence
Archiviazione Apple indica circa 7 GB di spazio libero per i modelli Apple Intelligence
Toolchain Xcode 26, richiesto da App Store Connect anche per gli upload da aprile 2026

Se il tuo progetto compila ancora con una versione precedente di Xcode, vedi Il requisito Xcode 26 di Apple per le app Capacitor. Il deployment target minimo della tua app non deve cambiare. Il plugin supporta iOS 15 e versioni successive e tocca i Foundation Models solo su iOS 26.

Installa il plugin

bun add @capgo/capacitor-llm
bunx cap sync ios

Usa il plugin 8.x con Capacitor 8. Non servono chiavi Info.plist o entitlements per Apple Intelligence. Se usi ancora Capacitor 7, la guida all'aggiornamento a Capacitor 8 viene prima. Documentazione di riferimento: /docs/plugins/llm/.

Passaggio 1: Seleziona il modello e verifica la disponibilità

setModel({ path: 'Apple Intelligence' }) seleziona il modello di sistema e si risolve subito. La disponibilità effettiva arriva da getReadiness(), che mappa l'enum di disponibilità di Apple in stringhe leggibili:

readiness valore Significato Cosa mostrare
ready Modello disponibile La funzionalità
Device is not eligible for Apple Intelligence Hardware non supportato Nascondi la funzionalità o usa un fallback cloud
Apple Intelligence is not enabled L'utente l'ha disattivata Un suggerimento per attivarla nelle Impostazioni
Model is not ready Modello ancora in download o in preparazione “In preparazione”, riprova più tardi
Apple Intelligence requires iOS 26.0 or later iOS più vecchi Nascondi la funzionalità
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';
}

Ricontrolla quando l'app torna in primo piano. Gli utenti spesso abilitano Apple Intelligence dopo aver visto il tuo suggerimento, e il download del modello può completarsi mentre l'app è in background.

import { App } from '@capacitor/app';

App.addListener('appStateChange', async ({ isActive }) => {
  if (isActive) updateAIState(await initAppleIntelligence());
});

Passaggio 2: Crea una chat con istruzioni

Una chat corrisponde a un LanguageModelSession, che mantiene la cronologia della conversazione. Il createChat() non accetta opzioni, quindi inserisci le istruzioni all'inizio del primo messaggio:

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();

Usa una chat per ogni task. Una chat che continua a crescere finirà per raggiungere il limite di contesto descritto di seguito.

Passaggio 3: Fai streaming della risposta nella UI

Su iOS, ogni textFromAi l'evento contiene uno snapshot della risposta fino a quel momento, perché è così che Foundation Models gestisce lo streaming. Su Android con Gemini Nano, gli eventi contengono solo il nuovo testo. Questo helper gestisce entrambi i casi e restituisce il testo finale:

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()));
  }
}

Mettiamo tutto insieme: riassumere le note sul dispositivo

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);
}

Il slice è una protezione rudimentale contro input enormi. Un approccio migliore è riassumere i documenti lunghi in chunk e poi riassumere i riassunti, ognuno in una nuova chat.

In un componente del framework, disabilita il pulsante mentre ask è in esecuzione. Il plugin rifiuta una seconda sendMessage sulla stessa chat con il messaggio “la chat sta rispondendo, attendi prima di porre nuove domande”.

La context window da 4.096 token

Il modello on-device ha una context window di 4.096 token. Tutto contribuisce al limite: istruzioni, ogni turno precedente della chat, il nuovo prompt e la risposta in generazione. Quando una sessione lo supera, Foundation Models restituisce un errore “exceeded context window size”, che ti arriva come generationError evento e una promessa rifiutata sendMessage.

Regole pratiche:

  • Una chat per task, non una chat per schermata.
  • Mantieni le istruzioni brevi e specifiche.
  • Per chat multi-turno, avvia una nuova chat quando diventa lunga e passa un breve riassunto della conversazione precedente.
  • Chiedi output concisi. Le risposte lunghe consumano lo stesso budget.

Ottimizzazione output

Sul percorso Apple Intelligence il plugin usa le impostazioni di generazione predefinite del sistema. temperature, topk, e maxTokens nella setModel si applicano ai percorsi dei modelli personalizzati LiteRT-LM e MediaPipe. Per guidare il modello di Apple, affidati al prompt: indica quanto deve essere lunga la risposta, specifica il formato (elenchi puntati, JSON, una frase) e includi un breve esempio quando il formato conta.

Lo stesso code su Android

Cambia solo la selezione del modello:

const path = Capacitor.getPlatform() === 'ios' ? 'Apple Intelligence' : 'Gemini Nano';
await CapgoLLM.setModel({ path });

Su Android, setModel rifiuta quando Gemini Nano non è disponibile e puoi usare come fallback un modello Gemma scaricabile tramite lo stesso plugin. I dettagli sono in come usare Gemini Nano in un'app Capacitor.

Test

  • Dispositivo reale: la via affidabile. Usa un iPhone supportato su iOS 26 con Apple Intelligence attivo.
  • Simulatore: può usare il modello se il Mac host esegue macOS 26 su Apple silicon con Apple Intelligence attivo. Comportamento e velocità sono diversi da quelli di un telefono, quindi verifica sull'hardware.
  • Stati non supportati: testa con Apple Intelligence disattivato per verificare la UI “abilita in Impostazioni”, e su un iPhone o una versione di iOS precedente per controllare che la funzionalità si nasconda correttamente.

App Review e privacy

Prompt e risposte restano sul dispositivo, quindi la generazione on-device non aggiunge di per sé alcuna raccolta dati alla tua etichetta privacy. Restano comunque due cose a tuo carico:

  1. Apple pubblica i requisiti di utilizzo accettabile per il framework Foundation Models. Leggili prima di pubblicare, soprattutto per le funzionalità che generano contenuti mostrati ad altri utenti.
  2. Il modello ha guardrail integrati e potrebbe rifiutare alcuni prompt o output. Tratta un rifiuto come un risultato normale e mostra un messaggio chiaro.

Poiché i prompt sono semplici stringhe nel tuo code web, puoi migliorarli dopo il lancio con Live updates di Capgo invece di aspettare una nuova build per l'App Store. Le modifiche al code nativo, inclusi gli upgrade dei plugin, richiedono ancora un rilascio sugli store, che puoi buildare in cloud con Build Capgo.

Errori comuni e soluzioni

Sintomo Causa probabile Soluzione
readiness è “Device is not eligible” iPhone precedenti al 15 Pro o iPad non supportati Nascondi la funzionalità o usa un modello server
readiness è “not enabled” L'utente ha disattivato Apple Intelligence Mostra un hint in Impostazioni, ricontrolla al resume
readiness è “Model is not ready” Modello ancora in download Mostra uno stato di preparazione, riprova più tardi
sendMessage rifiuta con “error deviceNotEligible error” Invio senza verificare la disponibilità Gate attivo getReadiness() per primo
“chat non trovata” Chat creata prima di una nuova setModel chiamata In chiamata setModel cancella le chat, creane una nuova
“la chat sta rispondendo” Secondo messaggio inviato durante lo streaming Disabilita l'input fino a aiFinished
generationError menzionando la context window Chat troppo lunga Inizia una nuova chat con un riassunto
Errore di build sui Foundation Models Xcode precedente alla versione 26 Aggiorna Xcode o fai la build nel cloud

In sintesi

Apple Intelligence porta un modello linguistico gratuito, privato e offline su ogni iPhone compatibile con iOS 26, e un'app Capacitor può usarlo con poche righe di TypeScript. Seleziona il modello, vincola la UI a getReadiness(), tieni ogni task nella sua chat breve, fai lo streaming degli snapshot nella UI e gestisci i rifiuti e gli errori di contesto come esiti normali. Per una visione più ampia su come rilasciare funzionalità AI nelle app ibride, leggi perché Capacitor è ideale per le app mobile AI.

Live updates per le app Capacitor

Quando un bug nel web-layer è live, rilascia la fix tramite Capgo invece di aspettare giorni l'approvazione degli store. Gli utenti ricevono l'update in background, mentre le modifiche native restano nel normale processo di review.

Ultimi articoli dal blog

Capgo ti offre gli insight migliori che ti servono per creare un'app mobile davvero professionale.