跳过主要内容

如何在Capacitor应用中使用Gemini Nano

使用Gemini Nano在安卓设备上进行Capacitor应用中的AI处理:设备支持、AICore检查、@capgo/capacitor-llm流式传输以及Gemma备用方案。

文章来源

马丁·多纳迪厄

作者

Valeria

审阅者

乔丹

编辑

如何在Capacitor应用中使用Gemini Nano

要在Capacitor应用中使用Gemini Nano,请安装 @capgo/capacitor-llm然后 setModel({ path: 'Gemini Nano' }) 在Android上 textFromAi event. The plugin talks to Gemini Nano through Google’s ML Kit GenAI Prompt API, which runs the model inside Android’s AICore system service, so text never leaves the phone.

该插件通过Google的ML Kit GenAI Prompt code与Gemini Nano进行通信,该模型在Android的AICore系统服务中运行,因此文本永远不会离开手机。

本指南介绍了Gemini Nano的运行方式、支持的设备、准确的插件调用、流式传输、配额和限制、Gemini Nano的Gemma替代品以及__CAPGO_KEEP_0__如何在iOS上实现Apple Intelligence。

如何在Android上运行Gemini Nano AICore 服务下载并更新它,运行推理,应用通过 ML Kit GenAI API:

  • 提示 API: 免费形式的文本提示,API 这个插件使用(com.google.mlkit:genai-prompt).
  • 功能 API: 固定任务,如摘要、校对、重写和图像描述。

Google 将提示 API 作为 beta 版本发布,没有 SLA 或弃用政策,因此在发布之间期望行为变化,并将集成放在自己的小包装器后面。

由于推理是本地的,你可以获得三件云模型无法提供的东西:它可以在离线状态下工作,没有每个令牌的成本,用户文本也会在设备上保留。然而,这意味着使用较小的模型,短的上下文和输出,因此选择适合的任务:重写、摘要笔记、分类消息、提取字段、草拟短回复。

支持设备和要求

Google 在 ML Kit GenAI 网站上根据 API 发布支持列表,按 Gemini Nano 版本(nano-v2、nano-v3、nano-v4)分组。对于 Prompt API,它涵盖了 Pixel 9 和更高版本、最近的 Samsung Galaxy S 和 Z 旗舰机型,以及最近的 OnePlus、OPPO、Xiaomi、vivo、Honor、realme、Motorola 等旗舰机型。检查实时列表之前,不要对特定设备承诺特定功能。

每个支持设备也需要:

需求 详细
Android版本 API 26 或更高(插件会检查此版本)
引导加载程序 锁定。Google 不支持在解锁引导加载程序上运行 GenAI API
AI核心 存在并已设置。设备设置或重置后可能需要一段时间
应用程序状态 您的应用程序必须在推理期间处于顶层前台

不同 Nano 版本可能会为相同的提示返回不同的输出。请在您关心的每个版本上测试至少一个设备

安装插件

bun add @capgo/capacitor-llm
bunx cap sync

该插件遵循 Capacitor 的主要版本:使用 8.x 与 Capacitor 8。对于 Gemini Nano,不需要进行 Android 清单更改。详细参考: 插件文档 和 插件页面.

步骤 1:加载 Gemini Nano 并检查就绪

setModel 特殊路径 'Gemini Nano' 询问 ML Kit 模型状态。它在状态可用时解析,否则拒绝,并包含状态的消息:

AICore 状态 插件行为
可用 setModel 解析 readinessChange 发射 ready
可下载 拒绝:"Gemini Nano 可下载但未在本设备上下载"
下载中 拒绝:"Gemini Nano 在本设备上不可用"
不可用 该插件不会启动 AICore 模型下载。 如果设备报告可下载,模型通常在另一个应用或系统请求后到达,因此在后续启动时检查一次,而不是永久隐藏功能。
import { Capacitor } from '@capacitor/core';
import { CapgoLLM } from '@capgo/capacitor-llm';

