feat(aep): M2 — worker adapté (Bifrost + scrape léger + ntfy)
Reprend worker/enrich.js (fusion, pas réécriture) pour le nouveau format de
soumission libre et l'infra en prod (décisions MOE du 27/09) :
- LLM Mistral direct → Bifrost (${BIFROST_URL}/v1/chat/completions,
x-bf-vk), modèle WORKER_MODEL (défaut groq/llama-3.1-8b-instant).
- Scrape crawl4ai/Python → fetch natif Node 22 : timeout 8s, corps
plafonné 500 Ko, titre + meta description + og:* + texte tronqué 4000c.
- Email Resend → notification ntfy, jamais l'email ni le texte du
contributeur (id NocoDB, nom suggéré, type, confiance uniquement).
- Sortie LLM {nom, description, type_suggere, ville, tags, confiance} ;
le worker ne réécrit `nom`/`submission_type` que si le formulaire assoupli
a laissé un placeholder ("[à qualifier]" / "Type : non précisé").
- Seuil « 5 fiches pending » retiré (décision volume faible, notée si le
volume remonte).
- --dry-run : fixture locale, mock Bifrost/scrape par défaut, aucune
écriture NocoDB, DRY_RUN_LIVE=1 pour forcer de vrais appels réseau.
- worker/daily-digest.js supprimé (non référencé, cron purgé le 15/07).
deploy/aep-worker/ : service + timer (15 min) + README avec les étapes
exactes de déploiement pour la session qui déploiera (backup NocoDB,
copie, systemctl, test bout-en-bout M3) — rien exécuté ni copié ici.
PIPE-IA-DOC.md §11 : documente tous les écarts vs la version NAV V2 d'origine.
Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
This commit is contained in:
@@ -330,3 +330,54 @@ Pattern à généraliser :
|
||||
4. Normalize(tags) → taxonomie contrôlée
|
||||
5. Log(usage) → stats_usage
|
||||
```
|
||||
|
||||
---
|
||||
|
||||
## 11. B5 (2026-09-27) — Formulaire assoupli + pipe adapté (fusion, pas réécriture)
|
||||
|
||||
Ce qui suit documente les écarts posés par le batch B5 (décisions de la
|
||||
maîtrise d'œuvre du 27/09). Les sections 1 à 10 ci-dessus restent la
|
||||
référence de fond (taxonomie, système prompt d'origine, circuit breaker) ;
|
||||
cette section documente ce qui a changé dans `worker/enrich.js` et le pipe
|
||||
de soumission (`server/api/submit/`).
|
||||
|
||||
### 11.1 Mapping soumission libre → colonnes NocoDB existantes (M1)
|
||||
|
||||
Le formulaire `/proposer` assoupli (`components/FormLibre.vue`,
|
||||
`utils/submitLibre.ts`) écrit dans la table orgas existante, **aucune colonne
|
||||
nouvelle** :
|
||||
|
||||
| Champ formulaire | Colonne NocoDB | Règle |
|
||||
|---|---|---|
|
||||
| 1er lien de la liste | `url` | `null` si aucun lien |
|
||||
| texte « pourquoi » + tous les liens | `description_user` | `{texte}\n\nLiens :\n{lien1}\n{lien2}...` — et si aucun type suggéré, la ligne `Type : non précisé` est préfixée en tête |
|
||||
| — | `nom` | hostname du 1er lien, ou 60 premiers caractères du texte si aucun lien, préfixé `[à qualifier] ` |
|
||||
| chip type suggéré | `submission_type` | valeur choisie (`ecosysteme`/`reseau`/`job`/`outil`) ; si aucune chip → `ecosysteme` par défaut (voir ligne `Type : non précisé` ci-dessus) |
|
||||
| chip « Références » | *(table `ressources_references`, pas orgas)* | `titre`/`auteur` placeholders, `description` = texte + liens, comme les autres |
|
||||
| email (optionnel) | `submitted_by_email` | — |
|
||||
|
||||
**À faire au déploiement** : ajouter l'option `libre` à la liste de valeurs
|
||||
acceptées par `submission_type` si l'on veut un jour distinguer une
|
||||
soumission libre d'une soumission via un des 5 formulaires détaillés — non
|
||||
fait ici pour ne pas tester un ALTER contre la prod sans l'avoir vérifié.
|
||||
|
||||
### 11.2 Worker — écarts (M2)
|
||||
|
||||
| Sujet | NAV V2 (§1-10 ci-dessus) | AEP B5 |
|
||||
|---|---|---|
|
||||
| LLM | Mistral Nemo, appel direct | **Bifrost** (`${BIFROST_URL}/v1/chat/completions`, header `x-bf-vk`), modèle `WORKER_MODEL` (défaut `groq/llama-3.1-8b-instant`) |
|
||||
| Scrape | crawl4ai (Python, `AsyncHTTPCrawlerStrategy`) | **fetch natif Node 22** — timeout 8 s, corps plafonné 500 Ko, extraction titre + meta description + `og:*` + texte visible tronqué à 4000 caractères, `User-Agent: AEP/2.0 contact@trans-former.fr` |
|
||||
| Notification | Resend (email Jules) | **ntfy** (`POST https://ntfy.sh/$NTFY_TOPIC`) — le message ne contient JAMAIS l'email ni le texte libre du contributeur, seulement id NocoDB / nom suggéré / type / confiance |
|
||||
| Seuil « 5 fiches pending » | Email si ≥ 5 en attente | **Retiré** (décision MOE : volume faible, une notif par fiche traitée suffit — à réactiver si le volume monte) |
|
||||
| Sortie JSON du LLM | `description_enrichie, points_cles, tags_fonction, echelle, territoire, localisation_ville, confiance` | `{nom, description, type_suggere, ville, tags[], confiance}` — le worker écrit ensuite dans les colonnes existantes (`description_enrichie`, `tags_fonction`, `localisation_ville`) |
|
||||
| Écriture de `nom` | jamais réécrit | réécrit **seulement** si le nom actuel commence par `[à qualifier]` (placeholder posé par le formulaire assoupli) |
|
||||
| Écriture de `submission_type` | jamais réécrit | réécrit **seulement** si `description_user` commence par `Type : non précisé` (l'utilisateur n'a pas choisi de chip) et que le type suggéré par le LLM est valide |
|
||||
| Prix des tokens | fixe (prix Mistral Nemo) | variables `WORKER_PRICE_IN_USD_PER_M` / `WORKER_PRICE_OUT_USD_PER_M`, défaut **0** (tier Groq du tier RAPIDE Bifrost, gratuit) |
|
||||
| Lock | `/tmp/nav-worker.lock` | `/tmp/aep-worker.lock` (configurable `WORKER_LOCK_FILE`) |
|
||||
| Chemin VPS | `/opt/nav-carte/worker/` | `/opt/aep-worker/` (voir `deploy/aep-worker/README.md`) |
|
||||
| Timer | 5 min | 15 min (`deploy/aep-worker/aep-worker.timer`) |
|
||||
|
||||
Le mode `--dry-run` (`node enrich.js --dry-run`) lit
|
||||
`worker/fixtures/dry-run-rows.json` au lieu de NocoDB, n'écrit rien, et par
|
||||
défaut mock aussi le scrape et l'appel Bifrost (`DRY_RUN_LIVE=1` pour
|
||||
forcer de vrais appels réseau sans jamais toucher NocoDB).
|
||||
|
||||
Reference in New Issue
Block a user