Basic Inference
Run your first AI model inference in Flutter with ZETIC Melange.
This guide shows how to run inference from Dart after completing the Flutter setup.
Prerequisites
zetic_mlangeadded to your Flutter project- Platform setup completed for Android or iOS
- A compiled model on the Melange Dashboard
- Your Personal Key and model name in
account_name/project_nameformat
Running Inference
import 'dart:typed_data';
import 'package:zetic_mlange/zetic_mlange.dart';
// (1) Load model
// This handles model download, cache reuse, and native runtime initialization.
final model = await ZeticMLangeModel.create(
personalKey: personalKey,
name: 'account_name/project_name',
onProgress: (progress) {
print('Loading ${(progress * 100).round()}%');
},
);
// (2) Prepare model inputs
// Ensure shape and dtype match your model's input specification.
final input = Tensor.float32View(
Float32List.fromList([/* preprocessed values */]),
shape: const [1, 3, 224, 224],
);
// (3) Run inference
final outputs = model.run([input]);
// (4) Read output data
final scores = outputs.first.asFloat32List();
model.close();Understanding the Flow
- Model Download: On first use, the native SDK downloads the hardware-optimized model artifact for the current platform.
- Native Runtime Creation: The Flutter SDK calls the Android or iOS SDK through FFI and receives a native model handle.
- Tensor Copy and Execution: Dart
Tensorbytes are copied into native input buffers, the model runs on the selected backend, and output tensors are returned to Dart as typed views.
Input tensor shapes and data types must match the model's input specification. A mismatch throws MlangeException or a native SDK error.
Tensor Inputs
Use the typed constructors that match your preprocessing output:
final floatInput = Tensor.float32View(
floatValues,
shape: const [1, 3, 224, 224],
);
final intInput = Tensor.int64View(
tokenIds,
shape: const [1, 128],
);Use View constructors when your typed list is already in the correct layout and can be shared without an extra Dart-side copy. Use List constructors when you want defensive copy semantics.
Model Lifetime
Keep the model instance alive while you reuse it, then release the native handle when the screen or service is done:
if (!model.isClosed) {
model.close();
}Flutter does not expose Android's allocation-free getInputBuffers() path. run(inputs) copies each Dart tensor into the native model input buffer before execution.
Sample Applications
Please refer to the ZETIC Melange Apps repository for complete Flutter sample applications.
Next Steps
- Advanced Configuration: Model modes, version pinning, Hugging Face models, and LLMs
- Custom Preprocessing: Implement input preprocessing
- ZeticMLangeModel API Reference: Full Dart API documentation