Sdílet prostřednictvím


Spuštění odvozování ONNX v grafech toku dat WebAssembly (WASM)

Tento článek ukazuje, jak vkládat a spouštět malé modely Open Neural Network Exchange (ONNX) do modulů WebAssembly pro provádění odvozování v rámci grafů toku dat Azure IoT Operations. Tento přístup použijte pro rozšiřování a klasifikaci s nízkou latencí přímo u streamovaných dat bez volání externích prediktivních služeb.

Důležité

Grafy toku dat momentálně podporují pouze koncové body MQTT (Message Queuing Telemetry Transport), Kafka a OpenTelemetry. Jiné typy koncových bodů, jako jsou Data Lake, Microsoft Fabric OneLake, Azure Data Explorer a Local Storage, se nepodporují. Další informace najdete v tématu Známé problémy.

Proč používat interferenci ONNX v pásmu

Pomocí grafů toku dat Azure IoT můžete vložit malý inferenční model ONNX přímo do potrubí místo volání externí služby predikce. Tento přístup nabízí několik praktických výhod:

  • Nízká latence: Proveďte rozšiřování v reálném čase nebo klasifikaci ve stejné cestě operátoru, kam data přicházejí. Každá zpráva vyžaduje pouze místní zpracování procesoru a vyhýbá se obousměrné komunikaci po síti.
  • Kompaktní rozměry: Cílové kompaktní modely, jako jsou modely třídy MobileNet. Tato funkce není určená pro velké modely transformátorů, akceleraci GPU/TPU ani časté zavedení modelů A/B.
  • Optimalizováno pro konkrétní případy použití:
    • V souladu se zpracováním datových proudů z více zdrojů, kde jsou funkce už v grafu umístěné společně
    • Sladěno se sémantikou času událostí, takže odvození používá stejné časové značky jako ostatní operátory.
    • Uchovával se dostatečně malý pro vložení s modulem bez překročení praktických omezení velikosti WASM a paměti.
  • Jednoduché aktualizace: Odešlete nový modul pomocí WASM a vloženého modelu a pak aktualizujte odkaz na definici grafu. Není potřeba mít samostatný registr modelu ani změnu externího koncového bodu.
  • Hardwarová omezení: Back-end ONNX běží na procesoru prostřednictvím rozhraní WebAssembly System Interface (WASI). wasi-nn Žádné cíle GPU/TPU; spouštějí se pouze podporované operátory ONNX.
  • Horizontální škálování: Odvozování se škáluje při škálování grafu toku dat. Když modul runtime přidá další pracovní procesy pro propustnost, každý pracovní proces načte vložený model a účastní se vyrovnávání zatížení.

Kdy použít odvození ONNX v pásmu

Pokud máte tyto požadavky, použijte vyvozování pomocí in-band:

  • Nízká latence vyžaduje obohatit nebo klasifikovat zprávy během jejich příjmu.
  • Malé a efektivní modely, jako je vize třídy MobileNet nebo podobné kompaktní modely
  • Odvození, které musí být v souladu se zpracováním času událostí a stejnými časovými razítky jako ostatní operátory
  • Jednoduché aktualizace odesláním nové verze modulu s aktualizovaným modelem

Pokud máte tyto požadavky, vyhněte se odvozováním v pásmu:

  • Velké modely založené na transformátorech, akcelerace GPU/TPU nebo sofistikované testování A/B
  • Modely, které vyžadují více vstupů tensoru, ukládání do mezipaměti klíč-hodnota nebo nepodporované operátory ONNX

Poznámka:

Chcete zachovat moduly a vložené modely malé. Velké modely a úlohy náročné na paměť se nepodporují. Pro klasifikaci obrázků používejte kompaktní architektury a malé vstupní velikosti, jako je 224×224.

Požadavky

