Remarque
L’accès à cette page nécessite une autorisation. Vous pouvez essayer de vous connecter ou de modifier des répertoires.
L’accès à cette page nécessite une autorisation. Vous pouvez essayer de modifier des répertoires.
Cet article explique comment incorporer et exécuter de petits modèles ONNX (Open Neural Network Exchange) à l’intérieur de vos modules WebAssembly pour effectuer une inférence en bande dans le cadre des graphiques de flux de données Azure IoT Operations. Utilisez cette approche pour l’enrichissement et la classification à faible latence directement sur les données de streaming sans appeler des services de prédiction externes.
Important
Actuellement, les graphiques de flux de données prennent uniquement en charge les points de terminaison MQTT (Transport de télémétrie Message Queuing), Kafka et OpenTelemetry. D’autres types de points de terminaison tels que Data Lake, Microsoft Fabric OneLake, Azure Data Explorer et Stockage local ne sont pas pris en charge. Pour plus d’informations, consultez la section Problèmes connus.
Pourquoi utiliser l’interférence ONNX en bande
Avec les graphiques de flux de données Azure IoT Operations, vous pouvez incorporer une petite inférence de modèle ONNX directement dans le pipeline au lieu d’appeler un service de prédiction externe. Cette approche offre plusieurs avantages pratiques :
- Faible latence : effectuez un enrichissement ou une classification en temps réel dans le même chemin d’opérateur que celui où les données arrivent. Chaque message implique uniquement l’inférence du processeur local, évitant ainsi les allers-retours réseau.
- Encombrement compact : ciblez des modèles compacts tels que des modèles de type MobileNet. Cette fonctionnalité n’est pas destinée aux grands modèles transformateurs, à l’accélération GPU/TPU ou aux déploiements fréquents de modèles A/B.
-
Optimisé pour des cas d’usage spécifiques :
- En ligne avec le traitement de flux multi-source où les fonctionnalités sont déjà colocalisées dans le graphe
- Aligné avec la sémantique de temps d'événement, l'inférence emploie les mêmes horodatages que les autres opérateurs.
- Suffisamment petite pour être incorporée avec le module sans dépasser les contraintes de mémoire et de taille WASM pratiques
- Mises à jour simples : envoyez un nouveau module avec WASM et un modèle incorporé, puis mettez à jour la référence de définition de graphique. Il n’est pas nécessaire d’avoir un registre de modèles distinct ou un changement de point de terminaison externe.
-
Contraintes matérielles : le back-end ONNX s’exécute sur le processeur via l’interface système WebAssembly (WASI).
wasi-nnAucune cible GPU/TPU, seuls les opérateurs ONNX pris en charge s’exécutent. - Mise à l’échelle horizontale : l’inférence augmente à mesure que le graphe de flux de données s'étend. Lorsque le runtime ajoute davantage de Workers pour le débit, chaque Worker charge le modèle incorporé et participe à l’équilibrage de charge.
Quand utiliser l’inférence ONNX en bande
Utilisez l’inférence en bande lorsque vous avez les exigences suivantes :
- Les besoins en faible latence exigent d'enrichir ou de classifier les messages en temps réel lors de l'ingestion.
- Modèles petits et efficaces, tels que des modèles de vision de la classe MobileNet ou les modèles compacts similaires.
- Inférence qui doit s’aligner sur le traitement en temps d'événement et les mêmes marques temporelles que les autres opérateurs.
- Mises à jour simples en expédiant une nouvelle version de module avec un modèle mis à jour
Évitez l’inférence en bande lorsque vous avez ces exigences :
- Grands modèles transformateurs, accélération GPU/TPU ou déploiements A/B sophistiqués
- Modèles nécessitant plusieurs entrées tensorielles, une mise en cache clé-valeur ou des opérateurs ONNX non pris en charge
Note
Vous souhaitez conserver les modules et les modèles incorporés petits. Les grands modèles et les charges de travail gourmandes en mémoire ne sont pas pris en charge. Utilisez des architectures compactes et de petites tailles d’entrée comme 224×224 pour la classification d’images.
Prerequisites
Avant de commencer, vérifiez que vous disposez des points suivants :
- Un déploiement Azure IoT Operations avec des diagrammes de flux de données.
- Accès à un registre de conteneurs comme Azure Container Registry.
- Environnement de développement configuré pour le développement de modules WebAssembly.
Pour obtenir des instructions d’installation détaillées, consultez Développer des modules WebAssembly.
Modèle d’architecture
Le modèle courant pour l’inférence ONNX dans les graphiques de flux de données inclut :
-
Prétraitement des données : transformez les données d’entrée brutes en fonction du format attendu de votre modèle. Pour les modèles d’image, ce processus implique généralement :
- Décodage des octets d’image.
- Redimensionnement vers une dimension cible (par exemple, 224×224).
- Conversion de l’espace de couleur (par exemple, RVB en BGR).
- Normalisation des valeurs de pixels à la plage attendue (0 à 1 ou -1 à 1).
- Organisation des données dans la disposition correcte du tenseur : NCHW (lot, canaux, hauteur, largeur) ou NHWC (lot, hauteur, largeur, canaux).
-
Exécuter l’inférence : convertissez des données prétraite en tenseurs à l’aide de l’interface
wasi-nn, chargez votre modèle ONNX incorporé avec le back-end du processeur, définissez des tenseurs d’entrée sur le contexte d’exécution, appelez la passe de transfert du modèle et récupérez les tenseurs de sortie contenant des prédictions brutes. -
Post-traitement des sorties : transformez les sorties brutes du modèle en résultats significatifs. Opérations courantes :
- Appliquez softmax pour produire des probabilités de classification.
- Sélectionnez les prédictions « top-K ».
- Appliquez un seuil de confiance pour filtrer les résultats à faible confiance.
- Associer des indices de prédiction à des étiquettes faciles à lire pour l'homme.
- Mettre en forme les résultats pour la consommation en aval.
Dans les exemples IoT pour les opérateurs WASM Rust , vous trouverez deux exemples qui suivent ce modèle :
- Exemple de transformation de données « format » : décode et redimensionne les images en RVB24 224×224.
- Exemple de traitement d’image/vidéo « instantané » : incorpore un modèle ONNX MobileNet v2, exécute l’inférence du processeur et calcule softmax.
Configurer la définition de graphique
Pour activer l’inférence ONNX dans votre graphe de flux de données, vous devez configurer à la fois la structure de graphe et les paramètres de module. La définition de graphique spécifie le flux de pipeline, tandis que les configurations de module autorisent la personnalisation du runtime du prétraitement et du comportement d’inférence.
Activer la prise en charge de WASI-NN
Pour activer la prise en charge de l’interface réseau neuronal WebAssembly, ajoutez la wasi-nn fonctionnalité à votre définition de graphique :
moduleRequirements:
apiVersion: "1.1.0"
runtimeVersion: "1.1.0"
features:
- name: "wasi-nn"
Définir des opérations et un flux de données
Configurez les opérations qui forment votre pipeline d’inférence. Cet exemple montre un flux de travail de classification d’images classique :
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" }
Cette configuration crée un pipeline dans lequel :
-
camera-inputreçoit les données d’image brutes d’une source -
module-format/mapprétraite des images (décodage, redimensionnement, conversion de format) -
module-snapshot/mapexécute l’inférence et le post-traitement ONNX -
results-outputémet des résultats de classification dans un récepteur
Configurer les paramètres du module
Définissez des paramètres d'exécution pour personnaliser le comportement du module sans le recompiler. Ces paramètres sont passés à vos modules WASM lors de l’initialisation :
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
Votre opérateur init peut lire ces valeurs via l’interface de configuration du module. Pour plus d’informations, consultez les paramètres de configuration du module.
Empaqueter le modèle
L’incorporation de modèles ONNX directement dans votre composant WASM assure un déploiement atomique et une cohérence de version. Cette approche simplifie la distribution et supprime les dépendances d’exécution sur les fichiers ou registres de modèles externes.
Conseil / Astuce
L'intégration permet de versionner ensemble le modèle et la logique de l'opérateur. Pour mettre à jour un modèle, publiez une nouvelle version de module et mettez à jour votre définition de graphique pour la référencer. Cette approche élimine la dérive du modèle et garantit des déploiements reproductibles.
Instructions de préparation du modèle
Avant d’incorporer votre modèle, vérifiez qu’il répond aux exigences du déploiement WASM :
- Conservez les modèles de moins de 50 Mo pour les temps de chargement WASM pratiques et les contraintes de mémoire.
- Vérifiez que votre modèle accepte une seule entrée de capteur dans un format commun (float32 ou uint8).
- Vérifiez que le serveur principal du runtime WASM ONNX prend en charge chaque opérateur que votre modèle utilise.
- Utilisez les outils d’optimisation ONNX pour réduire la taille du modèle et améliorer la vitesse d’inférence.
Workflow d’incorporation
Procédez comme suit pour incorporer votre modèle et vos ressources associées :
-
Organisez les ressources du modèle : placez le fichier de modèle ainsi que le fichier facultatif
.onnxdans la hiérarchie de votre source. Utilisez une structure d’annuaires dédiée commesrc/fixture/models/etsrc/fixture/labels/pour une organisation claire. -
Incorporer au moment de la compilation : utilisez des mécanismes spécifiques au langage pour inclure des octets de modèle dans votre binaire. Dans Rust, utilisez-le
include_bytes!pour les données binaires etinclude_str!pour les fichiers texte. -
Initialisez le graphe WASI-NN : dans la fonction de l'opérateur
init, créez un graphe à partir des octets incorporés, en spécifiant l’encodage ONNX et la cible d’exécution du CPU. - Implémentez une boucle d’inférence : Pour chaque message entrant, prétraitez les entrées pour répondre aux exigences du modèle, définissez des tenseurs d’entrée, exécutez l’inférence, récupérez des sorties et appliquez le post-traitement.
- Gérer correctement les erreurs : implémentez une gestion appropriée des erreurs pour les échecs de chargement de modèle, les opérateurs non pris en charge et les erreurs d’inférence d’exécution.
Pour obtenir un modèle d’implémentation complet, consultez l’exemple « instantané ».
Structure de projet recommandée
Organisez votre projet de module WASM avec une séparation claire des préoccupations :
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
Exemples de références de fichier
Utilisez la disposition de fichier suivante à partir de l’exemple « instantané » comme référence :
- Répertoire d’étiquettes - Contient différents fichiers de mappage d’étiquettes
- Répertoire modèles - Contient des fichiers et métadonnées de modèle ONNX
Exemple minimal d’incorporation
L’exemple suivant illustre l’incorporation de Rust minimale. Les chemins d’accès sont relatifs au fichier source qui contient 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(())
}
Optimisation des performances
Pour éviter de recréer le graphique ONNX et le contexte d’exécution pour chaque message, initialisez-le une fois et réutilisez-le.
L’exemple public utilise un statique LazyLock:
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()?;
}
}
Déployer vos modules
Réutilisez les générateurs d'échantillons rationalisés ou construisez localement :
- Pour utiliser le générateur Docker simplifié, consultez l’exemple de générateur Docker Rust
- Pour obtenir des étapes générales de déploiement et d'enregistrement WebAssembly, consultez Utiliser WebAssembly avec des graphes de flux de données
Suivez ce processus de déploiement :
- Générez votre module WASM en mode mise en production et produisez un fichier
<module-name>-<version>.wasm. - Envoyez le module et éventuellement une définition de graphe vers votre registre en utilisant le registre OCI comme stockage (ORAS).
- Créez ou réutilisez un point de terminaison de Registre dans Azure IoT Operations.
- Créez une ressource de graphique de flux de données qui référence votre artefact de définition de graphique.
Exemple : classification d’images MobileNet
Les exemples publics IoT fournissent deux exemples câblés dans un graphique pour la classification d’images : l’exemple « format » fournit des fonctionnalités de décodage et de redimensionnement d’image, et l’exemple « instantané » fournit l’inférence ONNX et le traitement softmax.
Pour déployer cet exemple, extrayez les artefacts du registre public, envoyez-les à votre registre et déployez un graphique de flux de données, comme illustré dans l’exemple 2 : Déployer un graphique complexe. Le graphique complexe utilise ces modules pour traiter les instantanés d’image et émettre des résultats de classification.
Limites
L’inférence dans les graphiques de flux de données WASM présente les limitations suivantes :
- ONNX uniquement. Les graphiques de flux de données ne prennent pas en charge d’autres formats comme TFLite.
- Processeur uniquement. Aucune accélération GPU/TPU.
- Il est recommandé d'utiliser de petits modèles. Les modèles volumineux et l’inférence gourmande en mémoire ne sont pas pris en charge.
- Les modèles d’entrée à un seul tenseur sont pris en charge. Les modèles multi-entrée, la mise en cache clé-valeur et les scénarios de séquence ou de génération avancés ne sont pas pris en charge.
- Vérifiez que le back-end ONNX dans le runtime WASM prend en charge les opérateurs de votre modèle. Si un opérateur n’est pas pris en charge, l’inférence échoue au moment du chargement ou de l’exécution.