
IA agentique pour l’expérimentation moderne du Deep Learning
qui lit vos mesures, détecte les anomalies, applique des règles de réglage prédéfinies, redémarre les tâches si nécessaire et enregistre chaque décision, sans que vous ayez à regarder les courbes de perte à 2 heures du matin
Dans cet article, je vais fournir un agent léger conçu pour les chercheurs en apprentissage profond et les ingénieurs ML qui peut :
• Détecter automatiquement les pannes
• Raisonnez visuellement sur les mesures de performances
• Appliquez vos stratégies d’hyperparamètres prédéfinies
• Relancer les travaux
• Documenter chaque action et chaque résultat
Aucune recherche d’architecture. Pas d’AutoML. Aucune réécriture invasive de votre base de code.
L’implémentation est volontairement minimale : conteneurisez votre script de formation, ajoutez un petit agent basé sur LangChain, définissez des hyperparamètres en YAML et exprimez vos préférences en markdown. Vous en faites probablement déjà 50 %.
Déposez cet agent dans votre manuel train.py workflow et passer de 0️⃣ à 💯 en une seule journée.
Le problème avec vos expériences existantes
🤔 Vous réfléchissez sans cesse aux hyperparamètres.
▶️ Vous exécutez train.py.
🐛 Vous corrigez le bug dans train.py.
🔁Vous rediffusion train.py
👀 Vous regardez TensorBoard.
🫠 Vous remettez en question la réalité.
🔄Vous répétez.

Arrêtez de regarder votre modèle cracher des chiffres
Vous n’êtes pas un Jedi. Aucun regard fixe ne fera comme par magie votre [validation loss | classification accuracy | perplexity | any other metric you can name] avancez dans la direction que vous souhaitez.
Garder un mannequin en pleine nuit pour un dégradé qui disparaît/explose NaN dans un réseau profond basé sur des transformateurs que vous ne pouvez pas localiser – et qui pourrait même ne jamais apparaître ? Aussi un dur non.
Comment êtes-vous censé résoudre de vrais problèmes de recherche alors que la majeure partie de votre temps est consacrée à un travail qui doit techniquement être effectué, mais qui contribue très peu à la compréhension réelle ?
Si 70 % de votre journée est consacrée à la traînée opérationnelle, quand y réfléchissez-vous ?
Passage à des expériences basées sur des agents
La plupart des ingénieurs et chercheurs en apprentissage profond avec lesquels je travaille mènent encore des expériences manuellement. Une partie importante de la journée est consacrée à : analyser les poids et les biais ou TensorBoard pour l’exécution de la nuit dernière, comparer les exécutions, exporter les métriques, ajuster les hyperparamètres, enregistrer les notes, redémarrer les tâches. Puis répéter le cycle.
C’est un travail sec, fastidieux et répétitif.
Nous allons vous décharger de ces tâches répétitives afin que vous puissiez vous concentrer sur un travail à haute valeur ajoutée.
Le concept d’AutoML est franchement risible.
Ton [new] L’agent ne prendra pas de décisions sur la manière de modifier la topologie de votre réseau ou d’ajouter des fonctionnalités complexes : c’est votre travail. Il remplacera le travail de colle répétitif qui prend un temps précieux avec peu de valeur ajoutée.
Expériences pilotées par agents (ADE)
Passer d’expériences manuelles à un flux de travail piloté par des agents est plus simple qu’il n’y paraît au départ. Pas de réécriture de votre pile, pas de systèmes lourds, pas de dette technologique.

