liquid_ai_leap 0.2.2 copy "liquid_ai_leap: ^0.2.2" to clipboard
liquid_ai_leap: ^0.2.2 copied to clipboard

A Flutter plugin wrapper for the Liquid AI LEAP SDK. Provides on-device AI inference capabilities using Liquid Foundation Models (LFM) on iOS and Android.

Liquid AI LEAP Flutter Plugin #

A Flutter plugin for on-device AI inference using Liquid AI's LEAP SDK. Run Liquid Foundation Models (LFM) directly on iOS and Android devices with no cloud dependencies.

pub package License: MIT

Why this plugin? #

This supports GGUF models! Compared to LiteRT or ONNX GenAI, this give access to a much larger range of models.

Features #

  • 🚀 On-device inference - Run AI models locally without internet
  • 💬 Streaming responses - Real-time token-by-token output
  • 🖼️ Multimodal support - Text, images, and audio inputs
  • 🔧 Function calling - Let models call your app's functions
  • 📝 Constrained generation - JSON schema validation for structured output
  • 📦 Automatic model management - Download, cache, and manage models

Supported Models #

The plugin supports models from LiquidAI but also any GGUF model!

Liquid AI Models #

LFM2- Multimodal Models from liquid AI LEAP.

GGUF Models #

More about GGUF.

Note: The SDK now recommends using GGUF models instead of ExecuTorch bundles.

Tested models

These models have been successfully tested for on-device inference using the plugin.

Model Parameters Quantizations Capabilities
LFM2-VL-1.6B 1.6B Q8_0 (bundle) Text, Vision
LFM2-VL-3B 3B Q8_0 (bundle) Text, Vision
LFM2-VL-3B-GGUF 3B Q4_0 Text, Vision
Qwen3-VL-2B 2B Q4_K_M Text, Vision
GLM-Edge-V-2B 1.6B Q4_K_M Text, Vision
Qwen2-VL-2B 2B Q5, Q4 Text, Vision
InternVL3-2B 1.8B Q4_K_M Text, Vision
Omni-Reasoner-2B 1.5B Q4_0 Text, Vision
Granite-Vision-3.2-2B 2.5B Q4_K_M Text, Vision

Requirements #

iOS #

  • iOS 15.0+
  • Xcode 15.0+
  • Swift 5.9+
  • Physical device recommended (3GB+ RAM)

Un-tested: if you have, let me know.

Android #

  • API 31+ (Android 12)
  • arm64-v8a ABI
  • Physical device recommended (3GB+ RAM)

Tested on a Pixel 8a

Installation #

Add this to your package's pubspec.yaml:

dependencies:
  liquid_ai_leap: ^0.1.0

Then run:

flutter pub get

Quick Start #

1. Initialize and Load a Model #

import 'package:liquid_ai_leap/liquid_ai_leap.dart';

// Create plugin instance
final leap = LiquidAiLeap();

// Load a model (downloads if not cached)
final modelRunner = await leap.loadModel(
  model: 'LFM2-1.2B',
  quantization: 'Q5_K_M',
  onProgress: (progress, bytesPerSecond) {
    print('Downloading: ${(progress * 100).toStringAsFixed(1)}%');
  },
);

Note: The loadModel will search Leap models library using model and quantization parameters. During testing this was found to be somewhat unrialiable. If you are having issues with the auto-download like me, use the downloadModel method to download the model first, then use the loadModel method to load the model. downloadModel uses the url parameter to download the model (.bundle or .gguf) from Hugging Face for example.

2. Create a Conversation #

// Create a conversation with optional system prompt
final conversation = modelRunner.createConversation(
  systemPrompt: 'You are a helpful assistant.',
);

3. Generate Responses #

// Send a message and stream the response
final message = ChatMessage.user('What is the capital of France?');

await for (final response in conversation.generateResponse(message: message)) {
  switch (response) {
    case ChunkResponse(:final text):
      // Print streamed text
      stdout.write(text);
    case CompleteResponse(:final message, :final stats):
      // Generation complete
      print('\n\nTokens: ${stats?.totalTokens}');
      print('Speed: ${stats?.tokensPerSecond.toStringAsFixed(1)} tok/s');
  }
}

Advanced Usage #

Generation Options #

Control generation behavior with GenerationOptions:

await for (final response in conversation.generateResponse(
  message: ChatMessage.user('Write a haiku about Flutter'),
  options: GenerationOptions(
    temperature: 0.7,      // Creativity (0.0-2.0)
    topP: 0.9,             // Nucleus sampling
    maxTokens: 100,        // Maximum tokens to generate
    repetitionPenalty: 1.1, // Reduce repetition
  ),
)) {
  // Handle response
}

Function Calling #

Register functions for the model to call:

// Define a function
final weatherFunction = LeapFunction(
  name: 'get_weather',
  description: 'Get the current weather for a location',
  parameters: [
    LeapFunctionParameter(
      name: 'city',
      type: LeapFunctionParameterType.string(),
      description: 'The city name',
    ),
    LeapFunctionParameter(
      name: 'units',
      type: LeapFunctionParameterType.string(
        enumValues: ['celsius', 'fahrenheit'],
      ),
      description: 'Temperature units',
      optional: true,
    ),
  ],
);

