Transformers documentation
Étendre les exportateurs
Étendre les exportateurs
torch.export trace le modèle en un graphe, les étapes ultérieures transforment ce graphe, et une étape finale le réduit ou l’émet pour le runtime cible. La plupart des modèles passent sans modification. Lorsqu’un motif PyTorch n’est pas géré par le backend, l’exporteur applique un petit contournement à cette étape plutôt que de modifier le modèle.
Ajoutez un contournement en écrivant une fonction et en l’enregistrant avec un décorateur. Chaque contournement doit être placé au niveau le plus bas qui permet de l’exprimer proprement.
Correctifs et modifications
Un contournement est soit un correctif, soit une solution. Les deux diffèrent par leur réversibilité.
| Patch | Correction | |
|---|---|---|
| Ce qu'il fait | Remplace un attribut (une opération torch, un élément interne d’ExecuTorch ou une méthode du modèle) pour la durée de l’exportation | Réécrit le graphe ou le programme tracé |
| Annulé | Oui, l'original est restauré par la suite | Non, il répare l'artefact avant l'exécution de l'étape suivante |
| S'inscrire avec | @register_patch(backend, *paths) | @register_fx_node_fix(backend) ou @register_fx_program_fix(backend) |
Les deux sont enregistrées dans le registre de exporters/utils.py, et l’exportateur installe tout ce qui est enregistré pour son backend au bon moment.
Recourir à un correctif lorsque le problème est un bug de compilation propre à un seul backend : une traduction ONNX manquante, une particularité de validation ORT, ou une décomposition FX qui émet une opération morte. Le contournement reste dans l’exportateur, et le code de modélisation reste propre.
Lorsque les blocs de motifs sont exportés sur plusieurs backends, par exemple des boucles dépendantes des données, des caches avec état situés en dehors de Cache, ou une attention à boucle divisée écrite à la main, il est préférable de corriger le modèle. Une correction apportée une seule fois au modèle profite à tous les exportateurs.
Ajouter un patch
Supposons qu’une méthode de modèle fasse quelque chose que torch.export ne peut pas tracer. La méthode NllbMoeTop2Router._cast_classifier de NLLB-MoE convertit les poids du classifieur vers un autre dtype, ce qui n’est pas traçable. Remplacez-la par une opération nulle pour la durée de l’export.
Écrivez une fabrique qui prend la méthode d’origine et renvoie son remplacement, puis enregistrez la fabrique par rapport au chemin pointé de la méthode :
from transformers.exporters.utils import register_patch
@register_patch("dynamo", "transformers.models.nllb_moe.modeling_nllb_moe.NllbMoeTop2Router._cast_classifier")
def _patch_classifier_cast(_original):
# Replace the untraceable dtype cast with a no-op during export.
return lambda self, *args, **kwargs: NoneL'exportateur remplace la méthode avant le traçage et la restaure ensuite, de sorte que le correctif n'affecte que l'exportation. Quelques variantes :
- Passez des chemins supplémentaires pour partager une même usine entre plusieurs sites d’appel, par exemple
@register_patch("dynamo", path_a, path_b). - Patch une op
torchen pointant le chemin vers elle, par exemple@register_patch("onnx", "torch.where"). L’usine reçoit l’op réelle en tant qu’argument, de sorte que le remplacement peut appeler celle-ci. - Écrivez un correctif plutôt qu'un patch lorsque vous devez réécrire le graphe après le traçage. Le mécanisme est le même, une fonction décorée dans le registre correspondant.
Référence de stage
Les étiquettes de source de chaque exportateur marquent ses étapes par des blocs de commentaires # ── Stage N: … ──, de sorte que le fichier et cette référence correspondent. Consultez-les pour connaître les opérations et les classes exactes que chaque étape gère.
DynamoExporter
L'exportateur de base exécute une étape de patch et quatre utilitaires, dans l'ordre, dans DynamoExporter.export (voir exporter_dynamo.py).
- Correctif de la signature avant : donne à
model.forwardune signature d’arguments plate afin quetorch.exportne regroupe pas les entrées dans un seul tuple**kwargs. Il s’agit d’un élément interne et non d’un point d’extension. - Correctifs de modèle : remplacez les méthodes de modèle non traçables par des équivalents sûrs pour l’exportation pendant le traçage. Étendez avec
@register_patch("dynamo", ...). - Enregistrement Pytree : enregistrez chaque
CacheetModelOutputafin quetorch.exportpuisse les aplatir et les reconstruire (cela se produit généralement automatiquement). Ajoutez une branche à_flatten_to_context/_unflatten_from_contextpour un type que la traversée des attributs ne peut pas atteindre. - Formes dynamiques : assignez
Dim.AUTOà chaque tenseur et cachez la feuille lorsquedynamic=True. Remplacez parDynamoConfig.dynamic_shapes. - Nettoyage de l'état : réinitialiser les attributs de tenseurs qu'un modèle définit dans
forwardet quetorch.exportlaisse en tant que tenseurs factices. Pour étendre, ajouter le nom de l'attribut à_STATEFUL_CACHE_ATTRS.
OnnxExporter
OnnxExporter ajoute cinq étapes autour de torch.onnx.export (voir exporter_onnx.py).
Recherchez dans le fichier la liste complète des correctifs :
grep -nE "^def (_patch_|_fix_|_aten_)" src/transformers/exporters/exporter_onnx.py- Correctifs Torch : remplace les opérations
torchque l’exportateur ONNX ne peut pas traduire telles quelles. Étendez avec@register_patch("onnx", ...). - Correctifs ONNX : relancer les corrections de nœuds après
run_decompositionsafin que les nœuds de garde de forme nouvellement introduits soient réparés avant l’abaissement. Utilise le même registre@register_patch("onnx", ...). - Corrections des nœuds FX : réécriture des nœuds du graphe que l’exporteur ONNX ne peut pas abaisser, tels que les opérations d’alias, les vues in-place et les assertions mortes. Étendez avec
@register_fx_node_fix("onnx"). - Traductions ONNX : fournir une conversion personnalisée pour une opération aten lorsque la conversion par défaut est absente ou bogueuse (par exemple
aten.index_putouaten._grouped_mm). Ajouter une fonction_aten_*à_ONNX_TRANSLATION_TABLE. - Corrections de l’IR ONNX : réécrire le programme ONNX terminé pour contourner les bogues d’ONNX Runtime (par exemple en forçant
TopK(sorted=True)). Ajouter une fonction_fix_ir_*à_IR_FIXES.
ExecutorchExporter
ExecutorchExporter ajoute cinq étapes autour de to_edge_transform_and_lower et to_executorch,
en commençant par la préparation du backend (voir exporter_executorch.py).
- Préparation du backend : déplacer le modèle sur l'appareil et le type de données cibles et choisir son partitionneur (
prepare_for_xnnpack,prepare_for_cuda). Ajouter un backend en enregistrantprepare_for_<name>dans_BACKEND_PREPARE. - Correctifs Torch : remplace les opérations
torchque les backends ExecuTorch ne peuvent pas accepter, telles quesplit_copy,chunkettopk(k>dim). Étendez avec@register_patch("executorch", ...). - Patches ExecuTorch : remplace les composants internes d’ExecuTorch qui provoquent des plantages sur des graphes à formes dynamiques valides. Utilise le même registre
@register_patch("executorch", ...). - Corrections du programme FX : réparez le programme exporté lorsque la correction nécessite un contexte de programme complet, comme l’élargissement des contraintes d’étendue ou le remplissage de métadonnées de placeholder manquantes. Étendez avec
@register_fx_program_fix("executorch"). - Corrections des nœuds FX : réécriture de nœuds individuels, par exemple la correspondance des opérations symboliques Python vers
executorch_prim.*ou la réécriture depowen une chaîne demul. À étendre avec@register_fx_node_fix("executorch").
Contournements connus en amont
Certaines classes de modèles rencontrent des bugs confirmés dans l’optimiseur de graphes de onnxscript (plantage du repliement de constantes sur SplitToSequence, initialisateurs FPN supprimés). ONNX_DISABLE_OPTIMIZE désactive l’optimisation onnxscript pour ces modèles. Chaque entrée consigne le problème en amont à côté du nom du modèle. La liste est censée se réduire au fur et à mesure que les correctifs en amont sont intégrés ; une nouvelle entrée doit donc référencer un bug en amont spécifique plutôt que de désactiver l’optimisation arbitrairement.
EXPORT_SKIPS, exclut un petit nombre de classes de modèles du balayage d’exportation lorsque le modèle est fondamentalement non exportable en l’état (flux de contrôle dépendant des données qui ne peut pas être vectorisé, ou modules traités comme des arguments de forward). Chaque entrée contient une raison précisant la modification nécessaire côté modèle. Cette liste est également censée diminuer, et non augmenter.
Update on GitHub