À la base, une ADE nécessite trois étapes :
- Conteneurisez votre script de formation existant
- Enveloppez votre courant
train.pydans un conteneur Docker. Pas de refactorisation de la logique du modèle. Aucun changement architectural. Juste une limite d’exécution reproductible.
- Enveloppez votre courant
- Ajouter un agent léger
- Introduisez un petit script basé sur LangChain qui lit les métriques de votre tableau de bord, applique vos préférences, décide quand et où relancer, arrêter ou documenter et le planifier avec cron ou n’importe quel planificateur de tâches.
- Définir le comportement et les préférences avec le langage naturel
- Utiliser un fichier YAML pour la configuration et les hyperparamètres
- Utilisez un document Markdown pour communiquer avec votre agent
C’est tout le système. Maintenant, passons en revue chaque étape.
Conteneurisez votre script de formation
On pourrait dire que vous devriez le faire de toute façon. Cela facilite grandement le redémarrage et la planification et, si vous passez à un cluster Kubernetes pour la formation, la perturbation de votre processus existant est bien moindre.
Si vous le faites déjà, passez à la section suivante. Sinon, voici un code utile que vous pouvez utiliser pour commencer.
Tout d’abord, définissons une structure de projet qui fonctionnera avec Docker.
your experiment/
├── scripts/
│ ├── train.py # Main training script
│ └── health_server.py # Health check server
├── requirements.txt # Python dependencies
├── Dockerfile # Container definition
└── run.sh # Script to start training + health check
Nous devons nous assurer que votre train.py Le script peut charger un fichier de configuration depuis le cloud, permettant à l’agent de le modifier si nécessaire.
Je recommande d’utiliser GitHub pour cela. Voici un exemple de la façon de lire un fichier de configuration distant. L’agent disposera d’un outil correspondant pour lire et modifier ce fichier de configuration.
import os
import requests
import yaml
from box import Box
# add this to `train.py`
GITHUB_RAW = (
"https://raw.githubusercontent.com/"
"{owner}/{repo}/{ref}/{path}"
)
def load_config_from_github(owner, repo, path, ref="main", token=None):
url = GITHUB_RAW.format(owner=owner, repo=repo, ref=ref, path=path)
headers = {}
if token:
headers["Authorization"] = f"Bearer {token}"
r = requests.get(url, headers=headers, timeout=10)
r.raise_for_status()
return Box(yaml.safe_load(r.text))
config = load_yaml_from_github(...)
# use params throughout your `train.py` script
optimizer = Adam(lr=config.lr)
Nous incluons également un serveur de contrôle de santé à exécuter parallèlement au processus principal. Cela permet aux gestionnaires de conteneurs, tels que Kubernetes, ou à votre agent, de surveiller l’état de la tâche. sans inspecter les journaux.
Si l’état du conteneur change de manière inattendue, il peut être automatiquement redémarré. Cela simplifie l’inspection des agents, car la lecture et la synthèse des fichiers journaux peuvent être plus coûteuses en jetons que la simple vérification de l’état d’un conteneur.
# health_server.py
import time
from pathlib import Path
from fastapi import FastAPI, Response
app = FastAPI()
HEARTBEAT = Path("/tmp/heartbeat")
STATUS = Path("/tmp/status.json") # optional richer state
MAX_AGE = 300 # seconds
def last_heartbeat_age():
if not HEARTBEAT.exists():
return float("inf")
return time.time() - float(HEARTBEAT.read_text())
@app.get("/health")
def health():
age = last_heartbeat_age()
# stale -> training likely hung
if age > MAX_AGE:
return Response("stalled", status_code=500)
# optional: detect NaNs or failure flags written by trainer
if STATUS.exists() and "failed" in STATUS.read_text():
return Response("failed", status_code=500)
return {"status": "ok", "heartbeat_age": age}
Un petit script shell, run.shce qui démarre le health_server processus aux côtés du train.py
#!/bin/bash
# Start health check server in the background
python scripts/health_server.py &
# Capture its PID if you want to terminate later
HEALTH_PID=$!
# Start the main training script
python scripts/train.py
Et bien sûr, notre Dockerfile, qui est construit sur l’image de base de NVIDIA afin que votre conteneur puisse utiliser l’accélérateur de l’hôte sans friction. Cet exemple concerne Pytorch, mais vous pouvez simplement l’étendre à Jax ou Tensorflow si nécessaire.
FROM nvidia/cuda:12.1.0-cudnn8-devel-ubuntu20.04
RUN apt-get update && apt-get install -y \
python3 python3-pip git
RUN python3 -m pip install --upgrade pip
# Install PyTorch with CUDA support
RUN pip3 install torch torchvision torchaudio --extra-index-url https://download.pytorch.org/whl/cu121
WORKDIR /app
COPY . /app
CMD ["sh", "run.sh"]
✅Vous êtes conteneurisé. Simple et minimal.
Ajouter un agent léger
Il existe de nombreux frameworks d’agents parmi lesquels choisir. Pour cet agent, j’aime Langchain.
LangChaîne est un cadre pour construire des systèmes basés sur LLM qui combinent raisonnement et exécution. Il simplifie le chaînage des appels de modèle, la gestion de la mémoire et l’intégration de fonctionnalités externes afin que votre LLM puisse faire plus que générer du texte.
Dans LangChain, Outils sont des fonctions explicitement définies et liées au schéma que le modèle peut appeler. Chaque outil est une compétence ou une tâche idempotente (par exemple, lire un fichier, interroger une API, modifier un état).
Pour que notre agent fonctionne, nous devons d’abord définir les outils qu’il peut utiliser pour atteindre notre objectif.
Définitions d’outils
- read_preferences
- Lit les préférences utilisateur et les notes d’expérience à partir d’un document de démarque
- check_tensorboard
- Utilise Selenium avec un pilote Web Chrome pour capturer les métriques
- analyser_métrique
- Utilise le raisonnement LLM multimodal pour comprendre ce qui se passe dans la capture d’écran
- check_container_health
- Vérifie notre expérience conteneurisée à l’aide d’un bilan de santé
- redémarrer_conteneur
- Redémarre l’expérience si elle n’est pas saine ou si un hyperparamètre doit être modifié
- modifier_config
- Modifie un fichier de configuration distant et s’engage sur Github
- écrire_mémoire
- Écrit une chaîne d’actions dans une mémoire persistante (markdown)
Cet ensemble d’outils définit les limites opérationnelles de notre agent. Toutes les interactions avec notre expérience via ces outils, rendant le comportement contrôlable et, espérons-le, prévisible.
Au lieu de fournir ces outils en ligne, voici un l’essentiel de GitHub contenant tous les outils décrits ci-dessus. Vous pouvez les connecter à votre agent ou les modifier comme bon vous semble.
L’agent
Pour être tout à fait honnête, la première fois que j’ai essayé de consulter la documentation officielle de Langchain, j’ai immédiatement été complètement découragé par l’idée.
C’est trop verbeux et plus complexe que nécessaire. Si vous êtes nouveau dans le domaine des agents, ou si vous ne voulez tout simplement pas naviguer dans le labyrinthe qu’est la documentation Langchain, veuillez continuer à lire ci-dessous.

