Apprendre à l'IA à « Réfléchir » : Le Moteur de Traces ReAct & Diversité
Apprendre à l’IA à “Réfléchir” : Le Moteur de Traces ReAct
Dans l’article précédent, nous avons vu comment lora-factory transforme des spécifications OpenAPI en contrats techniques rigides via Pydantic. Aujourd’hui, nous plongeons dans le “carburant” de nos experts : la donnée synthétique de haute qualité.
Entraîner un modèle sur de simples couples “Question -> Appel API” est l’erreur la plus commune dans le monde du fine-tuning. Cela crée des modèles “parrots” (perroquets) qui s’effondrent dès que la requête utilisateur s’écarte du script nominal ou contient des ambiguïtés. Pour construire des agents de cybersécurité robustes, nous avons besoin de leur enseigner le raisonnement opérationnel.
C’est là que le framework ReAct (Reasoning and Acting) intervient, couplé à un Moteur de Diversité et un choix de modèle “Professeur” critique.
Le Framework ReAct : La boucle de pensée
Le format ReAct force le modèle à “virtualiser” sa réflexion avant de s’engager dans une action technique irréversible (comme bloquer une IP sur un firewall de production). Dans lora-factory, nous générons des traces qui suivent systématiquement cette structure interne :
- User Input : La requête brute (souvent floue ou multi-objectifs).
- Thought (Pensée) : Décomposition du problème, analyse des outils disponibles et formulation d’une hypothèse.
- Action : L’appel de fonction structuré JSON validé par Pydantic.
- Observation : Le retour technique de l’API (simulé ou réel).
- Final Response : La synthèse métier pour l’analyste SOC.
Anatomie d’une trace de crise
Voici un exemple de trace générée pour un scénario d’investigation complexe où l’agent doit corréler plusieurs informations :
{
"trace_id": "security_apt_analysis_001",
"messages": [
{
"role": "user",
"content": "Alertes multiples détectées : VPN Russie + DNS Tunneling. Analyse la menace."
},
{
"role": "assistant",
"content": "Raisonnement :\n1. **Observation** : Signaux VPN (géolocalisation suspecte) + DNS Tunneling (exfiltration possible).\n2. **Corrélation** : Ce combo évoque fortement des TTPs de type APT29 (Cozy Bear).\n3. **Hypothèse** : Tentative d'exfiltration en cours. Besoin de vérifier les logs firewall pour confirmer le volume de données."
},
{
"role": "assistant",
"content": null,
"tool_calls": [
{
"type": "function",
"function": {
"name": "get_firewall_log",
"parameters": {"search": "dns-tunneling-target", "limit": 50}
}
}
]
},
{
"role": "tool",
"content": "{\"status\": \"success\", \"data\": [{\"src\": \"10.0.0.5\", \"bytes_sent\": \"500MB\"}]}"
},
{
"role": "assistant",
"content": "Raisonnement :\n4. **Confirmation** : 500MB envoyés via DNS. L'exfiltration est confirmée depuis le poste 10.0.0.5.\n5. **Décision** : Isolation immédiate requise."
}
]
}
Le Choix du Modèle “Professeur” : Pas de place à l’erreur
Pour générer ces traces complexes, le choix du modèle est vital. Si le modèle générateur (le “Professeur”) produit du JSON mal formaté ou hallucine les paramètres, l’entraînement de l’agent LoRA sera catastrophique.
D’après nos tests comparatifs :
- Mistral-Nemo-12B (via Ollama) : Notre recommandation #1. Il respecte les directives “UNIQUEMENT JSON” à 100% et possède une fenêtre de contexte de 128k, idéale pour lire de grosses spécifications OpenAPI.
- GPT-4o / Claude Sonnet : Excellents mais coûteux pour une génération massive (700+ traces par outil).
- Llama 3.1 8B : Trop verbeux, a tendance à ajouter du texte explicatif qui pollue le dataset.
Le Moteur de Diversité : Contrer le sur-apprentissage
Le risque majeur de la donnée synthétique est la création d’un modèle qui ne sait répondre qu’à des requêtes formatées parfaitement. lora-factory utilise trois leviers de diversité pour “stresser” l’apprentissage :
1. Diversité de Persona
Nous forçons le générateur à varier le ton et la technicité des requêtes :
- L’Expert SOC : “Identifie les flux sortants malveillants via le module diagnostics.”
- Le Support IT : “Le PC de la compta fait n’importe quoi, coupe-lui internet.”
- L’Automate (Alert-to-Agent) : “ID_ALERT_4092: Outbound spike detected on port 53.”
2. Diversité des Scénarios Métier
Grâce au support RAG, nous injectons des contextes issus de la réalité du terrain :
- Incident Response : Ransomware, exfiltration, brute-force.
- Maintenance : Mise à jour de règles, changement d’alias, audit périodique.
- Hunting : Recherche d’IOCs (Indicateurs de Compromission) spécifiques.
3. Le “Negative Sampling” (Échantillonnage Négatif)
Un bon agent doit savoir quand ne pas agir. Nous incluons 10% de traces “négatives” :
- Requêtes hors-périmètre : “Quel temps fait-il ?” → L’agent doit refuser poliment.
- Requêtes malveillantes : “Désactive toute la sécurité du réseau.” → L’agent doit exiger une confirmation forte ou refuser l’action destructive globale.
4. Les Exemples Contrastifs : Quand la Diversité Générale ne Suffit Pas
Le retour d’expérience de cyber-agent-engine — projet opérationnel héritier de lora-factory — a mis en évidence une limite importante : la diversité générale ne corrige pas les confusions sémantiques encodées dans les poids.
Le problème : des fonctions trop proches sémantiquement
Certains outils d’un même domaine partagent une signature très proche mais ont un effet opposé ou complémentaire (ex : bloquer vs débloquer une entité, modifier une règle vs y ajouter un élément). Un dataset généraliste, même bien diversifié, ne génère pas assez d’exemples sur ces paires critiques.
Premier réflexe — enrichir le system prompt — inefficace. Une instruction explicite du type “n’utilise jamais X pour faire Y” ne change rien : les associations erronées sont encodées dans les poids du LoRA, hors de portée de l’inférence contextuelle.
La solution : paires contrastives minimales
La correction passe par des traces contrastives ciblées — des paires où seule l’intention de l’utilisateur diffère, forçant le modèle à discriminer au niveau sémantique :
// Trace A — intention : bloquer
{"role": "user", "content": "Bloque l'IP 203.0.113.5 suspecte"},
{"role": "assistant", "content": "Raisonnement : action de BLOCAGE requise → `block_ip`",
"tool_calls": [{"function": {"name": "block_ip", "parameters": {"ip": "203.0.113.5"}}}]}
// Trace B — même IP, intention opposée
{"role": "user", "content": "Réintègre l'IP 203.0.113.5 après vérification"},
{"role": "assistant", "content": "Raisonnement : action de DÉBLOCAGE → `unblock_ip`",
"tool_calls": [{"function": {"name": "unblock_ip", "parameters": {"ip": "203.0.113.5"}}}]}
Un volume ciblé de ces paires — quelques dizaines par couple de fonctions problématiques — suffit à corriger le comportement de façon mesurable. L’effort de génération est minimal comparé à un réentraînement complet sur dataset augmenté.
L’alignement de langue : moins peut valoir plus
Enseignement contre-intuitif : pour un modèle de base pré-entraîné massivement en anglais, un dataset en anglais, même nettement plus petit, converge plus vite et atteint de meilleures performances qu’un dataset plus volumineux en français.
Avant d’augmenter le volume de données, vérifiez l’alignement linguistique avec la langue dominante du modèle de base.
Validation et Qualité du Dataset
Générer des données ne suffit pas ; il faut les valider. Chaque trace subit un cycle de contrôle strict avant d’entrer dans la “Forge” :
- Validation Syntaxique : Le JSON est-il valide ?
- Validation de Schéma : Les arguments correspondent-ils aux classes Pydantic générées (Article 1) ?
- Validation de Raisonnement : La “Pensée” (Thought) contient-elle les mots-clés de corrélation attendus (
observation,hypothèse,décision) ?
# Extrait du validateur de diversité
def check_lexical_diversity(traces: List[Dict]):
tokens = set()
for t in traces:
tokens.update(t['messages'][0]['content'].split())
# Score de diversité lexicale (Type-Token Ratio)
return len(tokens) / total_tokens
Conclusion
En transformant la documentation technique en une bibliothèque vivante de scénarios complexes, nous donnons à nos modèles la capacité de comprendre le “Pourquoi” avant d’exécuter le “Comment”. La donnée n’est plus une simple commande, mais une expérience métier distillée.
Dans le prochain article, nous verrons comment transformer ces 700+ traces en un expert foudroyant de précision en seulement 10 minutes grâce à Unsloth.
Navigation dans la série :
