Funk-lab/progress/2026-06-22.md
ALI YESILKAYA 73b52cde2c
feat(stt): recherche web (SearXNG in-cluster) + fix cluster_status (#49)
Phase 2 d'Asa agentique : nouvel outil web_search adossé à un SearXNG
self-host in-cluster, + correction du faux positif de cluster_status.

- SearXNG (k8s/apps/searxng/) : Deployment + Service + ConfigMap settings.yml
  + IngressRoute searxng.lab.local, Application ArgoCD. Namespace ai, interne
  (l'outil tape http://searxng:8080). use_default_settings + search.formats
  inclut json (sinon API JSON 403) ; limiter/image_proxy off ; image pinnée ;
  conf copiée dans un emptyDir via initContainer (contourne le mount RO) ;
  PodSecurity restricted.
- Outil web_search (tools._web_search) ajouté au contexte asa + STT_SEARXNG_URL.
- fix(cluster_status) : les pods de CronJob TERMINÉS (Succeeded/Failed, ex.
  sacrifice-assign-renfort) comptaient comme « non prêts » → fausse alarme.
  Join kube_pod_status_phase{phase=~"Running |Pending"} (3 faux positifs → 0,
  validé in-cluster).
- Serveur 0.8.0 ; doc stt.md + journal mis à jour.

Co-authored-by: Claude Opus 4.8 <noreply@anthropic.com>
2026-06-22 22:10:59 +02:00

108 lines
7 KiB
Markdown
Raw Blame History

This file contains ambiguous Unicode characters

This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.

# 2026-06-22 — STT : transcription live + veille/réveil vocal ; relevé cluster (la veille)
## STT — streaming partiel & contrôle vocal veille/réveil (client 0.13.0 → 0.14.0)
Deux fonctionnalités demandées sur l'assistant vocal Asa.
### Transcription partielle live dans le HUD
En éveil, pendant qu'on parle, le buffer audio en cours est **re-transcrit périodiquement**
(`partial_interval_sec`, défaut 0,5 s) et poussé au HUD via un événement `partial` → le texte
**se forme en direct** dans une bulle dédiée (italique + curseur clignotant), puis la bulle
« user » finale la remplace.
- Auto-activée seulement avec l'ASR **onnx** (Parakeet ~11× temps réel en CPU) ; whisper large-v3
CPU est trop lent → laissé off (forçable via `[voice].partial_transcription`).
- Bornée : `partial_min_sec` (anti-bruit) … `partial_max_sec` (coût ; au-delà, seul le final suit).
- Transcription inline dans la boucle audio (thread unique → pas d'accès concurrent au modèle ASR).
### Veille / réveil vocal (« Asa stop » / « Asa »)
Refonte de la boucle en **machine à états** explicite veille (`asleep`) ↔ éveil :
- **Veille** : Asa transcrit chaque énoncé **uniquement** pour repérer le wake word ; ne répond à
rien d'autre. HUD : portrait atténué/désaturé, label « SOMMEIL ».
- **« Asa »** (mot entier, alias ASR tolérés) → réveil. « Asa, <question> » exécute la question.
- **« Asa stop »** (ou `stop`/`dors`/`au revoir`… = `sleep_words`) → retour veille (+ « Je me mets
en veille »). Timeout d'inactivité aussi.
- Wake word par défaut **`asa`** (était `hermes`) ; `wake_word`/`wake_aliases`/`sleep_words` config.
- Détection wake durcie : **mot entier** (plus de sous-chaîne — « asa » est court et matchait
« casa », « phrase »…).
Validé : tests unitaires (wake/sleep/alias) + Playwright (rendu `asleep`, bulle partielle mise à
jour en place puis remplacée par le final, nettoyage du partiel au changement d'état).
Bump client **0.14.0**. Doc : `admin/ia/stt.md` (section « Interaction vocale »).
> 🐛 **Trouvaille ASR (test sur poste)** : Parakeet FR ne transcrit **pas** « Asa » comme un mot
> — il l'entend **« a so » / « à ça » / « ah ça »** (deux tokens). La détection mot-entier ne
> matchait donc jamais → « rien ne se passe ». **Corrigé** : on **joint les 1-2 premiers mots**
> (déaccentués, sans espace) et on compare en égalité exacte à des alias compacts (`aso`, `aca`,
> `ahca`…). Faux positifs évités (« à cause » → `acause` ≠ alias). Ajout d'un log diagnostic
> `[stt.voice]` (journalctl, `STT_VOICE_LOG=0` pour couper) qui montre la transcription réelle.
> Validé en live : « Asa » réveille, « Asa stop » endort.
---
## (Rappel) Relevé d'état réel + RAG re-ingéré — fait la veille (2026-06-21, PR #44)
Pour mémoire, cette même journée de travail a aussi produit (PR #44, mergée) : alignement de la
doc sur l'état réel du cluster (`admin/ops/etat-cluster.md`), re-ingestion du RAG **436/436 chunks**
et le **fix du batch embed** (`llama-embed` ubatch 512 → 2048). Détail : `progress/2026-06-21.md`.
---
## Réconciliation `make apply-gpu` + durcissement IaC (soir)
-**Drop-in `llama-embed` réconcilié.** Apply ciblé `--tags llama_server` (commit llama.cpp pinné
→ zéro rebuild, seul `llama-embed` redémarre) : l'unit rendu par le rôle porte maintenant
`--batch-size/--ubatch-size 2048`. Drop-in temporaire `batch.conf` **supprimé**. `ubatch 2048`
effectif sur le process, `rag-query` OK → RAG intact.
- 🐛 **Repo `amdgpu` cassé sur gpu-01** (cause du blocage `make apply-gpu` complet) : le `dnf upgrade`
du rôle `common` avait bumpé l'hôte en AlmaLinux **9.8**, mais radeon.com ne publie pas de
`rhel/9.8` (ni 9.5) — seulement 9.4/9.6/**9.7**. Le repo package-shipped (`$amdgpudistro`) tombait
en 404. **Soigné en live** (`/etc/dnf/vars/amdgpudistro=9.7``dnf repolist` propre) et **durci en
IaC** : `rocm_rhel_version` 9.4 → 9.7, `llama_server_commit` pinné, pièges documentés dans les
README de rôle. (PR `fix/gpu-apply-amdgpu-repo-and-commit-pin`.)
## Asa agentique — boucle d'outils / function calling (Phase 1)
Asa ne répondait qu'à partir d'un contexte **figé** (RAG doc ou blocs live pré-câblés, à
présélectionner) → « gpu-01 tourne bien ? » tombait sur « la doc ne le précise pas » (état live
absent de la doc). Bascule vers une **boucle de function-calling** : le modèle décide quels outils
appeler, puis répond à partir des résultats.
- **Validé empiriquement avant de coder** : Qwen3-8B via llama.cpp fait du tool-calling natif
(pas besoin de `--jinja`), LiteLLM transmet bien les `tools`, et le tool-calling **survit au
`/no_think`**. → 100 % local, pas d'escalade Claude (choix utilisateur).
- **Nouveau contexte `asa`** (`STT_DEFAULT_CONTEXT=asa`, défaut prod) + `tools.py` (registre
schémas + exécuteurs) + `brain.ask_with_tools` (boucle bornée `STT_TOOL_MAX_ITERS=4`, réponse
forcée au-delà). Outils **Phase 1, lecture seule** : `search_docs`, `host_health`,
`cluster_status`, `prometheus_query`. Trace des outils → visualiseur HUD.
- **PromQL validés** contre le vrai Prometheus in-cluster (labels `gpu-01-node`/`storage-01`/
`llama-server-gpu` confirmés ; up/load/mem renvoient des données réelles). 3 tests unitaires de
la boucle (hors-ligne). (PR `feat/asa-tool-loop`.)
- **Choix** : web search = **SearXNG in-cluster** (Phase 2) ; modèle = **local uniquement**.
### Validation prod (#48 mergé) + Phase 2
-**Déployé et testé en prod** : « gpu-01 tourne bien ? » → outil `host_health` → *« en ligne,
charge 0.08, 48 % RAM, llama-server actif »*. « le cluster va bien ? » → `cluster_status`.
(Rollout : ArgoCD s'était calé sur le commit de merge ; un `refresh=hard` l'a fait rouler vers
l'image CI `sha-7cafc06`.)
- 🐛 **Fix `cluster_status`** : les pods de CronJob **terminés** (`sacrifice-assign-renfort`,
Succeeded) comptaient comme « non prêts » → fausse alarme. Join `kube_pod_status_phase{phase=~
"Running|Pending"}` → 3 faux positifs → 0 (validé in-cluster).
-**Phase 2 — recherche web** : SearXNG self-host (`k8s/apps/searxng/`, Application ArgoCD,
ns `ai`, interne) + outil `web_search` (`STT_SEARXNG_URL`). Gotcha clé : `search.formats` doit
inclure `json`. Image pinnée, conf via initContainer→emptyDir (mount RO contourné), PodSecurity
restricted. (PR `feat/asa-web-search`, serveur 0.8.0.)
## Prochaines étapes
- **Vérifier SearXNG au déploiement** : pod Ready + `web_search` renvoie des résultats réels
(test end-to-end comme pour #48). Ajuster les moteurs SearXNG si bruyant.
- **Phase 3** — outil `admin_action` (écriture) : brancher `hermes-exec` comme outil piloté par le
LLM, avec le handshake de confirmation vocale existant.
- Enrichir `host_health`/`cluster_status` (GPU via `rocm_scraper`, fs, températures) si utile.
- Si le wake word « asa » génère des faux positifs/négatifs, ajuster `wake_aliases`.
- **1er test d'action vocale** (#43, contexte 🤖 Agent → `hermes-exec`).