denisovav/flutter_edge_ai/flutter-edge-ai-inference
- community
Checking that the SKILL.md file is still in the repository.
Use when adding on-device LLM inference to a Flutter app with flutter_edge_ai — offline chat, running an LLM locally, installing a model from Hugging Face (gated repos included), streaming replies, a system prompt, thinking or reasoning output, image or audio prompts, picking a CPU, GPU or NPU backend, stopping generation — or setting up the recommended .litertlm engine (ModelFileType.litertlm) on Android, iOS, macOS, Windows, Linux or web, including the Android minSdk and internet permission,…
Install
npx vskill@latest install denisovav/flutter_edge_ai/flutter-edge-ai-inferenceSKILL.md
Running a model with flutter_edge_ai
Rules
- Depend on
flutter_edge_aiand an engine package, and import both. Engine packages do not re-export core. - Register the engine in
FlutterEdgeAi.initialize(inferenceEngines: [...]). Core ships none. - Declare
fileTypeoninstallModel. It defaults toModelFileType.task, and the declaration — never the file name — picks the engine. maxTokensis the context window. Cap the reply withmaxOutputTokenson the session or chat.- Pass
isUser: trueon every userMessage. - Close a session or chat when its conversation ends. Keep the model while the feature is in use, and close it when the app no longer needs it.
- Keep Hugging Face tokens out of source: read them with
String.fromEnvironment. That keeps a token out of git, not out of the app — it is compiled into the binary, and on web intomain.dart.js. A shipped app should download from a repo that needs no token. - On Android, set
minSdk 30for anything built on.litertlm— inference, embeddings, speech. - Read references/platform-setup.md before the first build on a platform: without those entries the model fails to load or the app is killed for memory.
Setup — the recommended engine (.litertlm)
Gemma 4 E2B is 2.6 GB and needs no token. On web use gemma-4-E2B-it-web.litertlm from the same repo (2.0 GB).
Supported models, their file types and engines: https://flutteredge.ai/docs/models.
install() skips the download when the file is already installed from the same source, so calling it at every launch is safe. The latest install becomes the model getActiveModel loads.
A gated repo needs a token, given once:
Build with --dart-define=HUGGINGFACE_TOKEN=hf_....
When a Hugging Face repo publishes a deployment manifest, one call picks the variant and its tested runtime settings. The engine carries its own resolver, so registering LiteRtLmEngine is enough:
Other sources on the same builder: .fromAsset(path) for a model bundled in the app, .fromFile(path) for one already on disk, .fromBundled(name) for a platform-bundled resource. A fromFile file is used in place and stays the app's: uninstalling leaves it, and it is active again after a restart. Installing the same file name again from another source replaces the install.
modelType tells flutter_edge_ai how the model writes tool calls and reasoning, and on some engines it also picks the prompt format. Gemma 3 and Gemma 3n are ModelType.gemmaIt — there is no gemma3. The full set: ModelType.general, ModelType.gemmaIt, ModelType.gemma4, ModelType.deepSeek, ModelType.qwen, ModelType.qwen3, ModelType.qwen35, ModelType.llama, ModelType.hammer, ModelType.functionGemma, ModelType.phi. A wrong type still generates text; tool calls and reasoning then arrive as raw text.
Traps
Core not imported
- Symptom:
Undefined name 'FlutterEdgeAi',Undefined class 'InferenceModel', with only the engine package imported. - Fix:
import 'package:flutter_edge_ai/flutter_edge_ai.dart';as well.
flutter_gemma names after upgrading to 2.0
- Symptom:
Undefined name 'FlutterGemma',Undefined name 'GemmaLogLevel', or apackage:flutter_gemma/...import that does not resolve. - Fix: the flutter_gemma names are gone in 2.0. Rename the dependencies and imports (
flutter_gemma*→flutter_edge_ai*;flutter_gemma_rag_sqliteandflutter_gemma_rag_qdrantbecomeflutter_edge_ai_sqliteandflutter_edge_ai_qdrant), then rundart fix --apply, which renames the old class names. Delete the oldflutter-gemma-*skill directories and rundart run skills@ get --allagain — they still teach the old names. RAG also left core in 2.0: see the flutter-edge-ai-rag skill.
Deep imports after upgrading to 2.3
- Symptom:
Target of URI doesn't exist: 'package:flutter_edge_ai/core/model.dart'— or any otherpackage:flutter_edge_ai/core/…,/mobile/…,/web/…,/desktop/…orflutter_edge_ai_interface.dartimport. - Fix: since
flutter_edge_ai2.3.0 core's internals are private underlib/src. Apps importpackage:flutter_edge_ai/flutter_edge_ai.dart; an engine or tokenizer package importspackage:flutter_edge_ai/engine.dart. The deprecated members went in the same release —setModelPath,installModelFromAsset,initialize(enableWebCache:)and the rest; core's MIGRATION.md lists each with its replacement.
After upgrading to 2.5
- Symptom:
The method 'fromLegacyUrl' isn't defined for the type 'InferenceModelSpec',generateEmbedding/generateEmbeddings/getDimensionundefined, or a deprecation warning onFlutterEdgeAiPlugin.instance.createModel. - Fix: build the spec as
InferenceModelSpec(name:, modelSource: ModelSource.network(url) /.asset/.bundled/.file, modelType:);fromLegacyUrldefaulted toModelType.general, so pass a model type explicitly. ReplacecreateModel(...)(removed in 2.6.0) withFlutterEdgeAi.getActiveModel(...)— on Android, iOS and desktop it ignoredmodelTypeandfileTypeand returned the active model anyway — or withFlutterEdgeAi.openModelfor several models. Embeddings:embed(EmbeddingInput.text(t), taskType: TaskType.retrievalQuery),embedAll,dimension(see the flutter-edge-ai-rag skill and core's MIGRATION.md).
No engine registered
- Symptom:
StateError: No inference engine can handle this model (ModelFileType.litertlm). Add the engine package to pubspec.yaml and pass it in inferenceEngines: of FlutterEdgeAi.initialize(...) - Fix: add the engine package and register its provider — or fix
fileTypeif the wrong engine is registered. - A
.ggufmodel needsflutter_edge_ai_llama(llama.cpp through llamadart): registerLlamaEngineProvider()and install withfileType: ModelFileType.gguf. Its build setup — thehooks: user_defines: llamadart:block, the Apple companion package with SwiftPM, iOS 16.4 / macOS 14, Android arm64-v8a and x86_64 only — is in that package's README.
`maxTokens` used as a reply length
- Symptom: replies are as long as ever. On native
.litertlmthe value is raised to 1024, the smallest context those models support, and only a debug-mode log says so. The web.litertlmengine does not take the value at all; on MediaPipe it is the real limit. - Fix:
Use 4096 or more with images or audio — one image costs hundreds of tokens.
`isUser` left out
- Symptom: an empty response, no error.
Message.isUserdefaults tofalse, so the prompt is read as the model's own turn. - Fix:
Message(text: prompt, isUser: true).
Same reply every time
- Symptom: identical output for identical input.
- Causes:
topK: 1is passed somewhere (greedy; it was the default up toflutter_edge_ai2.1); the model's family decodes greedily by default (ModelType.phi,ModelType.hammer); or the seed is fixed — an unsetrandomSeedis 1 (or the.litertlmbundle's own), so a freshly loaded model repeats its first sampled answer. - Fix: leave
temperature,topKandtopPunset to get the model's own sampler or its family's defaults (SamplingParams.forModelType), or pass atemperature— with notopK, a greedy family or bundle then contributes notopK: 1. Set them on the first session aftergetActiveModel: on.litertlmthe sampler of the first generation stays in effect for later sessions (a one-time warning says so when a later session asks for other values), and its random state carries on, so a new chat already gets a new answer. MediaPipe starts each session from its seed: varyrandomSeedthere for a different answer to the same prompt. - Exception: decoding stays greedy whatever you pass on
.litertlmrunning on the NPU (activeBackend == PreferredBackend.npu); a one-time warning says so when you set any of them. ONNX follows the model'sgenai_config.json, which is greedy unless it setsdo_sample; values you pass override it.
`Session is closed`
- Symptom:
StateError: Session is closedfrom a session or chat that is still in use. - Cause:
createSessionandcreateChatfill one slot per model; creating another closes the one before. - Fix: one conversation at a time, or
openSession/openChatfor several (below). On the web.litertlmengine a secondcreateSessionhands back the session that is already open, history and all, rather than a fresh one — close the current chat before creating the next.
Generate
Streaming:
To stop early, call await session.stopGeneration() — chat.stopGeneration() on a chat. Cancelling the stream subscription detaches Dart but does not stop native decoding on every engine. On .litertlm on Android, iOS and desktop the chat keeps working after a stop — whether the app called stopGeneration() or cancelled its subscription. With flutter_edge_ai_litertlm 1.15.0 and later it is rewound to before the stopped turn, which is put back with its partial reply, so the model still sees images and audio from earlier turns. With 1.14.0 and earlier, and on the NPU, it is rebuilt from text instead, and those are gone — re-send an image there if the next question is about it. The legacy flutter_gemma_litertlm package needs 1.8.1 or later for a stopped chat to answer again at all.
Multi-turn chat
This is the start of the file. Read the full SKILL.md on GitHub.
Security
- Security scanPassed, 90 of 100Pattern checks on the skill's files.
- Model reviewPassed
Quality evaluation
- Task evaluationNot runNo evaluation yet. Run one in Skill Studio.
Source
- SKILL.md in the repositoryCheckingpackages/flutter_edge_ai/skills/flutter-edge-ai-inference/SKILL.md
Popularity
- Repository stars
- 642
- Repository forks
- 176
- 7-day trend score
- 0
Stars and forks are for the whole GitHub repository, not this skill alone. Not refreshed yet.
Works with
Any agent vskill installs to: 56 targets in all. These 39 have a page on this site.
- Claude Code
- Cursor
- GitHub Copilot
- Windsurf
- Codex
- Gemini CLI
- Cline
- Amp
- Roo Code
- Goose
- Continue
- Kilo Code
- Junie
- Trae
- OpenHands
- Qwen Code
- AI Agent
- Tabnine Chat
- Sourcegraph Cody
- Amazon Q
- Firebase Genkit
- Sweep
- Devin
- Phind
- Mentat
- Claude Desktop
- Aider
- GPT Pilot
- Plandex
- bolt.new
- v0
- Replit Agent
- Anse
- TypingMind
- BetterChatGPT
- LibreChat
- Warp AI
- Pieces
- Fig AI
Embed badge
[](https://verified-skill.com/skills/denisovav/flutter_edge_ai/flutter-edge-ai-inference)