perf(tech-steps): corrige la largeur du textcat — démarrage ~5× plus rapide #25

Merged
kyuno merged 3 commits from perf/nlp-textcat-width into main 2026-09-04 08:14:41 +02:00

3 commits

Author SHA1 Message Date
dfd5a2f650 merge(main): rattrape main (#23 stepper + optimiseur)
All checks were successful
CI / lint (push) Successful in 2m54s
CI / build (push) Successful in 2m50s
CI / intent-service-test (push) Successful in 4m26s
CI / e2e (push) Successful in 8m5s
CI / test (push) Successful in 14m48s
2026-09-03 23:26:20 +02:00
6324a87445 fix(tech-steps): recule sur 65536/unigramme apres regression F1 en CI
Some checks failed
CI / e2e (push) Waiting to run
CI / lint (push) Has been cancelled
CI / test (push) Has been cancelled
CI / build (push) Has been cancelled
CI / intent-service-test (push) Has been cancelled
Le premier essai (length=2048 + ngram_size=2) a fait chuter le F1 agrege de
`tech-step-eval.test.ts` de 0.815 a 0.753, sous le plancher de 0.8. Balayage
mesure (fr, 25 iters, ngram=1, jeu de dev = derniere utterance tenue hors
entrainement ; collisions = tokens distincts partageant un bucket, sur 920) :

  length=262144  dev 97.3%  conf 0.809    2/920 collisions   400 s   <- defaut
  length=65536   dev 97.3%  conf 0.809   10/920 collisions   106 s   <- retenu
  length=16384   dev 97.3%  conf 0.808   50/920 collisions    35 s
  length=2048    dev 97.3%  conf 0.816  305/920 collisions    13 s   <- livre puis recule

Deux corrections :

- ngram_size 2 -> 1. Les bigrammes rendent le classifieur nettement plus
  confiant (0.809 -> 0.919), ce qui degrade la justesse bout-en-bout :
  `_classifyClause` (tech-step-matcher.ts) ne retombe sur l'ancre NER que
  sous CONFIDENCE_THRESHOLD, donc une classification confiante mais fausse
  sur une technique voisine (blindBake au lieu de bake, poach au lieu de
  boil) passe le seuil et ecrase l'ancre correcte. C'etait la seule cause
  de la chute du F1.

- length 2048 -> 65536. A 2048, 305/920 tokens entrent en collision (33 %)
  et la confiance moyenne se decale (0.816 vs 0.809). 65536 : 10 collisions,
  confiance identique au bit pres au defaut spaCy, memes verdicts sur les
  probes difficiles. ~5x plus rapide (vs ~30x pour 2048), 15x moins de
  parametres. Descendre plus bas est possible mais reste du travail pour la
  phase ou le jeu d'evaluation aura ete elargi et pourra le valider.

initialize() fr+en (chargement + entrainement) : 208.9 s contre ~930 s.
Suite pytest : 46 passed en 219.8 s (l'essentiel est le fixture qui entraine
le vrai corpus des deux locales, session-scoped).

start_period / timeout d'attente : 300s -> 600s (plafond pour runner lent).

Non verifie ici : le gate F1 lui-meme (tech-step-eval.test.ts, Postgres +
service requis, pas de Docker dans cet environnement) -> CI. Les 6 autres
echecs du job `test` (resetDatabase / seedReferenceData : contrainte unique
sur `key`, timeouts de hook) sont pre-existants sur `main` @ 81f7cb9 et sans
rapport avec ce changement.

Co-Authored-By: Claude Sonnet 5 <noreply@anthropic.com>
2026-09-03 23:25:05 +02:00
393300205d perf(tech-steps): corrige la largeur du textcat, entrainement 32x plus rapide
Some checks failed
CI / build (push) Successful in 1m27s
CI / e2e (push) Successful in 6m39s
CI / lint (push) Successful in 1m41s
CI / intent-service-test (push) Successful in 3m4s
CI / test (push) Failing after 12m43s
Le service mettait ~930 s (15-16 min) a devenir `healthy`, ce que le README
presentait comme "un compromis assume, pas un defaut de configuration a
corriger". Mauvais diagnostic : le cout ne venait ni des iterations ni de la
taille du corpus, mais du parametre `length` de `spacy.TextCatBOW.v3`, laisse
a son defaut spaCy de 262144 faute d'etre passe explicitement.

Avec `no_output_layer: False` et 74 techniques, la couche de sortie faisait
19 398 730 parametres mis a jour par Adam a chaque pas de gradient, pour une
table de hachage vide a 99 % (le corpus tient dans quelques milliers de
tokens distincts).

Mesure contre le vrai corpus (fr, 25 iterations, jeu de dev = derniere
utterance de chaque technique tenue hors entrainement) :

  length=262144 ngram=1  dev 97.3%  conf 0.809  394.7 s   <- avant
  length=2048   ngram=2  dev 97.3%  conf 0.919   12.3 s   <- apres

Meme accuracy, meilleure confiance, 32x plus rapide. Les bigrammes profitent
des locutions du corpus ("faire fondre", "laisser mijoter") qu'un sac
d'unigrammes ne distingue pas de leurs constituants isoles.

PipelineRegistry.initialize() (fr+en, chargement + entrainement) mesure a
28,5 s contre ~930 s. Suite pytest complete : 46 passed en 40,6 s.

- locale_pipeline.py : `_TEXTCAT_MODEL_LENGTH` / `_TEXTCAT_NGRAM_SIZE`
  explicites et commentes avec les mesures ; historique de calibration de
  `_TRAINING_ITERATIONS` corrige (il attribuait le cout aux iterations)
- README : sections "Temps de demarrage" et "Limitations connues" reecrites
  (la couverture d'evaluation, 26/74 techniques, y devient la limitation
  bloquante ; ajout des collisions de classes observees)
- docker-compose.yml / ci.yml : commentaires citant ~930 s corriges,
  start_period et timeout 1200s -> 300s (plafond pour runner lent, pas cible)

Co-Authored-By: Claude Sonnet 5 <noreply@anthropic.com>
2026-09-03 18:01:06 +02:00