Skip to content

feat(ict,#17740): F-Lens/S-Lens sur capture dense — contraste quadri-instruments (volet outillage) - #18837

Merged
myia-ai-01 merged 1 commit into
mainfrom
feature/17740-four-instrument-contrast
Oct 2, 2026
Merged

myia-ai-01 merged 1 commit into
mainfrom
feature/17740-four-instrument-contrast

Conversation

@jsboige

@jsboige jsboige commented Oct 2, 2026

Copy link
Copy Markdown
Owner

Grain: DEEP/notebook-python — lane myia-po-2025:CoursIA — prev: DEEP/notebook-python #18829

See #17740 (KEEP path 1, volet outillage — le rapport mesuré quadri-instruments suit dans une PR fille, après la passe GPU).

Ce que la PR livre

Le volet outillage du contraste quadri-instruments #17740 : F-Lens et S-Lens deviennent mesurables sur le même substrat que SAE (ICT-21) et J-Lens (ICT-24), sous le même contrat d'alignement.

Fichier Rôle
ict/flens_traces.py Chargeur de capture dense + mesures F-Lens : NC@p par prompt (weighted_pca/nc_at de factor_geometry), alignement des top-k sous-espaces intra-jeu vs inter-jeux contre nulle appariée (paires de sous-espaces aléatoires — la forme prescrite par l'avertissement de null_overlap_distribution, pas la primitive-artefact)
ict/slens_traces.py S-Lens transposé au banc réel : probe ridge de self-location positionnelle (organe ict.slens.ridge_probe/probe_metrics réutilisé tel quel), lecture pooled + extrapolation par prompt, contrôle shuffle des étiquettes
ict/geometry_contrast.py contrast() étendu : --dense (ou autodécouverte traces/ict25_dense_layer16_trained.npz) → F-Lens/S-Lens mesurés après garde d'alignement (model/layer/seed/variant + tokens strictement égaux) ; per_set_summary = table de lecture croisée par jeu, jamais un score composite. Sans capture dense : absences explicites inchangées (rétrocompatible)
scripts/extract_dense_traces.py Extracteur GPU de la capture dense : même bench (PROMPT_SETS importé d'extract_sae_traces, source unique), même couche 16, même tokenisation, hook CaptureHook réutilisé ; --check-align exige l'égalité exacte des tokens contre ICT-21 avant d'écrire ; variant control = permutation seedée des embeddings (convention ICT-21)
3 fichiers de tests 31 tests nouveaux : roundtrip chargeur, refus de trace partielle/méta incomplète/désalignement, récupération de structure factorielle connue (same-set au-delà de la nulle, cross-set en dessous), décodage positionnel (R²>0.95, shuffle au plancher), bruit isotrope (verdict faux, R² bas), intégration contraste

Validation

  • python -m pytest tests/ -q (série ICT complète, post-dernier-commit) : 1280 passed, 8 warnings — dont 31 nouveaux ; 0 échec.
  • CLI rétrocompatibilité sur les traces committées (sans capture dense) : python -m ict.geometry_contrast --traces-dir traces → comptes SAE/J-Lens inchangés (colocalized 0, dissociated 0, chance 4, undefined 16), f_lens/s_lens restent not_comparable, pas de per_set_summary.
  • scripts/extract_dense_traces.py : AST-parse OK ; l'exécution exige torch+CUDA (ci-dessous), ruff F821/F401/F841 à zéro sur les 7 fichiers touchés.

Verdict SOTA — RECOVERABLE-MACHINE (stated, pas maquillé)

La capture dense elle-même (9B bf16 ≈ 18-19 GiB) ne tient pas sur le GPU local 16 Go : routée vers GPU 2 d'ai-01 (convention extract_sae_traces : vLLM tient GPU 0-1), RECOVERABLE-MACHINE :

CUDA_VISIBLE_DEVICES=2 python scripts/extract_dense_traces.py --stage smoke --check-align traces/ict21_sae_layer16_trained.npz
CUDA_VISIBLE_DEVICES=2 python scripts/extract_dense_traces.py --stage full  --check-align traces/ict21_sae_layer16_trained.npz

Les modules de mesure sont eux validés dès maintenant sur fixtures synthétiques à vérité connue (tests ci-dessus) : structure factorielle → verdict same-set au-delà de la nulle ; position linéaire → R² > 0.95. Le rapport mesuré sur le banc 9B réel (et le commit du npz ~20 Mo avec décision de dépôt vs GDrive) vit dans la PR fille — cette PR ne prétend aucune mesure réelle non exécutée.

Décisions de conception (pièges mesurés, consignés dans le code)

  • frobenius_alignment = ‖B₁ᵀB₂‖_F/√k, pas la moyenne des |cos| : celle-ci vaut 1/k pour des bases identiques (seule la diagonale est non nulle) et passe SOUS le hasard quand k grandit — mesuré sur le fixture (0.125 identiques vs 0.2 aléatoires à k=8).
  • Nulle appariée sans PCA : un PCA sur une base orthonormale lue comme activations rend R^k entier → alignement 1.0 systématique (piège mesuré) ; les bases nulles passent par le même comparateur _basis_statistics que les paires réelles, sans l'étape PCA.
  • S-Lens = méthode, pas oracle : le banc de textes naturels n'a pas d'oracle variable→valeur ; le module mesure la décodabilité positionnelle (interpolation pooled vs extrapolation par prompt, rapportées séparément) et le dit dans son interprétation.

🤖 Generated with Claude Code

…-instruments

- ict/flens_traces.py : chargeur dense + NC@p, alignement top-k intra/inter
  jeux contre nulle appariee (paires de sous-espaces aleatoires, forme
  prescrite par l'avertissement de null_overlap_distribution)
- ict/slens_traces.py : probe ridge de self-location positionnelle sur le
  banc reel (organes ict.slens reutilises), pooled + extrapolation par
  prompt, controle shuffle
- ict/geometry_contrast.py : --dense -> F-Lens/S-Lens mesures sous garde
  d'alignement (model/layer/seed/variant + tokens egaux), per_set_summary ;
  retrocompatible sans capture dense (absences explicites)
- scripts/extract_dense_traces.py : extracteur GPU (bench PROMPT_SETS
  importee, couche 16, --check-align exige l'egalite des tokens vs ICT-21)
- tests : 31 nouveaux (structure factorielle recuperee, decodage
  positionnel, nulle sans PCA, bruit isotrope, integration contraste)

Serie ICT complete : 1280 passed.

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

github-actions Bot commented Oct 2, 2026

Copy link
Copy Markdown
Contributor

No organ-duplication: no added def/class collides with another series organ API (scripts/audit/organ_api_index.yaml).

Detector: python scripts/audit/detect_organ_duplication.py --base <merge-base> --body-file <pr body>
Rationale: #16776 / #13564 (rule merged in #16778).

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

@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: LGTM

[Hermes] — review du head 7c7e0e9e (volet outillage quadri-instruments #17740, +925/−11, 7 fichiers). Deep review avec exécution firsthand.

Tests exécutés au head (staging complet : 8 modules ict/ + les 2 traces npz réelles ict21_sae_layer16_trained.npz / ict24_jlens_layer16_trained.npz téléchargées au SHA) : 31/31 passés (pytest tests/test_flens_traces.py tests/test_slens_traces.py tests/test_geometry_contrast.py), 1 warning rétro-compat attendu (manifeste SAE historique sans instrument). Le premier échec de run était un artefact de staging (npz absents de mon arbre), pas de la PR.

Lecture intégrale des 3 modules — points vérifiés :

  • Contrat d'alignement fail-loud : _aligned_dense refuse (ValueError) model/layer/seed/variant divergents, jeux de prompts différents, et tokens non strictement égaux (np.array_equal par prompt) — la PR fait ce que son body promet : « refuse plutôt que de présenter un substrat différent comme le même run ».
  • Nulle appariée à chemin partagé : null_pairs passe les bases QR par le même _basis_statistics que les paires réelles — la statistique observée et la nulle ne peuvent pas diverger de calcul ; le docstring documente aussi le piège PCA-sur-base-orthonormale évité (R²≡1 systématique).
  • S-Lens sans réimplémentation : ridge_probe/probe_metrics importés de ict.slens existant au head (vérifié contents API), shuffle-control qui ne permute que le train, held-out intact. Les deux échelles (pooled interpolatif / par-prompt extrapolatif) rapportées séparément, jamais fusionnées — conforme au contrat « quatre lectures, jamais un score composite ».
  • extract_dense_traces.py : prompts importés d'extract_sae_traces (source unique, pas de copie), --check-align exige l'égalité des __tokens contre ICT-21 avant d'écrire, torch confiné dans scripts/, garde GPU unique réutilisée.
  • Rétro-compat : sans capture dense, f_lens/s_lens restent des absences explicites (not_comparable avec raison) — le comportement des consommateurs existants est inchangé.

Sécurité : 0 ajout au grep credentials. PR gate fail = jambe DWELL documentée (tête 10:55:54Z, plancher 120 min — minuteur, rien à corriger), tous les autres organes verts au head.

Le grain de mesure (beyond_null = moyenne vs q95 de la nulle appariée, verdict faux ≠ absence de structure) est correctement rapporté comme lecture et non comme preuve. Rien à corriger.

[Hermes hermes-pr-review, cycle :11 02/10, host f6be46d1b7a3, sig=f11fb7ed]

@jsboige

jsboige commented Oct 2, 2026

Copy link
Copy Markdown
Owner Author

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

@myia-ai-01
myia-ai-01 merged commit c89b374 into main Oct 2, 2026
23 of 24 checks passed
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

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.

3 participants