1. Séparer le programme, ses paramètres et le suivi commercial
Le code décrit le comportement du programme. La configuration précise la charge : modèle, données, batch, précision et destination. Les secrets donnent accès aux ressources nécessaires. Gardez ces éléments distincts pour changer un essai sans réécrire le code ni copier un jeton dans un fichier partagé.
La référence de commande Kernodeck permet de retrouver le contexte de location dans votre compte. L’identifiant d’essai distingue les exécutions de votre programme pendant cette période. Associez-les dans vos notes si cela vous aide, mais ne demandez pas à votre script de déduire l’état du calcul depuis le statut du paiement.
Prenons un projet de classement de documents qui doit être lancé plusieurs fois sur un même échantillon. Le contrat du programme décrit le fichier d’entrée, les paramètres admis, le dossier de sortie et la manière de rendre les erreurs. Le guide sur les données précise la validation du contenu ; ici, nous organisons l’interface qui relie ces étapes.
2. Écrire un contrat d’entrée explicite et versionné
Documentez les champs obligatoires et les valeurs acceptées. Évitez les valeurs par défaut silencieuses pour une décision qui change le résultat, comme le modèle ou le périphérique. Un numéro de schéma distingue la forme de la configuration de la version du code ; il ne remplace pas cette dernière.
Dans cet exemple pédagogique, le fichier JSON contient un schéma, un chemin d’entrée, un batch et le périphérique demandé. Les chemins relatifs se lisent à partir du dossier de configuration. Cette règle choisie pour l’exemple évite de dépendre du répertoire depuis lequel un collègue lance la commande.
Lire du JSON valide seulement sa syntaxe. Votre programme doit ensuite vérifier les types, les champs et les contraintes du projet. En cas d’erreur, il doit s’arrêter avant le chargement d’une ressource coûteuse, avec un message qui nomme le paramètre à corriger.
{
"schema_version": 1,
"input": "../data/pilote.jsonl",
"batch_size": 4,
"device": "cuda"
}3. Préparer un point d’entrée qui refuse les erreurs simples
argparse permet de déclarer des options et de produire une aide pour votre commande. L’exemple suivant constitue uniquement un précontrôle : il lit la configuration, vérifie ses champs et repère un dossier de sortie déjà utilisé. Il ne charge ni modèle ni données en mémoire et ne teste pas la disponibilité du GPU.
Enregistrez ce code pédagogique dans prepare_run.py si vous souhaitez l’adapter. Il est proposé sans exécution attestée. Ajoutez ensuite vos contrôles métier dans l’application, plutôt que considérer le message final comme un résultat de calcul. Le périphérique cuda reste une demande ; PyTorch utilise aussi ce nom avec ROCm.
Le refus d’un répertoire de sortie existant est ici une convention de protection contre le mélange des essais. Une vraie commande de reprise doit recevoir une option et des contrôles distincts. Ne transformez pas un lancement neuf en reprise implicite parce que des fichiers sont présents.
import argparse
import json
from pathlib import Path
parser = argparse.ArgumentParser(description="Valider un lancement du projet")
parser.add_argument("--config", type=Path, required=True)
parser.add_argument("--run-dir", type=Path, required=True)
args = parser.parse_args()
try:
config_path = args.config.resolve()
config = json.loads(config_path.read_text(encoding="utf-8"))
except (OSError, UnicodeError, json.JSONDecodeError) as exc:
parser.error(f"Configuration illisible : {exc}")
expected = {"schema_version", "input", "batch_size", "device"}
if not isinstance(config, dict) or set(config) != expected:
parser.error("Champs attendus : schema_version, input, batch_size, device")
if type(config["schema_version"]) is not int or config["schema_version"] != 1:
parser.error("schema_version doit valoir 1")
if type(config["batch_size"]) is not int or config["batch_size"] < 1:
parser.error("batch_size doit être un entier positif")
if config["device"] not in ("cpu", "cuda"):
parser.error("device doit valoir cpu ou cuda")
if not isinstance(config["input"], str) or not config["input"]:
parser.error("input doit être un chemin non vide")
input_path = (config_path.parent / config["input"]).resolve()
run_dir = args.run_dir.resolve()
if not input_path.is_file():
parser.error("Fichier d’entrée absent")
if run_dir.exists():
parser.error("Choisissez un nouveau dossier de sortie")
print(json.dumps({
"status": "configuration_validated",
"input": str(input_path),
"run_dir": str(run_dir),
"device_requested": config["device"],
"batch_size": config["batch_size"]
}, ensure_ascii=False))python prepare_run.py --config config/pilote.json --run-dir runs/pilote-0014. Donner une identité aux exécutions et à leurs résultats
Associez chaque lancement à un identifiant court, unique dans votre campagne. Notez la révision du code, le schéma et les paramètres effectivement utilisés, puis la référence des données et du modèle. Conservez ces valeurs avec les sorties afin qu’un résultat ne dépende pas d’un fichier de configuration modifié plus tard.
Pour comparer deux tailles de batch, créez deux essais et deux répertoires. Gardez le même échantillon et identifiez la différence volontaire. Les noms pilote-001 et pilote-002 n’expliquent pas seuls ce qui a changé : le manifeste relie le nom aux paramètres.
Réservez un format de bilan lisible par vos outils. Il peut distinguer éléments reçus, réussis, refusés et restant à traiter. Choisissez une règle de réussite complète et ne marquez pas un essai terminé dès l’écriture du premier résultat. Le code retour du programme doit rester cohérent avec cette conclusion.
Faites défiler le tableau pour lire toutes les colonnes.| Fichier ou état | Rôle | Contrôle attendu |
|---|---|---|
| manifest.json | Identité du code, des données et des paramètres | Valeurs effectivement utilisées, sans secret. |
| results.jsonl | Une sortie par élément accepté | Identifiants connus et format conforme. |
| errors.jsonl | Éléments refusés et motif utile | Pas de disparition silencieuse ni contenu sensible inutile. |
| summary.json | Conclusion de l’essai et compteurs | Somme cohérente, fichiers relus avant statut final. |
5. Exposer des événements utiles à vos outils
Rendez visibles quelques transitions : configuration acceptée, données accessibles, modèle chargé, première sortie écrite et fin du traitement. Une trace doit permettre de répondre « où en est ce lancement ? » sans recopier les documents ou prompts. Associez l’étape et l’identifiant d’essai au message.
Le module logging de Python permet d’organiser les messages par niveau et destination. Choisissez ensuite votre propre convention d’événements et documentez-la. Une application qui écrit une erreur puis termine avec un succès rend l’automatisation trompeuse ; à l’inverse, chaque avertissement ne signifie pas que le résultat est inutilisable.
Ne confondez pas événement émis et résultat durable : un message « sauvegarde commencée » ne prouve pas qu’un fichier a été relu. Pour une exécution longue, le guide dédié explique le lien entre processus et session. Votre interface doit surtout conserver une conclusion accessible après la fin de la connexion interactive.
6. Définir l’échec, la reprise et la vérification finale
Classez les échecs utiles : configuration invalide, ressource absente, erreur de calcul et résultat non conforme. Donnez pour chacun une prochaine action. N’installez pas de relance automatique sans décider quels effets peuvent être répétés : réécrire une sortie déjà acceptée et reprendre un checkpoint demandent des règles différentes.
Votre procédure finale explique comment lancer, observer, arrêter, reprendre et exporter. Pour un traitement de documents, gardez la liste des identifiants terminés et ceux à retraiter. Pour un entraînement, utilisez un protocole qui vérifie les états sauvegardés dans un nouveau processus. Un dossier non vide n’est pas une preuve de reprise correcte.
Contrôlez enfin le projet depuis une nouvelle invocation, avec une configuration connue et une destination distincte. Vérifiez les refus attendus, puis un petit parcours complet. Le précontrôle de cette page ne couvre ni accès concurrents, ni exposition publique d’un service, ni permissions de stockage : ces sujets demandent leur propre conception.