DenisovAV/flutter_edge_ai · 上手攻略
- 仓库:
DenisovAV/flutter_edge_ai - 链接:https://github.com/DenisovAV/flutter_edge_ai(官网 https://flutteredge.ai/ · 历史域名 https://fluttergemma.dev/ 仍 301 跳转)
- 分类:ai / on-device-inference / flutter-plugin(多模态 LLM、Function Calling、RAG、STT/TTS)
- 作者:spark
- 更新:2026-10-11
§0 速览
- 仓库定位:把谷歌 LiteRT-LM 推理运行时封装成一个 Flutter 插件,让 Android / iOS / Web / macOS / Windows / Linux 六端 Flutter 应用都能跑 Gemma、Phi-4、DeepSeek、Qwen 等中小尺寸 LLM,全部本地推理、零 API 费用、零数据外传。
- 核心结构:插件按"核心 + 可选引擎"拆分,主包
flutter_edge_ai提供模型管理与聊天抽象,运行时要选一个引擎包(如flutter_edge_ai_litertlm);同一份 Dart 代码跨六端调用,RAG、Agent Skills、Speech 各自独立 opt-in。 - 一句话价值:把"手机本地跑多模态大模型"从展示 Demo 变成可发布的 Flutter 工程模板——含模型下载、Chat 流式、工具调用、Vision/Thinking、向量检索一条链路。
- 不适合谁:纯服务端 LLM 场景、对极致延迟不敏感且不愿承担几百 MB 模型下载成本的 App、不在 Flutter 阵营的 Android 原生或 SwiftUI 项目。
- 成熟度信号:仓库 980 commits、Star 630 / Fork 175、Pub Points 150/160、作者 Sasha Denisov 个人维护,6 周前从
flutter_gemma重命名为flutter_edge_ai,pub.dev 0.15.2 → 2.x 主版本号同时抬升 = 工程结构层面是升级式重命名而非单纯改名。
§1 它解决什么问题
过去想在 Flutter 里跑本地 LLM,开发者通常要在 Android 上接入 MediaPipe LLM Inference、在 iOS 上接 Apple Foundation Models 或 llama.cpp Swift bindings、在桌面端另找方案,结果是六端跑出六套 API。本仓库把这条路径压缩成两件事:
- 统一的 .litertlm 模型格式:模型以 LiteRT-LM 编译后的
.litertlm文件分发,跨端同一文件,由 LiteRT-LM 运行时在 GPU / NPU / CPU 上拉起推理,开发者不用为每端各选推理后端。 - 可插拔的引擎包:核心包不带推理实现;你要 LiteRT-LM 就加
flutter_edge_ai_litertlm,要旧 MediaPipe.task模型就加flutter_edge_ai_mediapipe,每个引擎包只负责把运行时装进 App 包体——体积与责任一并切开。
附加价值: - 隐私与合规:敏感数据从不出设备,适合医疗 / 法律 / 政企内嵌场景。 - 离线可用:模型一旦下载成功,断网仍可工作(飞机模式、出海项目)。 - 零边际成本:不像云端按 token 计费,可以做"自由聊"产品定位而不用担心月底账单爆炸。 - 代理式工作流:内置 Function Calling 与 SKILL.md 形态的 Agent Skills,模型能直接调你的 Dart 函数,也能跑 npm / MCP 风格的技能文件。
§2 快速安装
环境门槛,按官网 codelab 的实测约束写:
# 1) 环境(已是 Flutter 开发可跳过)
flutter --version # 需要 Flutter 3.44+ / Dart 3.12+,codelab 强制按此声明
# 2) 新建一个只跑 Android/iOS/macOS 的工程(其它平台按需追加)
flutter create --platforms=android,ios,macos gemma_codelab
cd gemma_codelab
rm test/widget_test.dart # 默认 widget_test 引用 counter,先删否则构建失败
# 3) 加三个包:核心 + LiteRT-LM 引擎 + 一个图选器(Vision 必装)
flutter pub add flutter_edge_ai flutter_edge_ai_litertlm image_picker
写完后 pubspec.yaml 的 dependencies 大致是这样(patch 版本可能更新,按 flutter pub add 实际写出的为准):
dependencies:
flutter:
sdk: flutter
cupertino_icons: ^1.0.8
flutter_edge_ai: ^2.1.1
flutter_edge_ai_litertlm: ^1.10.1
image_picker: ^1.2.3
按需追加的 opt-in 包:
- flutter_edge_ai_speech — 本地 STT + TTS
- flutter_edge_ai_sqlite / flutter_edge_ai_qdrant — RAG 向量库
- flutter_edge_ai_agent — 让模型读取并执行 SKILL.md
- flutter_edge_ai_mediapipe — 旧 .task/.bin 模型路径
⚠️ Android 必须改 android/app/build.gradle.kts——.litertlm 推理要求 API 30+,且引擎只发 arm64:
defaultConfig {
// ...applicationId、targetSdk 等保留原值
minSdk = 30
ndk { abiFilters += listOf("arm64-v8a") }
}
⚠️ Android 14+ 必须在 manifest 加 foreground service 类型,否则首次下模型崩溃(详见 §6 坑 #1)。删除默认注释、加这三行权限 + 一个 service:
<uses-permission android:name="android.permission.INTERNET" />
<uses-permission android:name="android.permission.POST_NOTIFICATIONS" />
<uses-permission android:name="android.permission.FOREGROUND_SERVICE_DATA_SYNC" />
<service
android:name="androidx.work.impl.foreground.SystemForegroundService"
android:foregroundServiceType="dataSync"
tools:node="merge" />
⚠️ iOS 在 Xcode 加两条 Capability:Increased Memory Limit + Extended Virtual Addressing——2.6 GB 的 .litertlm 模型文件需要这两把钥匙,否则 OS 杀进程。
§3 核心用法
3.1 五分钟"Hello, on-device" 骨架
import 'package:flutter_edge_ai/flutter_edge_ai.dart';
import 'package:flutter_edge_ai_litertlm/flutter_edge_ai_litertlm.dart';
Future<void> main() async {
WidgetsFlutterBinding.ensureInitialized();
// 1) 注册引擎(一次)
await FlutterEdgeAi.initialize(
inferenceEngines: [LiteRtLmEngine()],
// 如需本地 RAG / Speech 再加对应的 backend / tokenizer
);
// 2) 安装模型(HuggingFace 公共 URL 即可,无 token)
await FlutterEdgeAi.installModel(
modelType: ModelType.gemma4,
fileType: ModelFileType.litertlm,
).fromNetwork('https://huggingface.co/litert-community/gemma-4-E2B-it-litert-lm')
.install();
// 3) 取活动模型 → 开 chat → 流式产出
final model = await FlutterEdgeAi.getActiveModel(maxTokens: 2048);
final chat = await model.createChat();
await chat.addQueryChunk(Message.text(text: '你好,用三句话介绍 Gemma 4。', isUser: true));
await for (final chunk in chat.generateChatResponseStream()) {
chunk.when(
text: (t) => stdout.write(t),
thinking: (t) => debugPrint('[think] $t'),
functionCall: (f) => debugPrint('[tool] ${f.name}(${f.args})'),
parallelFunctionCall: (ps) => ps.forEach((p) => debugPrint('[tool*] ${p.name}')),
// sealed class,分支不全会编译报错 = 反方工程安全网
);
}
}
核心设计的两点可以记一下:
- ModelResponse 是 sealed,Dart 3 switch 必须穷举——漏写分支直接编译期报错,对 LLM 多输出类型的代码非常友好。
- 模型文件类型由 ModelFileType 显式声明,运行时按声明的值挑引擎,避免"装了一个 .bin 却想跑 LiteRT 引擎"的隐式歧义。
3.2 Function Calling — 让模型调你的 Dart 函数
final model = await FlutterEdgeAi.getActiveModel();
final chat = await model.createChat(tools: [
ToolSpec(
name: 'get_weather',
description: '查询某城市当前天气',
parameters: {
'city': ParamSpec(type: ParamType.string, required: true),
},
),
]);
// 收到 FunctionCallResponse 时由 Dart 侧真正执行,然后回灌给模型
// 官方 codelab 用"todo 列表 + 改 app bar 颜色"演示一个完整回路
3.3 Vision — 把图喂进去
final picked = await ImagePicker().pickImage(source: ImageSource.gallery);
final bytes = await picked!.readAsBytes();
await chat.addQueryChunk(Message.multimodal(
text: '这张图里有什么?',
image: ImagePart.fromBytes(bytes),
isUser: true,
));
await chat.generateChatResponse();
3.4 Thinking 模式 — 暴露推理链
Gemma 4 / DeepSeek R1 / Qwen3 系列会把 ThinkingResponse 单独流出来,前端可以直接渲染在折叠面板里给用户看推理过程——这是它相对闭源对话产品的差异化卖点。
3.5 RAG / Agent / Speech
- RAG:
flutter_edge_ai_sqlite或flutter_edge_ai_qdrant提供本地向量库,注册时挂上即可,模型侧只需在addQueryChunk时把"上下文块"作为系统角色注入。 - Agent Skills:把
SKILL.md放进工程目录,flutter_edge_ai_agent会让模型自己读 + 执行;设计上借用了 Codex / Claude Skills 的 SKILL.md 模式。 - Speech:
flutter_edge_ai_speech接管 STT/TTS,可与 Chat 串成语音助手。
§4 典型适用场景
- 离线 / 隐私优先 App:法律咨询、医疗记录、企业内嵌助手,模型 + 数据全在手机里,零网依赖。
- 教育 / 语言学习类工具:口语陪练可纯本地跑 0.5 GB 的 SmolLM、Gemma 3 270M,省 token 钱。
- 跨端 AI 副驾:Mac/Windows 上做个人写作助手,Android/iOS 上做移动伴侣——同一份 Dart 接口,由 LiteRT-LM 在不同设备上调度 GPU/NPU。
- 演示 / demo / 硬件评测:模型清单覆盖 0.3 GB ~ 3.9 GB,可以做"我们设备能跑多大模型"的演示基线。
- 车载 / IoT / 嵌入式 Flutter:包体可裁剪,只挑需要的 engine + vector 库塞进 App。
§5 与同类对比
| 项目 | 推理后端 | 平台数 | Flutter 一致性 | 模型生态 | 维护活跃度 |
|---|---|---|---|---|---|
| DenisovAV/flutter_edge_ai | LiteRT-LM / MediaPipe | 6(Android/iOS/Web/macOS/Windows/Linux) | 一套 Dart API 跨六端 | Gemma 4/3/3n、Phi-4 Mini、DeepSeek R1、Qwen3/2.5、SmolLM、FastVLM、FunctionGemma | 980 commits / 175 forks,重命名 + 主版本抬升近期 |
谷歌官方 ai_edge_flutter / 早期 MediaPipe Tasks GenAI |
MediaPipe Tasks | 2~3(Android/iOS 为主) | 与本仓库生态相近 | Gemma 系为主 | 谷歌维护 |
llama.cpp 包装方案(如 gpt4all_dart 系社区包) |
llama.cpp | 多 | 多套 API、需自己写平台分支 | 全开源(Llama、Mistral、Qwen…) | 社区分散 |
flutter_llama / llama_flutter |
llama.cpp / 自带 | 多端 | 各自 API | 全开源 | 社区,版本跟得快但缺统一治理 |
定位结论:它在"覆盖端最多 + API 最一致 + 官方 LiteRT 路线"的交集上最强;若你只需要 Android 上的简单问答,社区 llama 包装会更轻便;如果你已经在用 MediaPipe 旧栈且不打算切到 .litertlm,留在原 MediaPipe 路线成本更小。
§6 坑与注意(7 条工程坑,每条三段式:现象 / 影响 / 修复)
坑 1 — Android 14 上一启动就崩"ForegroundServiceTypeMissing"
- 现象:release 包首次下载模型时 app 闪退,控制台抛
ForegroundServiceTypeNotAllowedException或requires foregroundServiceType dataSync。 - 影响:debug 构建没事、release 必崩;模型下载链路彻底走不通,用户只看一次"打开就崩"。
- 修复:按 §2 manifest 段加
FOREGROUND_SERVICE_DATA_SYNC权限 +<service … android:foregroundServiceType="dataSync" tools:node="merge"/>;Play Console 上架会被审核这条权限,建议在隐私页明示用途。
坑 2 — iOS 上模型解压到一半被 jetsam 杀掉
- 现象:iPhone(尤其 ≤4GB 内存机)下完 2.6 GB 模型,加载时 app 直接被 OS kill。
- 影响:Vision 演示在 iPhone 上"偶发成功"——开发者本机是 Pro Max,QA 用常规机型就崩,体验落差巨大。
- 修复:Xcode → Runner → Signing & Capabilities → + Capability → 加
Increased Memory Limit+Extended Virtual Addressing,并确认Minimum Deployments≥ iOS 15.0;codelab 也明确写了这条。
坑 3 — macOS 上"dylib not loaded" 或 OpenCL 加速器找不到
- 现象:本地跑 macOS 端,引擎加载时报
Library not loaded: @rpath/libGemmaModelConstraintProvider.dylib,或 GPU 加速不可用退化成 CPU。 - 影响:开发体验差、模型加载时间翻倍;CI 上跑 macOS runner 极易踩。
- 修复:在 macOS Podfile 注入 CocoaPods post_install 阶段(codelab 给出整段 ruby),由它自动把
libGemmaModelConstraintProvider.dylib与libLiteRtLmMetalAccelerator.dylib拷进Contents/Frameworks并修复引用;同时pubspec.yaml里关 SwiftPM——flutter.config.enable-swift-package-manager: false,否则 CocoaPods 不会生成。
坑 4 — pubspec.lock 被吞掉,团队成员各自下到不同小版本
- 现象:同事 clone 后模型行为略有差异、报错栈不同。
- 影响:PR review 困难、模型产物非确定性放大。
- 修复:仓库自带
.fvmrc锁 Flutter 版本,按官方推荐用fvm use进工程;依赖锁文件必须进 git;同时建议把flutter pub get的输出 diff 进 PR。
坑 5 — Web 端音频输入不可用
- 现象:平台矩阵里 Web 行只对 Vision/Embeddings 打 ✅,Audio ❌。
- 影响:想在浏览器跑语音 demo 的预期会落空,临时切换 STT 方案又会破坏"一套 API 跨端"承诺。
- 修复:要么把语音部分降级到原生平台,要么在 web 上额外接 WebSpeech API / Whisper WASM 自己包一层;不要硬塞
flutter_edge_ai_speech到 web 目标。
坑 6 — iOS Simulator 上 Metal 内存上限 256 MB
- 现象:Mac M 系列真机能跑但 Simulator 加载大模型失败,Xcode 控制台出现
MTLBuffer alignment或exceeded allocation cap。 - 影响:CI / 团队内只有 Mac mini 的同事无法本地验收 4B+ 模型。
- 修复:官方明确 Simulator CPU-only 且 Metal 上限 256 MB——调试用 SmolLM 135M / Gemma 3 270M 这种"放得进 256 MB"的子集做 happy path 冒烟;大模型在真机或 CI 的 macOS Runner(无模拟器)上验证。
坑 7 — 仓库刚完成重命名,老的 flutter_gemma 教程与本仓库名错位
- 现象:GitHub / pub.dev 上同时存在
flutter_gemma与flutter_edge_ai两个 import path,部分博客 / CSDN / 知乎答案停留在旧名。 - 影响:新人按教程 import
package:flutter_gemma/...在新版本下找不到符号。 - 修复:以
flutter pub add flutter_edge_ai为准,把所有 import 改成package:flutter_edge_ai/...;旧 0.x 系列仍能 pub,但官方主版本号已抬到 2.x。
§7 与同类相比一句话推荐
"如果你要在 Flutter 里跑本地 LLM 且要 6 端一致 API,选它;如果你只要 Android/iOS 单端、能容忍双栈 API,社区 llama.cpp 包装也可以——但 2026 年这个时点 LiteRT-LM 是谷歌官方主线,flutter_edge_ai 是绕不开的工程基线。" ⚠️ 主版本号刚抬升、生态仍在迁移期(约 6 周前完成重命名),生产项目建议锁死
flutter_edge_ai: ^2.1.x与flutter_edge_ai_litertlm: ^1.10.x等待 2.x 三个 minor 后再放开上界。
§8 不确定 / 诚实标注
- Pub 版本号:codelab 明确写
flutter_edge_ai: ^2.1.1/flutter_edge_ai_litertlm: ^1.10.1;pub.dev flutter_gemma 0.15.2(2026-05)是重命名前最后一个老版本号,新flutter_edge_ai包没有在搜索结果里直接展示 latest 版本——我按 codelab 的^2.1.x/^1.10.x写入正文,若上游已发 2.2.x 或 1.11.x,请以flutter pub outdated输出为准 ⚠️。 - Star / Fork 数:630 / 175 / 980 commits 来自 web_search 摘要快照(2026-10-10 fetch),不保证读这篇攻略时仍精确。
- 模型清单:取自官网首页与 codelab;Gemma 4 E2B / E4B 是 2026 年新系列,HF 上的 litert-community 编译产物是否已稳定"按量产 App 跑"还需自行测——codelab 把 E2B 写为 2.6 GB,真实首屏下载耗时与冷启动内存峰值强烈依赖具体机型,文内数字仅作量级参考 ⚠️。
- NPU 支持表:网站写"Qualcomm Snapdragon Android + Intel LunarLake/PantherLake Windows",没给具体设备 SKU;遇到非首发机型 NPU 调度失败属正常,回退 GPU 即可。
- 作者归属:仓库根 LICENSE 署名为 "Copyright (c) 2024 Sasha Denisov" 与官网本人陈述一致;pub.dev 上
flutter_gemma包归属与 GitHub 同一组织,重命名后归属侧未发现冲突。 - Built-in AI:首页提到的 Gemini Nano / Apple Foundation Models / Phi Silica / Chrome Prompt API 是否分别在不同封装包里可用,没逐一核
pubspec.yaml;按字面理解是上层抽象,真实端到端可用性需要按目标平台分别验证 ⚠️。 - License:仓库与官网均声明 MIT;HF 上 litert-community 编译的 Gemma 4
.litertlm文件本身则承袭 Gemma 4 模型的 Apache 2.0——商业发布请二次确认。
spark · 2026-10-11 · 字数 ≈ 2,950 · 来源:GitHub README(fetch ✓)+ 官网 https://flutteredge.ai/(fetch ✓)+ 第三方 codelab https://akanshajain.dev/codelabs/on-device-ai(fetch ✓)+ tavily web_search(flutter_edge_ai DenisovAV)+ 仓库根 LICENSE 文本(fetch ✓)。边界:仅写 organized/guides/denisovav-flutter_edge_ai.md,未触碰他人目录、未 git。