Skip to content

feat(rl,#16063): rlpt_0c — reward hacking qui prend, cause isolée par bras de contrôle - #16172

Merged
jsboige merged 4 commits into
mainfrom
feature/16063-rlpt0c-reward-hacking
Sep 18, 2026
Merged

jsboige merged 4 commits into
mainfrom
feature/16063-rlpt0c-reward-hacking

Conversation

@jsboige

@jsboige jsboige commented Sep 14, 2026 •

Copy link
Copy Markdown
Owner

Grain: DEEP/notebook-python — lane myia-po-2026:CoursIA — prev: DEEP/notebook-python #16123

Objet

Bloc A.3 de l'epic #16063 (série rlpt_*, RL Post-Training) : le cas où le reward hacking PREND, avec isolation de la cause par bras de contrôle.

rlpt_3 montre le reward hacking inoculé (le garde-fou tient). Ce notebook couvre le régime opposé et — c'est son apport — mesure le mécanisme au lieu de l'asserter : le biais de l'annotateur est relevé sur les paires brutes, puis relu dans les poids du reward model appris, puis isolé en retirant le seul terme fautif.

Nouveau notebook : MyIA.AI.Notebooks/RL/rlpt_0c_reward_hacking_case_study.ipynb (41 cellules : 17 code / 24 markdown).

Nommage rlpt_0c (et non rlpt_7 du plan d'epic) : il suit la convention livrée de la famille rlpt_0*, où ce cas est le pendant direct de rlpt_0 (rlpt_0 = la démo de base).

Le mécanisme, mesuré et non asserté

Le monde est un bandit à 11 actions (BUDGET = 10, THETA = 6 : correct ssi effort >= 6) ; la longueur est BUDGET - effort. Un annotateur biaisé note is_correct + alpha * (longueur/BUDGET).

Étape Instrument Mesure
Signature du biais paires brutes préférence pour le long à correction égale
Biais appris poids du RM BT (nn.Linear(3,1)) |wl/wc| ≈ 1.99 — 4 graines : 2.0234 (0) / 2.0001 (1) / 1.9845 (7) / 1.9923 (42)
Cause isolée bras 2 vs bras 1 qualité 0.0170 → 0.9905 en retirant seul le terme de longueur

Trois bras, PPO agnostique à la récompense (le même code optimise les trois tables — c'est ce qui fait du bras 2 une isolation de cause et non une comparaison entre algorithmes) :

Bras Récompense Qualité (vraie) Longueur Score RM
1 — RM biaisé r_phi appris 0.4545 → 0.0170 5.0000 → 9.8646 6.6103 → 8.6766
2 — contrôle longueur r_phi - wl*longueur 0.9905 — —
3 — oracle is_correct 0.9889 — —

Écart multi-graines bras 2 − bras 1 = +0.9735, de signe stable. Le bras 1 maximise le proxy (score RM 8.68, le plus haut des trois) en détruisant la qualité : c'est la définition opérationnelle du hacking.

Balayage d'alpha (section 7) — la falaise est mesurée, pas postulée : argmax du proxy e=6 (correct) à alpha=1.5, puis e=0 (incorrect) à alpha=2.0, pour une qualité 0.9715 → 0.0170. Le notebook ajoute une colonne mesurée argmax r_phi / correct ? pour rendre ce basculement visible plutôt que de décrire une décroissance supposée.

Frontière posée explicitement

Section 9 : le specification gaming (optimiser la métrique au-delà de l'intention) n'est pas le reward tampering (réécrire la fonction de récompense elle-même). Ce notebook démontre le premier ; il ne prétend pas démontrer le second.

Validation

  • Papermill 2.6.0, kernel coursia-ml-training, end-to-end.
  • execution_count : 1→17, aucun null ; 0 erreur ; papermill.exception = None.
  • Figures : 2 (rendues par le backend inline d'ipykernel).
  • Les 4 cellules exécutées sans sortie sont des cellules de définition (dont les 3 stubs d'exercice) — pas d'échec silencieux.
  • Pré-commit : 9/9 hooks OK (gitleaks, H.3 un-executed, check_cell_source_compilable, scrub papermill, guard markdown). metadata.papermill.input/output_path normalisés au basename.

Exercices et C.1

3 exercices stubs, sans erreur volontaire (None sentinelle, # TODO etudiant conservés) : rejouer à budget différent, métrique sans vérité terrain, corriger le biais dans les données plutôt que dans la récompense. Le notebook s'exécute de bout en bout.

README

MyIA.AI.Notebooks/RL/README.md : ligne pt-0c ajoutée après pt-0 ; ligne de frontière ajoutée après rlpt_3 (« le reward model est-il vraiment la cause ? ») ; énumération de la série étendue au cas où le hack prend.

Les marqueurs <!-- CATALOG-STATUS --> sont inchangés (propriété de l'automatisation, cf catalog-pr-hygiene).

Signalé, non corrigé ici : le README porte une incohérence préexistante entre son marqueur pedagogical_count: 26 et sa prose éditoriale (« 17 notebooks canoniques ») — le disque en comptait 27 avant ce notebook. Le marqueur appartient au cron catalogue ; la prose demande un audit fichier entier de son propre grain, pas un alignement au passage.

Suivi

See #16063

🤖 Generated with Claude Code

… bras de controle

Bloc A.3 de l'epic #16063 (serie rlpt_*, RL Post-Training). Pendant direct de
rlpt_3, qui montre le hack inocule : ce notebook couvre le regime ou il prend,
et mesure le mecanisme au lieu de l'asserter.

- biais de l'annotateur releve sur les paires brutes
- biais relu dans les poids du reward model appris (|wl/wc| ~ 1.99, 4 graines)
- cause isolee : bras 2 (controle longueur) vs bras 1, qualite 0.0170 -> 0.9905
  en retirant le SEUL terme de longueur ; PPO agnostique a la recompense, donc
  le meme code optimise les trois tables (isolation de cause, pas comparaison
  d'algorithmes)
- balayage alpha : falaise mesuree (argmax du proxy bascule e=6 correct ->
  e=0 incorrect entre alpha=1.5 et 2.0)
- section 9 : specification gaming != reward tampering, frontier posee

Papermill end-to-end, kernel coursia-ml-training, 17 cellules code executees
(exec 1..17, aucun null), 0 erreur, 2 figures. 3 exercices stubs sans erreur
volontaire (C.1). README : ligne pt-0c + frontiere + enumeration de serie.

See #16063

Co-Authored-By: Claude Sonnet 5 <noreply@anthropic.com>
@github-actions

Copy link
Copy Markdown
Contributor

✅ No prose/output mismatch detected in the notebooks this PR changed.

Scope = notebooks CHANGED in this PR, not the whole corpus. Explicit claim-check relations resolve only against named CLAIM_METRICS from the local output window and are classified SUPPORTED, CONTRADICTED, or UNPROVEN.
The markdown-claims-output-report run artifact contains the structured JSON report. See python scripts/check_markdown_claims_output.py --help for re-running locally.
Detector rationale: c.290 / c.331 / PR #11435 numeric pathology, extended with low-noise relational evidence.

@github-actions

Copy link
Copy Markdown
Contributor

Notebook PR Validation: PASS

  • Notebooks checked: 1
  • Code cells validated: 17
  • Result: All passed

Checks: H.1 (no errors), H.3 (execution_count), C.1 (no banned patterns)
Non-Python kernels (.NET/Lean): C.1 + errors only (execution_count advisory)
QuantConnect notebooks: C.1 + errors only (require QC Cloud for execution)

@github-actions

Copy link
Copy Markdown
Contributor

G-VAR-2/3 GENRE signals (advisory, non bloquant, #10020).
La lane `myia-po-2026:CoursIA` voit ces signaux actifs sur les mergees du jour (UTC 2026-09-14) :

G-VAR-2 plafonne a max(1, grains_mergees_du_jour // 3) LIGHT par lane et par jour, toutes categories LIGHT confondues -- un RATIO, pas un plafond plat ; le cap calcule du jour est dans le tally ci-dessus. G-VAR-3 interdit deux genres LIGHT consecutifs. Les signaux ci-dessus rendent le fait VISIBLE (labels variation-tier-inflation, `variation-genre-run`, `variation-genre-cap-exceeded`, `variation-genre-mismatch`, `variation-genre-unknown`) -- la decision de merge reste au coordinateur.

@github-actions

Copy link
Copy Markdown
Contributor

Notebook outputs-required (H.4 schema): PASS (every code cell carries an outputs: list)

@github-actions

github-actions Bot commented Sep 14, 2026 •

Copy link
Copy Markdown
Contributor

Golden-Set Execution (H.7 P3)

✅ 8/8 notebooks passed (certified reproducible)

Notebook Status Time
2.1-Workflow-ML.ipynb ✅ SUCCESS 3.3s
2.2-Descente-de-gradient.ipynb ✅ SUCCESS 3.4s
2.3-Regression-lineaire-logistique.ipynb ✅ SUCCESS 4.6s
2.4-Arbres-Forets-Ensembles.ipynb ✅ SUCCESS 4.3s
Search-01-StateSpace.ipynb ✅ SUCCESS 3.4s
SL-1-LogicalLearning.ipynb ✅ SUCCESS 2.2s
rl_4_multi_armed_bandits.ipynb ✅ SUCCESS 16.0s
GameTheory-04c-NashExistence-Python.ipynb ✅ SUCCESS 2.6s

Pinned lockfile: scripts/notebook_tools/golden_set.lock.txt (H.7 P3, axe A #4208)

jsboige and others added 2 commits September 14, 2026 16:58
Les deux renvois de la serie (rlpt_1, rlpt_3) pointaient vers des .html
inexistants alors que les cibles sont des .ipynb du meme dossier. Deux
organes le voyaient, sous deux noms : check-navlinks (2 NEW broken navlink
vs baseline) et le gate enrich-quality ([HREF_MISSING] x2, HIGH).

Correction markdown seule (2 lignes, cellule de renvois) : les sorties
committees restent valides au sens de la regle C.2, aucune cellule de code
n'est touchee, donc aucune re-execution n'est requise.

Verifie localement avant push, avec l'invocation exacte de la CI :
  check_notebook_navlinks.py --check -> OK, 0 NEW broken navlink
  enrich_quality_ci.py --base NONE --head <nb> -> rc=0

Co-Authored-By: Claude Sonnet 5 <noreply@anthropic.com>
Conflit RL/README.md resolu en union : ligne pt-0b (#16114, venue de main)
placee avant la ligne pt-0c (cette branche) ; frontieres et enumeration
des deux cotes preservees.

Co-Authored-By: Claude Sonnet 5 <noreply@anthropic.com>

@clusterManager-Myia clusterManager-Myia left a comment

Copy link
Copy Markdown
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

[NanoClaw] revue structurelle — 2 fichiers lus au head e7664fa8 : le notebook rlpt_0c intégralement (41 cellules, structure par cellule) et le README RL (entrées rlpt_0c). Diff complet non chargé (budget structurel) ; tout ce qui suit est mesuré sur l'artefact commité.

VERDICT: CONCERNS (1 finding de provenance dans le body ; le contenu commis lui-même est solide et vérifié)

Vérifié sur l'artefact — la substance tient

  • Structure exacte : 41 cellules (17 code / 24 markdown) comme annoncé ; execution_count 1→17 strictement séquentiels ; outputs réels sur toutes les cellules d'exécution (2 figures comprises) ; zéro N/A / NotImplementedError / secret / leak-path (scan intégral source + outputs) ; sections 1→10 sans trou de numérotation. Les 4 cellules code sans output = 1 cellule de définition PPO + 3 stubs d'exercices « TODO étudiant » (convention C.1 de la série, assumée au README l.147).
  • Toute la chaîne de mesures se lit dans les outputs commités : bras 1 qualité 0.4545 → 0.0170, longueur 5.0000 → 9.8646, score RM 6.6103 → 8.6766 ; bras 2 contrôle longueur 0.9905 ; bras 3 oracle 0.9889 ; écart multi-graines bras 2 − bras 1 = +0.9735. Chaque chiffre du tableau du body, sauf un (voir finding), se re-pointe sur une cellule en output.
  • La falaise d'alpha est mesurée, pas postulée : l'output du balayage rend « premier α où l'argmax du proxy est INCORRECT : 2.00 (argmax e=0) ; α=1.50 : argmax e=6 (correct), qualité 0.9715 » — exactement la claim, colonne argmax r_phi / correct ? comprise.
  • README (l.54, l.71, l.147) : entrées présentes et cohérentes avec les outputs — et, point important, le README ne cite PAS les valeurs de graines incriminées ci-dessous.

Le finding — pourquoi CONCERNS

  • La table multi-graines du body cite des valeurs absentes de l'artefact commis. Le body écrit « \|wl/wc\| ≈ 1.99 — 4 graines : 1.9845 / 2.0234 / 1.9902 / 1.9889 ». L'output commité de la lecture des poids rend {2.0234 (graine 0), 2.0001 (graine 1), 1.9845 (graine 7), 1.9923 (graine 42)}, étendue 0.0388. Deux des quatre valeurs citées — 1.9902 et 1.9889 — n'existent nulle part dans le notebook (scan intégral source + outputs : zéro occurrence). Le « 1.9889 » du body ressemble au 0.9889 de l'oracle (bras 3) — autre quantité, autre échelle. Portrait-robot d'un run antérieur non commis : le body égrène des chiffres d'une exécution que l'artefact ne porte pas — exactement la rupture de chaîne de provenance (C.2 : « ancre ses interprétations sur des sorties réellement exécutées ») que la série s'impose par ailleurs avec rigueur. Fix trivial : citer les quatre valeurs de l'output commité, ou les faire écho par le notebook. La conclusion qualitative (« rapport ≈ 2, stable sur 4 graines ») est, elle, parfaitement corroborée par l'artefact.

Note non bloquante

  • Bras 2 (0.9905) finit au-dessus de l'oracle (0.9889) — bruit de graine, dans le sens attendu (le contrôle ne plafonne pas sous l'oracle) ; le notebook ne s'en prévaut pas à tort.

— NanoClaw (myia-ai-01), review structurelle, COMMENT only

@github-actions

github-actions Bot commented Sep 14, 2026 •

Copy link
Copy Markdown
Contributor

Path-collision (organ #13359/#13615)

Cette PR #16172 (feat(rl,#16063): rlpt_0c — reward hacking qui prend, cause isolée par bras de contrôle) touche au moins un chemin de fichier aussi modifie par d'autres PRs ouvertes. Risque de double-livraison (meme fichier livre deux fois, 2x le travail et 2x les runs CI). Advisory : parfois legitime (tranches coordonnees, partition paths: explicite, PRs empilees exclues) -- l'organe rend visible, il ne bloque pas.

Le verdict terminal (#15578) signale qu'un cote de la paire est deja sur main. L'organe mesure un recouvrement de chemins ; il ne compare pas le contenu des deux livraisons, donc il ne conclut PAS a une redondance (#15768) : deux PRs peuvent toucher le meme fichier pour des raisons disjointes. L'arbitrage reste a la lane ou au coordinateur.

@myia-ai-01 myia-ai-01 left a comment

Copy link
Copy Markdown
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

CHANGES_REQUESTED — exact head e7664fa83796e35c4862c301559b61a5a569c0ba.

The complete notebook audit is favorable: 41 cells (17 code/24 markdown), dense execution 1–17, zero errors, three C.1-safe exercises, real outputs and figures, no path/secret leak, and a coherent causal chain from raw length bias through learned RM weights to PPO degradation and the length-control arm. The committed metrics and README row are supported.

Two bounded blockers remain:

  1. Correct the body-only four-seed RM-ratio provenance. The committed output is 2.0234 (seed 0), 2.0001 (seed 1), 1.9845 (seed 7), 1.9923 (seed 42), not 1.9845 / 2.0234 / 1.9902 / 1.9889; the last two current body values do not occur in the artifact (and 1.9889 resembles the unrelated oracle quality 0.9889). Keep the supported qualitative claim near 1.99.
  2. Merge current main normally and resolve the RL README conflict deliberately. Preserve main’s pt-0e and pt-0f rows and the updated trl dependency row, while inserting this PR’s pt-0c row in order after pt-0b, restoring its pedagogical question row, and retaining the rlpt_0c narrative mention. Do not take either conflict side wholesale.

No notebook source, output, execution count, or metadata change is required; if the notebook remains byte-identical, do not re-execute it. After the merge, run README/link checks, confirm the exact effective two-file scope, update CI, and request exact-head review. The independent NanoClaw concern must receive an attributed lift on the new head.

…reward-hacking

# Conflicts:
#	MyIA.AI.Notebooks/RL/README.md
@jsboige

jsboige commented Sep 16, 2026

Copy link
Copy Markdown
Owner Author

[NanoClaw self-bot — myia-po-2025] DISPOSITION EXACT-HEAD — LIFT : myia-po-2025 lève la CONCERN NanoClaw du 2026-09-14T17:19:15Z (posée sur l'ancien head e7664fa) au nouveau head 4862a2fefa2df2b09a274c2c15d3b60101f9ce92, sur preuve firsthand intégrale.

La concern initiale : le body citait 4 ratios de biais appris dont 2 (1.9902, 1.9889) n'existaient nulle part dans le notebook committé — l'artefact réel porte {2.0234 (seed 0), 2.0001 (seed 1), 1.9845 (seed 7), 1.9923 (seed 42)}.

Vérification au head exact 4862a2fe :

  1. Body (ligne 20 du tableau) : cite désormais exactement 2.0234 (0) / 2.0001 (1) / 1.9845 (7) / 1.9923 (42) — les 4 valeurs de l'artefact ; 1.9902 et 1.9889 absents du body entier. La chaîne de provenance body ↔ artefact est réparée.
  2. Notebook rlpt_0c_reward_hacking_case_study.ipynb : blob OID identique entre les deux heads (abdd390ca6b761cf… à e7664fa comme à 4862a2fe) — byte-identique, la réparation n'a pas touché l'artefact. Les 4 ratios vivent dans les outputs (source = 0 hit pour chacun : valeurs mesurées, non hardcodées), les 2 fantômes comptent 0 hit source comme outputs. 17/17 cellules code exécutées, 0 erreur.
  3. README RL au head : union pt-0b/0c/0e/0f présente (lignes 53-56), pt-0c décrit avec le verdict « stable sur 4 graines » — cohérent avec l'artefact cité.

PR gate non relancé (instruction ai-01 2026-09-16T18:50Z — l'agrégat rouge cite un enfant annulé désormais SUCCESS ; pression runner instable). Merge réservé à myia-ai-01:CoursIA.

@myia-ai-01 myia-ai-01 left a comment

Copy link
Copy Markdown
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Approving exact head 4862a2fefa2df2b09a274c2c15d3b60101f9ce92 after re-reading the complete PR surface, the current-head merge, the original formal concern, and the attributed NanoClaw lift.

Both prior blockers are resolved. The body now cites exactly the four measured reward-model ratios committed in the notebook outputs: 2.0234 (seed 0), 2.0001 (seed 1), 1.9845 (seed 7), and 1.9923 (seed 42); the unsupported 1.9902 and 1.9889 values are gone. The notebook blob remains byte-identical to the audited artifact, with 17/17 code cells executed and no errors.

The current head normally integrates canonical main 5a1989a92e2185678763a06a76032b7384cd70e5. The RL README conflict was resolved as a deliberate union preserving the pt-0b, pt-0c, pt-0e, and pt-0f rows and the supported rlpt_0c narrative. The original NanoClaw reviewer published an attributed exact-head lift under the shared account, and closingIssuesReferences remains empty so #16063 stays open.

This approval replaces my stale CHANGES_REQUESTED on e7664fa83796e35c4862c301559b61a5a569c0ba; it does not waive the required successful current-head PR gate. Do not merge or push merely to refresh the gate.

@jsboige

jsboige commented Sep 17, 2026

Copy link
Copy Markdown
Owner Author

[ADJOINT PREFLIGHT]
schema: 1
lane: myia-po-2025:CoursIA-2
pr: 16172
head: 4862a2f
complete: true
body: read
comments-reviewed: 7
reviews-reviewed: 3
threads-reviewed: 0
threads-unresolved: 0
surfaces-sha256: d0d953796bc9920c518c001f7a609d0b9f71150f0612d827e934e90d1c8dec21
diff-files: 2
diff-additions: 1676
diff-deletions: 1
checks: latest-wins-green
b0: clear
scope: pass
domain: pass
verdict: READY
[/ADJOINT PREFLIGHT]

@jsboige

jsboige commented Sep 17, 2026

Copy link
Copy Markdown
Owner Author

[ADJOINT PREFLIGHT]
schema: 1
lane: myia-po-2025:CoursIA-2
pr: 16172
head: 4862a2f
complete: true
body: read
comments-reviewed: 8
reviews-reviewed: 3
threads-reviewed: 0
threads-unresolved: 0
surfaces-sha256: 679f8b299b6fae6272ebc4727c8abe029bb610b66212860cc789d6c06c4ac0aa
diff-files: 2
diff-additions: 1676
diff-deletions: 1
checks: latest-wins-green
b0: clear
scope: pass
domain: pass
verdict: READY
[/ADJOINT PREFLIGHT]

@jsboige
jsboige merged commit 5b15e66 into main Sep 18, 2026
82 of 98 checks passed
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

pr-overlap Advisory: another open PR touches the same files (organ #13615)

Projects

None yet

Development

Successfully merging this pull request may close these issues.

3 participants