Skip to main content

lib_onnx 0.2.0-dev.1 copy "lib_onnx: ^0.2.0-dev.1" to clipboard
lib_onnx: ^0.2.0-dev.1 copied to clipboard

ONNX Runtime inference for Dart and Flutter with explicit execution policies and experimental CoreML and QNN integration.

example/lib/main.dart

import 'dart:async';
import 'dart:convert';
import 'package:flutter/foundation.dart';
import 'package:flutter/material.dart';
import 'package:flutter/services.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) => MaterialApp(
    title: 'lib_onnx native inference',
    theme: ThemeData(colorSchemeSeed: Colors.indigo, useMaterial3: true),
    home: const HomeScreen(),
  );
}

class HomeScreen extends StatefulWidget {
  const HomeScreen({super.key});

  @override
  State<HomeScreen> createState() => _HomeScreenState();
}

class _HomeScreenState extends State<HomeScreen> {
  OnnxRuntime? _runtime;
  InferenceSession? _session;
  ExecutionProvider _provider = switch (defaultTargetPlatform) {
    TargetPlatform.macOS || TargetPlatform.iOS => ExecutionProvider.coreML,
    TargetPlatform.android => ExecutionProvider.qnn,
    _ => ExecutionProvider.cpu,
  };
  bool _allowCpuFallback = false;
  bool _running = false;
  String _status = 'Ready';
  String _runtimeInfo = 'Not initialized';
  DiagnosticReport? _report;
  String? _json;
  List<double>? _output;
  List<String> _compiledProviders = const [];

  @override
  void initState() {
    super.initState();
    unawaited(_initialize());
  }

  Future<void> _initialize() async {
    try {
      final runtime = await OnnxRuntime.createAsync();
      if (!mounted) {
        await runtime.close();
        return;
      }
      setState(() {
        _runtime = runtime;
        _compiledProviders = runtime.getAvailableProviders();
        _runtimeInfo =
            'Bridge ${OnnxRuntime.bridgeVersion}; ORT ${OnnxRuntime.ortVersion}';
      });
    } catch (error) {
      if (mounted)
        setState(() {
          _status = 'Native runtime unavailable: $error';
        });
    }
  }

  @override
  void dispose() {
    // close() stops accepting work, cancels/drains accepted tasks, then frees.
    unawaited(_runtime?.close());
    super.dispose();
  }

  Future<void> _run() async {
    final runtime = _runtime;
    if (runtime == null || _running) return;
    setState(() {
      _running = true;
      _status = 'Loading the bundled MLP model…';
      _report = null;
      _json = null;
      _output = null;
    });
    OnnxTensor? input;
    Map<String, OnnxTensor>? outputs;
    try {
      final asset = await rootBundle.load('assets/mlp_smoke.onnx');
      final session = await InferenceSession.loadBytes(
        asset.buffer.asUint8List(asset.offsetInBytes, asset.lengthInBytes),
        runtime: runtime,
        options: SessionOptions(
          policy: ExecutionPolicy(
            providerPriority: [
              _provider,
              if (_allowCpuFallback && _provider != ExecutionProvider.cpu)
                ExecutionProvider.cpu,
            ],
            fallbackPolicy: _allowCpuFallback
                ? FallbackPolicy.allowed
                : FallbackPolicy.strict,
            // This is an acceleration preference. A registered EP alone does
            // not establish physical GPU/NPU use.
            hardwareRequirement: HardwareRequirement.any,
          ),
        ),
      );
      _session = session;
      if (mounted) setState(() => _status = 'Running native ONNX inference…');
      input = OnnxTensor.fromFloat32([
        1,
        4,
      ], Float32List.fromList([-1, 0, 1, 2]));
      final result = await session.runWithDiagnostics({'input': input});
      outputs = result.outputs;
      final values = outputs['output']!.asFloat32List().toList();
      const expected = [0.0, 0.5, 1.5, 2.5];
      for (var i = 0; i < expected.length; i++) {
        if (!values[i].isFinite || (values[i] - expected[i]).abs() > 1e-5) {
          throw StateError(
            'MLP result mismatch: expected $expected, got $values',
          );
        }
      }
      if (mounted) {
        setState(() {
          _output = values;
          _report = result.diagnostic;
          _status = 'Native MLP result verified. This does not validate Qwen.';
        });
      }
    } catch (error) {
      if (mounted) setState(() => _status = 'Inference failed: $error');
    } finally {
      input?.dispose();
      for (final tensor in outputs?.values ?? <OnnxTensor>[]) {
        tensor.dispose();
      }
      await _session?.close();
      _session = null;
      if (mounted) setState(() => _running = false);
    }
  }