Než začnete, ujistěte se, že máte:

  • Nasazení operací Azure IoT s možnostmi grafů toku dat
  • Přístup k registru kontejneru, jako je Azure Container Registry.
  • Vývojové prostředí nastavené pro vývoj modulů WebAssembly

Podrobné pokyny k nastavení najdete v tématu Vývoj modulů WebAssembly.

Architektonický vzor

Běžný vzor pro odvozování ONNX v grafech toku dat zahrnuje:

  1. Předběžné zpracování dat: Transformujte nezpracovaná vstupní data tak, aby odpovídala očekávanému formátu modelu. U modelů obrázků tento proces obvykle zahrnuje:
    • Dekódování bajtů obrázků
    • Změna velikosti na cílovou dimenzi (například 224×224).
    • Převod barevného prostoru (například RGB na BGR)
    • Normalizace hodnot pixelů do očekávaného rozsahu (0–1 nebo -1 až 1).
    • Uspořádání dat ve správném rozložení tenzoru: NCHW (dávka, kanály, výška, šířka) nebo NHWC (dávka, výška, šířka, kanály).
  2. Spuštění odvozování: Převod předzpracovaných dat na tensory pomocí wasi-nn rozhraní, načtení vloženého modelu ONNX s backendem CPU, nastavení vstupních tenzorů v kontextu provádění, vyvolání posunu vpřed modelu a načtení výstupních tenzorů obsahujících surové předpovědi.
  3. Výstupy postprocesu: Transformujte nezpracované výstupy modelu na smysluplné výsledky. Běžné operace:
    • Použití softmaxu k vytvoření pravděpodobností klasifikace
    • Vyberte nejlépe hodnocené predikce.
    • Použijte prahovou hodnotu spolehlivosti pro filtrování výsledků s nízkou spolehlivostí.
    • Mapovat predikční indexy na popisky čitelné pro člověka.
    • Formátovat výsledky pro další zpracování.

V ukázkách IoT pro Rust WASM Operátor najdete dvě ukázky, které se řídí tímto vzorem:

Konfigurace definice grafu

Pokud chcete povolit odvozování ONNX v grafu toku dat, musíte nakonfigurovat jak strukturu grafu, tak parametry modulu. Definice grafu určuje tok kanálu, zatímco konfigurace modulů umožňují přizpůsobení předzpracování a chování při odvozování za běhu.

Povolení podpory WASI-NN

Pokud chcete povolit podporu rozhraní Neurální sítě WebAssembly, přidejte tuto wasi-nn funkci do definice grafu:

moduleRequirements:
  apiVersion: "0.2.0"
  hostlibVersion: "0.2.0"
  features:
    - name: "wasi-nn"

Definování operací a toku dat

Nakonfigurujte operace, které tvoří kanál odvozování. Tento příklad ukazuje typický pracovní postup klasifikace obrázků:

operations:
  - operationType: "source"
    name: "camera-input"
  - operationType: "map"
    name: "module-format/map"
    module: "format:1.0.0"
  - operationType: "map"
    name: "module-snapshot/map"
    module: "snapshot:1.0.0"
  - operationType: "sink"
    name: "results-output"

connections:
  - from: { name: "camera-input" }
    to: { name: "module-format/map" }
  - from: { name: "module-format/map" }
    to: { name: "module-snapshot/map" }
  - from: { name: "module-snapshot/map" }
    to: { name: "results-output" }

Tato konfigurace vytvoří kanál, kde:

  • camera-input přijímá nezpracovaná data obrázků ze zdroje.
  • module-format/map předběžné zpracování obrázků (dekódování, změna velikosti, převod formátu)
  • module-snapshot/map spouští inferenci a následné zpracování ONNX.
  • results-output odesílá výsledky klasifikace do úložiště.

Konfigurace parametrů modulu

Definujte běhové parametry pro přizpůsobení chování modulu bez opětovného sestavení. Tyto parametry se předávají modulům WASM při inicializaci:

moduleConfigurations:
  - name: module-format/map
    parameters:
      width:
        name: width
        description: "Target width for image resize (default: 224)"
        required: false
      height:
        name: height
        description: "Target height for image resize (default: 224)"
        required: false
      pixelFormat:
        name: pixel_format
        description: "Output pixel format (rgb24, bgr24, grayscale)"
        required: false

  - name: module-snapshot/map
    parameters:
      executionTarget:
        name: execution_target
        description: "Inference execution target (cpu, auto)"
        required: false
      labelMap:
        name: label_map
        description: "Label mapping strategy (embedded, imagenet, custom)"
        required: false
      scoreThreshold:
        name: score_threshold
        description: "Minimum confidence score to include in results (0.0-1.0)"
        required: false
      topK:
        name: top_k
        description: "Maximum number of predictions to return (default: 5)"
        required: false

init Operátor může tyto hodnoty číst prostřednictvím konfiguračního rozhraní modulu. Podrobnosti najdete v tématu Parametry konfigurace modulu.

Zabalení modelu

Vkládání modelů ONNX přímo do vaší komponenty WASM zajišťuje jednotné nasazení a konzistentnost verzí. Tento přístup zjednodušuje distribuci a odebírá závislosti modulu runtime na souborech nebo registrech externího modelu.

Návod

Vkládání udržuje model a logiku operátoru společně verzované. Pokud chcete aktualizovat model, publikujte novou verzi modulu a aktualizujte definici grafu tak, aby na ni odkazovat. Tento přístup eliminuje posun modelu a zajišťuje reprodukovatelná nasazení.

Pokyny pro přípravu modelu

Před vložením modelu se ujistěte, že splňuje požadavky na nasazení WASM:

  • Udržujte modely pod 50 MB kvůli praktickým dobám načítání WASM a omezením paměti.
  • Ověřte, že model přijímá jeden vstup tensoru ve společném formátu (float32 nebo uint8).
  • Ověřte, že back-end modulu runtime WASM ONNX podporuje všechny operátory, které model používá.
  • Pomocí optimalizačních nástrojů ONNX snižte velikost modelu a zvyšte rychlost odvozování.

Pracovní postup vkládání

Při vkládání modelu a přidružených prostředků postupujte takto:

  1. Uspořádání prostředků modelu: Umístěte .onnx soubor modelu a volitelně labels.txt do stromu zdrojů. Používejte vyhrazenou adresářovou strukturu, například src/fixture/models/ a src/fixture/labels/ pro jasnou organizaci.
  2. Vložení v době kompilace: K zahrnutí bajtů modelu do binárního souboru použijte mechanismy specifické pro jazyk. V Rustu použijte include_bytes! binární data a include_str! textové soubory.
  3. Inicializace WASI-NN grafu: Ve funkci operátora init vytvořte wasi-nn graf z vložených bajtů a určete kódování ONNX a cíl spouštění procesoru.
  4. Implementujte smyčku odvozování: Pro každou příchozí zprávu předzpracovává vstupy tak, aby odpovídaly požadavkům modelu, nastavily vstupní tensory, spouštěly odvozování, načítaly výstupy a použily postprocesing.
  5. Zpracování chyb bez problémů: Implementujte správné zpracování chyb pro chyby při načítání modelu, nepodporované operátory a chyby odvozování za běhu.

Kompletní vzor implementace najdete v ukázce "snapshot".

Uspořádejte projekt modulu WASM s jasným oddělením obav:

src/
├── lib.rs                 # Main module implementation
├── model/
│   ├── mod.rs            # Model management module
│   └── inference.rs      # Inference logic
└── fixture/
    ├── models/
    │   ├── mobilenet.onnx      # Primary model
    │   └── mobilenet_opt.onnx  # Optimized variant
    └── labels/
        ├── imagenet.txt        # ImageNet class labels
        └── custom.txt          # Custom label mappings

Ukázkové odkazy na soubory