export async function loadGeminiNano(): Promise<boolean> {
  if (Capacitor.getPlatform() !== 'android') return false;

  try {
    await CapgoLLM.setModel({
      path: 'Gemini Nano',
      temperature: 0.3,
      topk: 16,
    });
  } catch (error) {
    console.warn('Gemini Nano not ready:', error);
    return false;
  }

  const { readiness } = await CapgoLLM.getReadiness();
  return readiness === 'ready';
}

步骤 2:创建聊天并流式传输答案

一个聊天会保留会话历史。 在 Android 上,

在生成开始时立即解决,文本通过事件传递。 Wrap 在一个 promise 中,解决于 sendMessage 用于一个真实功能,例如为客户评论撰写回复: aiFinished:

import { CapgoLLM } from '@capgo/capacitor-llm';

// Android sends deltas. iOS Apple Intelligence sends the full text so far.
// This merge handles both.
function mergeChunk(current: string, chunk: string) {
  return chunk.startsWith(current) ? chunk : current + chunk;
}

export async function ask(
  chatId: string,
  message: string,
  onText: (textSoFar: string) => void,
): Promise<string> {
  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', (event) => {
      if (event.chatId !== chatId) return;
      text = mergeChunk(text, event.text);
      onText(text);
    }),
    CapgoLLM.addListener('aiFinished', (event) => {
      if (event.chatId === chatId) finish(text);
    }),
    CapgoLLM.addListener('generationError', (event) => {
      if (!event.chatId || event.chatId === chatId) fail(new Error(event.error));
    }),
  ]);

  // If the app is backgrounded mid-answer, neither event may arrive
  const timeout = setTimeout(() => fail(new Error('Generation timed out')), 60_000);

  try {
    await CapgoLLM.sendMessage({ chatId, message });
    return await done;
  } finally {
    clearTimeout(timeout);
    await Promise.all(handles.map((h) => h.remove()));
  }
}

不需要任何选项,因此在第一条消息的开始添加说明。 为每个任务创建一个新聊天。 在 Gemini Nano 路径上,插件会在内存中保留历史并在每个消息中发送,因此长聊天会迅速耗尽输入预算。

const INSTRUCTIONS =
  'You write short, polite replies to customer reviews for a small shop. ' +
  'Answer each point, stay under 60 words, never promise refunds.';

export async function draftReply(review: string, render: (t: string) => void) {
  const { id } = await CapgoLLM.createChat();
  return ask(id, `${INSTRUCTIONS}\n\nReview:\n${review}\n\nReply:`, render);
}

createChat() 下载

设计限制

限制 值 要做什么
输入 在 Google 的请求中,token 数量不超过 4,000 个 保持聊天短暂,简化长篇文章
输出 Gemini Nano 响应的插件限制在 256 个 token 要求短输出,拆分长任务
前景 仅在应用程序位于顶部时进行推理 不要从后台任务中运行它
配额 每个应用程序的配额 BUSY 和电池配额错误 防抖,避免每次敲击键盘时都生成
并发 每个聊天记录生成一次 禁用发送按钮时正在流式传输
速度 几秒钟用于段落 始终将流式传输传递到 UI

将配额错误视为暂时性。显示一个重试选项而不是错误对话框

fallback: Gemma 4 当 Gemini Nano 缺失时

大多数在使用中的 Android 手机都没有 Gemini Nano。同样的插件可以通过 LiteRT-LM 运行开源的 Gemma 模型,所以您可以保留一个 API。该模型很大,通常超过 1GB,因此请在用户同意后下载它,理想情况下在 Wi-Fi 网络下下载。

import { Preferences } from '@capacitor/preferences';
import { CapgoLLM } from '@capgo/capacitor-llm';

const GEMMA_URL =
  'https://huggingface.co/litert-community/gemma-4-E2B-it-litert-lm/resolve/main/gemma-4-E2B-it.litertlm?download=true';