  void _exportReport() {
    final report = _report;
    if (report == null) return;
    setState(() {
      _json = const JsonEncoder.withIndent('  ').convert({
        'scope': 'bundled mlp_smoke.onnx inference only; not Qwen validation',
        'requested_provider': _provider.ortName,
        'active_provider': report.activeProvider?.ortName,
        'evidence': report.evidenceLevel.description,
        'duration_us': report.durationUs,
        'model_hash': report.modelHash,
        'hardware_details': report.hardwareDetails,
        'fallback_occurred': report.fallbackOccurred,
        'node_distribution': report.nodeDistribution,
        'output': _output,
      });
    });
  }

  @override
  Widget build(BuildContext context) => Scaffold(
    appBar: AppBar(title: const Text('lib_onnx native inference')),
    body: ListView(
      padding: const EdgeInsets.all(20),
      children: [
        Text(_runtimeInfo),
        Text('EPs in this ORT build: ${_compiledProviders.join(', ')}'),
        const Text(
          'Build capability does not prove device initialization or GPU/NPU use.',
        ),
        const SizedBox(height: 20),
        DropdownButtonFormField<ExecutionProvider>(
          initialValue: _provider,
          decoration: const InputDecoration(labelText: 'Requested backend'),
          items: const [
            DropdownMenuItem(
              value: ExecutionProvider.coreML,
              child: Text('CoreML acceleration preference'),
            ),
            DropdownMenuItem(
              value: ExecutionProvider.qnn,
              child: Text('QNN HTP acceleration preference'),
            ),
            DropdownMenuItem(
              value: ExecutionProvider.cpu,
              child: Text('Explicit CPU correctness baseline'),
            ),
          ],
          onChanged: _running
              ? null
              : (value) {
                  if (value != null) setState(() => _provider = value);
                },
        ),
        SwitchListTile(
          contentPadding: EdgeInsets.zero,
          title: const Text('Allow CPU fallback'),
          subtitle: const Text(
            'Strict rejects ORT CPU graph fallback. '
            'It does not prohibit CPU inside CoreML.',
          ),
          value: _allowCpuFallback,
          onChanged: _running
              ? null
              : (value) => setState(() => _allowCpuFallback = value),
        ),
        const SizedBox(height: 12),
        FilledButton(
          onPressed: _runtime == null || _running ? null : _run,
          child: Text(_running ? 'Running…' : 'Run bundled ONNX MLP'),
        ),
        const SizedBox(height: 20),
        SelectableText(_status),
        if (_output != null)
          SelectableText('relu([-1, 0, 1, 2] + 0.5) = $_output'),
        if (_report case final report?) ...[
          const Divider(),
          Text(
            'Actual provider: ${report.activeProvider?.ortName ?? 'unknown'}',
          ),
          Text('Evidence: ${report.evidenceLevel.description}'),
          Text('Native duration: ${report.durationMs.toStringAsFixed(3)} ms'),
          SelectableText('Model SHA-256: ${report.modelHash ?? 'unavailable'}'),
          Text(
            'CPU fallback: ${report.fallbackOccurred?.toString() ?? 'unknown'}',
          ),
          Text(report.hardwareDetails),
          OutlinedButton(
            onPressed: _exportReport,
            child: const Text('Show actual diagnostic JSON'),
          ),
        ],
        if (_json != null) SelectableText(_json!),
      ],
    ),
  );
}
0
likes
0
points
657
downloads

Publisher

verified publishergsmlg.dev

Weekly Downloads

ONNX Runtime inference for Dart and Flutter with explicit execution policies and experimental CoreML and QNN integration.

Repository (GitHub)
View/report issues

License

unknown (license)

Dependencies

code_assets, crypto, ffi, hooks, meta, native_toolchain_c, path

More

Packages that depend on lib_onnx