ONNX (Open Neural Network Exchange)
ONNX est un format ouvert et standardisé de représentation de modèles de machine learning, qui définit un graphe de calcul extensible ainsi qu’un ensemble d’opérateurs et de types de données intégrés. Il permet d’entraîner un modèle dans un framework (PyTorch, TensorFlow, scikit-learn, etc.) et de l’exécuter de manière optimisée sur n’importe quel matériel supporté, via ONNX Runtime ou d’autres moteurs d’inférence compatibles.
ONNX est le « traducteur universel » de l’IA. Vous développez votre modèle avec votre framework préféré, vous l’exportez en .onnx, et vous le déployez partout : CPU, GPU NVIDIA, GPU AMD, GPU Intel, NPU mobile, navigateur web, ou appareil embarqué. C’est cette portabilité qui a fait d’ONNX un standard de facto pour les pipelines de déploiement multi-plateformes en production.
- Type
- Format ouvert d’échange et de représentation de modèles IA
- Créé en
- Septembre 2017 (Facebook + Microsoft)
- Gouvernance
- Linux Foundation AI & Data (LF AI & Data)
- Version actuelle
- ONNX 1.20.1 (stable, janvier 2026) / 1.21.0 (RC, mars 2026)
- Opset actuel
- Opset 27, IR version 13
- Runtime principal
- ONNX Runtime (Microsoft), open source
- Frameworks supportés
- PyTorch, TensorFlow, scikit-learn, XGBoost, LightGBM, PaddlePaddle, etc.
- Accélérateurs
- CUDA, TensorRT, OpenVINO, DirectML, CoreML, QNN (Qualcomm), CANN (Huawei)
- Licence
- Apache 2.0
Histoire et adoption
ONNX naît en septembre 2017, porté par Facebook (Meta) et Microsoft, pour résoudre un problème concret : la fragmentation de l’écosystème ML. À l’époque, un modèle entraîné dans PyTorch ne peut pas être facilement exécuté dans TensorFlow, et vice versa. Chaque framework a son propre format de sérialisation, ses propres opérateurs, et ses propres optimisations. Déployer un modèle sur du matériel spécifique (GPU mobile, NPU, FPGA) exige souvent une conversion manuelle, fragile et propice aux erreurs.
L’idée d’ONNX : créer un format intermédiaire standardisé. Vous exportez votre modèle vers ONNX depuis n’importe quel framework, et n’importe quel runtime compatible peut l’exécuter de manière optimisée. En 2018, Microsoft open-source ONNX Runtime, le moteur d’exécution de référence. En 2019, ONNX rejoint la Linux Foundation AI, cimentant son statut de standard ouvert. Les acteurs de l’industrie s’alignent rapidement : NVIDIA intègre ONNX dans TensorRT, Intel dans OpenVINO, Qualcomm dans QNN, Apple dans CoreML.
Aujourd’hui, ONNX Runtime alimente les produits Microsoft (Office, Azure, Bing, Windows ML, Visual Studio) et des milliers de projets dans l’industrie. La spécification ONNX elle-même en est à l’opset 27 (version 1.20.1 stable), avec des opérateurs dédiés aux LLM récemment ajoutés (RotaryEmbedding, RMSNormalization).
Comment fonctionne ONNX
Le modèle comme graphe de calcul
Un fichier .onnx contient un graphe de calcul dirigé acyclique (DAG). Les nœuds représentent des opérateurs (MatMul, Conv, Relu, Attention, etc.), les arêtes représentent les tenseurs (les données) qui circulent entre les opérations. Chaque nœud spécifie quel opérateur il utilise, sa version (opset), et ses attributs. Les poids du modèle sont stockés comme des « initializers » (tenseurs constants) dans le graphe.
Cette représentation en graphe permet aux runtimes d’appliquer des optimisations puissantes : fusion de nœuds (combiner plusieurs opérations en une seule plus efficace), élimination de sous-expressions constantes (constant folding), réordonnancement des opérations pour minimiser la consommation mémoire, et remplacement d’opérateurs par des kernels matériels spécialisés.
Le système d’opsets
ONNX utilise un système de versions d’opérateurs appelé « opsets ». Chaque opset regroupe un ensemble immuable de spécifications d’opérateurs. Quand un opérateur est ajouté, modifié ou retiré, le numéro d’opset augmente. Un fichier .onnx déclare les opsets qu’il utilise, ce qui permet au runtime de savoir exactement quels opérateurs et quelle sémantique appliquer.
L’opset actuel (27) inclut des opérateurs récents comme RotaryEmbedding (pour les embeddings positionnels rotatifs des LLM), RMSNormalization, et le support du type FLOAT4E2M1 pour la quantification 4 bits à virgule flottante. Les opérateurs de quantification standards (QuantizeLinear, DequantizeLinear, QLinearMatMul) ciblent principalement INT8.
Les Execution Providers (EP)
ONNX Runtime utilise un système d’Execution Providers qui abstrait le matériel d’exécution. Chaque EP implémente un sous-ensemble d’opérateurs ONNX optimisés pour un accélérateur spécifique. Les nœuds du graphe sont assignés à l’EP qui les supporte le mieux :
| Execution Provider | Matériel | Cas d’usage |
|---|---|---|
| CPU | x86, ARM | Inférence universelle, fallback |
| CUDA | GPU NVIDIA | Inférence GPU standard |
| TensorRT | GPU NVIDIA | Performance maximale NVIDIA |
| DirectML | GPU Windows (tout vendeur) | Applications Windows, gaming |
| OpenVINO | CPU/GPU/VPU Intel | Edge Intel, IoT |
| CoreML | Apple Silicon | Applications iOS/macOS |
| QNN | Qualcomm Snapdragon | Mobile Android, NPU |
| CANN | Huawei Ascend | NPU Huawei |
| WebGPU / WASM | Navigateur | Inférence côté client web |
Le fallback fonctionne automatiquement : si un opérateur n’est pas supporté par l’EP GPU, il est exécuté sur CPU de manière transparente. C’est ce qui rend ONNX Runtime fiable : même si un opérateur exotique n’a pas d’implémentation GPU, le modèle tourne quand même.
ONNX et les LLM
L’arrivée des LLM a posé de nouveaux défis à ONNX. Les modèles de type Transformer sont auto-régressifs (chaque token dépend des précédents), ce qui nécessite une boucle de génération avec gestion d’état (cache KV). Le format ONNX brut ne gère pas nativement cette boucle.
ONNX Runtime GenAI
Pour résoudre ce problème, Microsoft a publié onnxruntime-genai en 2024. Cette extension encapsule le runtime ONNX avec toute la logique spécifique aux LLM : tokenisation, boucle de génération, stratégies de recherche (beam search, sampling), gestion du cache KV, et spécifications de grammaire pour l’appel d’outils (function calling).
ONNX Runtime GenAI alimente Foundry Local (Microsoft), Windows ML, et le Visual Studio Code AI Toolkit. Il supporte de nombreuses architectures : Llama, Mistral, Phi (texte + vision), Qwen, Gemma, DeepSeek, Granite, Whisper, etc. Des modèles pré-quantifiés au format ONNX sont disponibles sur Hugging Face Hub, prêts à l’emploi sans conversion.
import onnxruntime_genai as og
model = og.Model("microsoft/Phi-3-mini-4k-instruct-onnx")
tokenizer = og.Tokenizer(model)
params = og.GeneratorParams(model)
params.set_search_options(max_length=200)
prompt = "Explain quantum computing in simple terms."
tokens = tokenizer.encode(prompt)
params.input_ids = tokens
output_tokens = model.generate(params)
print(tokenizer.decode(output_tokens))
Quantification via ONNX
ONNX Runtime supporte la quantification INT8 et INT4 via plusieurs chemins :
Quantification dynamique : les poids sont convertis en INT8 hors ligne, et les échelles d’activation sont calculées à la volée pour chaque entrée. Simple à mettre en place, bon pour l’inférence CPU. Pas de dataset de calibration nécessaire.
Quantification statique : poids et activations sont quantifiés avec des paramètres fixés à l’avance, après une passe de calibration. Plus performant sur les accélérateurs (les échelles sont connues, pas de calcul dynamique). Nécessite un dataset représentatif.
Via Optimum (Hugging Face) : la bibliothèque Optimum permet d’exporter un modèle Hugging Face Transformers au format ONNX avec quantification intégrée :
pip install optimum[onnxruntime]
optimum-cli export onnx
--model meta-llama/Llama-3.1-8B-Instruct
-t text-generation
--device cuda
my_onnx_model/
ONNX vs GGUF
Les deux formats ciblent l’inférence mais avec des philosophies différentes :
| Critère | ONNX | GGUF |
|---|---|---|
| Philosophie | Interopérabilité multi-framework, multi-matériel | Inférence locale optimisée, fichier unique |
| Scope | Tout type de modèle ML (vision, NLP, tabular, etc.) | LLM (et quelques autres via GGML) |
| Runtime | ONNX Runtime (multi-EP), TensorRT, OpenVINO | llama.cpp, Ollama, LM Studio |
| Quantification | INT8 standard, INT4 via extensions | 1,5 à 8 bits, K-quants, I-quants |
| CPU performance LLM | Bonne | Excellente (kernels assembleur optimisés) |
| Portabilité matérielle | Excellente (10+ Execution Providers) | Bonne (CPU, Metal, CUDA, HIP, Vulkan) |
| Écosystème entreprise | Large (Microsoft, Azure, Windows ML) | Communautaire |
| Fichier auto-contenu (tokenizer) | Non (fichiers séparés) | Oui |
Pour l’inférence LLM locale pure, GGUF via llama.cpp reste le choix le plus performant et le plus simple. ONNX brille dans les pipelines multi-modèles, multi-plateformes, et dans les environnements entreprise (Azure, Windows) où l’interopérabilité entre différents types de modèles (vision, NLP, tabular) est critique.
ONNX vs TensorRT
TensorRT est le moteur d’optimisation et d’inférence de NVIDIA. Il peut consommer des modèles ONNX comme format d’entrée, puis les compiler en engines binaires ultra-optimisés pour le GPU NVIDIA cible. La relation est complémentaire : ONNX est le format d’échange, TensorRT est le compilateur/runtime spécialisé.
ONNX Runtime intègre TensorRT comme Execution Provider (TensorRTExecutionProvider), ce qui permet de bénéficier des optimisations TensorRT tout en gardant la portabilité ONNX : si un nœud n’est pas supporté par TensorRT, il est automatiquement exécuté sur le CPU EP. C’est le meilleur des deux mondes pour les déploiements NVIDIA.
Performances
Les optimisations d’ONNX Runtime (fusion de graphe, kernels spécialisés) produisent des gains significatifs par rapport à PyTorch standard. Sur les modèles Llama 2, ONNX Runtime atteint un throughput end-to-end 2,4× supérieur à PyTorch compile pour le 13B, et 1,8× pour le 7B, en CUDA FP16. Pour la génération de tokens à batch size 1, le modèle 70B (sur multi-GPU via Megatron Tensor Parallelism) atteint environ 30 tokens/seconde.
ONNX Runtime 2.10 (la version courante) apporte des améliorations d’accélération matérielle et peut offrir jusqu’à 9× de gain d’inférence et 13× de réduction de taille de modèle par rapport à des configurations naïves, selon les benchmarks Rust (crate ort).
Quand utiliser ONNX
ONNX n’est pas toujours le meilleur choix pour chaque scénario. Voici les cas où il excelle et ceux où d’autres solutions sont préférables.
Utilisez ONNX quand : vous devez déployer le même modèle sur plusieurs plateformes (cloud + edge + mobile + navigateur), vous intégrez des modèles de différents types (vision + NLP + tabular) dans un pipeline unifié, vous ciblez du matériel non-NVIDIA (Intel OpenVINO, Qualcomm QNN, Apple CoreML), vous travaillez dans un environnement Microsoft/Azure (Windows ML, Foundry Local, VS Code AI Toolkit), ou vous avez des contraintes de gouvernance qui imposent un format ouvert et standardisé.
Préférez d’autres solutions quand : vous faites de l’inférence LLM locale sur CPU ou Apple Silicon (→ GGUF via Ollama), vous servez des LLM à haute concurrence sur GPU NVIDIA (→ vLLM avec GPTQ/AWQ), ou vous avez besoin de quantification LLM agressive à 4 bits avec la meilleure qualité possible (→ GPTQ/AWQ natifs ou K-quants GGUF).
Exporter depuis PyTorch
L’export PyTorch vers ONNX a considérablement évolué. Depuis PyTorch 2.6, l’exporteur recommandé utilise le système torch.export, qui trace le modèle de manière statique (Ahead-of-Time) pour produire un graphe d’opérateurs ATen normalisé avant la traduction en ONNX.
import torch
model = ... # Votre modèle PyTorch
example_input = torch.randn(1, 3, 224, 224)
torch.onnx.export(
model,
args=(example_input,),
f="model.onnx",
dynamo=True, # Utilise torch.export (défaut depuis PyTorch 2.9)
external_data=True, # Obligatoire si poids > 2 Go
dynamic_shapes={
"input": {0: torch.export.Dim("batch", min=1, max=32)}
},
)
Le paramètre dynamic_shapes est important : sans lui, les dimensions sont figées aux valeurs de l’exemple d’entrée. Pour un LLM, vous voudrez des dimensions dynamiques pour le batch size et la longueur de séquence. Pour les modèles Hugging Face, Optimum automatise ces détails et produit des fichiers ONNX optimisés directement.
Limites
Conversion parfois complexe. L’export d’un modèle PyTorch vers ONNX peut échouer sur des architectures avec du contrôle de flux dynamique (boucles conditionnelles, formes dynamiques complexes). Le nouvel exporteur basé sur torch.export (PyTorch 2.6+) améliore nettement la situation, mais des cas limites subsistent.
Quantification LLM moins mature que GPTQ/AWQ. Les opérateurs de quantification standard d’ONNX ciblent principalement INT8. La quantification INT4 pour les LLM nécessite des extensions ou des opérateurs custom, ce qui complique le workflow par rapport à GPTQ ou AWQ.
Pas de fichier auto-contenu pour les LLM. Contrairement à GGUF qui embarque le tokenizer, un modèle LLM au format ONNX nécessite des fichiers de configuration et de tokenizer séparés. ONNX Runtime GenAI gère cette complexité, mais le format lui-même est moins « plug and play » que GGUF.
Taille de fichier limitée à 2 Go. Les modèles dont les poids dépassent 2 Go nécessitent le stockage des données externes (external_data=True lors de l’export), ce qui produit plusieurs fichiers au lieu d’un seul. C’est systématique pour les LLM de 7B+ en FP16.
Dépendance aux Execution Providers. Les performances dépendent fortement de l’EP choisi et de son support des opérateurs de votre modèle. Un EP peut ne pas supporter certains opérateurs quantifiés, forçant un fallback CPU qui dégrade les performances.
Questions fréquentes sur ONNX
ONNX est-il un framework d’entraînement ?
Non. ONNX est un format de représentation de modèles, pas un framework d’entraînement. Vous entraînez votre modèle dans PyTorch, TensorFlow, ou tout autre framework, puis vous l’exportez en ONNX pour le déploiement. ONNX Runtime dispose d’un module de training (pour accélérer l’entraînement PyTorch de modèles Transformer), mais ce n’est pas son usage principal. Le cœur d’ONNX, c’est l’inférence portable et optimisée.
Dois-je utiliser ONNX pour déployer un LLM en local ?
Pour l’inférence locale de LLM, GGUF via Ollama ou llama.cpp est généralement plus simple et plus performant qu’ONNX. ONNX devient intéressant quand vous avez besoin de portabilité multi-plateforme (le même modèle sur Windows, Linux, mobile, navigateur), quand vous intégrez un LLM dans un pipeline avec d’autres modèles ML au format ONNX, ou quand vous déployez sur du matériel spécifique (Intel OpenVINO, Qualcomm QNN, etc.).
Comment exporter un modèle PyTorch en ONNX ?
Depuis PyTorch 2.6, l’exporteur recommandé utilise torch.export : torch.onnx.export(model, args, "model.onnx", dynamo=True). Le paramètre dynamo=True (par défaut depuis PyTorch 2.9) utilise le nouveau système d’export basé sur le tracing, plus robuste que l’ancien export TorchScript. Pour les modèles Hugging Face Transformers, la bibliothèque Optimum simplifie encore le processus avec optimum-cli export onnx.
ONNX est-il compatible avec les modèles quantifiés GPTQ et AWQ ?
Pas directement. Les formats GPTQ et AWQ utilisent des schémas de quantification spécifiques qui ne correspondent pas aux opérateurs de quantification standard d’ONNX. La conversion est possible via des outils comme Optimum, mais elle peut nécessiter des opérateurs custom ou une émulation. Pour la quantification INT8 standard, ONNX Runtime offre un support natif excellent. Pour l’INT4 de type GPTQ/AWQ, les solutions natives (vLLM, AutoGPTQ) restent plus adaptées.
Quelle est la différence entre ONNX et ONNX Runtime ?
ONNX est la spécification du format (le « langage »). ONNX Runtime est le moteur d’exécution (l’« interpréteur »). ONNX définit comment un modèle est représenté : son graphe, ses opérateurs, ses types de données. ONNX Runtime charge un fichier .onnx et l’exécute de manière optimisée sur le matériel disponible, en utilisant les Execution Providers appropriés. D’autres runtimes peuvent aussi exécuter des fichiers ONNX (TensorRT, OpenVINO), mais ONNX Runtime est le plus complet et le plus portable.