En un mot, voici comment fonctionnent les agents Langchain :
Notre agent utilise un rapide décider quoi faire à chaque fois étape.
Mesures sont créés dynamiquement en remplissant l’invite avec le contexte actuel et les sorties précédentes. Chaque appel LLM [+ optional tool invocation] est une étape, et sa sortie alimente la suivante, formant un chaîne.
Utiliser ceci boucle conceptuellement récursivel’agent peut raisonner et exécuter l’action correcte prévue sur toutes les étapes requises. Le nombre d’étapes dépend de la capacité de raisonnement de l’agent et de la clarté avec laquelle la condition de terminaison est définie.
C’est une chaîne Lang. L’obtenir? 🤗
L’invite
Comme indiqué, l’invite est le ciment récursif qui maintient le contexte à travers les invocations de LLM et d’outils. Vous verrez des espaces réservés (définis ci-dessous) utilisés lors de la première initialisation de l’agent.
Nous utilisons un peu des abstractions de mémoire intégrées de LangChain, incluses avec chaque appel d’outil. En dehors de cela, l’agent comble les lacunes, décidant à la fois de l’étape suivante et de l’outil à appeler.
Pour plus de lisibilité, l’invite principale se trouve ci-dessous. Vous pouvez soit le connecter directement au script de l’agent, soit le charger à partir du système de fichiers avant de l’exécuter.
"You are an experiment automation agent responsible for monitoring
and maintaining ML experiments.
Current context:
{chat_history}
Your workflow:
1. First, read preferences from preferences.md to understand thresholds and settings
2. Check TensorBoard at the specified URL and capture a screenshot
3. Analyze key metrics (validation loss, training loss, accuracy) from the screenshot
4. Check Docker container health for the training container
5. Take corrective actions based on analysis:
- Restart unhealthy containers
- Adjust hyperparameters according to user preferences
and anomalous patterns, restarting the experiment if necessary
6. Log all observations and actions to memory
Important guidelines:
- Always read preferences first to get current configuration
- Use visual analysis to understand metric trends
- Be conservative with config changes (only adjust if clearly needed)
- Write detailed memory entries for future reference
- Check container health before and after any restart
- When modifying config, use appropriate values from preferences
Available tools: {tool_names}
Tool descriptions: {tools}
Current task: {input}
Think step by step and use tools to complete the workflow.
"""
Maintenant, avec environ 100 lignes, nous avons notre agent. L’agent est initialisé, puis nous définissons une série d’étapes. Pour chaque étape, le current_task La directive est renseignée dans notre invite et chaque outil met à jour une instance de mémoire partagée ConverstationSummaryBufferMemory
Nous allons utiliser OpenAI pour cet agent, cependant, Langchain propose des alternatives, notamment l’hébergement de la vôtre. Si le coût est un problème, il existe des modèles open source qui peuvent être utilisés ici.
import os
from datetime import datetime
from pathlib import Path
from langchain.agents import AgentExecutor, create_react_agent
from langchain_openai import ChatOpenAI
from langchain.prompts import PromptTemplate
from langchain.memory import ConversationSummaryBufferMemory
# Import tools from tools.py
from tools import (
read_preferences,
check_tensorboard,
analyze_metric,
check_container_health,
restart_container,
modify_config,
write_memory
)
PROMPT=open("prompt.txt").read()
class ExperimentAutomation:
def __init__(self, openai_key=None):
"""Initialize the agent"""
self.llm = ChatOpenAI(
temperature=0.8,
model="gpt-4-turbo-preview",
api_key=openai_key or os.getenv('OPENAI_API_KEY')
)
# Initialize memory for conversation context
self.memory = ConversationSummaryBufferMemory(
llm=self.llm,
max_token_limit=32000,
memory_key="chat_history",
return_messages=True
)
def create_agent(self):
"""Create LangChain agent with imported tools"""
tools = [
lambda **kwargs: read_preferences(memory=self.memory, **kwargs),
lambda **kwargs: check_tensorboard(memory=self.memory, **kwargs),
lambda **kwargs: analyze_metric(memory=self.memory, **kwargs),
lambda **kwargs: check_container_health(memory=self.memory, **kwargs),
lambda **kwargs: restart_container(memory=self.memory, **kwargs),
lambda **kwargs: modify_config(memory=self.memory, **kwargs),
lambda **kwargs: write_memory(memory=self.memory, **kwargs)
]
# Create the prompt template
prompt = PromptTemplate.from_template(PROMPT)
agent = create_react_agent(
llm=self.llm,
tools=tools,
prompt=prompt
)
# Create agent executor with memory
return AgentExecutor(
agent=agent,
tools=tools,
memory=self.memory,
verbose=True,
max_iterations=15,
handle_parsing_errors=True,
return_intermediate_steps=True
)
def run_automation_cycle(self):
"""Execute the full automation cycle step by step"""
write_memory(
entry="Automation cycle started",
category="SYSTEM",
memory=self.memory
)
try:
agent = self.create_agent()
# Define the workflow as individual steps
workflow_steps = [
"Read preferences from preferences.md to capture thresholds and settings",
"Check TensorBoard at the specified URL and capture a screenshot",
"Analyze validation loss, training loss, and accuracy from the screenshot",
"Check Docker container health for the training container",
"Restart unhealthy containers if needed",
"Adjust hyperparameters according to preferences and restart container if necessary",
"Write all observations and actions to memory"
]
# Execute each step individually
for step in workflow_steps:
result = agent.invoke({"input": step})
# Write step output to memory
if result.get("output"):
memory_summary = f"Step: {step}\nOutput: {result['output']}"
write_memory(entry=memory_summary, category="STEP", memory=self.memory)
write_memory(
entry="Automation cycle completed successfully",
category="SYSTEM",
memory=self.memory
)
return result
except Exception as e:
error_msg = f"Automation cycle failed: {str(e)}"
write_memory(entry=error_msg, category="ERROR", memory=self.memory)
raise
def main():
try:
automation = ExperimentAutomation(openai_key=os.environ["OPENAI_API_KEY"])
result = automation.run_automation_cycle()
if result.get('output'):
print(f"\nFinal Output:\n{result['output']}")
if result.get('intermediate_steps'):
print(f"\nSteps Executed: {len(result['intermediate_steps'])}")
print("\n✓ Automation cycle completed successfully")
except Exception as e:
print(f"\n✗ Automation failed: {e}")
write_memory(entry=f"Critical failure: {str(e)}", category="ERROR")
import sys
sys.exit(1)
if __name__ == "__main__":
main()
Maintenant que nous avons notre agent et nos outils, discutons de la manière dont nous exprimons réellement notre intention en tant que chercheur – la pièce la plus importante.
Définir le comportement et les préférences avec le langage naturel
Comme décrit, définir ce que nous recherchons lorsque nous démarrons une expérience est essentiel pour obtenir le comportement correct d’un agent.
Bien que les modèles de raisonnement par images aient parcouru un certain chemin et disposent d’une bonne part de contexte, ils ont encore du chemin à parcourir avant de pouvoir comprendre à quoi ressemble une bonne courbe de perte de politique dans l’optimisation hiérarchique des politiques, ou à quoi devrait ressembler la perplexité du livre de codes dans un contexte d’optimisation de politique hiérarchique. Auto-encodeur variationnel quantifié vectorielquelque chose que j’ai optimisé au cours de la semaine dernière.
Pour cela, nous initialisons tout raisonnement automatisé avec un preferences.md.
Commençons par quelques paramètres généraux
# Experiment Preferences
This file defines my preferences for this experiment.
The agent should always read this first before taking any action.
---
## General Settings
- experiment_name: vqvae
- container_name: vqvae-train
- tensorboard_url: http://localhost:6006
- memory_file: memory.md
- maximum_adjustments_per_run: 4
---
## More details
You can always add more sections here. The read_preferences task will parse
and reason over each section.
Maintenant, définissons les métriques intéressantes. Ceci est particulièrement important dans le cas du raisonnement visuel.
Dans le document de démarque, définissez yaml blocs qui seront analysés par l’agent à l’aide du read_preferences outil. L’ajout de ce morceau de structure est utile pour utiliser les préférences comme arguments pour d’autres outils.
```yaml
metrics:
- name: perplexity
pattern: should remain high through the course of training
restart_condition: premature collapse to zero
hyperparameters: |
if collapse, increase `perplexity_weight` from current value to 0.2
- name: prediction_loss
pattern: should decrease over the course of training
restart_condition: increases or stalls
hyperparameters: |
if increases, increase the `prediction_weight` value from current to 0.4
- name: codebook_usage
pattern: should remain fixed at > 90%
restart_condition: drops below 90% for many epochs
hyperparameters: |
decrease the `codebook_size` param from 512 to 256.
```
L’idée clé est que le preferences.md devrait fournir suffisamment de détails structurés et descriptifs l’agent peut donc :
Comparez son analyse à votre intentionpar exemple, si l’agent voit une perte de validation = 0,6 mais que les préférences disent val_loss_threshold should be 0.5il sait quelle doit être l’action corrective
Lire les seuils et contraintes (YAML ou valeur-clé) pour les métriques, les hyperparamètres et la gestion des conteneurs.
Comprendre l’intention ou les modèles d’intention décrit dans des sections lisibles par l’homme, comme « n’ajuster le taux d’apprentissage que si la perte de validation dépasse le seuil et que la précision stagne ».
Câblage du tout ensemble
Maintenant que nous avons une expérience conteneurisée + un agent, nous devons planifier l’agent. C’est aussi simple que d’exécuter le processus d’agent via un cron tâche. Cela exécute notre agent une fois par heure, offrant un compromis entre le coût (en jetons) et l’efficacité opérationnelle.
0 * * * * /usr/bin/python3 /path/to/agent.py >> /var/log/agent.log 2>&1
J’ai constaté que cet agent n’a pas besoin du dernier modèle de raisonnement et fonctionne bien avec les générations précédentes d’Anthropic et OpenAI.
Conclusion
Si le temps de recherche est limité, il devrait être consacré à la recherche et non à des expériences de surveillance.
Votre agent doit gérer la surveillance, les redémarrages et les ajustements des paramètres sans supervision constante. Lorsque la difficulté disparaît, il ne reste plus que le travail proprement dit : formuler des hypothèses, concevoir de meilleurs modèles et tester des idées importantes.
Espérons que cet agent vous libérera un peu pour imaginer la prochaine grande idée. Apprécier.
Références
Müller, T., Smith, J. et Li, K. (2023). LangChain : un framework pour développer des applications avec de grands modèles de langage. Dépôt GitHub. https://github.com/hwchase17/langchain
OpenAI. (2023). Documentation de l’API OpenAI. https://platform.openai.com/docs