export async function loadGemma(onProgress: (pct: number) => void) {
  const saved = await Preferences.get({ key: 'gemmaPath' });
  if (saved.value) {
    try {
      await CapgoLLM.setModel({ path: saved.value, modelType: 'litertlm', maxTokens: 4096 });
      return;
    } catch {
      // File missing or corrupt, download again
    }
  }

  const sub = await CapgoLLM.addListener('downloadProgress', (e) => onProgress(e.progress));
  try {
    const { path } = await CapgoLLM.downloadModel({
      url: GEMMA_URL,
      filename: 'gemma-4-E2B-it.litertlm',
    });
    await Preferences.set({ key: 'gemmaPath', value: path });
    await CapgoLLM.setModel({ path, modelType: 'litertlm', maxTokens: 4096 });
  } finally {
    await sub.remove();
  }
}

然后在启动时选择引擎:

export async function initOnDeviceAI(userAcceptedDownload: boolean, onProgress: (p: number) => void) {
  if (await loadGeminiNano()) return 'gemini-nano';
  if (userAcceptedDownload) {
    await loadGemma(onProgress);
    return 'gemma';
  }
  return 'none';
}

如果无法实现,请隐藏该功能或调用云模型。不要阻塞本地 AI 流程。

同样的 code 在 iOS 上

在 iOS 上,插件使用 Apple Intelligence 通过 Foundation Models 框架。只需修改一行代码:

await CapgoLLM.setModel({ path: 'Apple Intelligence' });

createChat, sendMessage,并且事件保持不变, mergeChunk 上面的助手已经处理了 iOS 流式传输格式。设备要求不同(iOS 26 和 Apple Intelligence 兼容设备)。我们的指南《在 __CAPGO_KEEP_0__ 应用中使用 Apple Intelligence》 Apple Intelligence in a Capacitor app 测试

Testing

  • 测试
  • 記錄拒絕的 setModel 消息。它告訴你 AICore 報告的具體狀態。
  • 在剛剛設定或重置的設備上,等待 AICore 完成初始設定時線上,然後重試。
  • 在您支持的 Nano 最低版本上測試您的提示。更短、更明確的提示在版本之間更穩定。

故障排除

“该设备上Gemini Nano不可用。” “這台設備上無法使用 Gemini Nano”。

設備未在 Google 的清單中,啟動器被解鎖,或 AICore 尚未設定。 “Gemini Nano 可下載但未下載”。

設備支持它,但模型未出現。提供 Gemma 附加或稍後重試。 “聊天會話未找到”。 sendMessage 您曾經 setModel正在加载模型会清除现有的聊天记录,所以请创建一个新的聊天记录。

“模型尚未准备好”。 setModel 失败或未被调用 createChat.

输出中断在句子中。 您已达到输出限制。请要求更短的答案或将任务分解。

应用程序切换到后台时出现错误。 推理仅在前台进行。请在暂停时取消 UI 状态并让用户重试。

隐私和商店评论

Gemini Nano 的提示和响应会在设备上保留,这简化了您的数据安全表单。Google 的 ML Kit 条款仍然提到指标处理,因此在隐私政策中描述设备上的 AI 使用。如果您添加 Gemma 降级,模型下载来自 Hugging Face,因此也要提到网络请求。

AI 功能的提示和 UI 复制内容会经常变化。如果您需要在发布后调整它们,请 Capgo实时更新 让您可以在不等待商店评论的情况下发布新的 web code。关于混合应用中的 AI 的更大背景,请阅读 为什么 Capacitor 适合 AI 移动应用.

总结

Gemini Nano 为 Capacitor 应用提供了免费、安全、离线的文本生成功能,支持的 Android 手机上可以使用。 setModel({ path: 'Gemini Nano' })载入它,流式传输 textFromAi保持提示和输出短,遵守前景和配额规则,并为无法安装它的许多设备保留一个 Gemma 或云备份。

Capacitor 应用程序的即时更新

Capgo 应用程序的即时更新

当 web 层面的 bug 在 live 时,通过 __CAPGO_KEEP_0__ 发布修复,而不是等待几天的 app store 审核。用户在后台接收更新,而原生变化仍然在正常的审查路径中。

来自马丁的人性化支持

立即开始

Capgo 为您提供了创建真正专业的移动应用所需的最佳见解。