Configuration et routes de l'entraînement de modèles
Chaque clé du bloc model_training, la façon dont les exécutions sont mises en file, évaluées et stockées, les routes d'administration et d'agent, et des remèdes aux erreurs courantes.
Nouveauté de la v2.14.0
Cette page est la référence du bloc model_training d'une configuration Potato et de ce qui arrive à une exécution après son lancement. Elle s'adresse à la personne qui mène une étude et veut limiter les exécutions, les envoyer à une autre machine, montrer les prédictions d'un modèle aux annotateurs ou lancer l'entraînement depuis un script. Chaque clé, chaque valeur par défaut, chaque route et chaque message ci-dessous a été vérifié dans le code de Potato. Pour une première exécution, commencez par Entraîner votre premier modèle. Les modules d'entraînement et leurs paramètres sont listés dans Modules d'entraînement.
Une configuration complète
La configuration ci-dessous entraîne un classifieur de sentiment sur des avis de produits. auto_retrain réajuste sklearn-text après chaque série de 25 nouvelles annotations. Avec les caractéristiques TF-IDF par défaut, sklearn-text s'entraîne sur le processeur et ne demande rien de plus qu'une installation ordinaire de Potato. Des exécutions automatiques fréquentes coûtent donc peu. L'écriture en retour montre aux annotateurs chaque prédiction dont la confiance atteint au moins 0,8. Avec include_unlabeled, une exécution prédit aussi sur les avis que personne n'a encore étiquetés. Les valeurs par défaut de hf-text-classification et le backend gpu-server servent les exécutions lancées à la main depuis la page Training.
annotation_task_name: "Review sentiment with model training"
task_dir: "."
data_files:
- "data/reviews.json"
item_properties:
id_key: "id"
text_key: "text"
output_annotation_dir: "annotation_output"
user_config:
allow_all_users: true
annotation_schemes:
- annotation_type: "radio"
name: "sentiment"
description: "Is this review positive or negative?"
labels: ["positive", "negative"]
model_training:
enabled: true
split_seed: 0
splits: {train: 0.7, val: 0.15, test: 0.15}
aggregation: consensus
retain_runs: 5
queue_max: 10
max_wall_seconds: 3600
max_ram_mb: 8192
num_threads: 4
trainer_params:
sklearn-text:
classifier: sklearn.linear_model.LogisticRegression
classifier_kwargs: {max_iter: 1000}
hf-text-classification:
model_name: answerdotai/ModernBERT-base
epochs: 4
lora: true
auto_retrain:
enabled: true
trainer: sklearn-text
schemas: [sentiment]
min_interval_s: 600
update_frequency: 25
writeback:
schemas: [sentiment]
min_confidence: 0.8
include_unlabeled: true
backends:
gpu-server:
type: ssh
host: gpu-server
python: /opt/conda/bin/python3
gpus: auto
min_free_gpu_mb: 4000Gardez split_seed fixe pendant toute la vie de l'étude. Une nouvelle graine réattribue chaque item, si bien que des items réservés se retrouvent dans l'entraînement et que les scores ultérieurs cessent d'être comparables aux précédents. Le seuil min_confidence de 0,8 est un point de départ, et le bon seuil dépend du premier score sur items réservés. Activez include_unlabeled une fois que ce score justifie de montrer des pré-étiquettes, car les pré-étiquettes ancrent les annotateurs sur la réponse du modèle.
Clés de model_training
Chaque clé se place sous model_training.
| Clé | Défaut | Signification |
|---|---|---|
enabled | false | Enregistre la page Training, les routes sous /admin/training et les routes d'agent sous /api/training. Sans enabled: true, les routes n'existent pas. |
retain_runs | 5 | Exécutions terminées conservées dans le registre des exécutions. Une exécution plus ancienne quitte le registre, sauf si ses prédictions sont encore stockées. Les répertoires des exécutions restent sur le disque. |
grace_seconds | 20 | Secondes dont dispose une exécution annulée pour se terminer avant que Potato tue le processus. 0 ou plus, et envoyé avec la tâche aux backends de type ssh, slurm et agent. |
queue_max | 10 | Nombre d'exécutions qui peuvent attendre derrière l'exécution en cours. |
split_seed | 0 | Graine pour répartir les items entre les partitions train, val et test. |
splits | {train: 0.7, val: 0.15, test: 0.15} | Fractions des partitions, normalisées pour que leur somme vaille 1. Les noms sont train, val et test, et train est obligatoire. |
aggregation | consensus | Comment les étiquettes de plusieurs annotateurs sur un item deviennent une seule étiquette. consensus ajuste le modèle de Dawid-Skene quand l'étude compte plus d'un annotateur et revient au vote majoritaire si l'ajustement échoue. majority prend le vote majoritaire. |
max_wall_seconds | non défini | Limite de durée d'une exécution. Potato vérifie une exécution locale chaque fois qu'elle signale un événement, et une exécution ssh ou d'agent chaque seconde. |
max_ram_mb | non défini | Limite d'espace d'adressage du processus d'entraînement, fixée avec setrlimit. Sur une plateforme sans cette limite, l'exécution consigne un avertissement et continue. |
device | auto | auto, cpu, cuda, cuda:N ou mps. auto prend CUDA, puis Metal d'Apple, puis le processeur. |
num_threads | non défini | Fixe OMP_NUM_THREADS, MKL_NUM_THREADS et OPENBLAS_NUM_THREADS pour l'exécution, sauf si l'environnement fixe déjà ces variables. |
auto_retrain | désactivé | Réentraînement à mesure que les annotations arrivent. Voir auto_retrain. |
writeback | aucun | Publication des prédictions sous forme de pré-étiquettes. Voir writeback. |
backend | local | Le backend des exécutions qui n'en nomment pas d'autre. |
backends | aucun | Backends nommés ssh, slurm et agent. Voir Backends. |
max_predictions_mb | 512 | Taille maximale du predictions.jsonl qu'un agent distant peut téléverser. |
trainer_params | aucun | Valeurs par défaut des paramètres, indexées par nom de module. |
tiling | enabled: auto | Découpage des grandes images en tuiles pour les modules de détection et de segmentation. Voir tiling. |
Les params propres à une exécution remplacent trainer_params, qui remplace les valeurs par défaut du module. Un nom de paramètre que le module n'accepte pas est refusé au démarrage du serveur quand le nom se trouve sous trainer_params, et au lancement de l'exécution dans les autres cas. Modules d'entraînement donne cet ordre avec un exemple.
auto_retrain
Le réentraînement automatique cherche une nouvelle exécution à lancer après chaque enregistrement d'annotation.
| Clé | Défaut | Signification |
|---|---|---|
enabled | false | Active la vérification. |
trainer | aucun | Nom du module. Obligatoire. |
schemas | aucun | Schémas à entraîner. Obligatoire. |
min_interval_s | 600 | Secondes écoulées depuis la fin de la dernière exécution avant qu'une autre démarre. |
update_frequency | 25 | Nombre de nouvelles annotations depuis la dernière exécution automatique avant qu'une autre démarre. |
params | {} | Paramètres du module, comme les params d'une exécution par l'API. |
backend | model_training.backend | Backend des exécutions automatiques. |
accept_licence | false | Confirme la licence d'un module qui demande une confirmation (ultralytics-detect, ultralytics-segment, layoutlmv3). Sans cette confirmation, les exécutions automatiques de ces modules sont sautées. |
Quand une vérification décide de ne pas lancer d'exécution, la raison apparaît dans le champ skip_reason de GET /admin/training/api/status, par exemple « waiting for 3 more annotation(s) » ou « a run is already in progress ». Les exécutions automatiques ne rejoignent jamais la file d'attente des exécutions. La prochaine annotation enregistrée après que la file s'est vidée relance la vérification, avec davantage d'annotations pour s'entraîner. Potato garde les décomptes d'annotations en mémoire, si bien qu'après un redémarrage un projet qui s'est déjà entraîné compte les nouvelles annotations à partir du redémarrage.
writeback
L'écriture en retour décide quelles prédictions les annotateurs voient.
| Clé | Défaut | Signification |
|---|---|---|
schemas | [] | Schémas dont les prédictions sont visibles par les annotateurs. Une liste vide n'en montre aucune. |
min_confidence | 0.0 | Les prédictions sous le seuil sont stockées mais pas montrées. Une prédiction sans confiance passe. |
field | predictions | Champ de l'item dans lequel les pré-étiquettes sont écrites. |
include_unlabeled | false | Prédit aussi sur les items que personne n'a étiquetés et pré-étiquette ces items. Sans include_unlabeled, une exécution ne prédit que sur ses propres items val et test. |
tiling
Les modules de détection et de segmentation redimensionnent chaque image à quelques centaines de pixels. À cette taille, les objets d'une image de lame entière ou d'une scène satellite se perdent. Pour un schéma image_annotation, microscopy ou geo_annotation, Potato découpe donc chaque grande image en tuiles au moment où les données d'entraînement de l'exécution sont construites. La partition d'une image est décidée avant le découpage de l'image, si bien que les tuiles d'une même lame ne tombent jamais dans deux partitions. Les prédictions sont reportées sur l'image entière, et les scores sur items réservés sont calculés sur des images entières. Le tutoriel sur la vision traite des lames et des cartes en pratique.
| Clé | Défaut | Signification |
|---|---|---|
enabled | auto | auto découpe les formats de lames (.svs, .ndpi, .mrxs, .scn, et d'autres) et les images dont le grand côté atteint au moins auto_min_side. true découpe toutes les images, et false aucune. |
auto_min_side | 4096 | Longueur du grand côté, en pixels, à partir de laquelle auto commence à découper une image. |
tile_size | 1024 | Côté d'une tuile, en pixels tels que les voit le module. |
overlap | 128 | Pixels que partagent des tuiles voisines, au plus la moitié de tile_size. Gardez un chevauchement au moins aussi grand que les objets, sinon un grand objet est trouvé en morceaux. |
downsample | 1 | Pixels en pleine résolution par pixel de tuile. |
mpp | aucun | Microns par pixel de tuile. Remplace downsample pour une lame qui enregistre sa résolution. |
background | 0.25 | Tuiles vides échantillonnées par tuile contenant un objet. Fixez background: 0 pour des lames annotées en partie seulement. |
max_predict_tiles | 2000 | Nombre maximal de tuiles prédites par image. Les tuiles qui contiennent le plus de tissu sont conservées. |
min_visible | 0.4 | Part d'un objet qui doit se trouver dans une tuile pour que l'objet s'y entraîne. |
tissue_threshold | 0.05 | Part d'une tuile de lame qui doit être du tissu pour que le modèle prédise sur la tuile. |
Les lames sont lues avec openslide, installé par pip install "potato-annotation[wsi]", sur la machine qui construit les données d'entraînement. Un backend distant télécharge les tuiles et jamais la lame.
La file d'attente des exécutions
Une seule exécution tourne à la fois. Une exécution lancée depuis la page Training ou l'API pendant qu'une autre est en cours attend au lieu d'être refusée. La requête de lancement renvoie 202 avec queued: true et la position de l'exécution, et le tableau Runs liste l'exécution sous la forme waiting #N avec un bouton Cancel run. Quand l'exécution en cours se termine, la plus ancienne exécution en attente démarre.
Les exécutions en attente sont des enregistrements du registre des exécutions, si bien que la file survit à un redémarrage, et la première exécution en attente démarre quand le serveur revient. Une exécution que le serveur précédent était en train de mener est marquée interrupted au même moment. Les données d'entraînement d'une exécution en attente sont construites au démarrage de l'exécution, si bien que l'exécution s'entraîne sur les annotations présentes à ce moment-là. Un lancement qui serait refusé, comme un lancement qui nomme un schéma inconnu, est refusé aussitôt plutôt qu'à son tour dans la file. Une exécution dont le schéma ou le module a quitté la configuration pendant l'attente échoue avec invalid_when_dequeued, et l'exécution suivante démarre.
Envoyez "queue": false dans le corps de la requête pour obtenir 409 au lieu d'une place dans la file. Quand queue_max exécutions attendent déjà, un nouveau lancement reçoit 429. GET /admin/training/api/status liste dans l'ordre les exécutions en attente sous queue.
Vérifications avant une exécution
potato validate signale d'un coup tous les problèmes du bloc model_training, et le serveur refuse de démarrer sur les mêmes problèmes.
potato validate config.yaml --strictLes vérifications couvrent les cas suivants.
splitsavec un nom autre quetrain,valettest, une fraction inférieure à 0 ou qui n'est pas un nombre, des fractions dont la somme vaut 0, ou l'absence detrain.- Une clé que
writebackouauto_retrainn'a pas, une entrée dewriteback.schemasqui n'est pas un schéma, ou unmin_confidencehors de l'intervalle 0 à 1.accept_licenseest signalé comme une faute d'orthographe deaccept_licence. - Un bloc
pre_annotationactivé dont lefielddiffère dewriteback.field. Aucune pré-étiquette d'entraînement ne s'afficherait sous un tel bloc. - Avec
auto_retrain.enabled, un module ou un schéma qui n'existe pas, un schéma que le module ne peut pas apprendre, des paramètres que le module n'accepte pas ou du mauvais type, unbackendabsent debackends, oudecision-calibratesur un backend autre quelocal. - Un paramètre sous
trainer_paramsque le module n'accepte pas, ou du mauvais type. Dansdp, la vérification porte aussi sur chaque clé et sur sa plage de valeurs. - Un
grace_secondsinférieur à 0 ou qui n'est pas un nombre, ou unretain_runsousplit_seedinférieur à 0 ou qui n'est pas un entier. - Sous
backends, untypemanquant ou inconnu, une clé que le type n'a pas, un backend ssh sanshost, une valeur degpusautre queauto,noneou des indices de GPU, un backend distant nommélocal, ou unmodel_training.backendqui n'est pas défini.
potato training check teste un backend avant qu'une exécution l'utilise. Pour local, la commande affiche le périphérique qu'une exécution utiliserait, par exemple local: this machine, Apple Metal (mps) sur un Mac avec puce Apple. Pour un backend ssh, la commande indique la version de Python, chaque GPU avec sa mémoire libre, le GPU qu'une exécution obtiendrait et les paquets d'entraînement qui manquent à l'interpréteur distant. Le bouton Check de la page Training lance le même test, et --json affiche le rapport en JSON.
potato training check local config.yaml
potato training check gpu-server config.yamlUne exécution lancée depuis la page Training ou l'API est vérifiée de nouveau à son démarrage. Les codes d'état sont listés sous Routes.
Backends
Une exécution tourne sur un backend, et le menu Runs on de la page Training liste les backends configurés. model_training.backend fixe la valeur par défaut, et une exécution par l'API ou auto_retrain peut nommer un autre backend avec backend. Potato a quatre types de backend.
| Type | Où tourne le module | Qui lance le module |
|---|---|---|
local | Cette machine, dans un sous-processus. Toujours disponible, et par défaut. | Potato |
ssh | Une autre machine que Potato peut joindre par ssh, comme un serveur GPU. | Potato, par ssh |
slurm | Un nœud de calcul d'un cluster, comme travail par lots. | Potato, par ssh vers le nœud de connexion puis sbatch |
agent | Une machine que Potato ne peut pas joindre, comme un poste de travail derrière un NAT. | Une personne, avec potato training agent |
Un backend ssh utilise l'authentification par clé avec BatchMode activé, si bien qu'une invite de mot de passe échoue au lieu de se bloquer. Un backend slurm n'utilise que sbatch, squeue et scancel, plus scontrol sur les clusters qui fournissent scontrol, et a besoin d'un remote_dir sur un stockage que partagent les nœuds de calcul. Un backend agent n'a besoin d'aucun port entrant, car l'agent ouvre chaque connexion. Le nom local est réservé à cette machine, et decision-calibrate ne tourne que sur local. Entraîner sur un serveur GPU, un cluster SLURM ou une machine derrière un NAT déroule les trois types distants avec leurs clés.
Scores sur items réservés
Chaque exécution évalue ses propres prédictions sur les items val et test par rapport aux étiquettes humaines résolues. Les noms de métriques portent la partition, comme dans val_macro_f1 ou test_f1. Un item qui a une étiquette et aucune prédiction compte comme faux, si bien que laisser de côté les items difficiles ne peut pas améliorer le score d'un module. <split>_coverage indique la part des items qui ont reçu une prédiction.
Le score principal apparaît dans la colonne Held-out score du tableau Runs, avec la partition et la métrique dans l'infobulle. Le score principal est la métrique principale du premier schéma, sur la première des partitions val et test qui contient des items. Quand un module a choisi le meilleur point de contrôle d'après le score val, Potato essaie test en premier, car le module a déjà vu le score val. Les modules d'affinage qui gardent la meilleure époque, comme hf-text-classification, torchvision-detect et llm-sft, prennent le score principal sur test. sklearn-text, setfit, rdkit-property, les modules pour modèles de décision et les passerelles d'inférence ne choisissent rien sur val, et une exécution de l'un de ces modules prend le score principal sur val dès que val contient des items. Une exécution sans item val ni test est affichée comme « not scored ».
La métrique principale dépend du type d'annotation du schéma, comme le montre le tableau ci-dessous pour les types courants.
| Type d'annotation | Métrique principale |
|---|---|
radio, select, likert | macro-F1 (aussi l'exactitude, et l'erreur absolue moyenne pour des étiquettes likert numériques) |
multiselect | micro-F1 (aussi le macro-F1 et la correspondance exacte) |
span | F1 sur les empans qui concordent sur le début, la fin et l'étiquette |
text | F1 de jetons (aussi la correspondance exacte) |
pairwise en mode binary | exactitude sur les items non répondus comme égalité |
ranking | tau de Kendall |
image_annotation, microscopy, geo_annotation | mAP COCO à IoU 0,5 (map_50), avec map_50_95 aussi enregistré |
audio_annotation | F1 sur les segments de même étiquette avec un IoU d'au moins 0,5 |
speech_transcript | word_accuracy, 1 moins le taux d'erreur sur les mots |
volume_annotation | mean_dice |
Le F1 de jetons accorde du crédit à une réponse qui utilise les bons mots dans le mauvais ordre, si bien qu'il faut lire le F1 de jetons avec la correspondance exacte. Le score principal de détection utilise un IoU de 0,5 plutôt que la moyenne de 0,5 à 0,95, car les boîtes de deux annotateurs pour un même objet se recouvrent rarement à un IoU de 0,9. Le tableau amont des scores sur items réservés liste les métriques de chaque type d'annotation.
Écriture en retour
Après une exécution réussie, Potato stocke les prédictions de l'exécution et écrit dans le champ predictions de chaque item, ou dans le champ que nomme writeback.field, les prédictions qui passent quatre vérifications. Les vérifications s'enchaînent dans cet ordre, et le rapport d'écriture en retour de l'exécution compte chaque saut.
- Les items de la partition train ne sont jamais pré-étiquetés. La vérification couvre la partition train de chaque exécution encore présente dans le registre, et une pré-étiquette qu'une exécution antérieure a laissée sur un item est retirée quand une exécution ultérieure s'entraîne sur l'item.
- Seuls les schémas de
writeback.schemassont publiés. La liste est vide par défaut, si bien qu'activer l'entraînement ne change rien pour les annotateurs. - Les paires rejetées sont sautées. Une paire item-schéma avec un verdict
rejectdans la relecture des modèles n'est plus montrée. - Le seuil de confiance s'applique. Une prédiction sous
min_confidenceest stockée mais pas publiée.
L'écriture en retour ne modifie jamais une étiquette humaine, car les prédictions vont dans les données des items et les annotations vivent dans l'état utilisateur de chaque annotateur. Une pré-étiquette s'affiche comme une réponse préremplie que l'annotateur peut modifier, par exemple un choix comme option sélectionnée et une réponse en texte libre dans la zone de texte du schéma, et aucun bloc pre_annotation n'est nécessaire. La pré-étiquette ne devient la réponse de l'annotateur que lorsque celui-ci la modifie ou passe à la suite. Une pré-étiquette que personne n'a modifiée ni dépassée ne devient donc jamais une étiquette d'entraînement. Une paire annotateur-item que ai_support.holdout place dans le groupe de comparaison sans assistance de l'étude ne montre aucune pré-étiquette, et les données d'item envoyées pour cette paire omettent à la fois writeback.field et pre_annotation.field. Le rapport d'écriture en retour est le champ writeback de GET /admin/training/api/status, et le summary du rapport dit pourquoi une exécution n'a rien publié.
Potato garde une prédiction par item et par schéma, et la prédiction d'une exécution plus récente remplace celle d'une exécution plus ancienne. Quand la prédiction plus récente est stockée mais pas montrée, parce qu'elle est sous min_confidence, vide ou rejetée, la pré-étiquette de l'exécution plus ancienne est retirée de l'item aussitôt, et le rapport d'écriture en retour compte l'item dans n_superseded_cleared. Les pré-étiquettes fournies avec les données sont laissées intactes. Au démarrage, les prédictions stockées pour les schémas de writeback.schemas sont réécrites dans les données des items sous les mêmes quatre vérifications, si bien que les pré-étiquettes survivent à un redémarrage. Pour retirer les pré-étiquettes d'une exécution, envoyez DELETE /admin/training/api/runs/<run_id>/predictions. La requête supprime les prédictions stockées et retire les pré-étiquettes des items.
Les corrections et les items épinglés s'entraînent toujours
Deux sortes d'items vont dans la partition train de chaque exécution ultérieure, quelle que soit la place de l'item dans la partition stable.
- Les items qu'un relecteur a corrigés. Un verdict
correctdans la relecture des modèles signifie qu'une personne a corrigé la réponse du modèle. Les corrections viennent des items sur lesquels le modèle était le plus faible, si bien qu'un item corrigé dansvaloutestévaluerait le modèle sur un échantillon de ses propres erreurs. Les verdictsacceptetrejectlaissent un item là où il était. - Les items épinglés. Train on these, à côté d'une tranche de la page Catalog, épingle les items que la tranche retient, par exemple la tranche intégrée
model-found-nothing. Un item épinglé s'entraîne dès que quelqu'un l'a étiqueté.
Une exécution qui a déplacé des items réservés vers train consigne un avertissement avec leur nombre. Le score sur items réservés de l'exécution est alors calculé sans ces items et n'est pas directement comparable au score d'une exécution antérieure. Les décomptes se trouvent sous stats.forced_train dans le manifest.json des données d'entraînement.
Enregistrer une partition comme version de jeu de données
Keep this split as a dataset, sur la page d'une exécution, enregistre les items val, test ou train de l'exécution, avec leurs étiquettes humaines consensuelles, comme nouvelle version d'un jeu de données. Une version de jeu de données ne change plus ensuite, si bien que des modèles et des prompts de LLM ultérieurs peuvent être comparés sur exactement ces items. La fonction demande datasets.enabled: true. Chaque version enregistrée contient une seule partition et repart de zéro au lieu de s'ajouter à la dernière version du jeu de données. Les items val de l'exécution 2 ajoutés à ceux de l'exécution 1 inclueraient sinon des items sur lesquels l'exécution 2 s'est entraînée. Les inputs de chaque exemple omettent le champ de pré-étiquette, si bien qu'une évaluation ne peut pas lire la réponse du modèle.
D'où vient une pré-étiquette
GET /admin/model-review inclut un provenance pour chaque item de la file de relecture dont une exécution d'entraînement a écrit la pré-étiquette. Pour chaque schéma, l'entrée donne l'identifiant de l'exécution, le module et le score sur items réservés de l'exécution. Les pré-étiquettes fournies avec les données n'ont pas d'entrée.
Où les exécutions sont stockées
Chaque exécution a un répertoire à l'emplacement <task_dir>/<output_annotation_dir>/training/runs/<run_id>/.
| Chemin | Contenu |
|---|---|
bundle/ | Les données d'entraînement : train.jsonl, val.jsonl, test.jsonl, unlabeled.jsonl avec include_unlabeled, labels.json, manifest.json et media/. |
artifacts/ | model_card.json, predictions.jsonl et le modèle, par exemple model.pkl pour sklearn-text ou un répertoire model/ pour les modules à transformers. |
spec.json | Ce que l'exécution devait faire. |
events.jsonl, stdout.log, stderr.log | Les événements de progression et la sortie de l'exécution. |
agent.log | La sortie propre de l'agent distant, sur les backends ssh. |
bundle.tar.gz | Les données d'entraînement telles que l'agent les a téléchargées, médias compris, sur les backends distants. |
Le registre des exécutions vit dans la base de données du projet, <task_dir>/project.sqlite, et enregistre les exécutions, la partition de chaque item par exécution, les items épinglés à l'entraînement, les prédictions stockées, les jetons d'agent et les envois vers le Hugging Face Hub. retain_runs élague le registre et n'élague jamais une exécution dont les prédictions sont encore stockées, si bien que chaque pré-étiquette peut être reliée à l'exécution qui l'a écrite. L'élagage laisse les répertoires des exécutions sur le disque.
Une exécution LoRA n'enregistre que l'adaptateur, de quelques mégaoctets à quelques centaines, et charge le modèle de base par model_name quand l'exécution prédit. Un affinage complet enregistre le modèle entier. Fixez la variable d'environnement POTATO_MODEL_CACHE à un répertoire, et le processus d'entraînement utilise ce répertoire pour HF_HOME, TRANSFORMERS_CACHE et SENTENCE_TRANSFORMERS_HOME, sauf si ces variables sont déjà définies. Sur une machine isolée du réseau, placez à l'avance dans ce répertoire les modèles que nomment les modules.
Routes
La page Training et ses routes JSON se trouvent sous /admin/training et demandent un accès d'administrateur. L'accès d'administrateur signifie une session d'administrateur ou l'en-tête X-API-Key. Les requêtes POST et DELETE venant d'un navigateur doivent provenir de la même origine. La spécification OpenAPI de Potato marque les 26 opérations d'entraînement avec x-potato-requires-config: model_training.enabled: true.
| Route | Rôle |
|---|---|
GET /admin/training | La page Training, avec le formulaire d'exécution, la liste des exécutions et les modules. |
GET /admin/training/runs/<run_id> | La page d'une exécution, avec l'état, les métriques, les événements et la partition de chaque item. |
GET /admin/training/api/trainers | Chaque module, avec ses genres, ses modalités, sa licence et son état d'installation. |
GET /admin/training/api/schemas | Les schémas de l'étude, le genre de chaque schéma et les modules qui conviennent à chacun. |
GET /admin/training/api/status | L'exécution en cours ou la dernière, avec l'état, la progression, les métriques, les avertissements, skip_reason, writeback et queue. |
GET /admin/training/api/runs | L'historique des exécutions. ?limit= vaut 50 par défaut, avec un maximum de 500. |
POST /admin/training/api/runs | Lance une exécution. 200 quand l'exécution démarre, et 202 avec queued: true et position quand elle attend. |
GET /admin/training/api/runs/<run_id> | L'enregistrement d'une exécution, plus review, la précision des prédictions de l'exécution sous les verdicts de relecture. |
GET /admin/training/api/runs/<run_id>/events | Le journal d'événements de l'exécution. ?limit= vaut 200 par défaut. |
POST /admin/training/api/runs/<run_id>/cancel | Annule l'exécution en cours ou une exécution en attente. 400 pour tout autre identifiant d'exécution. |
DELETE /admin/training/api/runs/<run_id>/predictions | Retire les prédictions stockées et les pré-étiquettes de l'exécution. |
POST /admin/training/api/runs/<run_id>/push-to-hub | Publie le modèle de l'exécution sur le Hugging Face Hub. Voir Publier sur le Hugging Face Hub. |
POST /admin/training/api/runs/<run_id>/pin-split | Enregistre une partition comme version de jeu de données, avec le corps {"dataset": name, "split": "val"}. |
GET /admin/training/api/backends | Les backends configurés. |
POST /admin/training/api/backends/<name>/check | Teste un backend, comme le fait potato training check. |
GET /admin/training/api/pinned | Les items épinglés, regroupés par raison. |
POST /admin/training/api/pinned | Épingle des items à train, avec {"slice": name} ou {"instance_ids": [...]}. |
DELETE /admin/training/api/pinned | Désépingle les instance_ids listés, ou tous les items épinglés quand le corps n'en liste aucun. |
Une requête d'exécution accepte trainer, schemas (une liste ou un seul nom), params, backend, accept_licence et queue. Chaque module n'ajuste que le premier schéma nommé. La requête ci-dessous lance une exécution sklearn-text sur le schéma sentiment de l'exemple.
curl -X POST -H "X-API-Key: $KEY" -H "Content-Type: application/json" \
http://localhost:8000/admin/training/api/runs \
-d '{"trainer": "sklearn-text", "schemas": ["sentiment"]}'Un lancement refusé donne la raison dans error.
| État | Quand |
|---|---|
400 | Aucun module ou aucun schéma dans le corps, un module ou un schéma inconnu, un schéma que le module ne peut pas apprendre, un module que le projet ne peut pas exécuter, ou un module dont la licence demande confirmation, avec needs_licence_ack: true, tant que la requête ne fixe pas accept_licence: true |
409 | Un paramètre que le module n'accepte pas ou du mauvais type ou intervalle, un backend inconnu, decision-calibrate sur un backend autre que local, ou une exécution déjà en cours avec "queue": false |
429 | queue_max exécutions attendent déjà |
Protocole d'agent
model_training.enabled enregistre aussi les routes qu'appelle un agent d'entraînement, sous /api/training. Un agent envoie son jeton sous la forme Authorization: Bearer <token>, et un jeton absent ou invalide reçoit 401. L'enregistrement d'un backend demande à la place la clé d'API d'administration. potato/training/protocol.py décrit le protocole pour quiconque écrit un nouvel agent, et potato/training/agent.py en est l'implémentation de référence.
| Route | Rôle |
|---|---|
POST /api/training/backends/register | Délivre un jeton d'agent pour un nom de backend, avec X-API-Key. potato training register appelle cette route. |
POST /api/training/backends/<name>/heartbeat | Un agent inactif signale qu'il est en vie. 403 pour un jeton délivré à un autre backend. |
GET /api/training/jobs/next?wait=30 | Interrogation longue. 200 avec un travail, ou 204 quand aucun travail n'arrive en wait secondes. |
GET /api/training/jobs/<run_id> | Le travail, sa spécification et son éventuelle annulation. |
GET /api/training/jobs/<run_id>/bundle | Les données d'entraînement en tar.gz, médias compris. La route répond aux requêtes Range, si bien qu'un agent reprend un téléchargement interrompu, jusqu'à cinq tentatives. 410 quand le lot a disparu. |
POST /api/training/jobs/<run_id>/progress | Événements de progression. Une annulation revient dans la réponse. |
POST /api/training/jobs/<run_id>/predictions | predictions.jsonl. 413 au-delà de max_predictions_mb. |
POST /api/training/jobs/<run_id>/complete | Code de sortie et événements finaux. |
QLoRA
llm-sft, llm-dpo, hf-text-classification, vlm-sft et reward-model acceptent lora: {quantize: 4bit}, la mise en place de QLoRA (Dettmers et al., 2023). Le modèle de base se charge avec des poids NF4 sur 4 bits et une double quantification, et un adaptateur LoRA s'entraîne par-dessus en bf16 là où le GPU gère bf16. quantize: 8bit est l'option intermédiaire, et les prédictions chargent le modèle de base de la même façon.
model_training:
trainer_params:
llm-sft:
model_name: Qwen/Qwen2.5-7B-Instruct
lora: {quantize: 4bit}Sur 4 bits, les poids de base occupent le quart de la mémoire que les mêmes poids occupent en bf16, et les activations, l'adaptateur et l'état de l'optimiseur s'y ajoutent. Potato n'a pas encore mesuré sur un GPU la mémoire d'une exécution QLoRA, si bien qu'il faut partir de la ligne « Peak GPU memory » de l'exécution elle-même. Chaque exécution de transformer consigne cette ligne à la fin. QLoRA demande un GPU CUDA et une version de bitsandbytes construite pour le CUDA de cette machine. L'exécution vérifie les deux avant de charger le modèle en quantifiant quelques nombres sur le GPU, et quand les deux versions ne correspondent pas, l'erreur nomme les deux versions. Le tutoriel d'affinage de LLM met QLoRA au travail sur des exécutions SFT et DPO.
Publier sur le Hugging Face Hub
Une exécution réussie dont le modèle se trouve sur le serveur Potato a Publish to the Hugging Face Hub sur sa page. L'envoi téléverse le modèle et une fiche de modèle README.md rédigée à partir de l'exécution, qui nomme le module, le modèle de base et l'adaptateur, les schémas et les étiquettes, la taille des partitions, le score sur items réservés et la partition sur laquelle il a été mesuré, ainsi que les identifiants de l'exécution et du lot. La fiche d'une exécution dp a aussi une ligne « Differential privacy » avec l'epsilon dépensé face à la cible, le delta et la partition train que couvre la garantie. La ligne omet la cible ou le delta lorsque l'exécution n'a pas enregistré la valeur.
Le téléversement porte sur une liste fixe de fichiers plutôt que sur tout le répertoire artifacts/. La liste contient les fichiers de poids, par exemple .safetensors, .bin, .pt et .pkl, les fichiers de configuration et de tokenizer du répertoire model/ enregistré, model_card.json avec les chemins locaux remplacés par des noms de fichiers, et calibration.json. Les réponses du modèle sur les items du projet (predictions.jsonl, et raw_answers.jsonl pour les modèles de décision) restent sur le serveur. Les points de contrôle, l'état de l'optimiseur, les copies des données d'entraînement que font certains modules (yolo_data/, wev_data/, laya_data/) et tout lien symbolique qui pointe hors de artifacts/ sont écartés eux aussi.
Le formulaire protège de plusieurs façons contre un envoi accidentel ou public.
- Vous saisissez deux fois le nom du dépôt, et l'envoi n'a lieu que si les deux noms correspondent.
- Private est coché par défaut. Tant que Private est coché, Potato ne publie pas vers un dépôt public existant, et l'API répond
409. - Le formulaire nomme une variable d'environnement du serveur,
HF_TOKENpar défaut, qui contient un jeton d'écriture Hugging Face. Le jeton lui-même n'est jamais saisi dans la page. Le nom de la variable doit contenirTOKENou commencer parHF_, et la valeur doit commencer parhf_, si bien que la valeur d'aucune autre variable ne peut atteindre le Hub. - Quand le Hub ne peut pas dire si le dépôt existe, rien n'est envoyé, et un dépôt que l'envoi a créé est de nouveau supprimé si le téléversement échoue ensuite.
- La licence de la fiche de modèle est l'identifiant de licence du Hub que vous donnez, comme
apache-2.0. À défaut, la fiche dit que la licence du modèle de base s'applique. Un module dont la licence demande confirmation, commeultralytics-detect(AGPL-3.0), demande la même confirmation pour publier. - Un modèle laissé sur un hôte distant avec
fetch_artifacts: false, ou entraîné sur un backend agent, ne peut pas être publié depuis le serveur, et l'erreur nomme l'endroit où se trouve le modèle.
Chaque envoi est un commit. La page de l'exécution liste chaque envoi avec le dépôt, la visibilité et le commit, et le registre enregistre qui a fait l'envoi. Par l'API, le corps de POST /admin/training/api/runs/<run_id>/push-to-hub accepte repo_id, confirm_repo_id, private (true par défaut), token_env (HF_TOKEN par défaut), licence et accept_licence. La route renvoie 201 avec le commit, 400 pour une discordance, une variable de jeton manquante, l'absence de fichiers de modèle ou une licence non confirmée, et 502 quand le Hub refuse.
Dépannage
Les entrées ci-dessous couvrent les erreurs les plus probables lors d'une première mise en place. La liste de dépannage amont couvre les pilotes de GPU, les versions de CUDA et les messages propres à chaque module.
/admin/trainingrenvoie 404.model_training.enabledn'est pastrue, et Potato n'enregistre les routes que lorsque la clé vauttrue.- « Only N items in the train split ». Annotez davantage d'items, ou baissez
min_instancesdans lesparamsde l'exécution. La partition train contient par défaut 70 % des items étiquetés. - « Schema 'x' has 1 distinct label(s) in the data ». Un classifieur a besoin d'au moins deux étiquettes utilisées.
- « No resolved annotations to train on ». Le schéma nommé dans l'exécution diffère du schéma annoté, ou personne n'a encore rien annoté.
- L'exécution n'a publié aucune pré-étiquette. Lisez le rapport
writebackdansGET /admin/training/api/status. « No predictions were published: write-back is not enabled for any schema » signifie quewriteback.schemasest vide, et les décomptes de sauts montrent combien de prédictions chaque vérification a écartées. <trainer> does not take <name>. Un paramètre de l'exécution ou detrainer_paramsest mal orthographié ou appartient à un autre module. Le message liste les noms que le module accepte.- L'exécution a été tuée après que la machine a manqué de mémoire. Le processus s'est terminé sur SIGKILL, le plus souvent à cause du tueur de processus pour manque de mémoire. Utilisez un modèle plus petit ou moins d'items, ou fixez
max_ram_mbpour que l'exécution échoue dans sa propre limite. - « Stopped: the run took longer than model_training.max_wall_seconds ». L'exécution a atteint la limite de durée. Relevez
max_wall_seconds, ou entraînez sur moins d'items. - « The GPU ran out of memory ». Baissez
batch_sizeet relevezgradient_accumulationpour garder le lot effectif, fixezlora: trueoulora: {quantize: 4bit}, ou pourllm-sftfixezgradient_checkpointing: trueou choisissez un modèle plus petit. - « ssh to host failed: Permission denied ». Potato lance
sshavecBatchMode=yes, si bien quessh <host> truedoit réussir depuis le compte du serveur sans invite. Une clé protégée par une phrase secrète fonctionne quandssh-agentdétient la clé. - Une exécution sur un backend agent reste en attente. Aucun agent portant ce nom de backend n'interroge le serveur. Lancez un agent avec
potato training agent --backend <name>, et vérifiez le jeton avec Check sur la page Training.
Pour aller plus loin
- Entraîner des modèles sur vos propres annotations : la boucle d'entraînement, la page Training et un démarrage rapide.
- Modules d'entraînement : chaque module, les schémas dont chacun apprend et les commandes d'installation.
- Entraîner sur un serveur GPU, un cluster SLURM ou une machine derrière un NAT : les backends ssh, SLURM et d'agent pas à pas.
- Le modèle dans la boucle : écriture en retour, relecture,
auto_retrainet versions de jeu de données dans une même étude. - Apprentissage actif : ordonner les items selon l'incertitude du modèle.
- Repérer les pré-étiquettes validées sans lecture : vérifier si les annotateurs acceptent les pré-étiquettes sans les lire.
- Référence amont : les tableaux complets de paramètres de chaque module.
Références
- Dawid, A. P., and Skene, A. M. (1979). Maximum Likelihood Estimation of Observer Error-Rates Using the EM Algorithm. Applied Statistics, 28(1). https://doi.org/10.2307/2346806
- Dettmers, T., Pagnoni, A., Holtzman, A., and Zettlemoyer, L. (2023). QLoRA: Efficient Finetuning of Quantized LLMs. Advances in Neural Information Processing Systems 36 (NeurIPS 2023). https://proceedings.neurips.cc/paper_files/paper/2023/hash/1feb87871436031bdc0f2beaa62a049b-Abstract-Conference.html