Nota
L'accesso a questa pagina richiede l'autorizzazione. È possibile provare ad accedere o modificare le directory.
L'accesso a questa pagina richiede l'autorizzazione. È possibile provare a modificare le directory.
Questo articolo illustra come incorporare ed eseguire modelli ONNX (Open Neural Network Exchange) di piccole dimensioni all'interno dei moduli WebAssembly per eseguire l'inferenza in banda come parte dei grafici dei flussi di dati di Azure IoT Operations. Usare questo approccio per l'arricchimento a bassa latenza e la classificazione direttamente sui dati di streaming senza chiamare servizi di stima esterni.
Importante
I grafici del flusso di dati attualmente supportano solo gli endpoint MQTT (Message Queuing Telemetry Transport), Kafka e OpenTelemetry. Altri tipi di endpoint, ad esempio Data Lake, Microsoft Fabric OneLake, Esplora dati di Azure e Archiviazione locale, non sono supportati. Per altre informazioni, vedere Problemi noti.
Perché usare l'interferenza ONNX in banda
Con i grafici del flusso di dati delle operazioni IoT di Azure, è possibile incorporare l'inferenza di un modello ONNX di piccole dimensioni direttamente nella pipeline anziché chiamare un servizio di stima esterno. Questo approccio offre diversi vantaggi pratici:
- Bassa latenza: consente di eseguire l'arricchimento o la classificazione in tempo reale nello stesso percorso dell'operatore in cui arrivano i dati. Ogni messaggio comporta solo l'inferenza della CPU locale, evitando passaggi di rete.
- Ingombro compatto: Modelli compatti come quelli della classe MobileNet. Questa funzionalità non è destinata a modelli trasformatori di grandi dimensioni, accelerazione GPU/TPU o implementazioni frequenti del modello A/B.
-
Ottimizzato per casi d'uso specifici:
- In linea con l'elaborazione del flusso di dati multi-sorgente in cui le funzionalità sono già preesistenti nella rete
- Allineato alla semantica del tempo degli eventi per consentire all'inferenza di utilizzare gli stessi timestamp degli altri operatori.
- Mantenuto sufficientemente piccolo da incorporarsi con il modulo senza superare i vincoli pratici di memoria e dimensioni WASM
- Aggiornamenti semplici: spedire un nuovo modulo con WASM e un modello incorporato, quindi aggiornare il riferimento alla definizione del grafo. Non è necessario modificare un registro modelli o un endpoint esterno separato.
-
Vincoli hardware: il back-end ONNX viene eseguito sulla CPU tramite WebAssembly System Interface (WASI).
wasi-nnNessuna destinazione GPU/TPU; vengono eseguiti solo gli operatori ONNX supportati. - Scalabilità orizzontale: l'inferenza si espande man mano che aumenta la scala del grafico del flusso di dati. Quando il runtime aggiunge più worker per aumentare la capacità di elaborazione, ciascun worker carica il modello integrato e partecipa al bilanciamento del carico.
Quando utilizzare l'inferenza ONNX in-band
Utilizza l'inferenza in banda quando si hanno questi requisiti:
- La bassa latenza deve arricchire o classificare i messaggi in linea in fase di inserimento
- Modelli piccoli ed efficienti, come i modelli di visione della classe MobileNet o modelli compatti simili
- Inferenza che deve essere allineata all'elaborazione in fase di evento e agli stessi timestamp di altri operatori
- Aggiornamenti semplici tramite spedizione di una nuova versione del modulo con un modello aggiornato
Evitare l'inferenza in banda in presenza di questi requisiti:
- Modelli di trasformatore di grandi dimensioni, accelerazione GPU/TPU o implementazioni A/B sofisticate
- Modelli che richiedono più input tensor, memorizzazione nella cache di chiave-valore o operatori ONNX non supportati
Annotazioni
Si vogliono mantenere i moduli e i modelli incorporati di piccole dimensioni. I modelli di grandi dimensioni e i carichi di lavoro con utilizzo elevato di memoria non sono supportati. Usare architetture compatta e piccole dimensioni di input come 224×224 per la classificazione delle immagini.
Prerequisiti
Prima di iniziare, assicurarsi di disporre di:
- Una distribuzione di Operazioni IoT di Azure con funzionalità di grafici del flusso di dati.
- Accesso a un registro di container come Azure Container Registry.
- Ambiente di sviluppo configurato per lo sviluppo di moduli WebAssembly.
Per istruzioni dettagliate sulla configurazione, vedere Sviluppare moduli WebAssembly.
Modello di architettura
Il modello comune per l'inferenza ONNX nei grafici del flusso di dati include:
-
Pre-elaborare i dati: trasformare i dati di input non elaborati in modo che corrispondano al formato previsto del modello. Per i modelli di immagine, questo processo comporta in genere:
- Decodifica dei byte di immagini.
- Ridimensionamento in una dimensione di destinazione, ad esempio 224×224.
- Conversione dello spazio dei colori, ad esempio RGB in BGR.
- Normalizzazione dei valori pixel nell'intervallo previsto (da 0 a 1 o da -1 a 1).
- Disposizione dei dati nel layout del tensore corretto: NCHW (batch, canali, altezza, larghezza) o NHWC (batch, altezza, larghezza, canali).
-
Eseguire l'inferenza: convertire i dati pre-elaborati in tensori usando l'interfaccia
wasi-nn, caricare il modello ONNX incorporato con il back-end della CPU, impostare i tensori di input nel contesto di esecuzione, richiamare il passaggio in avanti del modello e recuperare i tensori di output contenenti stime non elaborate. -
Output post-elaborazione: trasformare gli output grezzi del modello in risultati significativi. Operazioni comuni:
- Applicare softmax per produrre probabilità di classificazione.
- Selezionare le previsioni Top-K.
- Applicare una soglia di attendibilità per filtrare i risultati con bassa confidenza.
- Eseguire il mapping degli indici di previsione alle etichette leggibili dall'utente.
- Formattare i risultati per il consumo downstream.
Negli esempi IoT per gli operatori RUST WASM è possibile trovare due esempi che seguono questo modello:
- Esempio di trasformazione dei dati "format": decodifica e ridimensiona le immagini in RGB24 224×224.
- Esempio di "snapshot" di elaborazione di immagini/video: incorpora un modello ONNX di MobileNet v2, esegue l'inferenza della CPU e calcola softmax.
Configurare la definizione del grafo
Per abilitare l'inferenza ONNX nel grafico del flusso di dati, è necessario configurare sia la struttura del grafo che i parametri del modulo. La definizione del grafo specifica il flusso della pipeline, mentre le configurazioni del modulo consentono la personalizzazione del runtime del comportamento di pre-elaborazione e inferenza.
Abilitare il supporto WASI-NN
Per abilitare il supporto dell'interfaccia di rete neurale WebAssembly, aggiungere la wasi-nn funzione alla definizione del grafo.
moduleRequirements:
apiVersion: "1.1.0"
runtimeVersion: "1.1.0"
features:
- name: "wasi-nn"
Definire operazioni e flussi di dati
Configurare le operazioni che formano la pipeline di inferenza. Questo esempio mostra un tipico flusso di lavoro di classificazione delle immagini:
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" }
Questa configurazione crea una pipeline in cui:
-
camera-inputriceve dati di immagine non elaborati da un'origine -
module-format/mappre-elabora le immagini (decodifica, ridimensionamento, conversione del formato) -
module-snapshot/mapesegue l'inferenza ONNX e l'elaborazione successiva -
results-outputgenera i risultati della classificazione in un sink
Configurare i parametri del modulo
Definire i parametri di runtime per personalizzare il comportamento del modulo senza ricompilare. Questi parametri vengono passati ai moduli WASM all'inizializzazione:
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
L'operatore init può leggere questi valori tramite l'interfaccia di configurazione del modulo. Per informazioni dettagliate, vedere Parametri di configurazione del modulo.
Impacchettare il modello
L'incorporamento di modelli ONNX direttamente nel componente WASM garantisce la coerenza delle versioni e della distribuzione atomica. Questo approccio semplifica la distribuzione e rimuove le dipendenze di runtime da registri o file di modello esterni.
Suggerimento
L'incorporazione mantiene il modello e la logica dell'operatore versionati insieme. Per aggiornare un modello, pubblicare una nuova versione del modulo e aggiornare la definizione del grafo per farvi riferimento. Questo approccio elimina la deriva del modello e garantisce distribuzioni riproducibili.
Linee guida per la preparazione del modello
Prima di incorporare il modello, assicurarsi che soddisfi i requisiti per la distribuzione WASM:
- Mantenere i modelli sotto i 50 MB per tempi di caricamento e vincoli di memoria pratici per WASM.
- Verificare che il modello accetti un singolo input tensore in un formato comune (float32 o uint8).
- Verificare che il back-end di runtime ONNX WASM supporti ogni operatore usato dal modello.
- Usare gli strumenti di ottimizzazione ONNX per ridurre le dimensioni del modello e migliorare la velocità di inferenza.
Incorporazione del flusso di lavoro
Seguire questa procedura per incorporare il modello e le risorse associate:
-
Organizzare gli asset del modello: posizionare il file del modello
.onnxe illabels.txtfacoltativo nella struttura di origine. Usare una struttura di directory dedicata,src/fixture/models/ad esempio esrc/fixture/labels/per un'organizzazione chiara. -
Incorporare in fase di compilazione: usare meccanismi specifici del linguaggio per includere i byte del modello nel file binario. In Rust usare
include_bytes!per i dati binari einclude_str!per i file di testo. -
Inizializzare il grafo WASI-NN: nella funzione
initdell'operatore creare un grafowasi-nndai byte incorporati, specificando la codifica ONNX e la destinazione di esecuzione su CPU. - Implementare il ciclo di inferenza: per ogni messaggio in ingresso, pre-elaborare gli input in modo che corrispondano ai requisiti del modello, impostare tensori di input, eseguire inferenza, recuperare gli output e applicare la post-elaborazione.
- Gestire gli errori con eleganza: implementare una corretta gestione degli errori per il caricamento del modello, gli operatori non supportati e gli errori di inferenza di runtime.
Per un modello di implementazione completo, vedere l'esempio di "snapshot".
Struttura del progetto consigliata
Organizzare il progetto di modulo WASM con una netta separazione delle problematiche:
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
Riferimenti ai file di esempio
Usare il layout di file seguente dell'esempio "snapshot" come riferimento:
- Directory Etichette : contiene vari file di mapping delle etichette
- Directory Models : contiene i file e i metadati del modello ONNX
Esempio di incorporamento minimo
L'esempio seguente illustra l'incorporamento minimo di Rust. I percorsi sono relativi al file di origine che contiene la macro:
// 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(())
}
Ottimizzazione delle prestazioni
Per evitare di ricreare il grafo ONNX e il contesto di esecuzione per ogni messaggio, inizializzarlo una volta e riutilizzarlo.
L'esempio pubblico usa un oggetto staticoLazyLock:
use crate::wasi::nn::{
graph::{load, ExecutionTarget, Graph, GraphEncoding, GraphExecutionContext},
tensor::{Tensor, TensorData, TensorDimensions, TensorType},
};
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).compute()?;
}
}
Distribuire e implementare i moduli
Riutilizzare i generatori di esempi semplificati o compilare localmente:
- Per usare il generatore Docker semplificato, vedere l'esempio di Generatore Docker di Rust
- Per una distribuzione WebAssembly generale e i passaggi del Registro di sistema, vedere Usare WebAssembly con grafici del flusso di dati
Seguire questo processo di distribuzione:
- Compilare il modulo WASM in modalità di rilascio e produrre un
<module-name>-<version>.wasmfile. - Eseguire il push del modello e facoltativamente di una definizione del grafo nel Registro di sistema usando ORAS (OCI Registry as Storage).
- Creare o riutilizzare un endpoint del Registro di sistema in Operazioni IoT di Azure.
- Creare una risorsa del grafo del flusso di dati che fa riferimento all'artefatto della definizione del grafo.
Esempio: Classificazione delle immagini mobileNet
Gli esempi pubblici IoT forniscono due esempi cablati in un grafico per la classificazione delle immagini: l'esempio "format" fornisce la funzionalità di decodifica e ridimensionamento delle immagini e l'esempio di "snapshot" fornisce l'inferenza ONNX e l'elaborazione softmax.
Per distribuire questo esempio, eseguire il pull degli artefatti dal registro pubblico, eseguirne il push nel registro e distribuire un grafico del flusso di dati, come illustrato nell'esempio 2: Distribuire un grafico complesso. Il grafico complesso usa questi moduli per elaborare gli snapshot delle immagini e generare risultati di classificazione.
Limitazioni
L'inferenza nei grafici del flusso di dati WASM presenta le limitazioni seguenti:
- Solo compatibile con ONNX. I grafici del flusso di dati non supportano altri formati come TFLite.
- Solo CPU. Nessuna accelerazione GPU/TPU.
- Modelli di piccole dimensioni consigliati. I modelli di grandi dimensioni e l'inferenza a elevato utilizzo di memoria non sono supportati.
- Sono supportati modelli di input a tensore singolo. I modelli multi-input, la memorizzazione nella cache chiave-valore e gli scenari avanzati di sequenza o generazione non sono supportati.
- Verificare che il back-end ONNX nel runtime WASM supporti gli operatori del modello. Se un operatore non è supportato, l'inferenza ha esito negativo in fase di caricamento o esecuzione.