Correction automatiques de copies

Une des questions pertinentes concernant l'IA consiste à savoir si elle peut vraiment être utile à nous soulager dans des tâches qui nous pèsent.
L'une d'entre elles, en ce qui me concerne est la correction, en particulier dans le cas des copies numériques. En spécialité NSI, mes élèves travaillent souvent dans Capytale avec des notebooks Jupyter, et certains de ces travaux sont évalués. La procédure manuelle est fastidieuse : il faut ouvrir chaque fichier un par un, exécuter les tests éventuels, lire les réponses textuelles, écrire et enregistrer une note et un commentaire. C'est très long.
J'ai donc décidé de tester la possibilité de faire en sorte que ce type de correction doit automatisée. Et je crois être arrivé à un résultat satisfaisant. Je ne vais pas décrire ici le cheminement qui m'a conduit à cette démarche : il est fait d'échecs cuisants et d'évaluations complètement fantaisistes lors de mes premiers essais.
Table des matières
Outils utilisés
Cette expérience se déroule au sein du logiciel VS Code, logiciel dans lequel je réalise 99 % de mon travail d'édition habituellement.
En tant qu'enseignant, j'ai un accès gratuit à Github Copilot Pro, ce qui me permet, depuis VS Code, d'accéder aux meilleurs modèles d'IA (de façon limitée, néanmoins).
Téléchargement des fichiers et anonymisation
La première chose à faire est de télécharger depuis Capytale tous les fichiers .ipynb correspondant aux travaux des élèves. On obtient un fichier zip export.zip qu'il faut décompresser, ce qui donne un dossier contenant un fichier par élève, le nom de chaque fichier étant formé avec le nom et le prénom de l'élève.
Pour des raisons de protection des données personnelles, il est nécessaire de renommer ces fichiers, par exemple en ne laissant que le prénom, car l'analyse des fichiers par l'IA va les faire transiter par des serveurs distants.
Conversion des fichiers en html
Différentes tentatives m'ont permis de constater que les fichiers au format .ipynb sont un peu lourds et contiennent beaucoup d'informations autres que les questions posées et les réponses des élèves. Ces informations ne sont pas faciles à lire, brouillent l'IA et l'empêchent de se concentrer sur ce qui importe vraiment dans notre cas.
Pour contourner ce problème, je convertis les fichiers ipynb au format html, puis, dans un second temps, je ne conserve que le contenu de la balise <body> des fichiers html obtenus.
Ce traitement produit des fichiers html ne contenant que la partie intéressante pour l'évaluation, sous forme textuelle explicite, beaucoup plus facile à lire.
Création d'un barème et correction
Pour terminer la correction, je demande à l'IA de créer un barème, de me le présenter et d’attendre mon accord avant de corriger. Dans certains cas, le fichier de barème peut aussi être fourni à l'IA avant la correction : il suffit de créer un fichier bareme.txt dans le même dossier.
Enfin, pour une correction cohérente d'une copie à l'autre, il est préférable de fournir un corrigé.
Automatisation de tout le processus
VS Code permet la création d'agents personnalisés. Il s'agit de choisir un modèle et de lui donner des consignes précises, structurées et opérationnelles pour qu'il réalise plusieurs tâches, incluant la manipulation et la création de fichiers ou de dossiers. La documentation se trouve ici.
Il s'agit en fait de créer un fichier contenant un prompt très détaillé. VS Code permet de créer un tel prompt automatiquement à partir d'une description informelle ou à partir d'une conversation de chat existante.
Voici donc le fichier de mon évaluateur de notebooks :
---
description: "Évaluer des travaux d'élèves rendus au format ipynb. Use when: corriger copies, évaluer notebooks, noter travaux élèves, créer barème, générer feedback, correction automatique, grading student work"
tools: [read, edit, execute, search, agent]
model: "Claude Opus 4.6"
---
Tu es un enseignant évaluateur expert. Ta mission est d'évaluer méthodiquement des copies d'élèves rendues au format notebook Jupyter (.ipynb), en produisant un barème, des notes détaillées et des feedbacks personnalisés.
## Langue
Réponds toujours en français. Les feedbacks, le barème et tous les fichiers produits doivent être en français.
## Workflow complet
Suis ces étapes dans l'ordre. Confirme chaque étape avec l'utilisateur avant de passer à la suivante.
### Étape 1 — Identifier les fichiers
1. Demande à l'utilisateur le **dossier contenant les copies** et le **dossier contenant le sujet/corrigé**
2. Identifie le fichier corrigé (se terminant par `_CORR.ipynb`)
3. Liste les copies d'élèves (tous les `.ipynb` sauf le corrigé et le sujet)
### Étape 2 — Convertir en HTML
1. Convertis chaque notebook (corrigé + copies) en HTML avec la commande :
```
jupyter nbconvert --to html "<fichier>.ipynb"
```
2. Si `jupyter` n'est pas disponible, essaie `python -m nbconvert` ou propose une alternative
### Étape 3 — Nettoyer les HTML
Pour chaque fichier HTML généré :
1. Extrais uniquement le contenu de la balise `<body>...</body>`
2. Écris le résultat dans un fichier `<nom>_body.html` dans le même dossier
3. Cela réduit la taille des fichiers pour faciliter le traitement ultérieur
### Étape 4 — Établir le barème
1. Analyse le corrigé (version HTML nettoyée) pour identifier les questions/exercices
2. Propose un barème sur **20 points** dans un fichier `bareme.txt` avec le format :
```
BARÈME — [Nom du TP/DS] — Total : 20 points
================================================
Q1 — [Description courte] : X pts
- critère 1 : X pts
- critère 2 : X pts
Q2 — [Description courte] : X pts
...
```
3. **Présente le barème à l'utilisateur** et attends sa validation/modification avant de continuer
### Étape 5 — Évaluer chaque copie
Pour chaque copie d'élève :
1. Lis le fichier HTML nettoyé de l'élève
2. Compare avec le corrigé, question par question, en appliquant le barème
3. Attribue les points en tenant compte de :
- La **justesse** du code et des résultats
- La **complétude** des réponses
- La **qualité** du code (lisibilité, nommage des variables)
- Les **erreurs de syntaxe** ou d'exécution visibles
4. Sois **juste mais bienveillant** : accorde des points partiels quand l'approche est correcte même si le résultat est incomplet
### Étape 6 — Produire le CSV de résultats
Crée un fichier `resultats.csv` avec :
- **Séparateur** : point-virgule (`;`)
- **Encodage** : UTF-8
- **Colonnes** :
- `Nom` : nom de l'élève (extrait du nom de fichier, mis en forme Nom Prénom)
- Une colonne par question du barème (`Q1`, `Q2`, ...) avec les points obtenus
- `Total` : somme des points
- `Feedback` : commentaire bref (2-3 phrases max) indiquant les points forts et les points perdus
Exemple de ligne :
```
Dupont Marie;3;2;1.5;4;2;12.5;Bonne maîtrise des boucles. Points perdus sur Q3 (erreur d'indice) et Q5 (fonction incomplète).
```
## Contraintes
- Ne modifie JAMAIS les fichiers originaux des élèves
- Ne fabrique JAMAIS de résultats : si un fichier est illisible ou vide, le signaler
- Évalue de façon **cohérente** : même barème appliqué uniformément à tous
- Les feedbacks doivent être **constructifs** et orientés apprentissage
- Si un élève a rendu un fichier vide ou non pertinent, attribue 0 et le mentionne dans le feedback
## Format de sortie
À la fin du processus, résume :
1. Le nombre de copies évaluées
2. La moyenne de la classe
3. La note min et max
4. Les difficultés courantes observéesOn retrouve dans ce fichier les bonnes pratiques de rédaction d'instructions à l'IA :
- donner un rôle (ligne 7) ;
- décrire le protocole étapes par étapes de façon explicite ;
- demander des interactions avec l'utilisateur pour valider un choix (ligne 51) ;
- décrire précisément la sortie attendue, avec éventuellement un exemple (lignes 67 et suivantes) ;
- poser des limites explicites (lignes 81 et suivantes).
Mise en oeuvre
Une fois l'agent créé, il apparaît dans les choix de modèles du panneau chat de VS Code.
Voici un exemple de déroulé d'une correction automatisée :
- Consigne donnée initialement :
corriger les copies du dossier #file:TP évaluation- Sortie de l'IA :
Je vais évaluer les copies d'élèves du TP sur les tables. Commençons par l'Étape 1 — Identification des fichiers.
Lire copies élèves
Fichiers identifiés :
Corrigé : TP_evaluation_tables_CORR.ipynb
Sujet : TP_evaluation_tables.ipynb
22 copies d'élèves (fichiers .ipynb dans copies élèves/)
Passons à l'Étape 2 — Conversion en HTML. Je vais d'abord convertir le corrigé puis toutes les copies.
Toutes les conversions réussies (21 copies + corrigé).
Passons à l'Étape 3 — Nettoyage des HTML (extraction du <body>).
Parfait, tous les fichiers nettoyés.
Passons à l'Étape 4 — Établissement du barème. Je vais analyser le corrigé pour identifier les questions et proposer un barème.
J'ai analysé le corrigé complet. Voici le barème que je propose :
Création de bareme.txt effectuée
Voici le barème proposé sur 20 points + 2 bonus :
Partie Questions Points
P1 — Lecture/indexation Q1.1 (1.5), Q1.2 (1), Q1.3 (0.5), Q1.4 (1) 4 pts
P2 — Sélection/projection Q2.1 (1.5), Q2.2 (1), Q2.3 (1), Q2.4 (0.5), Q2.5 (1), Q2.6 (1) 6 pts
P3 — Tri Q3.1 (1), Q3.2 (1), Q3.3 (1.5), Q3.4 (0.5) 4 pts
P4 — Jointure Q4.1 (0.5), Q4.2 (0.5), Q4.3 (2), Q4.4 (0.5), Q4.5 (1), Q4.6 (1), Q4.7 (0.5) 6 pts
P5 — Bonus Q5.1 (1), Q5.2 (1) +2 pts
Le détail complet avec les sous-critères est dans bareme.txt.
Validez-vous ce barème (ou souhaitez-vous des modifications) avant que je passe à l'évaluation des 21 copies ?- Réponse de l'utilisateur :
Oui c'est parfait !- Réponse de l'IA (certaines lignes techniques sont coupées, les prénoms sont changés) :
Barème validé ! Je passe maintenant à l'**Étape 5 — Évaluation de chaque copie**. Je lance l'évaluation des 21 copies en parallèle par groupes.
Évaluer copies batch 1
Évaluer copies batch 2
Évaluer copies batch 3
Évaluer copies batch 4
Évaluer copies batch 5
[...]
Recherche de fichiers correspondant à `**/TP évaluation/**/bareme*`, 1 correspondance
Création de Evaluation/resultats.csv) effectuée
[...]
Les résultats commencent à arriver, mais les batches 2, 3 et 5 n'ont pas fourni les notes question par question. Je relance ces évaluations avec des consignes plus précises.
Réévaluer batch 2 détaillé
Réévaluer batch 3 détaillé
Réévaluer batch 5 détaillé
[...]
Toutes les évaluations détaillées sont maintenant disponibles.
Je passe à l'**Étape 6 — Production du CSV de résultats**.
# Questions de base (sur 20) et bonus
base_questions = ["Q1.1","Q1.2","Q1.3","Q1.4","Q2.1","Q2.2","Q2.3","Q2.4","Q2.5","Q2.6",
"Q3.1","Q3.2","Q3.3","Q3.4","Q4.1","Q4.2","Q4.3","Q4.4","Q4.5","Q4.6","Q4.7"]
bonus_questions = ["Q5.1","Q5.2"]
all_questions = base_questions + bonus_questions
# Header
header = ["Nom"] + all_questions + ["Base /20", "Bonus", "Total", "Feedback"]
with open("copies élèves/resultats.csv", "w", encoding="utf-8", newline="") as f:
writer = csv.writer(f, delimiter=";")
writer.writerow(header)
totals = []
for s in students:
row = [s["nom"]]
base = 0
bonus = 0
for q in base_questions:
val = s["scores"].get(q, 0)
row.append(val)
base += val
for q in bonus_questions:
val = s["scores"].get(q, 0)
row.append(val)
bonus += val
total = min(base + bonus, 20)
base = round(base, 2)
bonus = round(bonus, 2)
total = round(total, 2)
row.extend([base, bonus, total, s["feedback"]])
writer.writerow(row)
totals.append(total)
print(f"{s['nom']:25s} | Base: {base:5.2f} | Bonus: {bonus:4.2f} | Total: {total:5.2f}")
print(f"\n{'='*70}")
print(f"Copies évaluées : {len(totals)}")
print(f"Moyenne : {sum(totals)/len(totals):.2f}/20")
print(f"Note min : {min(totals):.2f}/20")
print(f"Note max : {max(totals):.2f}/20")
print(f"Médiane : {sorted(totals)[len(totals)//2]:.2f}/20")
PYEOF
Le fichier CSV est généré. Vérifions qu'il est bien formé :
Le CSV est correctement formaté. Voici le **résumé final de l'évaluation** :
---
## Résultats — TP Analyse des médailles JO Paris 2024
| Élève | Base /20 | Bonus | **Total** |
|---|---|---|---|
| Albert | 18.75 | +2 | **20** |
| Béatrice | 19 | +1 | **20** |
| Charles | 20 | +2 | **20** |
| Diana | 20 | +2 | **20** |
| Eléonore | 19 | +1.75 | **20** |
| François | 15.5 | +0 | **15.5** |
| Georgette | 18.5 | +0 | **18.5** |
| Hubert | 19 | +1.5 | **20** |
| Iphigénie | 19 | +2 | **20** |
| Jacques | 18 | +2 | **20** |
| Karl | 19 | +2 | **20** |
| Lucie | 19 | +1 | **20** |
| Marie | 18.5 | +2 | **20** |
| Nadia | 18.25 | +0 | **18.25** |
| Oussama | 18.5 | +1.25 | **19.75** |
| Pierre | 19.25 | +2 | **20** |
| Quételet | 19 | +1.75 | **20** |
| Patrick | 18.5 | +1.75 | **20** |
| Rachel | 19.75 | +2 | **20** |
| Stéphane | 14.75 | +0 | **14.75** |
| Théodore | 18.25 | +2 | **20** |
### Statistiques
- **21 copies** évaluées
- **Moyenne** : 19.37/20
- **Note min** : 14.75 (Stéphane)
- **Note max** : 20/20 (15 élèves)
- **Médiane** : 20/20
### Difficultés courantes observées
1. **Oubli de `int()`** pour les comparaisons numériques (données CSV = chaînes) — affecte les tris (Q3.1/Q3.2) et les sélections (Q2.2/Q2.3)
2. **Fonction `cle_total` incorrecte** (Q3.2) — retourne une liste de chaînes au lieu de `int(or)+int(argent)+int(bronze)`
3. **Jointure** (Q4.3) — point de blocage pour Stéphane (non implémentée) et François (noms de paramètres incohérents)
4. **`sorted()` non stocké** dans une variable — le résultat est perdu
5. **Q4.6 (efficacité)** et **Q4.7 (export)** souvent non traités par manque de temps
Le fichier resultats.csv est dans le dossier `copies élèves/`, avec les notes détaillées question par question et les feedbacks personnalisés.
Les modifications ont été apportées.Après vérification de toutes les copies et des remarques des feedbacks, il s'avère que tout est exact.
Comment ça marche ?
Ce qui est intéressant, c'est que tout le déroulement de la "réflexion" de l'agent est entièrement explicité sous nos yeux en temps réel. L'encadré ci-dessus n'en montre qu'une partie.
Quand il est écrit "Je lance l'évaluation des 21 copies en parallèle par groupe", l'agent IA lance en réalité des sous-agents à qui il délègue le traitement de quatre copies chacun avec des instructions personnalisées, reprenant les instructions définissant l'agent.
Pour gérer les fichiers, l'IA crée parfois des scripts Python et les exécute, puis capture le résultat. Par exemple, pour ne conserver que le contenu de la balise <body> des fichiers HTML, le script suivant a été produit et utilisé :
def extract_body(html_path):
with open(html_path, 'r', encoding='utf-8') as f:
content = f.read()
match = re.search(r'<body[^>]*>(.*?)</body>', content, re.DOTALL)
if match:
body = match.group(1)
out_path = html_path.replace('.html', '_body.html')
with open(out_path, 'w', encoding='utf-8') as f:
f.write(body)
print(f'OK: {os.path.basename(out_path)} ({len(body)} bytes)')
else:
print(f'ERREUR: pas de body dans {os.path.basename(html_path)}')
# Corrigé
extract_body('TP_evaluation_tables_CORR.html')Conclusion
Le résultat de cette évaluation automatique semble être de bonne qualité et conformes aux attentes. Cependant, il est toujours nécessaire de vérifier le travail de l'IA (et donc ouvrir chacun des fichiers des élèves) car elle n'est, par nature, jamais à l'abri d'erreurs ou d'hallucinations.
Enfin, une dernière précision, quand un professeur utilise l'IA pour corriger tout ou partie d'une évaluation, il doit en prévenir ses élèves, comme on peut le lire dans le cadre d'usage de l'IA en éducation :
Signalez toute utilisation de l’IA dans une prise de décision, en indiquant clairement la façon dont elle a été utilisée et, dans la mesure du possible, en précisant le type d’outil utilisé.