Back to blog
    Flutter应用中的AI:云API、TFLite和端侧LLM
    FlutterDartTFLitecloud APIon-device AIllama.cppsegment:mobile-builder

    Flutter应用中的AI:云API、TFLite和端侧LLM

    Flutter中AI的三条路径。通过http包使用云API,TensorFlow Lite用于传统ML任务,llama.cpp端侧LLM用于文本生成。面向Dart开发者的实用比较。

    EErtas Team·

    构建AI功能的Flutter开发者有三条不同的路径。云API通过HTTP调用让你访问前沿模型。TensorFlow Lite在设备上处理传统ML任务。而llama.cpp通过平台通道将完整的LLM文本生成带到设备端。

    每条路径服务于不同的目的。本指南从Dart开发者的视角进行比较。

    路径1:云API

    Flutter的httpdio包让云API集成变得简单。该模式在iOS、Android、Web和桌面上的工作方式完全相同。

    基本集成

    import 'dart:convert';
    import 'package:http/http.dart' as http;
    
    Future<String> generateResponse(String prompt) async {
      final response = await http.post(
        Uri.parse('https://api.openai.com/v1/chat/completions'),
        headers: {
          'Content-Type': 'application/json',
          'Authorization': 'Bearer $apiKey',
        },
        body: jsonEncode({
          'model': 'gpt-4o-mini',
          'messages': [{'role': 'user', 'content': prompt}],
        }),
      );
    
      final data = jsonDecode(response.body);
      return data['choices'][0]['message']['content'];
    }

    SSE流式传输

    对于在令牌到达时即时显示的聊天界面:

    import 'package:flutter_client_sse/flutter_client_sse.dart';
    
    void streamResponse(String prompt, Function(String) onToken) {
      SSEClient.subscribeToSSE(
        url: 'https://api.openai.com/v1/chat/completions',
        header: {
          'Content-Type': 'application/json',
          'Authorization': 'Bearer $apiKey',
        },
        body: {
          'model': 'gpt-4o-mini',
          'messages': [{'role': 'user', 'content': prompt}],
          'stream': true,
        },
      ).listen((event) {
        if (event.data == '[DONE]') return;
        final parsed = jsonDecode(event.data!);
        final token = parsed['choices'][0]['delta']['content'];
        if (token != null) onToken(token);
      });
    }

    何时使用云API

    云API是原型验证、功能验证和极低用量应用的正确选择。它们不需要原生代码,在所有Flutter平台上都能工作,让你访问前沿模型。

    权衡是标准的云API权衡:按令牌的成本增长、网络依赖、500-3,000ms延迟,以及每次请求数据离开设备。

    路径2:TensorFlow Lite

    tflite_flutter插件为Flutter提供TFLite支持。TFLite在设备上运行优化的ML模型,用于特定任务。

    TFLite擅长什么

    • 图像分类和物体检测
    • 文本分类和情感分析
    • 端侧翻译(预构建模型)
    • 姿态估计
    • 音频分类

    集成模式

    import 'package:tflite_flutter/tflite_flutter.dart';
    
    class TextClassifier {
      late Interpreter _interpreter;
    
      Future<void> loadModel() async {
        _interpreter = await Interpreter.fromAsset('model.tflite');
      }
    
      List<double> classify(List<int> tokenizedInput) {
        var output = List.filled(1 * numClasses, 0.0).reshape([1, numClasses]);
        _interpreter.run([tokenizedInput], output);
        return output[0];
      }
    }

    TFLite不能做什么

    TFLite不支持大型语言模型进行开放式文本生成。没有TFLite版本的ChatGPT或Claude。你不能用TFLite做对话AI、内容起草、摘要或任何需要生成自然语言回复的任务。

    这些任务需要云API或端侧LLM。

    成本

    免费。TFLite完全在设备上运行。模型很小(通常1-50MB),随应用捆绑。

    路径3:通过llama.cpp的端侧LLM

    在用户设备上运行完整的语言模型。llama.cpp处理推理。GGUF模型提供智能。Flutter通过平台通道(方法通道或FFI)通信。

    集成方法

    平台通道: 用Swift(iOS)和Kotlin(Android)编写轻薄的原生封装来调用llama.cpp,然后从Dart通过MethodChannel通信。

    // Dart端
    class OnDeviceLlm {
      static const _channel = MethodChannel('com.app/llm');
    
      Future<void> loadModel(String path) async {
        await _channel.invokeMethod('loadModel', {'path': path});
      }
    
      Future<String> generate(String prompt) async {
        return await _channel.invokeMethod('generate', {'prompt': prompt});
      }
    
      Stream<String> generateStream(String prompt) {
        const eventChannel = EventChannel('com.app/llm_stream');
        _channel.invokeMethod('startGeneration', {'prompt': prompt});
        return eventChannel.receiveBroadcastStream().map((e) => e as String);
      }
    }

    Dart FFI: 使用dart:ffi直接调用llama.cpp的C API。这避免了平台通道开销但需要更多设置:

    import 'dart:ffi';
    
    // 绑定llama.cpp共享库
    final llamaLib = DynamicLibrary.open('libllama.so'); // Android
    // DynamicLibrary.process() 用于iOS(静态链接)
    
    typedef LlamaInitNative = Pointer Function(Pointer<Utf8>);
    typedef LlamaInit = Pointer Function(Pointer<Utf8>);
    
    final llamaInit = llamaLib
        .lookupFunction<LlamaInitNative, LlamaInit>('llama_load_model');

    Flutter中的模型分发

    捆绑: 将GGUF文件放在平台特定的资源目录中。Android使用asset delivery处理大文件。iOS添加到Xcode项目。

    下载: 使用diohttp进行带进度的后台下载:

    import 'package:dio/dio.dart';
    
    Future<void> downloadModel() async {
      final dir = await getApplicationDocumentsDirectory();
      final modelPath = '${dir.path}/model.gguf';
    
      await Dio().download(
        modelCdnUrl,
        modelPath,
        onReceiveProgress: (received, total) {
          final progress = received / total;
          // 更新UI显示下载进度
        },
      );
    }

    性能

    端侧推理性能与原生应用相同,因为llama.cpp原生运行,不通过Dart VM。平台通道或FFI开销可以忽略不计(每令牌不到1ms)。

    设备1B模型(令牌/秒)3B模型(令牌/秒)
    iPhone 15 Pro (A17)35-4518-25
    Galaxy S24 (SD 8 Gen 3)35-4518-25
    Pixel 9 (Tensor G4)30-4015-22
    2024年+中端18-258-12

    对比

    因素云APITFLite端侧LLM
    文本生成
    图像分类通过API是(优化)
    离线支持
    每次推理成本$0.0001-$0.01$0$0
    Flutter集成原生Dart插件平台通道/FFI
    自定义模型通过API选择自定义TFLite任何GGUF模型
    模型大小不适用(服务器端)1-50MB600MB-1.7GB

    实际决策框架

    使用云API的情况: 验证功能、用户基数小,或需要前沿推理。http包让这在Dart中变得轻而易举。

    使用TFLite的情况: 需要图像分类、物体检测、文本分类或其他传统ML任务。Google的预构建模型覆盖了许多常见用例。

    使用端侧LLM的情况: 需要对话AI、内容生成、摘要或任何文本密集型AI功能。零推理成本、离线支持和隐私保障使其成为规模化生产应用的正确选择。

    微调步骤是让端侧模型在你的特定任务上与云API竞争的关键。像Ertas这样的平台处理完整工作流:上传训练数据,用LoRA微调,导出GGUF,部署到任何设备。微调的3B模型在领域特定任务上通常优于通过提示使用的云模型。

    Ship AI that runs on your users' devices.

    Early bird pricing starts at $14.50/mo — locked in for life. Plans for builders and agencies.

    Keep reading