// Register the function
conversation.registerFunction(weatherFunction);

// Handle function calls in responses
await for (final response in conversation.generateResponse(
  message: ChatMessage.user('What is the weather in Paris?'),
)) {
  switch (response) {
    case FunctionCallResponse(:final calls):
      for (final call in calls) {
        final result = await handleFunctionCall(call);
        // Provide result back to model
      }
    case ChunkResponse(:final text):
      stdout.write(text);
  }
}

Constrained JSON Generation #

Force the model to output valid JSON matching a schema:

final response = await conversation.generateResponse(
  message: ChatMessage.user('Generate a user profile'),
  options: GenerationOptions(
    jsonSchemaConstraint: '''
    {
      "type": "object",
      "properties": {
        "name": { "type": "string" },
        "age": { "type": "integer" },
        "email": { "type": "string" }
      },
      "required": ["name", "email"]
    }
    ''',
  ),
);

Image Input (Vision Models) #

import 'dart:io';
import 'dart:typed_data';

// Load image bytes
final imageBytes = await File('photo.jpg').readAsBytes();

// Create message with image
final message = ChatMessage(
  role: ChatMessageRole.user,
  content: [
    ChatMessageContent.text('What do you see in this image?'),
    ChatMessageContent.image(imageBytes),
  ],
);

await for (final response in conversation.generateResponse(message: message)) {
  // Handle response
}

Audio Input (Audio Models) #

// Create message with audio
final message = ChatMessage(
  role: ChatMessageRole.user,
  content: [
    ChatMessageContent.text('Transcribe this audio:'),
    ChatMessageContent.audio(wavBytes),
  ],
);

Model Management #

// Check if a model is cached
final isCached = await leap.isModelCached(
  model: 'LFM2-1.2B',
  quantization: 'Q5_K_M',
);

// Download without loading
final manifest = await leap.downloadModel(
  model: 'LFM2-1.2B',
  quantization: 'Q5_K_M',
  url: 'https://huggingface.co/LiquidAI/LeapBundles/resolve/main/LFM2-1_2B_8da4w.bundle?download=true',
  onProgress: (progress, bytesPerSecond) {
    print('Downloading: ${(progress * 100).toStringAsFixed(1)}%');
  },
);

// Delete a cached model
await leap.deleteModel(
  model: 'LFM2-1.2B',
  quantization: 'Q5_K_M',
);

Cleanup #

// Unload model to free memory
await modelRunner.unload();

Error Handling #

import 'package:liquid_ai_leap/liquid_ai_leap.dart';

try {
  final runner = await leap.loadModel(...);
} on LeapNetworkException catch (e) {
  print('Network error: ${e.message}');
} on LeapModelNotFoundException catch (e) {
  print('Model not found: ${e.model}');
} on LeapInsufficientMemoryException catch (e) {
  print('Not enough memory to load model');
} on LeapException catch (e) {
  print('LEAP error: ${e.message}');
}

Platform Setup #

iOS #

The plugin uses Swift Package Manager to fetch the LEAP SDK. No additional setup required.

If you need to customize the build, update ios/liquid_ai_leap.podspec.

Android #

The plugin uses Maven to fetch the LEAP SDK. You may need to configure authentication for the Maven repository.

Add to your app's android/build.gradle:

allprojects {
    repositories {
        maven {
            url 'https://maven.pkg.github.com/Liquid4All/leap-android'
            credentials {
                username = System.getenv('GITHUB_USERNAME')
                password = System.getenv('GITHUB_TOKEN')
            }
        }
    }
}

Scripts #

Dependency Management #

# Sync dependencies to pinned versions
./scripts/dependencies.sh sync

# Check for and upgrade to latest SDK versions
./scripts/dependencies.sh upgrade

Publishing #

# Publish a bug fix (0.1.0 -> 0.1.1)
./scripts/publish.sh fix

# Publish a new feature (0.1.0 -> 0.2.0)
./scripts/publish.sh minor

# Publish a breaking change (0.1.0 -> 1.0.0)
./scripts/publish.sh major

API Reference #

See the API documentation for detailed information.

Contributing #

Contributions are welcome!

License #

This project is licensed under the MIT License - see the LICENSE file for details.

Acknowledgments #

1
likes
160
points
--
downloads

Publisher

unverified uploader

Weekly Downloads

A Flutter plugin wrapper for the Liquid AI LEAP SDK. Provides on-device AI inference capabilities using Liquid Foundation Models (LFM) on iOS and Android.

Repository (GitHub)
View/report issues

Topics

#liquid-ai #gguf #genai #liquid-ai-leap #edge-inference

Documentation

Documentation
API reference

License

MIT (license)

Dependencies

flutter, plugin_platform_interface

More

Packages that depend on liquid_ai_leap

Packages that implement liquid_ai_leap