Pipelines de Code Automatisés
Mis à jour le 29 juillet 2026
Automatiser le développement avec Codestral et Devstral
Jusqu’ici, chaque outil de Mistral AI a été présenté seul et devant un humain. Leur intérêt véritable apparaît quand on les enchaîne : Codestral, Devstral et Codestral Embed forment ensemble une pipeline de développement automatisée, capable de rechercher, générer et revoir du code sans intervention manuelle à chaque étape.
Architecture d’une pipeline de code
Une pipeline complète se décompose en trois étapes, chacune confiée au modèle qui excelle sur ce point précis.
- Code Search — trouver le code pertinent dans le codebase (Codestral Embed)
- Code Generation — générer ou modifier du code (Codestral ou Devstral)
- Code Review — vérifier et valider les changements (Devstral)
Le flux de données se lit de haut en bas, chaque bloc consommant la sortie du précédent.
Requête utilisateur
|
[Codestral Embed] -> Fichiers pertinents
|
[Codestral / Devstral] -> Code généré/modifié
|
[Devstral] -> Review automatique
|
Pull Request / Commit
Étape 1 : Code Search avec Codestral Embed
Générer du code sans connaître l’existant produit du code qui ne ressemble à rien de ce que fait déjà le projet. La première étape consiste donc à retrouver les fichiers concernés, en s’appuyant sur l’index d’embeddings construit à la leçon précédente. La fonction ci-dessous transforme la description de la tâche en vecteur, la compare à chaque fichier indexé, et retourne les cinq plus proches.
from mistralai import Mistral
import numpy as np
client = Mistral(api_key=os.environ["MISTRAL_API_KEY"])
def rechercher_contexte(description_tache: str, index_codebase: list) -> list:
"""Trouve les fichiers pertinents pour une tâche donnée."""
response = client.embeddings.create(
model="codestral-embed-latest",
inputs=[description_tache],
)
vecteur = np.array(response.data[0].embedding)
scores = []
for fichier in index_codebase:
vec_fichier = np.array(fichier["embedding"])
score = np.dot(vecteur, vec_fichier) / (
np.linalg.norm(vecteur) * np.linalg.norm(vec_fichier)
)
scores.append((fichier, score))
scores.sort(key=lambda x: x[1], reverse=True)
return [f for f, s in scores[:5]]
Étape 2 : Code Generation avec Codestral
Le contexte trouvé, Codestral peut générer. Le résultat vaudra ce que vaut la présentation de ce contexte : les fichiers retrouvés sont concaténés dans le message système, accompagnés d’une consigne explicite de respect des conventions existantes. Le temperature=0.1 maintient la sortie proche du déterminisme, ce qui est souhaitable quand le code produit doit s’intégrer à un projet plutôt que surprendre son auteur.
def generer_code(tache: str, contexte: list[dict]) -> str:
"""Génère du code en tenant compte du contexte existant."""
fichiers_contexte = "\n\n---\n\n".join([
f"# {f['chemin']}\n{f['contenu']}"
for f in contexte
])
response = client.chat.complete(
model="codestral-latest",
messages=[
{
"role": "system",
"content": f"""Vous êtes un développeur senior. Voici le code existant du projet :
{fichiers_contexte}
Respectez les conventions de code existantes (nommage, style, patterns)."""
},
{
"role": "user",
"content": tache
}
],
temperature=0.1,
max_tokens=2000,
)
return response.choices[0].message.content
Étape 3 : Code Review avec Devstral
Le contrôle vient en dernier. Devstral reçoit l’avant, l’après et la description de la tâche, et rend son verdict dans un format JSON imposé — un choix déterminant, car une review en prose libre n’est pas exploitable par du code en aval, alors qu’un champ approuve booléen permet de décider automatiquement de la suite. Les catégories demandées séparent volontairement les problèmes bloquants, les suggestions d’amélioration et les questions de sécurité, qui n’appellent pas le même traitement.
def reviewer_code(code_original: str, code_modifie: str, description: str) -> dict:
"""Review automatique du code généré."""
response = client.chat.complete(
model="devstral-small-latest",
messages=[
{
"role": "system",
"content": """Vous êtes un reviewer de code senior. Analysez le diff et retournez un JSON :
{
"approuve": true/false,
"problemes": ["liste des problèmes trouvés"],
"suggestions": ["liste des améliorations possibles"],
"securite": ["problèmes de sécurité éventuels"]
}"""
},
{
"role": "user",
"content": f"Tâche : {description}\n\nCode original :\n{code_original}\n\nCode modifié :\n{code_modifie}"
}
],
temperature=0,
)
return response.choices[0].message.content
Pipeline complète : du ticket à la PR
Les trois fonctions s’assemblent alors en un enchaînement unique, qui part d’un ticket et rend une modification déjà relue. Gardez les print intercalés : sur une pipeline automatisée, la trace de ce qui a été trouvé, généré et relu reste votre seul moyen de comprendre après coup pourquoi le résultat vous a déplu.
def pipeline_ticket_to_code(ticket: str, codebase_index: list) -> dict:
"""Pipeline complète : ticket -> code -> review."""
# 1. Recherche contextuelle
fichiers_pertinents = rechercher_contexte(ticket, codebase_index)
print(f"Fichiers trouvés : {[f['chemin'] for f in fichiers_pertinents]}")
# 2. Génération de code
code_genere = generer_code(ticket, fichiers_pertinents)
print(f"Code généré : {len(code_genere)} caractères")
# 3. Review automatique
review = reviewer_code(
code_original=fichiers_pertinents[0]["contenu"],
code_modifie=code_genere,
description=ticket,
)
print(f"Review : {review}")
return {
"ticket": ticket,
"fichiers_modifies": fichiers_pertinents,
"code": code_genere,
"review": review,
}
Intégration CI/CD
Cette mécanique prend tout son sens branchée sur votre CI. Un workflow GitHub Actions déclenché à l’ouverture et à chaque mise à jour d’une pull request suffit à faire tourner la review sur chaque changement proposé, sans que personne ait à y penser.
name: AI Code Review
on:
pull_request:
types: [opened, synchronize]
jobs:
ai-review:
runs-on: ubuntu-latest
steps:
- uses: actions/checkout@v4
- name: Run AI Review
env:
MISTRAL_API_KEY: $\{{ secrets.MISTRAL_API_KEY }}
run: |
python scripts/ai_review.py --pr $\{{ github.event.pull_request.number }}
Le script appelé récupère le diff, passe chaque fichier modifié à reviewer_code, et ne commente la PR que lorsque la review n’approuve pas. Cette condition est essentielle : un bot qui commente tout devient un bruit que l’équipe apprend à ignorer en quelques jours.
# scripts/ai_review.py
def review_pull_request(pr_number: int):
"""Review automatique d'une PR avec Devstral."""
# 1. Récupérer le diff de la PR
diff = obtenir_diff_pr(pr_number)
# 2. Analyser chaque fichier modifié
for fichier in diff.fichiers:
review = reviewer_code(
code_original=fichier.avant,
code_modifie=fichier.apres,
description=diff.titre,
)
# 3. Poster un commentaire sur la PR
if not review["approuve"]:
poster_commentaire_pr(pr_number, fichier.chemin, review)
Les déclinaisons courantes en production
Les équipes qui exploitent ce schéma le déclinent sur quelques usages récurrents. La génération automatique de tests, d’abord : à chaque nouveau fichier, la pipeline produit les tests correspondants, ce qui déplace la corvée sans supprimer la relecture. La documentation continue ensuite, où les docstrings sont générées et mises à jour au fil des commits plutôt qu’à l’occasion d’un audit. La détection de régressions, où Devstral analyse les diffs à la recherche d’effets de bord probables. Et la migration de code, qui automatise la conversion entre frameworks ou entre versions — le terrain où le gain de temps est le plus net, parce que la transformation est répétitive et le résultat vérifiable par les tests existants.
Une réserve, pour finir, qui vaut pour les quatre : la review automatique ne remplace pas la review humaine. Elle attrape les oublis mécaniques et laisse à vos développeurs le jugement sur ce qui compte vraiment.
Points clés à retenir
- Une pipeline de code IA combine recherche (Embed), génération (Codestral), et review (Devstral)
- Codestral Embed trouve le contexte, Codestral génère, Devstral vérifie
- L’intégration CI/CD permet d’automatiser les reviews et la génération de tests
- Le pattern recherche -> génération -> review est applicable à de nombreux workflows
- La review automatique ne remplace pas la review humaine, mais la complète