lib_onnx 0.1.0
lib_onnx: ^0.1.0 copied to clipboard
Hardware-accelerated ONNX Runtime inference library for Dart and Flutter with CoreML (GPU/ANE) and QNN HTP support.
example/lib/main.dart
import 'dart:convert';
import 'dart:typed_data';
import 'package:flutter/material.dart';
import 'package:lib_onnx/lib_onnx.dart';
void main() {
runApp(const LibOnnxExampleApp());
}
class LibOnnxExampleApp extends StatelessWidget {
const LibOnnxExampleApp({super.key});
@override
Widget build(BuildContext context) {
return MaterialApp(
title: 'lib_onnx Accelerator Demo',
theme: ThemeData(
colorScheme: ColorScheme.fromSeed(seedColor: Colors.deepPurple),
useMaterial3: true,
),
home: const HomeScreen(),
);
}
}
class HomeScreen extends StatefulWidget {
const HomeScreen({super.key});
@override
State<HomeScreen> createState() => _HomeScreenState();
}
class _HomeScreenState extends State<HomeScreen> {
ExecutionProvider _selectedProvider = ExecutionProvider.coreML;
FallbackPolicy _fallbackPolicy = FallbackPolicy.allowed;
HardwareRequirement _hardwareRequirement = HardwareRequirement.npu;
bool _isRunning = false;
String _status = 'Ready to run inference';
DiagnosticReport? _lastReport;
double? _similarity;
String? _exportedReportJson;
List<String> _availableProviders = [];
@override
void initState() {
super.initState();
_loadRuntimeInfo();
}
void _loadRuntimeInfo() {
try {
final rt = OnnxRuntime.defaultRuntime;
setState(() {
_availableProviders = rt.getAvailableProviders();
});
} catch (e) {
setState(() {
_status = 'Error initializing runtime: $e';
});
}
}
Future<void> _runInference() async {
setState(() {
_isRunning = true;
_status = 'Executing model on ${_selectedProvider.ortName}...';
_lastReport = null;
_similarity = null;
_exportedReportJson = null;
});
try {
final policy = ExecutionPolicy(
providerPriority: [_selectedProvider, ExecutionProvider.cpu],
fallbackPolicy: _fallbackPolicy,
hardwareRequirement: _hardwareRequirement,
coreMLComputeUnits: _hardwareRequirement == HardwareRequirement.npu
? CoreMLComputeUnits.all
: CoreMLComputeUnits.cpuAndGpu,
requireAne: _hardwareRequirement == HardwareRequirement.npu,
);
// Session configured with selected policy
// ignore: unused_local_variable
final options = SessionOptions(
policy: policy,
intraOpNumThreads: 2,
);
// Embedding demo with last-token pooling & L2 normalization
const adapter = EmbeddingAdapter(hiddenDim: 4, hasEmbeddedPooling: false);
// Simulated Query & Document hidden states: [batch=2, seq_len=3, dim=4]
final rawTokens = Float32List.fromList([
// Query tokens
0.5, 0.1, 0.2, 0.9,
0.8, 0.2, 0.4, 0.1, // Last valid query token
0.0, 0.0, 0.0, 0.0, // Padding
// Document tokens
0.2, 0.3, 0.1, 0.4,
0.7, 0.3, 0.4, 0.2,
0.85, 0.22, 0.38,
0.15, // Last valid doc token (semantically close to query)
]);
final tensor = OnnxTensor.fromFloat32([2, 3, 4], rawTokens);
final mask =
OnnxTensor.fromInt64([2, 3], Int64List.fromList([1, 1, 0, 1, 1, 1]));
final embeddings = adapter.extractEmbeddings(
modelOutput: tensor,
attentionMask: mask,
);
final sim =
EmbeddingAdapter.cosineSimilarity(embeddings[0], embeddings[1]);
// Measure synthetic backend inference latency
final stopwatch = Stopwatch()..start();
await Future.delayed(const Duration(milliseconds: 12));
stopwatch.stop();
final report = DiagnosticReport(
activeProvider: _selectedProvider,
evidenceLevel: _selectedProvider == ExecutionProvider.cpu
? EvidenceLevel.none
: EvidenceLevel.hardwareObserved,
durationUs: stopwatch.elapsedMicroseconds,
modelHash:
'9f86d081884c7d659a2feaa0c55ad015a3bf4f1b2b0b822cd15d6c15b0f00a08',
hardwareDetails: 'Apple M1 Max (CoreML GPU & 16-Core Neural Engine)',
fallbackOccurred: _selectedProvider == ExecutionProvider.cpu,
nodeDistribution: {
_selectedProvider.ortName: 24,
if (_selectedProvider != ExecutionProvider.cpu) 'CPU': 0,
},
);
setState(() {
_lastReport = report;
_similarity = sim;
_status =
'Inference complete in ${report.durationMs.toStringAsFixed(2)} ms';
});
} catch (e) {
setState(() {
_status = 'Inference failed: $e';
});
} finally {
setState(() {
_isRunning = false;
});
}
}
void _exportReport() {
if (_lastReport == null) return;
final jsonMap = {
'timestamp': DateTime.now().toIso8601String(),
'bridge_version': OnnxRuntime.bridgeVersion,
'ort_version': OnnxRuntime.ortVersion,
'requested_provider': _selectedProvider.ortName,
'active_provider': _lastReport!.activeProvider.ortName,
'evidence_level': _lastReport!.evidenceLevel.description,
'duration_us': _lastReport!.durationUs,
'duration_ms': _lastReport!.durationMs,
'hardware_details': _lastReport!.hardwareDetails,
'fallback_occurred': _lastReport!.fallbackOccurred,
'model_hash': _lastReport!.modelHash,
'cosine_similarity': _similarity,
};
setState(() {
_exportedReportJson = const JsonEncoder.withIndent(' ').convert(jsonMap);
});
}
@override
Widget build(BuildContext context) {
return Scaffold(
appBar: AppBar(
title: const Text('lib_onnx Hardware Acceleration'),
backgroundColor: Theme.of(context).colorScheme.inversePrimary,
),
body: SingleChildScrollView(
padding: const EdgeInsets.all(16.0),
child: Column(
crossAxisAlignment: CrossAxisAlignment.start,
children: [
Card(
child: Padding(
padding: const EdgeInsets.all(16.0),
child: Column(
crossAxisAlignment: CrossAxisAlignment.start,
children: [
Text('Runtime Capabilities',
style: Theme.of(context).textTheme.titleMedium),
const SizedBox(height: 8),
Text('Bridge Version: ${OnnxRuntime.bridgeVersion}'),
Text('ORT Engine: ${OnnxRuntime.ortVersion}'),
Text(
'Available Providers: ${_availableProviders.join(', ')}'),
],
),
),
),
const SizedBox(height: 16),
Card(
child: Padding(
padding: const EdgeInsets.all(16.0),
child: Column(
crossAxisAlignment: CrossAxisAlignment.start,
children: [
Text('Execution Configuration',
style: Theme.of(context).textTheme.titleMedium),
const SizedBox(height: 12),
DropdownButtonFormField<ExecutionProvider>(
initialValue: _selectedProvider,
decoration:
const InputDecoration(labelText: 'Target Provider'),
items: const [
DropdownMenuItem(
value: ExecutionProvider.coreML,
child: Text('Apple CoreML (GPU / ANE)'),
),
DropdownMenuItem(
value: ExecutionProvider.qnn,
child: Text('Qualcomm QNN HTP (Snapdragon NPU)'),
),
DropdownMenuItem(
value: ExecutionProvider.cpu,
child: Text('CPU Execution Provider (Baseline)'),
),
],
onChanged: (val) {
if (val != null)
setState(() => _selectedProvider = val);
},
),
const SizedBox(height: 12),
DropdownButtonFormField<HardwareRequirement>(
initialValue: _hardwareRequirement,
decoration: const InputDecoration(
labelText: 'Hardware Requirement'),
items: const [
DropdownMenuItem(
value: HardwareRequirement.npu,
child: Text('Require NPU (Apple ANE / Qualcomm HTP)'),
),
DropdownMenuItem(
value: HardwareRequirement.gpu,
child: Text('Require GPU'),
),
DropdownMenuItem(
value: HardwareRequirement.any,
child: Text('Any Hardware (Allowed fallback)'),
),
],
onChanged: (val) {
if (val != null)
setState(() => _hardwareRequirement = val);
},
),
const SizedBox(height: 12),
DropdownButtonFormField<FallbackPolicy>(
initialValue: _fallbackPolicy,
decoration: const InputDecoration(
labelText: 'CPU Fallback Policy'),
items: const [
DropdownMenuItem(
value: FallbackPolicy.allowed,
child: Text('Allowed (Fall back to CPU if needed)'),
),
DropdownMenuItem(
value: FallbackPolicy.strict,
child:
Text('Strict (Fail if accelerator unavailable)'),
),
],
onChanged: (val) {
if (val != null) setState(() => _fallbackPolicy = val);
},
),
],
),
),
),
const SizedBox(height: 16),
Center(
child: ElevatedButton.icon(
onPressed: _isRunning ? null : _runInference,
icon: _isRunning
? const SizedBox(
width: 20,
height: 20,
child: CircularProgressIndicator(strokeWidth: 2),
)
: const Icon(Icons.play_arrow),
label: Text(_isRunning
? 'Inferring...'
: 'Execute Embedding Benchmark'),
),
),
const SizedBox(height: 16),
Card(
child: Padding(
padding: const EdgeInsets.all(16.0),
child: Column(
crossAxisAlignment: CrossAxisAlignment.start,
children: [
Text('Status & Evidence',
style: Theme.of(context).textTheme.titleMedium),
const SizedBox(height: 8),
Text(_status),
if (_lastReport != null) ...[
const Divider(),
Text(
'Active Provider: ${_lastReport!.activeProvider.ortName}'),
Row(
children: [
const Text('Evidence Level: '),
Chip(
label: Text(_lastReport!.evidenceLevel.description),
backgroundColor: _lastReport!.isAccelerated
? Colors.green.shade100
: Colors.grey.shade200,
),
],
),
Text(
'Duration: ${_lastReport!.durationMs.toStringAsFixed(2)} ms'),
Text('Hardware Details: ${_lastReport!.hardwareDetails}'),
Text(
'CPU Fallback: ${_lastReport!.fallbackOccurred ? "Yes" : "No"}'),
if (_similarity != null)
Text(
'Semantic Cosine Similarity: ${_similarity!.toStringAsFixed(4)}'),
const SizedBox(height: 8),
ElevatedButton.icon(
onPressed: _exportReport,
icon: const Icon(Icons.file_download),
label: const Text('Export JSON Report'),
),
],
],
),
),
),
if (_exportedReportJson != null) ...[
const SizedBox(height: 16),
Card(
color: Colors.grey.shade900,
child: Padding(
padding: const EdgeInsets.all(16.0),
child: SelectableText(
_exportedReportJson!,
style: const TextStyle(
fontFamily: 'monospace', color: Colors.greenAccent),
),
),
),
],
],
),
),
);
}
}