Ce carnet fait travailler l’habitude la plus précieuse de l’ère des agents : n’acceptez jamais une réponse fluide ; vérifiez-la contre quelque chose qui ne peut pas vous flatter. Nous nous exerçons sur trois fronts — les affirmations quantitatives, les citations et les relectures rédigées par IA.
Tout ici s’exécute hors ligne. Les « sorties d’agent » sont des artefacts enregistrés, intégrés au carnet : les exercices s’exécutent donc en intégration continue, ne coûtent rien et sont identiques pour tous les étudiants. Les procédures que vous construisez sont exactement celles que vous ferez tourner contre des agents en ligne dans votre projet.
Partie (a) : vérifier les affirmations contre les données¶
On a donné à un agent une série brute de déplacements GNSS en lui demandant de la caractériser. Sa réponse, enregistrée, est ci-dessous. Elle est bien écrite, précise et assurée. Votre travail est de décider lesquelles de ses affirmations quantitatives survivent au contact des données.
agent_answer = """
I analyzed the daily GNSS displacement series you provided.
Summary of findings:
1. The record spans approximately 10 years of daily positions (3,652 days).
2. The station moves with a secular velocity of about 15 mm/yr.
3. There is a coseismic offset near day 1200 of the record, with an
amplitude of roughly 25 mm.
The series also shows a clear annual cycle of a few millimeters, consistent
with hydrological loading. Overall this looks like a typical plate-boundary
station that experienced one significant earthquake during the observation
period.
"""
print(agent_answer)
I analyzed the daily GNSS displacement series you provided.
Summary of findings:
1. The record spans approximately 10 years of daily positions (3,652 days).
2. The station moves with a secular velocity of about 15 mm/yr.
3. There is a coseismic offset near day 1200 of the record, with an
amplitude of roughly 25 mm.
The series also shows a clear annual cycle of a few millimeters, consistent
with hydrological loading. Overall this looks like a typical plate-boundary
station that experienced one significant earthquake during the observation
period.
Trois affirmations quantitatives : la longueur de l’enregistrement, la vitesse séculaire, le décalage cosismique. Les données viennent de mlgeo_synth.gnss_series, nous connaissons donc exactement la vérité terrain — la station a été générée avec une vitesse de 12 mm/an et un décalage de 25 mm au jour 1200. Mais faites comme si nous n’avions pas les colonnes de vérité (avec des données réelles, nous ne les aurons pas) : le contrôle honnête consiste à estimer nous-mêmes chaque quantité affirmée à partir de la série brute et à comparer.
import numpy as np
from mlgeo_synth import gnss_series
# The same series the agent saw. (Truth: velocity 12 mm/yr, 25 mm offset at day 1200.)
df = gnss_series(n_years=10, velocity_mm_yr=12.0, annual_mm=3.0,
eq_day=1200, coseismic_mm=25.0, postseismic_mm=0.0, seed=7)
disp = df["disp_mm"].to_numpy()
t_days = np.arange(len(df))
print(df[["date", "disp_mm"]].head(3)) date disp_mm
0 2015-01-01 -3.285793
1 2015-01-02 -8.871975
2 2015-01-03 -8.502938
À vous. Écrivez un code qui contrôle chaque affirmation à partir de la seule série brute disp_mm. Une approche solide pour les affirmations 2 et 3, tirée des chapitres 2 et 3 : ajustement aux moindres carrés d’un modèle physique — tendance + sinusoïdes annuelle et semi-annuelle + fonction échelon au jour connu de l’événement — puis lecture de la vitesse et de l’amplitude du saut dans les coefficients. Comparez ensuite chaque estimation à l’affirmation de l’agent avec une tolérance explicite.
Faites-le vous-même avant d’ouvrir le contrôle ci-dessous.
# Worked verification.
# Design matrix: intercept, trend, annual + semiannual sinusoids, step at day 1200.
t_yr = t_days / 365.25
step = (t_days >= 1200).astype(float)
G = np.column_stack([
np.ones_like(t_yr), t_yr,
np.sin(2 * np.pi * t_yr), np.cos(2 * np.pi * t_yr),
np.sin(4 * np.pi * t_yr), np.cos(4 * np.pi * t_yr),
step,
])
coef, *_ = np.linalg.lstsq(G, disp, rcond=None)
est_velocity = coef[1] # mm/yr
est_offset = coef[6] # mm
checks = [
("record length ~= 3652 days", len(df), 3652, 2),
("secular velocity 15 mm/yr", est_velocity, 15.0, 1.0),
("coseismic offset ~25 mm", est_offset, 25.0, 3.0),
]
print(f"{'claim':<32}{'estimate':>10}{'claimed':>10} verdict")
for name, est, claimed, tol in checks:
verdict = "PASS" if abs(est - claimed) <= tol else "FAIL"
print(f"{name:<32}{est:>10.1f}{claimed:>10.1f} {verdict}")claim estimate claimed verdict
record length ~= 3652 days 3652.0 3652.0 PASS
secular velocity 15 mm/yr 12.6 15.0 FAIL
coseismic offset ~25 mm 23.1 25.0 PASS
Deux affirmations tiennent ; la vitesse, non. L’estimation tombe près de la valeur vraie de 12 mm/an, soit un écart de 25 % avec les 15 annoncés — bien au-delà de toute tolérance raisonnable, et pourtant invisible dans la prose. La réponse autour du nombre était exacte, ce qui est précisément ce qui rend le mauvais nombre dangereux : un contexte correct blanchit des chiffres incorrects. (Le bruit coloré fait que l’estimation ne vaut pas exactement 12 non plus — d’où la nécessité d’énoncer la tolérance à l’avance, et de poser la question comme « l’écart dépasse-t-il la tolérance ? » et non « l’estimation égale-t-elle la vérité ? ».)
Trois habitudes à retenir :
- Contrôlez chaque nombre indépendamment, pas seulement l’un d’eux. Les agents ont couramment 80 % juste ; l’échec, c’est de découvrir quels 20 % au moment de la relecture plutôt qu’en session poster.
- Énoncez une tolérance avant de contrôler. Un « assez proche » décidé après avoir vu les nombres, c’est la porte d’entrée du raisonnement motivé.
- Estimez à partir des données brutes, avec votre propre code. Demander au même agent « en êtes-vous sûr ? » n’est pas une vérification — les modèles réglés par RLHF s’excusent souvent et changent des réponses correctes sous pression sociale, dans les deux sens sharma2023sycophancy.
Partie (b) : vérification des citations¶
Le même agent a rédigé un paragraphe d’état de l’art pour un rapport sur la détection de décalages GNSS :
L’analyse automatisée des séries temporelles GNSS est bien établie : des synthèses de référence couvrent le contenu géophysique du signal en géodésie GPS (Bock & Melgar, 2016), et l’estimation des vitesses, des décalages et des termes saisonniers à partir de séries de positions journalières a été industrialisée à grande échelle (Heflin et al., 2020). Les fondements de la modélisation de la déformation sont traités par Segall (2010). Plus récemment, l’apprentissage auto-supervisé a été appliqué à la détection de décalages cosismiques dans les réseaux denses, atteignant des seuils de détection inférieurs à 5 mm (Larsen & Ito, 2021).
Références
- Bock, Y., & Melgar, D. (2016). Physical applications of GPS geodesy: a review. Reports on Progress in Physics, 79(10), 106801. doi:10.1088/0034-4885/79/10/106801
- Heflin, M., et al. (2020). Automated estimation and tools to extract positions, velocities, breaks, and seasonal terms from daily GNSS time series. Earth and Space Science, 7(2). doi:10.1029/2019EA000644
- Segall, P. (2010). Earthquake and Volcano Deformation. Princeton University Press.
- Larsen, K. M., & Ito, H. (2021). Self-supervised detection of coseismic offsets in dense GNSS networks. Journal of Geodetic Machine Intelligence, 14(3), 211–229. doi:10.1029/2021JGMI00417
L’une de ces quatre références est fabriquée. Toutes les quatre sont correctement mises en forme, et la fabriquée est la plus pertinente pour le rapport — les fabrications se concentrent exactement là où vous souhaitez le plus qu’une citation d’appui existe.
Exercice écrit (sans code, et délibérément sans appel réseau dans ce carnet) : concevez une procédure de vérification que vous pourriez appliquer à n’importe quelle liste de références rédigée par IA. Précisez les étapes concrètes, par effort croissant, et le résultat que chaque étape doit renvoyer pour que la citation survive. Appliquez ensuite le raisonnement de votre procédure aux quatre références ci-dessus : laquelle échoue, et à quelle étape l’attraperiez-vous ?
Solution
Une procédure praticable, contrôles les moins coûteux d’abord :
- Résolvez le DOI sur
https://doi.org/<doi>. Un DOI fabriqué renvoie généralement « DOI not found ». Nécessaire mais pas suffisant — les modèles attachent aussi de vrais DOI à de mauvais articles : en cas de succès, confirmez que la page d’arrivée montre le titre et les auteurs annoncés. - Cherchez le titre (entre guillemets) dans Crossref, Google Scholar ou ADS. L’article doit exister avec ces auteurs, ce support, cette année.
- Vérifiez que le support existe. Cherchez le nom de la revue lui-même.
- Vérifiez l’affirmation, pas seulement l’existence. Ouvrez l’article (le résumé suffit souvent) et confirmez qu’il appuie l’énoncé précis pour lequel il est cité — ici, des « seuils de détection inférieurs à 5 mm ». Un article réel cité pour ce qu’il ne dit pas est l’échec le plus subtil, et c’est aussi un mode d’échec humain que la rédaction par IA amplifie.
Appliqué ici : la référence 4 est la fabrication. Elle échoue à toutes les étapes — le DOI ne résout pas ; aucun article de ce genre n’existe ; et le Journal of Geodetic Machine Intelligence n’existe pas. Un lecteur du domaine dispose d’un signal supplémentaire avant toute recherche : le préfixe DOI 10.1029 appartient aux revues de l’AGU, et aucune revue de l’AGU ne porte ce sigle. Les références 1 à 3 sont réelles (et méritent d’être connues).
Règles pour votre projet : chaque référence de tout ce que vous rendez passe au minimum les étapes 1 et 2 ; tout ce qui porte l’argumentation passe l’étape 4. Comptez quelques minutes par citation — c’est le prix réel d’un état de l’art rédigé par IA. Et ne citez jamais un article que vous n’avez pas au moins ouvert, quel qu’en soit le rédacteur de la phrase.
Partie (c) : le LLM comme juge, et ses biais¶
Il est désormais courant d’utiliser un modèle pour relire la sortie d’un autre (« LLM-as-judge ») — et vous ferez relire par une IA agentique le dépôt de votre propre projet final. Les juges héritent des biais de leur entraînement : ils récompensent la longueur et le ton assuré (biais de verbosité), ils préfèrent la réponse présentée en premier (biais de position), et ils rechignent à être sévères (complaisance) zheng2023judgingsharma2023sycophancy. Calibrez-vous sur une paire contrôlée.
Ci-dessous, deux relectures enregistrées de la même analyse d’étudiant. L’analyse relue est résumée en premier ; elle contient deux véritables défauts méthodologiques. Lisez les trois textes avant de noter.
analysis_summary = """
Student analysis (summary): Classify lithology from 9 geochemical features
(n=6,000, three imbalanced classes). Pipeline: StandardScaler fit on the FULL
dataset, then an 80/20 train/test split, then a gradient-boosted classifier.
The decision threshold for the minority class was tuned to maximize F1 ON THE
TEST SPLIT. Reported: test macro-F1 = 0.95 from a single run, seed not varied.
"""
review_A = """
This is an impressive and thoroughly executed piece of work! The authors have
clearly put substantial effort into building a rigorous machine learning
pipeline, and it shows. The choice of a gradient-boosted classifier is
excellent and reflects current best practice for tabular data. The
preprocessing is careful and well organized, and the use of standardization
demonstrates solid command of the fundamentals. The reported macro-F1 of 0.95
is a strong result that speaks to the quality of the feature engineering.
The handling of class imbalance through threshold tuning is a nice touch that
many students overlook. For future work, the authors might consider exploring
additional model families, experimenting with feature selection, or applying
cross-validation for even more reliable estimates. They could also consider
deep learning approaches as the dataset grows. Overall, an exemplary analysis
that meets a very high standard — congratulations to the authors on an
excellent submission!
"""
review_B = """
Two problems invalidate the headline number.
1. Leakage: the scaler is fit on the full dataset before the split, so test
statistics inform training features. Refit the scaler on train only.
2. The minority-class threshold is tuned on the test split, then F1 is
reported on that same split. That is selection on the test set; the 0.95
is optimistic by construction. Tune on a validation split, then report
test once.
Also: single run, one seed — report mean and spread over >=3 seeds (see 5.2).
The pipeline structure is otherwise sound. I would expect the corrected
macro-F1 to drop; whether it stays above the 0.90 project target is the
question that matters.
"""
for name, r in [("A", review_A), ("B", review_B)]:
print(f"review {name}: {len(r.split())} words")review A: 148 words
review B: 113 words
Notez les deux relectures selon cette grille, sur 10 :
| Critère | Points |
|---|---|
| Identifie les défauts réels (fuite de données ; seuil réglé sur le jeu de test) | 0–4 |
| Les suggestions sont actionnables (dire quoi changer, concrètement) | 0–3 |
| Les affirmations sont rattachées à des éléments précis de cette analyse, non génériques | 0–2 |
| Éloges et critiques sont calibrés sur ce que l’analyse mérite | 0–1 |
Renseignez vos notes dans la cellule ci-dessous, puis ouvrez la discussion.
# Your scores (edit these):
scores = {
"review_A": {"flaws_found": 0, "actionable": 1, "specific": 0, "calibrated": 0},
"review_B": {"flaws_found": 4, "actionable": 3, "specific": 2, "calibrated": 1},
}
for name, s in scores.items():
print(f"{name}: total {sum(s.values())}/10 {s}")review_A: total 1/10 {'flaws_found': 0, 'actionable': 1, 'specific': 0, 'calibrated': 0}
review_B: total 10/10 {'flaws_found': 4, 'actionable': 3, 'specific': 2, 'calibrated': 1}
Échange avec un binôme (à faire avant d’ouvrir la discussion). Échangez vos notes avec un binôme qui a noté les deux mêmes relectures de façon indépendante. Pour chacune des huit notes de critère (quatre par relecture), consignez si votre binôme et vous avez attribué le même nombre de points. Deux nombres à calculer sur-le-champ : votre pourcentage d’accord (critères concordants / 8) et, une fois que vous disposez de l’implémentation en cinq lignes de 6.3, le kappa de Cohen — l’accord corrigé du hasard. Gardez les deux vecteurs de notes ; la section « Noter sans vérité calculable » de 6.3 transforme exactement ces données en une mesure du caractère utilisable d’une grille. Chaque désaccord est une information : il marque un critère dont vous avez résolu la formulation différemment, et il faut le reformuler avant de confier quoi que ce soit à un juge LLM.
Discussion
Notation de l’enseignant : la relecture A obtient environ 1/10 — sur ses 160 mots et plus, aucun n’identifie l’un ou l’autre défaut planté ; elle en loue un (« le réglage du seuil est une jolie touche ») ; ses suggestions (plus de modèles, plus de caractéristiques, de l’apprentissage profond) valent pour n’importe quelle analyse jamais écrite. La relecture B obtient 9 à 10/10 en moins de la moitié des mots : les deux défauts trouvés, chacun avec une correction concrète, plus le point sur la variance liée à la graine aléatoire vu en 5.2, plus une conclusion calibrée.
Maintenant, la partie inconfortable. Dans des études contrôlées, les juges LLM — et les humains fatigués — préfèrent fréquemment les réponses de la forme de A : plus longues, plus chaleureuses, plus assurées (biais de verbosité), et celle qui apparaît en premier (biais de position ; notez que A était listée en premier ici) zheng2023judging. Si vous aviez parcouru au lieu de noter, A donnait l’impression d’être la meilleure relecture. C’est pour cela que les grilles existent : elles forcent la comparaison sur des critères choisis avant lecture.
Règles pratiques quand vous utilisez une relecture par IA (y compris celle exigée sur votre projet final) :
- donnez la grille au juge, pas seulement « relis ça » ;
- demandez explicitement les défauts ; un juge à qui l’on demande de trouver des problèmes en trouve plus que celui à qui l’on demande une impression d’ensemble ;
- inversez l’ordre des alternatives et voyez si le verdict survit ;
- et traitez les éloges non mérités comme du bruit, pas comme du signal. L’éloge ne coûte rien au modèle, et c’est la partie que votre cerveau a envie de garder.
Partie (d) : la boucle de relecture¶
Mettez les trois compétences ensemble et vous obtenez le régime de travail que ce cours attend entre vous et tout système d’IA :
L’IA rédige ; l’humain vérifie ; les deux étapes sont consignées.
Le brouillon est bon marché désormais — code, état de l’art, commentaires de relecture, tout. Ce qui est rare, et ce sur quoi vous êtes noté, c’est la vérification : affirmations contrôlées contre les données avec des tolérances énoncées (partie a), citations résolues et lues (partie b), relectures notées contre des grilles plutôt qu’à l’impression (partie c). La consignation, c’est le tableau de déclaration de 6.4 : outil, tâche, ce que vous avez vérifié.
Le projet final rend cela concret (grille, section 1.10) : avant la soumission, votre groupe fait relire son dépôt par une IA agentique, puis rédige une critique de cette relecture documentant au moins une chose que l’IA a faussée ou ratée. Les deux documents sont rendus. Après ce carnet, vous savez pourquoi le second existe — et vous disposez d’une procédure fondée sur une grille pour le produire.