SDK d'exécution TAO
Le SDK est la couche Python optionnelle pour les utilisateurs qui ont besoin de handles de job, d'enveloppe S3 I/O, ou de fonctionnalités spécifiques à la plateforme (Lepton multi-nœud, files d'attente SLURM/Lustre, Kubernetes Jobs, débogage Docker local, réutilisation d'instance Brev). La plupart des skills TAO fonctionnent avec juste docker run et n'en ont pas besoin. Utilisez le SDK quand :
- Vous voulez un handle
Jobpour interroger le statut et streamer les logs au fil du temps. - La plateforme est API-only (Lepton n'a pas d'équivalent docker-run).
- Vous avez besoin du téléchargement d'entrée S3-aware / upload de sortie intégré au point d'entrée.
- Vous chaînez plusieurs jobs et voulez un état persisté.
Vérification préalable
Installez nvidia-tao-sdk[all] avant d'utiliser cette plateforme — l'extra [all] télécharge chaque dépendance spécifique à la plateforme (Lepton, Brev, utilitaires S3, etc.) :
python -c "import tao_sdk" 2>/dev/null || {
echo "MISSING: nvidia-tao-sdk not installed. Run:"
echo " pip install nvidia-tao-sdk[all]"
exit 1
}
L'index de package est spécifique à l'environnement — le runner/conteneur est supposé avoir une configuration pip fonctionnelle (par ex. ~/.pip/pip.conf, PIP_INDEX_URL, PIP_EXTRA_INDEX_URL, ou proxy). Si l'installation échoue pour des raisons d'index/réseau, c'est un problème de configuration du runner ; ce skill reste agnostique au registre.
S'il est manquant, l'agent invite l'utilisateur à autoriser l'installation via Bash, puis relance la vérification. Ne jamais installer silencieusement en automatique.
Configuration
Les credentials proviennent de variables d'environnement — sourcées de ~/.config/tao/.env (auto-chargées par le hook SessionStart de la banque de skills).
from tao_sdk.platforms.lepton import LeptonSDK # DGX Cloud
from tao_sdk.platforms.brev import BrevSDK # Instances GPU Brev
sdk = LeptonSDK() # reads LEPTON_WORKSPACE_ID, LEPTON_AUTH_TOKEN
# or
sdk = BrevSDK() # reads BREV_API_TOKEN (optional — falls back to brev login)
Les deux SDKs valident les credentials en lazy sur la première utilisation et lèvent CredentialError avec un message clair si une variable d'environnement requise manque. Variables d'environnement requises :
| Plateforme | Requise | Optionnelle |
|---|---|---|
| Lepton | LEPTON_WORKSPACE_ID, LEPTON_AUTH_TOKEN |
— |
| Brev | — (le brev login manuel fonctionne) |
BREV_API_TOKEN |
| S3 I/O (toute plateforme) | S3_BUCKET_NAME, ACCESS_KEY, SECRET_KEY |
S3_ENDPOINT_URL, CLOUD_REGION |
| Environnement conteneur | NGC_KEY |
HF_TOKEN |
L'agent ne lit jamais les valeurs de credentials — il vérifie seulement la présence avec [ -n "$VAR_NAME" ].
Intake de lancement de workflow
Pour tout lancement de workflow ou action TAO, confirmez d'abord l'objectif de l'utilisateur. Demandez ensuite les préférences de plateforme et de monitoring avant les credentials ou les détails de lancement. Générez les choix de plateforme supportés à partir de l'helper fourni, pas en scannant les docs ou dossiers de plateforme :
${TAO_SKILL_BANK_PATH:-~/tao-skills-external}/scripts/list_tao_platforms.py \
--skill-bank ${TAO_SKILL_BANK_PATH:-~/tao-skills-external} --format text
Demandez :
- Quelle plateforme supportée doit exécuter ce workflow ?
- Le monitoring de longue durée doit-il rester activé ? Défaut : activé. Cela signifie que l'agent reste attaché et poste le statut jusqu'à l'état terminal, incluant les longues attentes de file
PENDING. - Combien de minutes entre les mises à jour de statut ? Défaut : 5 minutes.
Après que le modèle/action soient connus, résolvez l'image de conteneur par défaut à partir des métadonnées fournies et demandez à l'utilisateur de la confirmer ou de fournir image=<override> avant de créer les fichiers de runner :
${TAO_SKILL_BANK_PATH:-~/tao-skills-external}/scripts/resolve_tao_image.py \
--skill-bank ${TAO_SKILL_BANK_PATH:-~/tao-skills-external} \
--model <network_arch> --action <action> --format text
Pour les workflows de modèles capables d'entraînement, inspectez les métadonnées AutoML au niveau du modèle avant de créer un job d'entraînement simple :
${TAO_SKILL_BANK_PATH:-~/tao-skills-external}/scripts/list_tao_models.py \
--skill-bank ${TAO_SKILL_BANK_PATH:-~/tao-skills-external} \
--scope automl --format json
Si le modèle sélectionné a automl_enabled: true et un schéma d'entraînement valide, routez l'entraînement via skills/applications/tao-run-automl par défaut. Un workflow ne doit contourner AutoML que quand ses paramètres d'exécution incluent automl_policy: off, que l'utilisateur demande explicitement une exécution simple, ou que les métadonnées du modèle disent qu'AutoML est activé mais le schéma d'entraînement n'est pas encore fourni.
Après la sélection de la plateforme, obtenez le filtre de credentials :
${TAO_SKILL_BANK_PATH:-~/tao-skills-external}/scripts/list_tao_platforms.py \
--skill-bank ${TAO_SKILL_BANK_PATH:-~/tao-skills-external} \
--platform <platform> --format text
Demandez uniquement les credentials retournés pour la plateforme sélectionnée. Par exemple, SLURM a besoin de SLURM_USER et SLURM_HOSTNAME ; il n'a pas besoin des credentials Lepton. Kubernetes et Docker local n'ont pas besoin des credentials Lepton ou SLURM. Demandez les credentials de stockage comme les clés S3 seulement quand la plateforme sélectionnée et les URIs de données/résultat les requièrent.
API centrale
Tous les SDKs de plateforme implémentent la même forme de base :
sdk.create_job(image, command, gpu_count=1, env_vars=None, inputs=None, outputs=None, **kwargs) -> Job
sdk.get_job_status(job_id) -> JobStatus
sdk.get_job_logs(job_id, tail=None) -> str
sdk.cancel_job(job_id) -> bool
sdk.get_failure_analysis(job_id) -> dict | None
sdk.get_job_results_dir(job_id) -> str
sdk.check_path(remote_path) -> bool
sdk.list_path(remote_path) -> list[str]
Lepton uniquement :
sdk.get_job_replicas(job_id)— diagnostics au niveau du replica pour les jobs stuck-pending.
Brev uniquement :
sdk.delete_instance(instance_id)— nettoyer une instance éphémère.sdk.list_instances()— lister les instances actives.
Soumettre un job
L'agent construit toujours la commande de conteneur via build_entrypoint avant d'appeler create_job. L'agent lit le schéma de l'action de skill_info.yaml (command, config_format, inputs, outputs, upload_excludes) et passe ces champs comme kwargs. build_entrypoint intègre le runtime script_runner in-container (inliné en heredoc base64) et l'invocation CLI qui, à l'exécution, télécharge les entrées déclarées, écrit le fichier de spec à {config_path} avec les URIs distantes réécrites en chemins locaux, exécute la commande utilisateur, et upload les sorties. Le create_job du SDK de plateforme exécute la commande résultante tel quel — pas d'enveloppe implicite.
build_entrypoint déduit le mode (config / args / passthrough) à partir de ce que vous passez — vous ne passez jamais mode explicitement. Voir references/job-construction.md pour le contrat complet du point d'entrée, la stratégie de construction de spec/args par action mode, la table d'inférence de mode, et resolve_container_image(). Voir references/outputs.md pour où les sorties arrivent (les tables de destination runtime et la politique d'injection par plateforme) et la règle critique « spec est des dicts imbriqués, pas des clés pointées plates ». Voir references/examples.md pour les exemples complets pilotés par spec et par chemin de build_entrypoint + create_job.
Monitoring
status = sdk.get_job_status(job.id)
print(status.status) # Pending, Running, Complete, Error, Canceled
print(status.message) # détail spécifique à la plateforme
logs = sdk.get_job_logs(job.id, tail=200)
print(logs)
Pour les jobs Lepton stuck-Pending, les diagnostics de replica révèlent la cause (image pull, scheduling, erreurs de montage) :
for r in sdk.get_job_replicas(job.id):
issue = r["status"].get("readiness_issue")
if issue:
print(issue["reason"], issue["message"])
# par ex. "InProgress" / "Pulling image" (normal pour les grandes images)
# "Failed" / "ImagePullBackOff" (problème NGC_KEY)
# "ConfigError" / "Mount point not found" (mauvais nœud)
En cas d'échec, get_failure_analysis() classifie la cause racine :
analysis = sdk.get_failure_analysis(job.id)
if analysis:
print(analysis["err_class"]) # ERR_PROGRAM, ERR_INFRA, etc.
print(analysis["suggestion"]) # correction lisible par l'homme
for event in analysis.get("job_failure_by_node_event", []):
print(event["node_event_name"], event["message"]) # OOM, erreur GPU, etc.
Pattern de polling
Pour les exécutions interactives où l'utilisateur veut regarder :
import time
status_interval_minutes = status_interval_minutes or 5
while True:
status = sdk.get_job_status(job.id)
if status.status in ("Complete", "Error", "Canceled"):
break
print(f" {status.status}")
time.sleep(status_interval_minutes * 60)
if status.status == "Error":
print(sdk.get_job_logs(job.id, tail=100))
print(sdk.get_failure_analysis(job.id))
Avec le monitoring de longue durée activé, ne vous arrêtez pas après 30 minutes ou après quelques polls inchangés. Continuez à émettre des mises à jour tous les status_interval_minutes jusqu'à ce que le job se termine, échoue, soit annulé, ou que l'utilisateur demande de se détacher/arrêter. Si le chat/runtime ne peut pas rester ouvert aussi longtemps, dites-le explicitement et fournissez le chemin de workflow/log durable pour l'actualisation manuelle du statut.
N'utilisez pas une réponse finale pour les jobs non-terminaux monitorés. Finaliser le tour détache l'observateur de chat. Gardez les messages de statut non-terminaux dans les mises à jour en cours et continuez le polling ; ne finalisez qu'à l'état terminal, au détachement/arrêt explicite de l'utilisateur, ou une vraie limite de runtime qui empêche le polling ultérieur.
Pour les exécutions en arrière-plan, persistez job.id et le chemin state_file, puis ré-attachez-vous ultérieurement en construisant le même SDK et en appelant get_job_status(job_id) — l'état du job est lu depuis le store sur disque.
Patterns d'orchestration
Les workflows multi-étapes, les sweeps parallèles, et la durabilité du dossier d'exécution via ActionWorkflow sont dans references/orchestration-patterns.md. Lisez-le avant de chaîner les appels create_job, de faire un sweep de paramètre, ou de persister l'état d'exécution à travers les ruptures de contexte.
Utilitaires de dataset
Quand les noms de fichier documentés du skill ne correspondent pas à la disposition de l'utilisateur, listez le dataset pour confirmer :
assert sdk.check_path("s3://my-bucket/coco/")
files = sdk.list_path("s3://my-bucket/coco/train/")
# Utilisez les chemins réels pour définir les champs de spec.
Pour les chemins S3, supprimez les slashes finaux lors de la concaténation pour éviter // :
base = dataset_uri.rstrip("/")
specs["dataset"]["train_csv"] = f"{base}/train.csv" # imbriqué — voir « spec est des dicts imbriqués »
Notes spécifiques à la plateforme
Chaque backend (Lepton, Brev, SLURM, Kubernetes, Docker local) a son chemin d'importation, son modèle de stockage, ses options d'entraînement distribué, sa portée de credentials, et ses kwargs create_job. Voir references/platform-notes.md pour les détails par plateforme avant de générer ou lancer les artefacts de runner pour un backend donné.
Patterns d'erreur
Les mappages SDK error → root cause → fix sont dans references/error-patterns.md. Lisez-le quand vous rencontrez un CredentialError, une défaillance d'image-pull, un job stuck-Pending, ou similaire — les entrées mappent le texte d'exception à la cause sous-jacente.
Ce que le SDK ne fait PAS
Les guardrails de portée (pas de lecture de skill, pas de HPO, pas d'opinions sur spec, pas de sélection auto-plateforme, pas d'orchestration de workflow) sont dans references/scope.md.