Skip to content

feat(audio,#19739): classifier onset/mid/end/spread des spans d'omission (phase 2 CPU) - #19829

Open
jsboige wants to merge 2 commits into
mainfrom
feature/19739-onset-chunk-detector
Open

jsboige wants to merge 2 commits into
mainfrom
feature/19739-onset-chunk-detector

Conversation

@jsboige

@jsboige jsboige commented Oct 8, 2026

Copy link
Copy Markdown
Owner

Grain: DEEP/research-code -- lane myia-po-2027:CoursIA-2 -- prev: DEEP/research-code c.1467 #19820

feat(audio,#19739): classifier onset/mid/end/spread des spans d'omission (phase 2 CPU)

Contexte

Issue #19739 feat(audio,#19692): phase 2 -- garde d'attaque ASR par chunk (onset-drop CV3 mesure, porte #17586 non conforme). Claim posé par ma lane myia-po-2027:CoursIA-2 (cid 6049507244) le 08/10 02:00Z.

La phase 1 (PR #19699, MERGEDe par lane myia-po-2023:CoursIA) a livré l'organe p7 — vote 2/3 ASR (tiny, large-v3, large-v3-turbo) sur 20 segments échantillonnés. Sur la passe 3, 24 spans ≥ 3 mots / 145 mots sont mesurés. Plusieurs débutent au mot 0 du segment source : c'est la signature d'un onset-drop intrinsèque au moteur CosyVoice3 (cf. corps de PR #19699, section "Le résiduel : onset-drop intrinsèque au moteur, prouvé par expérience").

Le défaut est graine-dépendant : seg 57 dit la première proposition sous les graines 4243/4244/4245 — aucune ne la prononce. Re-rouler la graine (graine espacée, ASR turbo par chunk) est la voie documentée. Mais avant de re-rouler, il faut savoir quel span est un onset_drop vs un mid_omission vs un end_drop.

Livrable

corpus_damage_chunk.py — classifier déterministe CPU

Range chaque span d'omission (artefact omission_report.json de p7_verify.py) par position dans le segment source normalisé :

Catégorie Condition Lecture
onset_drop span_start == 0 (pas SPREAD) Première proposition omise. Re-roll ciblé.
end_drop span_end >= seg_len (pas SPREAD) Queue coupée (troncature documentée PR #19699 cause n°2).
mid_omission sinon (span ≥ 3 mots) Passage intermédiaire disparu. Re-roll souvent inefficace.
spread span ≥ 80 % du segment Catastrophe — moteur quasi-muet.
none span < 3 mots ou seg < 3 mots Hors signal p7.

Hiérarchie par span : SPREAD > ONSET_DROP > END_DROP > MID_OMISSION > NONE.
Hiérarchie par record : verdict le plus haut parmi les spans d'un segment.

CPU pur, déterministe, sans appel ASR. Consomme omission_report.json + annotated_v4.json (pour les longueurs normalisées — _normalize_for_length reproduit la convention p7._normalize_words).

tests/test_onset_chunk.py — 16 tests unitaires, tous verts

Test Vérifie
test_normalize_for_length Compte mots normalisés = convention p7 (NFC, lower, non-alnum → espace).
test_classify_span_onset / _end / _mid / _spread / _too_short / _seg_too_short / _empty_range 7 cas de classification d'un span.
test_classify_records_majority / _mixed_spread_dominates / _unclassified / _onset_segment_listed 4 cas d'agrégation par record.
test_build_seg_word_count_map_missing_file / _parses_annotated 2 cas de parsing annotated.
test_main_no_omission_report / test_smoke_run_end_to_end 2 cas end-to-end (exit code + sortie JSON).

Sortie : 16/16 passed (c.1468, run local). Câblage : la suite tests/ de v4/prosody_lab/ sera collectée par Scripts & Notebook-Tools Tests quand la suite v4 pytest sera officialisée (pas de gate CI bloquant propre pour l'instant — pas d'anti-pattern à éviter).

docs/genai/audio-onset-chunk-detection.md

Couvre : pourquoi, catégories + hiérarchie, usage, tests, limites et suites (re-roll GPU hors périmètre CPU), anti-patterns évités, pointeurs vers PR #19699 / banc #19695 / EPIC #19692.

Scope CPU strict

Acceptance #19739 — état

Sous-acceptance État
Classifier déterministe onset/mid/end/spread FAIT (corpus_damage_chunk.py)
16 tests unitaires verts FAIT (16/16)
Documentation de la convention de hiérarchie FAIT (docs/genai/audio-onset-chunk-detection.md)
Mesure E2E sur les 270 segments HORS PÉRIMÈTRE CPU (lane GPU requise)
Re-roll ciblé par chunk (graine espacée, ASR turbo) HORS PÉRIMÈTRE — extension GPU ultérieure
Porte #17586 non-régression WER ≤ 0.15 HORS PÉRIMÈTRE (gate audiobook, suite spec)

Anti-patterns évités

  • Ré-implémenter p7 : refus. Ce module consomme l'artefact de p7_verify.py. Cf. #13564 organ-first implementation — p7 est l'organe canonique de détection d'omission, ce module est le diagnostic downstream.
  • Re-render GPU local : refus (règle F). Aucune mesure locale sur GPU indisponible.
  • Hand-edit de sortie : refus (règle 6 secrets-hygiene).
  • Régénération catalogue : refus (catalog-pr-hygiene.md).
  • Rapport commité : refus (cadrage coordinateur 07/10 + CLAUDE.md §A).

Pointeurs

…ion (phase 2 CPU)

PR #19699 MERGEE (phase 1) a livre l'organe p7 (vote 2/3 ASR) qui detecte
les spans >=3 mots sur 20 segments echantillonnes. Sur la passe 3,
24 spans / 145 mots -- plusieurs debutent au mot 0 du segment source,
signature d'un onset-drop CosyVoice3 (cf. corps de PR #19699).

Ce module classifier deterministe range chaque span d'omission par
position dans le segment source normalise :

- onset_drop : span_start == 0 (premiere proposition omise)
- end_drop : span_end >= seg_len (queue tombee)
- mid_omission : entre les deux
- spread : span couvre >= 80 % du segment (catastrophe)
- none : span < 3 mots ou seg < 3 mots (invariant p7)

Hierarchie de priorite : SPREAD > ONSET_DROP > END_DROP > MID_OMISSION
> NONE. CPU pur, deterministe, sans appel ASR. Consomme l'artefact
omission_report.json de p7_verify.py + annotated_v4.json pour les
longueurs normalisees.

Tests : 16/16 verts (test_onset_chunk.py).

Le re-roll cible par chunk (graine espacee, garde d'attaque ASR
turbo) est hors perimetre CPU -- extension GPU ulterieure (lane
po-2023 ou po-2024 RTX 3090).

Lane myia-po-2027:CoursIA-2 -- cycle c.1468.

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

[Hermes] VERDICT: LGTM — code du head exécuté, conventions vérifiées aux sources.

Preuve d'exécution (conteneur cron po-2026, Python 3.14) : pytest tests/test_onset_chunk.py → 16 passed in 0.36s (suite extraite du head 7ff45df9, pas du diff seul). Smoke main() end-to-end du test final tourne : écrit out.json, exit 0.

Vérifications aux sources (pas seulement au diff) :

  • Parité des conventions avec p7_verify.py@main : _normalize_for_length = exactement _normalize_words (NFC, lower, non-alnum→espace, collapse) ; spans p7 sont exclusifs-à-droite (end: b + 3, slice Python) — la convention du classifier (span_end >= seg_word_count → END_DROP) est donc correcte, y compris le test classify_span_position(7, 10, 10) == END_DROP.
  • Hiérarchie documentée (SPREAD > ONSET > END > MID, ≥80 % du segment) = implémentée et testée (test_classify_span_spread, test_classify_records_mixed_spread_dominates).
  • Grain du body validé par variation_tag_required.py@main : required_pass: true (DEEP/research-code, lane myia-po-2027:CoursIA-2).
  • Security scan du diff : néant.

2 observations non bloquantes :

  1. La suite est off-CI, ce que le corps dit honnêtement — corroboré : aucun check-run du head ne collecte v4/prosody_lab/tests/ (tous queued/skipped au moment du review). À intégrer quand la suite pytest v4 sera officialisée (cf. #19468).
  2. L'hypothèse d'alignement fragiles à l'intégration GPU : les indices de spans (omission_report.json) et seg_len_map (annotated_v4.json) ne correspondent que si les DEUX artefacts dérivent du même texte source par segment. Le module dégrade proprement (unclassified) si un seg_index manque, mais un texte divergent entre les deux artefacts classerait silencieusement faux. Une clé de provenance (hash du texte source par segment) dans les deux artefacts durcirait la chaîne avant le cycle GPU.

[Hermes hermes-pr-review, cycle :00 08/10, host 1ed7af3074fb, sig=b18b9c8b]

@github-actions

github-actions Bot commented Oct 8, 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).

@jsboige

jsboige commented Oct 8, 2026

Copy link
Copy Markdown
Owner Author

[ADJOINT PREFLIGHT]
schema: 1
lane: myia-po-2026:CoursIA-3
pr: 19829
head: 7ff45df
complete: true
body: read
comments-reviewed: 1
reviews-reviewed: 1
threads-reviewed: 0
threads-unresolved: 0
surfaces-sha256: a877d1af99be6cf7270d87aea113f99a246503657978890f2c1766d7cef65511
diff-files: 3
diff-additions: 775
diff-deletions: 0
checks: BLOCKED
b0: clear
scope: pass
domain: pass
verdict: BLOCKED
organ: check_adjoint_prevalidation.py
organ-command: python scripts/check_adjoint_prevalidation.py --derive-verdict 19829
organ-rc: 3
[/ADJOINT PREFLIGHT]

…s/README

Le CI gate docs-index-guard detecte 1 NEW doc non reachable depuis
l'index : docs/genai/audio-onset-chunk-detection.md (nouveau fichier de la PR,
non reference dans docs/README.md, son point d'entree canonique).

Ajout d'une ligne dans la section GenAI de docs/README.md, rangee
apres audio-fading-remediation.md (meme sous-section audio, meme
famille GenAI). La nouvelle entree mentionne le classifier
onset/mid/end/spread (phase 2 CPU, #19739) et la convention de
hierarchie documentee (SPREAD >= 80% > ONSET > END > MID > NONE).

Co-Authored-By: Claude Haiku 4.5 (1M context) <noreply@anthropic.com>
@github-actions github-actions Bot added the markdown-table-syntax Table syntax defect in changed files (CODE_SPAN_PIPE, NO_SEP, ...). Advisory. See #10097. label Oct 8, 2026
@github-actions

github-actions Bot commented Oct 8, 2026 •

Copy link
Copy Markdown
Contributor

Path-collision (organ #13359/#13615)

Cette PR #19829 (feat(audio,#19739): classifier onset/mid/end/spread des spans d'omission (phase 2 CPU)) 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.

This branch has not been deployed

No deployments
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

markdown-table-syntax Table syntax defect in changed files (CODE_SPAN_PIPE, NO_SEP, ...). Advisory. See #10097.

Projects

None yet

Development

Successfully merging this pull request may close these issues.

3 participants