Jako referenci použijte následující rozložení souboru z ukázky snímku:

Příklad minimálního vkládání

Následující příklad ukazuje minimální vkládání Rust. Cesty jsou relativní vzhledem ke zdrojovému souboru, který obsahuje makro:

// src/lib.rs (example)
// Embed ONNX model and label map into the component
static MODEL: &[u8] = include_bytes!("fixture/models/mobilenet.onnx");
static LABEL_MAP: &[u8] = include_bytes!("fixture/labels/synset.txt");

fn init_model() -> Result<(), anyhow::Error> {
  // Create wasi-nn graph from embedded ONNX bytes using the CPU backend
  // Pseudocode – refer to the snapshot sample for the full implementation
  // use wasi_nn::{graph::{load, GraphEncoding, ExecutionTarget}, Graph};
  // let graph = load(&[MODEL.to_vec()], GraphEncoding::Onnx, ExecutionTarget::Cpu)?;
  // let exec_ctx = Graph::init_execution_context(&graph)?;
  Ok(())
}

Optimalizace výkonu

Abyste se vyhnuli opětovnému vytvoření grafu ONNX a kontextu spuštění pro každou zprávu, inicializujete ho jednou a znovu ho použijete. Veřejná ukázka používá statickouLazyLock:

use std::sync::LazyLock;
use wasi_nn::{graph::{load, Graph, GraphEncoding, ExecutionTarget}, GraphExecutionContext};

static mut CONTEXT: LazyLock<GraphExecutionContext> = LazyLock::new(|| {
  let graph = load(&[MODEL.to_vec()], GraphEncoding::Onnx, ExecutionTarget::Cpu).unwrap();
  Graph::init_execution_context(&graph).unwrap()
});

fn run_inference(/* input tensors, etc. */) {
  unsafe {
    // (*CONTEXT).set_input(...)?; (*CONTEXT).compute()?; (*CONTEXT).get_output(...)?;
  }
}

Nasazení modulů

Znovu použijte zjednodušené nástroje pro tvorbu ukázek nebo provádějte kompilaci lokálně:

Postupujte podle tohoto procesu nasazení:

  1. Sestavte modul WASM v režimu pro vydání a vytvořte <module-name>-<version>.wasm soubor.
  2. Nahrajte modul a volitelně i definici grafu do registru s využitím OCI Registry jako úložiště (ORAS).
  3. Vytvořte nebo znovu použijte koncový bod registru v operacích Azure IoT.
  4. Vytvořte prostředek grafu toku dat, který odkazuje na artefakt definice grafu.

Příklad: Klasifikace obrázků MobileNet

Veřejné ukázky IoT poskytují dva vzorky připojené k grafu pro klasifikaci obrázků: ukázka "format" poskytuje funkce dekódování a změny velikosti obrázku a ukázka snímku poskytuje odvozování ONNX a softmax zpracování.

Pokud chcete tento příklad nasadit, stáhněte artefakty z veřejného registru, nasdílejte je do registru a nasaďte graf toku dat, jak je znázorněno v příkladu 2: Nasazení složitého grafu. Složitý graf používá tyto moduly ke zpracování snímků obrázků a generování výsledků klasifikace.

Omezení

Odvozování v grafech toku dat WASM má následující omezení:

  • Pouze ONNX. Grafy toku dat nepodporují jiné formáty, jako je TFLite.
  • Pouze procesor. Žádná akcelerace GPU/TPU.
  • Doporučené malé modely. Velké modely a odvozování náročné na paměť se nepodporují.
  • Podporují se vstupní modely s jedním tensorem. Modely s více vstupy, ukládání do mezipaměti klíč-hodnota a pokročilé scénáře sekvence nebo generování se nepodporují.
  • Ujistěte se, že ONNX back-end ve WASM runtime podporuje operátory vašeho modelu. Pokud operátor není podporovaný, inferenční proces selže při načtení nebo během spuštění.