runbook: bifrost routage par cout — etat de la mesure 18/07
This commit is contained in:
@@ -0,0 +1,62 @@
|
|||||||
|
# Bifrost — routage texte par coût : état de la mesure (18/07/2026)
|
||||||
|
|
||||||
|
## Découverte clé : la mesure existe déjà
|
||||||
|
Bifrost journalise TOUT dans `/volume1/docker/bifrost/data/logs.db` (SQLite, table `logs`) :
|
||||||
|
`virtual_key_name`, `model`, `prompt_tokens`, `completion_tokens`, `cost` ($ réels),
|
||||||
|
`latency` (ms), `status`, `error_details`, `fallback_index`, `number_of_retries`.
|
||||||
|
Aucune instrumentation à développer. Lecture en RO :
|
||||||
|
```
|
||||||
|
sqlite3 'file:/volume1/docker/bifrost/data/logs.db?mode=ro'
|
||||||
|
```
|
||||||
|
Depuis mcp-nas : chemin `/mnt/docker/bifrost/data/logs.db`, via `python3 -c` (sqlite3 CLI absent).
|
||||||
|
|
||||||
|
## Requête de référence — coût 30 j par clé × modèle
|
||||||
|
```sql
|
||||||
|
SELECT COALESCE(virtual_key_name,'(aucune)'), model, COUNT(*),
|
||||||
|
SUM(prompt_tokens), SUM(completion_tokens), ROUND(SUM(cost),4),
|
||||||
|
SUM(CASE WHEN status!='success' THEN 1 ELSE 0 END)
|
||||||
|
FROM logs WHERE timestamp >= datetime('now','-30 days')
|
||||||
|
GROUP BY 1,2 ORDER BY 6 DESC;
|
||||||
|
```
|
||||||
|
Coût par tâche aboutie : `AVG(cost) WHERE status='success' AND cost>0`, par modèle.
|
||||||
|
|
||||||
|
## Constats (30 j au 18/07/2026)
|
||||||
|
- Dépense totale ≈ **1,47 $/30 j** (~15 % du plafond OpenCode 10 $). Pas d'urgence budgétaire.
|
||||||
|
- deepseek-v4-flash : 774 succès, **1,38 m$/tâche**, 1 942 tok sortie moy, 22,6 s.
|
||||||
|
- kimi-k2.6 : 93 succès, **3,99 m$/tâche** (2,9× flash) pour 909 tok sortie — confirme que
|
||||||
|
le prix affiché au token ne prédit pas le coût par tâche.
|
||||||
|
- 22× HTTP 429 `GoUsageLimitError` sur flash : le plafond OpenCode se fait déjà toucher.
|
||||||
|
- 270 replis `fallback_index=1` sur flash ; `attempt_trail` vide → destination du repli non tracée.
|
||||||
|
|
||||||
|
## BLOQUANT attribution : une seule clé pour tout
|
||||||
|
Seules 2 clés virtuelles actives (`Nabil-Key`, `Yesmine-Key`). Tous les consommateurs
|
||||||
|
(hermes ×3, crons veille, n8n, apps) partagent Nabil-Key → coût par consommateur IMPOSSIBLE.
|
||||||
|
`metadata` vide, `raw_request` vide. Prérequis n°1 avant tout routage :
|
||||||
|
**une clé virtuelle Bifrost par consommateur** (hermes-tt / hermes-nyora / hermes-perso /
|
||||||
|
n8n / veille-infra / veille-nexum / redaction-pro / family-help / nyora-veille /
|
||||||
|
gsparc-mezzouna / reglement-definitif). Zéro code — config governance Bifrost + .env clients.
|
||||||
|
|
||||||
|
## Incident en cours : 879× 401 en 30 j
|
||||||
|
`virtual_key_not_found` (784) + `virtual_key_required` (95), encore 4–26/jour cette semaine,
|
||||||
|
pic 328 le 11/07. Le client demande `deepseek-v4-flash` avec une clé absente de la DB —
|
||||||
|
probablement l'ancienne clé `yesmine-hermes-desktop` (vue dans les logs, absente de config.db)
|
||||||
|
ou une clé rotée. Un service croit appeler le LLM et échoue en silence depuis des semaines.
|
||||||
|
Identification : `docker logs bifrost` → IP source 172.27.x.x → container (réseau n8n).
|
||||||
|
|
||||||
|
## Protocole de mesure retenu (AVANT toute ligne de routage)
|
||||||
|
1. Créer les clés virtuelles par consommateur, distribuer dans les .env, redémarrer les clients.
|
||||||
|
2. Trouver et corriger l'émetteur des 401.
|
||||||
|
3. 7 jours de collecte attribuée, puis tableau coût/mois par consommateur (requête ci-dessus).
|
||||||
|
4. Définir les besoins texte à partir des données mesurées (piste : exécution-outils /
|
||||||
|
rédaction / raisonnement-agentique / vision-OCR / extraction structurée).
|
||||||
|
5. Seulement ensuite : sélecteur type nyora_models.py côté Bifrost, avec repli journalisé.
|
||||||
|
|
||||||
|
## Pièges
|
||||||
|
- `attempt_trail` est vide dans cette version de Bifrost : la cible réelle d'un repli ne se lit
|
||||||
|
pas dans logs.db — journaliser côté sélecteur.
|
||||||
|
- Comparer m$/tâche entre modèles n'a de sens qu'À BESOIN ÉGAL (mimo-v2.5 affiche 0,53 m$/tâche
|
||||||
|
mais sur des tâches à 84 tok de sortie — biais de sélection).
|
||||||
|
- config.db : clés provider en `plain_text` — ne jamais SELECT les colonnes `value` en clair.
|
||||||
|
|
||||||
|
Gabarit du sélecteur : VPS hermes-nabil `/data/nyora/nyora_models.py` + section 7 de
|
||||||
|
`common/hermes-nabil-images-flyers-navigateur.md`.
|
||||||
Reference in New Issue
Block a user