Upgrade to Pro — share decks privately, control downloads, hide ads and more …

flutter_kaigi_2025.pdf

Avatar for Kyohei Ito Kyohei Ito
November 13, 2025

 flutter_kaigi_2025.pdf

Avatar for Kyohei Ito

Kyohei Ito

November 13, 2025
Tweet

More Decks by Kyohei Ito

Other Decks in Programming

Transcript

  1. クラウド API とオンデバイス LLM の比較 比較項目 クラウド API オンデバイス LLM

    応答速度 △ (通信時間が発生) ◎ (通信不要) 利用環境 ✕ (インターネット必須) ◎ (どこでも使える) プライバシー △ (データを外部に送信) ◎ (端末内で完結) コスト △ (API 利用料・サーバー) ◯ (API 利用料ゼロ) モデル性能/機能 ◎ (常に最新・巨大モデル) △ (小型モデル・機能制限)
  2. 市場動向 Apple Intelligence iOS 18.1 以降でオンデバイス AI 機能を提供 Private Cloud

    Compute でハ イブリッド処理を実現 Writing Tools、Genmoji、 Image Playground を搭載 Gemini Nano Android 14 以降の対応端末で 利用可能 AICore 経由でシステムレベル の AI を提供 Pixel 8 以降、Galaxy S24 シ リーズなどで動作
  3. Agenda 1. オンデバイス LLM の基礎知識 2. Flutter で LLM を動かす選択肢

    3. オンデバイス LLM の応用機能 4. パフォーマンスと実践的な考慮点
  4. Agenda 1. オンデバイス LLM の基礎知識 2. Flutter で LLM を動かす選択肢

    3. オンデバイス LLM の応用機能 4. パフォーマンスと実践的な考慮点
  5. モバイルで注目の LLM モデル 特徴 Google Gemma Google AI Edge に最適化

    Meta Llama オープンソース、豊富なコミュニティ Microsoft Phi-3 小規模ながら高性能 DeepSeek 高い推論・コーディング能力 Qwen Alibaba の多言語対応モデル
  6. 量子化のイメージ 32 ビット浮動小数点(FP32) [0.17384529, -1.40821743, 0.98712456, -0.02941837, ...] ↓ 8

    倍圧縮 8 ビット整数(INT8) 範囲: -128 ~ 127 [14, -115, 80, -2, ...] ↓ さらに 2 倍圧縮 4 ビット整数(INT4) 範囲: -8 ~ 7 [7, -8, 4, -1, ...]
  7. パラメータ数と量子化の関係性の具体例 量子化前 量子化後 パラメータ数 7B (70 億) 7B (70 億)

    ビット幅 32 ビット (FP32) 4 ビット (INT4) サイズ(概算) 約 28GB 約 3.5GB ※量子化前サイズ概算: 70 億 ×4 バイト = 約 280 億バイト = 約 28GB ※量子化後サイズ概算: 70 億 ×0.5 バイト = 約 35 億バイト = 約 3.5GB
  8. Agenda 2. Flutter で LLM を動かす選択肢 1. オンデバイス LLM の基礎知識

    3. オンデバイス LLM の応用機能 4. パフォーマンスと実践的な考慮点
  9. llama_cpp_dart(テキスト) Llama.libraryPath = 'bin/MAC_ARM64/libllama.dylib'; final llama = Llama( '/path/to/model.gguf', );

    llama.setPrompt('2 + 2 = ?'); while (true) { var (token, done) = llama.getNext(); print(token); if (done) break; } llama.dispose();
  10. llama_cpp_dart(画像 + テキスト) Llama.libraryPath = 'bin/MAC_ARM64/libmtmd.dylib'; final llama = Llama(

    '/path/to/model.gguf', ... '/path/to/mmproj-model.gguf', ); final image = LlamaImage.fromFile(File('/path/to/image.png')); final prompt = """ <start_of_turn>user <image> 画像について説明してください。 <start_of_turn>model """; final stream = llama.generateWithMedia(prompt, inputs: [image]); await for (final token in stream) { print(token); } llama.dispose();
  11. Task(LiteRT-LM)フォーマット マルチモーダル対応で GPU や NPU を活用した高速推論に最適化さ れていて、ファイル自体は unzip 可能 マルチモーダル対応(テキスト、画像など)

    GPU や NPU を活用した高速推論 ファイルは unzip 可能で中身を確認できる flutter_gemma や ai_edge などのパッケージで利用可能
  12. flutter_gemma(テキスト) await FlutterGemma.installModel( modelType: ModelType.gemmaIt, ).fromNetwork( 'url_to_model', ).install(); final model

    = await FlutterGemma.getActiveModel(); final chat = await model.createChat(); await chat.addQueryChunk(Message.text( text: '2 + 2 = ?', isUser: true, )); await for (final response in chat.generateChatResponseAsync()) { if (response is TextResponse) { print(response.token); } } await chat.close(); await model.close();
  13. flutter_gemma(画像 + テキスト) final model = await FlutterGemma.getActiveModel( preferredBackend: PreferredBackend.gpu,

    supportImage: true, ); final chat = await model.createChat(supportImage: true); await chat.addQueryChunk(Message.withImage( text: ' 画像について説明してください。', imageBytes: imageBytes, isUser: true, )); await for (final response in chat.generateChatResponseAsync()) { if (response is TextResponse) { print(response.token); } } await chat.close(); await model.close();
  14. Cactus フォーマット オンデバイスでの利用に特化しており、 ARM CPU アーキテクチャ に最適化されている ARM CPU アーキテクチャに最適化

    FFI を利用したクロスプラットフォーム対応 Flutter、React Native、KMP で利用可能 cactus-flutter パッケージで利用可能
  15. cactus-flutter(テキスト) final lm = CactusLM(); await lm.downloadModel(model: 'qwen3-0.6'); await lm.initializeModel();

    final streamedResult = await lm.generateCompletionStream( messages: [ChatMessage(content: '2 + 2 = ?', role: 'user')], ); await for (final chunk in streamedResult.stream) { print(chunk); } lm.unload();
  16. cactus-flutter(音声) final stt = CactusSTT(); await stt.download(model: 'whisper-tiny'); await stt.init(model:

    'whisper-tiny'); final result = await stt.transcribe(); print(result.text); stt.dispose();
  17. ai_edge での実行例 final downloader = ModelDownloader(); final result = await

    downloader.downloadModel( Uri.parse('url_to_model'), ); await AiEdge.instance.initialize( modelPath: result.filePath, ); final stream = AiEdge.instance.generateResponseAsync('2 + 2 = ?'); await for (final event in stream) { print(event.partialResult); }
  18. 設定可能なパラメータ例 await aiEdge.initialize( modelPath: '/path/to/model.task', // 必須: モデルファイルのパス maxTokens: 2048,

    // 最大生成トークン数 preferredBackend: PreferredBackend.gpu, // ハードウェアバックエンド maxNumImages: 3, // マルチモーダル入力時の最大画像数 temperature: 0.7, // ランダム性の制御(0.0-1.0 ) randomSeed: 42, // 再現性のための乱数シード topK: 50, // Top-K サンプリング topP: 0.95, // Top-P (nucleus )サンプリング supportedLoraRanks: [4, 8], // LoRA アダプターのランク(ファインチューニング用) loraPath: '/path/to/lora_adapter.bin', // LoRA アダプターのパス enableVisionModality: true, // Vision 機能の有効化 );
  19. Agenda 3. オンデバイス LLM の応用機能 1. オンデバイス LLM の基礎知識 2.

    Flutter で LLM を動かす選択肢 4. パフォーマンスと実践的な考慮点
  20. Function Calling(Tool) の流れ 1. 利用可能な関数のスキーマ(名前・引数・説明)を定義 2. ユーザーのリクエストと関数スキーマを LLM に渡す 3.

    LLM が必要な関数と引数を JSON 形式で返答 4. アプリ側で実際の関数を実行 5. 関数の実行結果を LLM に渡す 6. LLM が結果を踏まえてユーザーに最終回答を生成
  21. ai_edge での関数設定例 final getWeather = FunctionDeclaration( name: 'get_weather', description: 'Get

    current weather for a location', properties: [ FunctionProperty( name: 'location', description: 'City name', type: PropertyType.string, required: true, ), ], ); await aiEdge.setFunctions([getWeather]);
  22. ai_edge での関数実行例 final response = await aiEdge.sendMessage( Message(role: 'user', text:

    ' 今日の東京の天気を教えてください。'), ); if (response.functionCall != null) { final call = response.functionCall!; switch (call.name) { case 'get_weather': final location = call.args.fields['location'] as String; final weather = await getWeather(location); final functionResponse = FunctionResponse( functionCall: call, response: {'result': weather}, ); final finalResponse = await aiEdge.sendFunctionResponse(functionResponse); print(finalResponse.text); } }
  23. プロンプトエンジニアリングによる FST の代替 プロンプト設計により関数呼び出しの形式を模倣可能 FST 制約なしで実装できるが、フォーマット遵守の信頼性は低下 システム: あなたは天気情報を提供する関数 get_weather(location: "location")

    を持っています。 天気に関する質問には以下のような json 形式で必要な関数を呼び出してください `{ "function": "get_weather", "args": { "location": " 東京" } }` ユーザー: 今日の大阪の天気を教えてください。
  24. ai_edge での実行例 await aiEdge.createEmbeddingModel( tokenizerModelPath: '/path/to/tokenizer.model', embeddingModelPath: '/path/to/embedding.tflite', modelType: EmbeddingModelType.gemma,

    vectorStore: VectorStore.sqlite, preferredBackend: PreferredBackend.gpu, ); await aiEdge.memorizeChunks([ 'Flutter は UI フレームワーク', 'Python で機械学習を実装', 'Dart 言語でアプリ開発', ]);
  25. Text Chunking とは? テキストを意味的な単位に分割するプロセスで、検索精度や処理効率 を向上させる 自然な文の境界で分割(例: 文、段落、セクション) チャンクサイズの最適化(例: 500 トークン程度)

    長いドキュメント(例: 技術文書、3000 トークン) ↓ Text Chunking チャンク1: "LLM とは大規模言語モデルのことで..." (500 トークン) チャンク2: " 量子化はモデルサイズを削減する技術で..." (500 トークン) チャンク3: "RAG は外部知識を活用する手法で..." (500 トークン) チャンク4: "Flutter での実装方法として..." (500 トークン) ...
  26. Vector DB とは? ベクトル化されたドキュメントを保存し、高速な類似度検索を可能に するデータベース インメモリ実装または永続化実装を選択可能 FAISS、ObjectBox、SQLite + ベクトル拡張などが利用可能 Vector

    DB: ID | 元の文章  | ベクトル 1 | "Flutter は UI フレームワーク" | [0.23, -0.41, 0.87, 0.15, ...] 2 | "Python で機械学習を実装" | [0.11, 0.34, -0.56, 0.78, ...] 3 | "Dart 言語でアプリ開発" | [-0.45, 0.67, 0.12, -0.34, ...] ... 検索結果: ID 1 ( 類似度 0.98), ID 3 ( 類似度 0.85)
  27. Function Calling の推論回数 final response = await aiEdge.sendMessage( Message(role: 'user',

    text: ' 今日の東京の天気を教えてください。'), ); if (response.functionCall != null) { final call = response.functionCall!; switch (call.name) { case 'get_weather': final location = call.args.fields['location'] as String; final weather = await getWeather(location); // 再度推論は行わずに、関数の実行結果をユーザーに返すように工夫する } }
  28. オンデバイス LLM で利用できるライブラリ ライブラリ 画像入力 音声入力 Function Calling RAG llama_cpp_dart

    (プロンプト) flutter_gemma (プロンプト) ai_edge (未実装) (Android) (Android) cactus-flutter