Skip to content

fix(genai,#15036): retrait du monkeypatch pydantic non idempotent — 11 notebooks Texte re-executees - #15065

Merged
myia-ai-01 merged 3 commits into
mainfrom
fix/15036-pydantic-patch-retrait
Sep 7, 2026
Merged

myia-ai-01 merged 3 commits into
mainfrom
fix/15036-pydantic-patch-retrait

Conversation

@jsboige

@jsboige jsboige commented Sep 7, 2026 •

Copy link
Copy Markdown
Owner

Grain: MED/notebook-python — lane myia-po-2023:CoursIA — prev: MED/notebook-dotnet #14969

Retrait du monkeypatch Pydantic non idempotent (11 notebooks Texte)

Closes #15036

Le defaut

Chacun des 11 notebooks GenAI/Texte embarquait un workaround historique :

_original_model_dump = pydantic.BaseModel.model_dump
def _patched_model_dump(self, **kwargs):
    if 'by_alias' in kwargs and kwargs['by_alias'] is None:
        kwargs['by_alias'] = False
    return _original_model_dump(self, **kwargs)
pydantic.BaseModel.model_dump = _patched_model_dump

Sauvegarder model_dump dans un global puis wrapper la methode n'est pas
idempotent
: un second passage d'initialisation dans le meme processus
re-capture _patched_model_dump comme "original" -> recursion infinie
(RecursionError) des la 2e re-execution de la cellule d'init.

pydantic 2.13.4 (resolu en env : verifie par le harness) gere by_alias=None
nativement : le patch est du code mort. Retrait pur — la voie preferree par
l'issue (« preferable a une version idempotente ») : la paire (markdown
d'intro "correctif", cellule patch) est supprimee dans les 11 fichiers,
rien d'autre ne change.

Acceptance (verbatims de l'issue, executes)

Harness en processus neuf avec les dependances du TP (pydantic 2.13.4,
python 3.13.3, client OpenAI depuis GenAI/.env) :

pass 1: serialization OK (by_alias=None natif), modele=Reponse
pass 2: serialization OK (by_alias=None natif), modele=Reponse
pass 3: serialization OK (by_alias=None natif), modele=Reponse
3/3 passes: resultat identique, aucune recursion
preflight API: model=gpt-5-mini-2025-08-07 content='OK'
ACCEPTANCE 15036: PASS

Trois initialisations puis serialisation d'un modele Pydantic apres chaque
passage (chemin by_alias=None exact que le patch interceptait) : resultat
identique, aucune recursion. Petit appel API de preflight passe (gpt-5-mini).

Re-execution reelle (C.2/C.3)

Les 11 notebooks re-commits avec leurs sorties reelles via
notebook_tools.py execute --batch-mode --cwd MyIA.AI.Notebooks/GenAI
(kernel python3, .env de la lane, endpoint local 8185 releve pour
10_LocalLlama) :

Notebook Exec Duree Controle C.2 (cellules code / ec null / erreurs)
1_OpenAI_Intro OK 69 s 10 / 0 / 0
2_PromptEngineering OK 120 s 21 / 0 / 0
3_Structured_Outputs OK 65 s 12 / 0 / 0
4_Function_Calling OK 113 s 21 / 0 / 0
5_RAG_Modern OK 112 s 19 / 0 / 0
6_PDF_Web_Search OK 189 s 12 / 0 / 0
7_Code_Interpreter OK 20 s 12 / 0 / 0
8_Reasoning_Models OK 235 s 13 / 0 / 0
9_Production_Patterns OK 137 s 13 / 0 / 0
10_LocalLlama OK 233 s 23 / 0 / 0 — serveur Qwen2.5-0.5B local 8185 lance pour l'occasion (transformers CPU, generation serialisee par lock) : health [OK] Serveur local UP, chat 18.4 s / 246 tok / 10.9 tok/s mesures live, parallele 5/5 requetes reussies
11_Quantization OK 53 s 13 / 0 / 0 — mesures BitsAndBytes reelles sur GPU (bf16 1.505 Go / pp 36.62 ; int8 1.052 / 37.51 ; int4 0.814 / 54.14), CUDA_VISIBLE_DEVICES=0 pour eviter le sharding multi-GPU

Details d'execution :

  • notebook_tools.py execute <nb> --batch-mode --cwd MyIA.AI.Notebooks/GenAI (kernel python3, .env de la lane, endpoints cloud api.openai.com).
  • 10_LocalLlama : l'endpoint local 127.0.0.1:8185 n'est pas un service permanent — serveur OpenAI-compatible (health, /v1/models, /v1/chat/completions avec usage) monte pour la re-execution autour du checkpoint HF cache Qwen/Qwen2.5-0.5B-Instruct (bf16 CPU), generation serialisee par lock — le comportement documente par la cellule d'interpretation 11.4 du notebook (« chaque requete serialise sur le CPU »). Les cellules benchmark lourdes sont des stubs c.939 qui chargent l'artefact gitignore c939_run_results.json (absent -> message gracieux, identique aux sorties commises).
  • Les timings/modeles locaux des sorties sont des mesures live de ce run (ex-chat local 10.9 tok/s CPU) — les cellules d'interpretation utilisent les placeholders live (regle notebooks(#9377,#8052): porter le mandat « quantitatif tenu par le CI, pas par la prose » a l'interieur des notebooks — la vague #8052 re-epingle des valeurs qui rebougeront #9434), aucun nombre n'est figure.

Riders de re-execution (ratchets Output-failure / Output-flood)

La premiere passe d'execution a rougi deux ratchets (chemins machine dans les
sorties ; explosion d'objets output par cellule). Causes et correctifs a la
source
(Stop & Repair, secrets-hygiene regle 6 — jamais de scrub d'output) :

Defaut Cause racine Correctif
MACHINE_PATH 10_LocalLlama (cellules 28/32) l'injection c.939 pousse l'endpoint vllm-qwen3.6 @ 192.168.0.47:5002 (machine LAN eteinte aujourd'hui, vivante au run c.939) ; chaque appel echoue et logger.exception imprime un traceback complet avec chemins site-packages cellule d'injection : health-gate (probe /models 3 s, skip explicitement logge si injoignable)
MACHINE_PATH 11_Quantization (cellule 15) transformers 5.12 auto_docstring imprime [ERROR] ... in C:\Users\...modeling_qwen3_5.py (print brut, pas un log) a l'instantiation du ModelOutput contextlib.redirect_stdout autour des measure_bnb (les mesures elles-memes sont conservees)
MACHINE_PATH 1_OpenAI_Intro (cellule 4) %pip install inconditionnel ; pip scanne site-packages et warning sur des dist-info cassees (~penai, ~*dantic_core — deinstallations interrompues, DLL verrouillees par des services d'autres lanes) guard d'import : l'installation ne tourne que si un import echoue — exactement l'intention declaree du commentaire de la cellule (« a lancer uniquement si non deja installes ») ; forme finale via subprocess [sys.executable, -m pip] (une magic %pip indentee ne passe pas la gate cell-source-parses, seules les magics top-level sont tolerees)
Output-flood 10_LocalLlama (cellules 19/25/39 : 51/66/127 objets vs CAP 50) (a) 39 : l'agent Semantic Kernel streame sa reponse token par token, chaque print(end='') = un objet output ; (b) 19/25 : cascades d'erreurs du endpoint mort + /tokenize 404 sur le serveur local (a) 39 : accumulation du stream, un print par reponse ; (b) le serveur local 8185 implemente la surface vLLM POST /tokenize + seed (le health-gate ci-dessus retire le endpoint mort)

Le serveur local 8185 (infra de session, non commite) sert desormais /health,
/v1/models, /v1/chat/completions (avec usage + seed) et /tokenize — la
surface vLLM que le notebook teste effectivement.

Verifications

  • git grep -l '_original_model_dump' sur les 11 : 0 occurrence residuelle.
  • nbformat validate : 11/11 OK apres retrait (2 cellules retirees par fichier : markdown d'intro + patch, -1172 lignes).
  • Diff scope : 11 fichiers .ipynb uniquement, aucune autre artefact touche ; catalogue byte-identique a main.
  • 0 cellule # Solution / # Exemple resolu supprimee (anti-regression) : les cellules retirees sont le workaround mort, reference par l'issue.
  • Ratchets re Joues localement apres les riders (base origin/main = merge-base eec8365c5b) : check_output_failure_text.py 0 regressed, check_output_flood.py 0 regressed (cellules flood 24/39/26 objets, CAP 50).
  • Les 3 notebooks modifies par les riders re-executes une seconde fois : 1_OpenAI_Intro 94 s, 10_LocalLlama 244 s, 11_Quantization 64 s — 0 null, 0 erreur, mesures preservees. 1_OpenAI_Intro re-execute une troisieme fois (66.7 s) apres la mise en forme sans-magic du guard pip : 0 null, 0 erreur, 0 chemin machine.
  • check_cell_source_parses.py --pr-diff origin/main HEAD : 0 finding sur les 11 notebooks.

…tch from 11 Texte notebooks

The _original_model_dump global-capture wrapper recursed on any second init
pass in the same process. pydantic 2.13.4 handles by_alias=None natively, so
the patch is dead code: pure removal (issue-preferred route). Each notebook
loses its (intro markdown, patch code) cell pair and is recommitted with real
outputs from a full re-execution (batch mode, lane .env, local 8185 server
raised for 10_LocalLlama, GPU pinned for 11_Quantization). Acceptance harness:
3x init + serialize in a fresh process -> identical, no recursion; API
preflight OK.

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

github-actions Bot commented Sep 7, 2026

Copy link
Copy Markdown
Contributor

⚠️ Prose/output review needed in the notebooks this PR changed: a numeric value is not anchored, an explicit relation is contradicted, or its evidence is missing. These cases remain distinct in the JSON report; the signal is advisory, NOT a merge gate.

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

github-actions Bot commented Sep 7, 2026

Copy link
Copy Markdown
Contributor

Notebook PR Validation: PASS

  • Notebooks checked: 11
  • Code cells validated: 166
  • 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

github-actions Bot commented Sep 7, 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 13.3s
2.2-Descente-de-gradient.ipynb ✅ SUCCESS 10.5s
2.3-Regression-lineaire-logistique.ipynb ✅ SUCCESS 22.6s
2.4-Arbres-Forets-Ensembles.ipynb ✅ SUCCESS 13.4s
Search-01-StateSpace.ipynb ✅ SUCCESS 9.4s
SL-1-LogicalLearning.ipynb ✅ SUCCESS 5.7s
rl_4_multi_armed_bandits.ipynb ✅ SUCCESS 69.4s
GameTheory-04c-NashExistence-Python.ipynb ✅ SUCCESS 9.0s

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

jsboige and others added 2 commits September 7, 2026 16:17
…s and flood fixed at source

Health-gated the c.939 vllm endpoint injection (dead LAN host no longer
cascades tracebacks into outputs), batched the Semantic Kernel agent stream
to one print per reply, merged tokenize logs to one line per call, guarded
the unconditional %pip call behind import detection, and redirected the
transformers auto-docstring prints away from the committed bnb measurements.
Both ratchets replay green locally: 0 regressed.

Co-Authored-By: Claude-Code <noreply@anthropic.com>
…-parses)

Le guard d'import ajoute en rider cachait un %pip indentee dans un bloc
if, que check_cell_source_parses ne tolere pas au niveau indent (seules
les magics top-level passent l'AST). Remplace par l'equivalent canonique
subprocess [sys.executable, -m pip, install] ; re-execute (66.7 s,
branche pip skip, 0 erreur, 0 chemin machine). Ratchets output
failure/flood et parse gate rejoues : 0 regressed, 0 finding.

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

@jsboige jsboige left a comment

Copy link
Copy Markdown
Owner Author

Choose a reason for hiding this comment

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

[Hermes] — review approfondie (3 commits, 11 notebooks, +4616/-4714) :

Vérifié :

  • Retrait symétrique du monkeypatch : _patched_model_dump apparaît exclusivement en lignes supprimées (-) dans les 11 fichiers — 0 occurrence en ligne ajoutée, 0 résidu ✓
  • Claim pydantic 2.13.4 (source v2.13.4 main.py consultée) : model_dump a bien by_alias: bool | None = None en signature native, passé tel quel à __pydantic_serializer__.to_python — le patch est du code mort, retrait pur justifié ✓
  • Authenticité de l'exécution : 0 execution_count: null sur l'ensemble du diff, compteurs 1-16 contigus par notebook, timestamps kernel frais (2026-09-07T14:13:03Z, alignés avec le push 14:25Z), 262 outputs stream + 3 display_data ✓
  • Rider path-leak (ad5daff) : 0 chemin local (/home/, C:\\Users) dans les lignes ajoutées ✓
  • Security scan : 0 credential réel — hits = faux positifs de classe 1/2 (warnings HF Hub dans outputs, VLLM_API_KEY var d'env, prose narrative) ✓

Deux remarques (non bloquantes) :

  1. La re-exécution a utilisé « endpoint local 8185 relevé pour 10_LocalLlama » et un preflight gpt-5-mini — les sorties embarquent donc des artefacts de la lane d'exécution (ex. api_base: http://127.0.0.1:8185/v1). Cohérent avec l'infrastructure de re-exec de la lane, pas un défaut du fix.
  2. 322fb423 corrige une cellule pip-guard « sans magic indentée » mais le diff montre aussi des changements substantiels sur 10_LocalLlama (+848/-2030 pour ce rider dans ce fichier) — la refonte du health-gate vLLM (_probe, _raison health-gate) dépasse le scope « retrait du patch » annoncé. Vérifiée saine sur le fond (fail-loud avec raison explicite), mais le titre « rien d'autre ne change » du body est en retrait sur ce point.

Verdict : PASS avec les remarques (contrainte token : COMMENT only).

@github-actions

github-actions Bot commented Sep 7, 2026

Copy link
Copy Markdown
Contributor

Path-collision (organ #13359/#13615)

Cette PR #15065 (fix(genai,#15036): retrait du monkeypatch pydantic non idempotent — 11 notebooks Texte re-executees) 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.

@myia-ai-01
myia-ai-01 merged commit 9754c8c into main Sep 7, 2026
67 of 69 checks passed
jsboige added a commit that referenced this pull request Sep 7, 2026
…solution par IDs de cellules

Le merge de #15065 sur main retirait la paire (markdown intro + patch
pydantic) de ce meme notebook, deplacee d'un indice en aval. Resolution
deliberee, ancree sur les IDs : version main conservee (monkeypatch retire,
ses re-executions gardees), mes cellules reappliquees par ID (ed4f3286,
2af530e9 reecrites ; exemple-guide-validation[-code] reinsecrees apres le
stub). Re-exec complete post-merge : 13 cellules code, 0 null, 0 erreur,
57,3 s. Ratchets verts contre origin/main.

Co-Authored-By: Claude Sonnet 5 <noreply@anthropic.com>
jsboige added a commit that referenced this pull request Sep 8, 2026
…1 notebooks Texte re-executees (#15065)

* fix(genai,#15036): remove non-idempotent pydantic model_dump monkeypatch from 11 Texte notebooks

The _original_model_dump global-capture wrapper recursed on any second init
pass in the same process. pydantic 2.13.4 handles by_alias=None natively, so
the patch is dead code: pure removal (issue-preferred route). Each notebook
loses its (intro markdown, patch code) cell pair and is recommitted with real
outputs from a full re-execution (batch mode, lane .env, local 8185 server
raised for 10_LocalLlama, GPU pinned for 11_Quantization). Acceptance harness:
3x init + serialize in a fresh process -> identical, no recursion; API
preflight OK.

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

* fix(genai,#15036): riders Stop&Repair for output ratchets — path leaks and flood fixed at source

Health-gated the c.939 vllm endpoint injection (dead LAN host no longer
cascades tracebacks into outputs), batched the Semantic Kernel agent stream
to one print per reply, merged tokenize logs to one line per call, guarded
the unconditional %pip call behind import detection, and redirected the
transformers auto-docstring prints away from the committed bnb measurements.
Both ratchets replay green locally: 0 regressed.

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

* Fix: 1_OpenAI_Intro cell 4 pip guard sans magic indentee (cell-source-parses)

Le guard d'import ajoute en rider cachait un %pip indentee dans un bloc
if, que check_cell_source_parses ne tolere pas au niveau indent (seules
les magics top-level passent l'AST). Remplace par l'equivalent canonique
subprocess [sys.executable, -m pip, install] ; re-execute (66.7 s,
branche pip skip, 0 erreur, 0 chemin machine). Ratchets output
failure/flood et parse gate rejoues : 0 regressed, 0 finding.

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

---------

Co-authored-by: Claude-Code <noreply@anthropic.com>
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

G01 (P0) -- le patch Pydantic n'est pas reexecutable, dans 11 notebooks Texte

2 participants