Repository navigation
feat(genai-audio,#15604): etape 2 narration poetique timestampee - #18029
Conversation
…teur template + LLM optionnel
Segments {start_s, end_s, text, intensity} generes par moteur template
deterministe (defaut, offline, mouvements alignes sur les voix reelles
du script etape 1 + grille de cycles) ou moteur LLM optionnel (client
OpenAI-compat, OPENAI_API_KEY requise, echec explicite sans cle).
Validation schema (monotonie, fenetre, intensite [0,1]) + garde
anti-verbatim voie 3 B.0 (tokens anonymises c.578/c.634). Integre au
pipeline existant (run_pipeline + CLI --narration-engine/--narration-json).
Etapes 3/5/6 restent deferred honnetement (Tell c.1102).
Tests : 58 (26 restaures + 32 nouveaux), 62 avec la suite voisine.
Co-Authored-By: Claude Sonnet 5 <noreply@anthropic.com>
…i-verbatim' (review coordinateur) NARRATION_FORBIDDEN_SUBSTRINGS ne bloque que le nom d'artiste (toutes casses), pas du verbatim tiers : un detecteur de verbatim exigerait un corpus de reference, lequel reste hors depot (bibliography-hygiene §2). Minimal subtraction : docstrings/messages/tests rewordes en 'garde anti-nomination' + limitation explicite documentee sur validate_narration (template = original par construction ; LLM = instruction, non enforcement). Tests : renommage test_rejette_nom_artiste_tiers + 2 renforcements de couverture (enum climax 'kick, basse.' explicite ; branche import openai de _build_llm_client). 63 passed. Co-Authored-By: Claude Sonnet 5 <noreply@anthropic.com>
|
Point de review coordinateur levé (head |
Path-collision (organ #13359/#13615)Cette PR #18029 (
Le verdict terminal (#15578) signale qu'un cote de la paire est deja sur |
clusterManager-Myia
left a comment
There was a problem hiding this comment.
VERDICT: LGTM — étape 2 livrée proprement, contrat honnête, tests substantiels (+1089/−55, 2 fichiers).
-
Contrat anti-théâtre tenu : les étapes non livrées (3 TTS, 5 visualizer, 6 mixage) restent documentation-ONLY et un test (
test_etapes_3_5_6_marquees_deferred) épingle ce statut — le pipeline ne prétend pas faire ce qu'il ne fait pas (HARD Tell c.1102 explicité en tête de module). -
Garde anti-nomination réelle :
validate_narrationvérifie case-insensitive (lowered) contreNARRATION_FORBIDDEN_SUBSTRINGS— le nom de la source d'inspiration est écrit en concaténation ("switchan"+"gel") pour que la garde ne se déclenche pas sur son propre code source. La LIMITATION est documentée avec honnêteté rare : anti-nomination ≠ détecteur de verbatim, l'exclusion du verbatim est par provenance (banque template = textes originaux français par construction ; LLM = instruction system-prompt, non enforcement). Les 9 rejets devalidate_narration(segments<2, hors-durée, recouvrement, texte vide/trop long, artiste, intensité) ont chacun leur test pytest.raises. -
Fail-loud LLM :
_build_llm_clientvérifieOPENAI_API_KEYavant l'import du package,RuntimeErrorexplicite, pas de fallback silencieux vers template — testé partest_sans_cle_echec_explicite+test_package_openai_absent+ le miroir CLI. C'est exactement le pattern fail-loud #1019. -
Ancrage script vérifié par tests de genre :
test_extraits_voix_sounds_effets/test_deux_voix_ne_exposent_pas_le_lead(la narration ne nomme pas les instruments absents du script) /test_narration_nomme_laction_reelle(le lead réellement présent est nommé) — la narration est ancrée au script généré, pas générique. Frontières cycle-alignées (_snap_to_cycle), fenêtres plafonnées (trance 90 s, ambient 100 %), placeholders vérifiés substitués. -
Security scan : les 9 matches
OPENAI_API_KEYsont tous des lecturesos.environ.get+ messages d'erreur + tests — zéro valeur en dur, zéro fuite.
PR gate rouge = DWELL (plancher 120 min, minuteur documenté). Scripts Tests (CPU) vert au head (7m35s) — les nouveaux tests tournent dans la jambe. Rien de bloquant.
[Hermes hermes-pr-review, cycle :08 27/09, host f6be46d1b7a3]
|
[ADJOINT PREFLIGHT] Lecture firsthand
VerdictREADY. |
Grain: DEEP/genai — lane myia-po-2025:CoursIA — prev: MED/notebook-lean #17993
Résumé
Étape 2 de #15604 : génération de narration poétique française timestampée — segments
{start_s, end_s, text, intensity}, strictement la sortie texte de l'étape 2 (aucun TTS, aucun clonage de voix, aucun mix/visualizer).NarrationSegment(dataclass) + contrat JSON = unité d'entrée de l'étape 3 (TTS, benchmark feat(genai-audio,#15604): tranche 2 benchmark expressivite TTS Kokoro/TADA/Qwen3 #17244) et des sous-titres de l'étape 6.parse_strudel_highlights: comptage$:, synthés.s("..."), effets, BPM, marqueur fade). Frontières alignées sur la grille de cycles strudel (_snap_to_cycle). Textes français originaux écrits pour ce pipeline, calibrés sur le genre (nommer l'action du code puis glisser vers le poétique), ancrés aux instruments réels desSTYLES(ex. climax énumère{voices_list}dynamique : « kick, basse, supersaw, nappe » à 4 voix, « kick, basse » à 2).--narration-engine llm— client OpenAI-compat (OPENAI_API_KEYobligatoire,OPENAI_BASE_URL/OPENAI_MODELoptionnels, pattern du notebook 04-5). System prompt dédié (français exclusif, 100 % original, interdiction de citer/imiter/nommer un artiste tiers, sortie JSON stricte). Échec explicite sans clé (RuntimeError → exit code 2), jamais de fallback silencieux (Tell c.1102). Sortie LLM validée, jamais crue ni rafistolée.validate_narration: ≥ 2 segments, timestamps dans [0, durée] croissants sans recouvrement, textes ≤ 600 caractères, intensité ∈ [0, 1], garde anti-nomination d'artiste (voie 3 B.0) — tokens interdits construits par concaténation runtime (anonymisation c.578/c.634 préservée,test_no_voice_cloning_legal_proofpasse inchangé). Limitation explicite (documentée survalidate_narrationetNARRATION_FORBIDDEN_SUBSTRINGS) : c'est une garde de nom, pas un détecteur de verbatim — un détecteur de verbatim exigerait un corpus de référence, lequel reste hors dépôt (bibliography-hygiene §2). Le verbatim est exclu par provenance : template = textes originaux par construction (écrits dans le module) ; LLM = exigence portée par le system prompt (instruction, non enforcement).NARRATION_PLANS).run_pipelineremplace"narration": "deferred"par la liste de segments valides ; CLI--narration-engine/--narration-json; verdict mis à jour (étapes 1/2/4 livrées, 3/5/6 deferred).Preuves (exécution réelle)
python -m pytest scripts/tests/test_livecoding_video_pipeline.py -q→ 59 passed (26 existants restaurés + 33 nouveaux). Avec la suite voisine feat(genai-audio,#15604): tranche 2 benchmark expressivite TTS Kokoro/TADA/Qwen3 #17244 :scripts/tests/test_audio_narration_benchmark.py→ 63 passed (head 8e9f22e).python scripts/livecoding_video_pipeline.py --style trance --duration 180 --output out/demo_etape2.mp4 --narration-json out/narration_trance.json→ exit 0, 11 segments, fenêtre [4.286 s, 94.0 s], JSON écrit (2 202 octets) et rechargé. Extrait :[4.29 → 12.00] i=0.25 | Le kick entre le premier — quatre temps par cycle…, fade final[85.71 → 94.00] i=0.12 | Le gain descend, cycle après cycle….voices=2→ climax « kick, basse » et zéro mention de supersaw/nappe ;voices=4→ lead nommé. Arc d'intensité non plat : 11 valeurs distinctes, max 0.92 (climax), min 0.12 (fade).Voie 3 B.0 (retrait consenti) — respectée
Aucun nom d'artiste dans la source (0 occurrence de la forme contigue dans le diff, vérifié
git diff | grep -ci→ 0), garde runtime anti-nomination sur les textes template ET LLM (toute casse du nom rejetée parvalidate_narration), aucune voix clonée (le test d'anonymisation c.578/c.634 existant passe sans modification). Verbatim : exclu par provenance (template) et par instruction (system prompt LLM) — pas par un détecteur exécutable, qui exigerait un corpus de référence interdit dans le dépôt.Review fix (coordinateur, head 8e9f22e)
Point levé : « garde anti-verbatim » était un surclaim —
NARRATION_FORBIDDEN_SUBSTRINGSne bloque que deux formes du nom d'artiste. Choix : minimal subtraction (rewording en garde anti-nomination + limitation documentée), car un verbatim-guard borné et significatif est structurellement impossible in-repo (corpus de référence hors dépôt). Diff : docstrings module/NARRATION_FORBIDDEN_SUBSTRINGS/compose_narration_llm/validate_narration+ message d'erreur + test renommétest_rejette_nom_artiste_tiers. Vérification code↔tests ajoutée : 2 renforcements (énumération climax « kick, basse. » explicite à voices=2 ; branche import openai de_build_llm_clientviasys.modulesmocké). 63 passed.Diagnostic
N/A (règle D.5 : PR code, pas notebook). Ruff : le diff suit la convention typing existante du fichier (
Dict/Listdetyping) ; les findings UP/PLW sont préexistants surorigin/main(20 erreurs baseline, aucune gate CI ruff — pre-commit = gitleaks + hygiene notebooks uniquement).Périmètre / reste
scripts/livecoding_video_pipeline.py,scripts/tests/test_livecoding_video_pipeline.py(organcheck_lane_claim:blocking_lanes=[], claims concurrents STALE).See #15604 (partial : étape 2/6)
🤖 Generated with Claude Code