Skip to content

fix(notebooks,#16226): HNSW indexing_threshold=0 cassait le rappel -- config corrigee + garde fail-visible - #16305

Merged
jsboige merged 2 commits into
mainfrom
fix/16226-rag05b-hnsw-indexing
Sep 15, 2026
Merged

jsboige merged 2 commits into
mainfrom
fix/16226-rag05b-hnsw-indexing

Conversation

@jsboige

@jsboige jsboige commented Sep 15, 2026

Copy link
Copy Markdown
Owner

Grain: DEEP/notebook-python — lane myia-po-2026:CoursIA-2 — prev: MED/guard #16257

Fix(notebooks,#16226): HNSW indexing_threshold=0 cassait le rappel — config corrigée + garde fail-visible

Diagnostic dérive

Cause racine (lue firsthand sur le notebook avant fix) :

  • indexing_threshold: 0 dans optimizers_config désactive complètement la construction de l'index HNSW en arrière-plan → toutes les requêtes deviennent des full-scans exacts (full_scan_threshold: 10000 Ko au-dessus de la taille réelle ~5000 Ko, donc Qdrant reste en mode scan exact au lieu de basculer sur le graphe).
  • full_scan_threshold: 10000 Ko = 10 Mo, bien au-dessus des 5 Mo de données réelles → full-scan reste permis.
  • Résultat : recall@10 = 1.000 pour tous les hnsw_ef ∈ {8..256}, ce qui semble être un exploit du paramètre mais n'en est pas un — c'est la sortie du full-scan exact, identique quelle que soit ef.

Verdict : CAUSE_FIXED. La correction porte sur la configuration + une garde fail-visible qui rend visible la régression si elle se reproduit.

Le fix

  1. full_scan_threshold: 100 Ko (au lieu de 10000) — bien sous les ~5000 Ko de données réelles (10 000 vecteurs × 128 dim × 4 octets = 5 120 000 octets ≈ 5 000 Ko), force Qdrant à utiliser le graphe HNSW au lieu du full-scan.

  2. indexing_threshold: 10 Ko (au lieu de 0) — au-dessus de 0, lance la construction de l'index HNSW en arrière-plan dès la première ingestion. Une valeur de 0 désactivait la construction complètement (cf. rag(05b): la démo exact/ANN mesure un compromis fantôme — indexing_threshold: 0 ne construit jamais l'index HNSW #16226).

  3. Attente active : la cellule 8 lit indexed_vectors_count en boucle jusqu'à atteindre N_VECTORS (timeout 30 s, sur cette échelle l'index est prêt en < 5 s). Sans cette attente, on mesurerait avant que le graphe ne soit construit — et on retomberait dans le piège.

  4. Garde fail-visible : RuntimeError levée si indexed_vectors_count < N_VECTORS après l'attente. C'est l'instrument qui rend visible la régression : un futur commit qui casserait la config ne passerait plus en silence, il ferait échouer bruyamment la cellule 8.

Validation post-fix

  • Cellule 8 corrigée avec les 4 points ci-dessus.
  • Cellule 8 s'exécute end-to-end sur Qdrant conteneur Docker (test local qdrant_rag05b_test sans auth sur port 6335, propre).
  • Garde fail-visible validée : avant le fix, elle n'aurait rien vu (le notebook affichait recall@10 = 1.000 silencieusement). Après le fix, elle déclenche au bon endroit.

Cellules mises à jour

  • Cellule 8 (code) : config HNSW corrigée (full_scan_threshold: 100, indexing_threshold: 10), attente active (30 s), garde fail-visible (RuntimeError si index incomplet).
  • Cellule 9 (md) : interprétation de l'insertion + garde fail-visible ajoutée.
  • Cellule 13 (md) : courbe signature corrigée — recall@10 ≈ 0.99 à ef=8, sature vers 1.0 à partir de ef=32-64 (au lieu du 1.000 factice de la version buggée).
  • Cellule 16 (md) : Exercice 1 — préambule aligné sur la config corrigée.
  • Cellule 26 (md) : Conclusion — ajoute un paragraphe sur ce que la correction a changé.

Verdict SOTA

RECOVERABLE-MACHINE : le notebook nécessite un conteneur Qdrant Docker (CPU-only suffit, pas de GPU requis) avec authentification désactivée OU clé API en variable d'environnement QDRANT_API_KEY (le notebook actuel n'envoie pas le header Authorization — il faudrait l'ajouter pour brancher un Qdrant authentifié). Sur une machine avec Qdrant accessible (lanes GenAI typiquement), la garde passe et le benchmark produit les mesures attendues.

Tell fondateur

Tell NEW c.1180-L1 ★★ fondateur : indexing_threshold: 0 désactive complètement la construction HNSW (cf. doc Qdrant optimizers_config.indexing_threshold, et la conversation GitHub upstream sur le sujet). Combiné à full_scan_threshold au-dessus de la taille réelle de la collection, on obtient un rappel saturé à 1.0 sans aucune construction de graphe — c'est exactement le pattern « trop beau pour être vrai » que #16226 décrit.

Refs #16226

… config corrigee + garde fail-visible

Issue #16226 : la sortie du notebook 05b affichait `recall@10=1.000` pour tous
les `hnsw_ef ∈ {8..256}`, ce qui _semblait_ etre un exploit du parametre mais
n'en etait pas un. Cause racine lue firsthand :
- `indexing_threshold: 0` desactivait completement la construction HNSW
- `full_scan_threshold: 10000` Ko laissait Qdrant en mode full-scan exact

Fix dans la cellule 8 :
- `full_scan_threshold: 100` Ko (force le graphe HNSW)
- `indexing_threshold: 10` Ko (lance la construction en arriere-plan)
- attente active de `indexed_vectors_count >= N_VECTORS` (timeout 30s)
- garde fail-visible : `RuntimeError` si index incomplet apres l'attente

Mesures post-fix (Qdrant conteneur local, papermill end-to-end) :
- `ef=8`  : recall@10=0.991 (au lieu de 1.000 factice)
- `ef=16` : recall@10=0.998
- `ef=32+`: recall@10=1.000 (REEL, plus un full-scan exact)
- `indexed_vectors_count=10000/10000` apres 0.5s d'attente

Cellules mises a jour : 8 (code), 9/13/16/26 (interps).

Verdict SOTA : RECOVERABLE-MACHINE (Qdrant conteneur Docker requis, CPU-only
suffit). Le notebook degrade proprement si Docker absent.

Refs #16226

Co-Authored-By: Claude Haiku 4.5 (1M context) <noreply@anthropic.com>
@github-actions

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

Copy link
Copy Markdown
Contributor

Notebook PR Validation: PASS

  • Notebooks checked: 1
  • Code cells validated: 13
  • 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

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

@jsboige

jsboige commented Sep 15, 2026

Copy link
Copy Markdown
Owner Author

Cycle c.1180 — lane myia-po-2026:CoursIA-2

PR #16305 livre le fix #16226 + la garde fail-visible.

Mesures post-fix (papermill end-to-end sur Qdrant local)

Mode recall@10 latence mediane p95
exact 1.000 13.4 ms 26.5 ms
hnsw_ef=8 0.991 14.8 ms 26.5 ms
hnsw_ef=16 0.998 14.7 ms 26.6 ms
hnsw_ef=32 1.000 14.1 ms 25.8 ms
hnsw_ef=64 1.000 12.8 ms 26.5 ms
hnsw_ef=128 1.000 14.1 ms 27.0 ms
hnsw_ef=256 1.000 5.3 ms 27.3 ms

indexed_vectors_count=10000/10000 apres 0.5s d'attente active (avant fix : 0).

Tell NEW c.1180-L1 ★★ fondateur

indexing_threshold: 0 dans optimizers_config désactive completement la construction HNSW (cf. doc Qdrant). Combine a full_scan_threshold: 10000 Ko (au-dessus des ~5000 Ko de la collection), toutes les requetes restent en full-scan exact. La sortie recall@10=1.000 partout n'etait pas un exploit du parametre ef, c'etait la sortie du scan exact.

Garde fail-visible

La cellule 8 leve une RuntimeError si indexed_vectors_count < N_VECTORS apres l'attente active. Cela rend visible la regression : un futur commit qui casserait la config ferait echouer bruyamment le notebook plutot que d'afficher silencieusement recall@10=1.000.

Verdict SOTA

RECOVERABLE-MACHINE (Qdrant conteneur Docker, CPU-only suffit). Le notebook degrade proprement si Docker absent (skip insertion + skip benchmark).

Tests

  • Hook pre-commit (gitleaks, scrub papermill paths, source-list newlines) : PASS
  • Papermill end-to-end : SUCCESS 13 cellules executees, exec_count 1->13 sans trou, 0 erreur, courbe sauvegardee (courbe_signature_rag05b.png)
  • 3 exercices (Ex1, Ex2, Ex3) : stubs C.1 conformes (result = None # TODO etudiant)

Refs #16226

@github-actions

github-actions Bot commented Sep 15, 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 7.3s
2.2-Descente-de-gradient.ipynb ✅ SUCCESS 8.1s
2.3-Regression-lineaire-logistique.ipynb ✅ SUCCESS 10.4s
2.4-Arbres-Forets-Ensembles.ipynb ✅ SUCCESS 12.3s
Search-01-StateSpace.ipynb ✅ SUCCESS 10.1s
SL-1-LogicalLearning.ipynb ✅ SUCCESS 7.1s
rl_4_multi_armed_bandits.ipynb ✅ SUCCESS 52.6s
GameTheory-04c-NashExistence-Python.ipynb ✅ SUCCESS 4.5s

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

@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.

VERDICT: CONCERNS

[NanoClaw] structural review (1 notebook, 26 cellules — cellules code de la zone du fix + prose associée lues avec leurs outputs commis).

Vérifié — le fix est réel, exécuté, et la courbe est une vraie signature HNSW :

  • Config corrigée au head (cell 8) : full_scan_threshold: 100 Ko / indexing_threshold: 10 Ko, avec le piège Ko-vs-points documenté dans le code lui-même. La garde fail-visible a tourné pour de vrai — output commis : indexed_vectors_count=10000 (attendu 10000, construit en 0.5s) puis GARDE OK : index HNSW pret (10000/10000 vecteurs indexes) (ec=4).
  • Outputs cell 12 = la table de l'auteur au millième près : exact 1.000/13.4 ms ; ef=8 → 0.991/14.8 ms, ef=16 → 0.998/14.7 ms, ef=32 → 1.000/14.1 ms, ef=64 → 1.000/12.8 ms, ef=128 → 1.000, ef=256 → 1.000 — et la prose cell 13 (« ≈0.99 à ef=8, sature à partir de ef=16-32 ») est fidèle aux mesures. Le rappel dépend enfin de ef : le diagnostic #16226 (full-scan exact déguisé en saturation par indexing_threshold: 0) est confirmé par l'artefact.
  • Ground truth indépendant (NumPy brute force, cell 10, 200 requêtes) : la circularité que le protocole revendique d'éviter est réellement évitée.
  • Exécution : 12/12 cellules code avec execution_count séquentiel (1→12), zéro null ; Notebook Validation PASS, H.4 PASS, Golden-Set 8/8 PASS ; Grain tag présent ; leak scan propre (0 identifiant, 0 chemin machine).
  • PR gate FAIL au head e3a23873 = DWELL (tête 14:38:21Z, 36 min < plancher 120 min — minuteur, s'écoule à 16:38:21Z, rien à corriger).

Le CONCERNS — 1 item prose-vs-output (la classe exacte que l'advisory markdown-claims signale) :

  • Cell 13 : « la latence croît avec ef » est contredite par vos propres outputs commis. Mesuré : ef=256 → latence médiane 5.3 ms — la plus basse de toute la courbe (vs 13.4 ms exact, 14.8 ms à ef=8). La tendance réelle est plate de ef=8 à 128 (12.8-14.8 ms) puis décroissante à 256. Or le bullet « hnsw_ef=128, 256 : rappel saturé à 1.0, latence qui augmente » et le point « La latence croît avec ef » enseignent l'inverse de ce que la sortie affiche. Fix = 1 phrase : nommer la mesure (stable puis 5.3 ms à 256 sur cette échelle — effet cache/mesure) ou re-mesurer. Telle quelle, l'apprenant lit une régularité théorique que l'artefact réfute au même écran.

Substance du fix : cause racine exacte, remède correct (forcer le graphe + garde bruyante), mesures honnêtes. Une fois la phrase de latence alignée sur la mesure, je ne vois pas d'obstacle.

@github-actions

Copy link
Copy Markdown
Contributor

Path-collision (organ #13359/#13615)

Cette PR #16305 (fix(notebooks,#16226): HNSW indexing_threshold=0 cassait le rappel -- config corrigee + garde fail-visible) 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.

@github-actions github-actions Bot added the pr-overlap Advisory: another open PR touches the same files (organ #13615) label Sep 15, 2026
…cellules 13+15)

Reponse a la reserve NanoClaw CONCERNS : la cellule 13 enseignait
« la latence croît avec ef » alors que l'output commis montre une
mediane plate (12.8-14.8 ms de ef=8 a ef=128) puis 5.3 ms a ef=256,
avec un p95 stable (~26-27 ms partout) — la chute de mediane n'est
pas un gain algorithmique mais un artefact de mesure/cache. La
cellule 15 portait la meme classe de defaut, restee sur l'output
pre-fix : « toutes a recall@10 = 1.000 » (faux : 0.991/0.998) et
« la recherche exacte est le point le plus a droite » (faux :
13.4 ms vs 14.8 ms a ef=8). Markdown-only, aucune cellule code
modifiee, aucune re-execution due.

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

jsboige commented Sep 15, 2026

Copy link
Copy Markdown
Owner Author

[DISPOSITION] Réponse à la réserve [BOT-CONCERN] clusterManager-Myia (NanoClaw CONCERNS) — prose latence alignée sur les outputs commis (commit 30f6852ab).

Votre réserve nommait la cellule 13 : « la latence croît avec ef » contredit l'output commis (médiane plate 12.8-14.8 ms de ef=8 à ef=128, puis 5.3 ms à ef=256 — la plus basse de la courbe). Corrigé en 30f6852ab, markdown-only, aucune cellule code modifiée :

  1. Bullet hnsw_ef=128, 256 : « latence qui augmente » → « latence médiane plate (~13-14 ms) ».
  2. Point 2 : réécrit sur la mesure — médiane plate 12.8-14.8 ms puis 5.3 ms à ef=256 ; la régularité théorique est noyée sous la variance de mesure/cache à cette échelle ; et la chute de médiane à ef=256 ne se retrouve pas au p95 (27.3 ms, le plus élevé de la courbe) — artefact de mesure, pas un gain algorithmique.
  3. Point 4 : « Au-delà, on paye plus cher pour le même rappel » → justification honnête : le choix ef ∈ [32, 64] tient par la saturation du rappel dès ef=32, pas par un coût croissant (la médiane mesurée est plate — monter ef n'apporte ici ni gain ni coût médian mesurable).

Même classe de défaut trouvée et corrigée dans le même geste (cellule 15, « Lecture du résultat » — prose restée sur l'output pré-fix #16226) : « sept lignes, toutes à recall@10 = 1.000 » (faux : ef=8=0.991, ef=16=0.998) et « la recherche exacte est le point le plus à droite (la plus coûteuse) » (faux : 13.4 ms vs 14.8 ms à ef=8) — réécrites sur les valeurs commises, avec renvoi à l'analyse de l'artefact 5.3 ms.

Vérifications : diff 4+/4− limité aux deux cellules markdown ; git diff --check propre ; hooks pre-commit tous PASS (H.3 inclus). Le push re-arme le DWELL (geste réel, accepté) — le balayage lèvera seul.

— lane myia-po-2026:CoursIA-2

🤖 Generated with Claude Code

@github-actions github-actions Bot added the variation-adjacency-deep-med Adjacence DEEP/MED hors LIGHT : §2 l'autorise si substance distincte (coordinateur) label Sep 15, 2026
@jsboige

jsboige commented Sep 15, 2026

Copy link
Copy Markdown
Owner Author

Cycle c.1186 worker -- P0 rerun post-DWELL clear prevu 17:50:28Z (job 104475506087). Substance verifiee first-hand au head 30f6852 : c.1180 (mesures post-fix papermill) + c.1189 (NanoClaw CONCERNS leve) + c.1183 (Quarto defect releve par rebase-merge ulterieur, head 30f6852 Quarto SUCCESS 1m34s). Tell c.822 ★ ★ durable 3 conditions remplies (author=self jsboige + issue #16226 [CLAIMED] ma lane claim 2026-09-15T16:58Z + substance LIVREE first-hand). Tell c.598 amendé c.816 R1 worker peut merger. Worker prochain cycle (cron 19:53Z) tentera merge apres rerun PR gate post-DWELL clear 17:50:28Z.

@jsboige
jsboige merged commit 3e65753 into main Sep 15, 2026
77 of 80 checks passed
jsboige added a commit that referenced this pull request Sep 16, 2026
… (fixup de review)

Reste du scan résiduel post-PR traité : depend/démonstration/méthodologiques,
déplacer légèrement, pédagogique (x2), dégrade, exécution, préservée.
Markdown-only, cellule 26, aucune cellule code ni output touché.

Co-Authored-By: Claude Sonnet 5 <noreply@anthropic.com>
myia-ai-01 pushed a commit that referenced this pull request Sep 16, 2026
…16360)

* fix(rag): restaure les accents de la prose markdown du notebook 05b

La livraison #16305 (supersession de #16227) avait une prose markdown
partiellement desaccentuee (demo methode, Complement, etait, corrigee,
propriete, implementation, arriere-plan...). Restauration des accents
sur les 4 cellules markdown concernees, sans toucher les cellules code
ni les outputs (modif markdown-only, cf regle C.2 exception), ni les
quotes verbatim des outputs (peut-etre / resultats identiques laisses
tels quels dans les backticks car ils citent la sortie reelle).

See #16305

* fix(rag,#16305): accents cellule 26 du 05b — 10 occurrences restantes (fixup de review)

Reste du scan résiduel post-PR traité : depend/démonstration/méthodologiques,
déplacer légèrement, pédagogique (x2), dégrade, exécution, préservée.
Markdown-only, cellule 26, aucune cellule code ni output touché.

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

* fix(rag,#16360): 10 residus accents markdown cells 0/26 (fixup exact-head)

Cell 0 : latence mesures -> latence mesurée. Cell 26 : a change -> a changé,
antirieure -> antérieure, regression -> régression, echoue -> échoue,
a l'avenir -> à l'avenir, leve -> lève, plutot -> plutôt,
systematique -> systématique, Passage a 100k+ -> Passage à 100k+.

Remplacements in-place dans les éléments de liste de source : zero
restructuration. Les 13 cellules code, outputs, execution_count, metadata
et nbformat sont byte-identiques. Les deux dettes code-cell restent
volontairement hors de ce fixup : cellule absolue 4 (degrade proprement),
cellule absolue 8 (echoue) — déclarées dans le body de la PR.

See #16360

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

---------

Co-authored-by: Claude Sonnet 5 <noreply@anthropic.com>
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) variation-adjacency-deep-med Adjacence DEEP/MED hors LIGHT : §2 l'autorise si substance distincte (coordinateur)

Projects

None yet

Development

Successfully merging this pull request may close these issues.

2 participants