Files
nas-runbooks/hermes-tt/nyora-notes-tt-embeddings-bypass-bifrost.md

128 lines
5.2 KiB
Markdown

# nyora-notes-tt -- contournement direct NVIDIA NIM/OpenRouter pour onedrive_vec
**Instance auteur** : hermes-tt (Claude, session nyora-notes-tt)
**Date** : 2026-08-05
**Tags** : nyora-notes-tt, bifrost, embeddings, nvidia-nim, openrouter
**Statut** : valide, backfill en cours
---
## Probleme
Le quota gratuit Google (`embed_content_free_tier_requests`, 1000/j sur
`gemini-embedding-001`) etait epuise, cassant a la fois le backfill embeddings
et la recherche vectorielle en temps reel de `search_onedrive_archive`. Le fix
de rotation multi-cles Bifrost (voir `common/bifrost-google-provider-key-rotation.md`)
ne resout rien : les 3 cles Google partagent le meme pool de quota.
Tentative de bascule vers NVIDIA NIM et OpenRouter (tous deux gratuits, comptes
crees le 05/08) **via Bifrost** : echec dans les deux cas, en 404. Confirme comme
bugs Bifrost upstream, pas une erreur de config :
- NVIDIA NIM : issue GitHub maximhq/bifrost#2356 (ouverte) -- Bifrost ne transmet
pas le header `Authorization` a l'API amont quand le provider est en
`custom_provider_config.base_provider_type: openai`.
- OpenRouter : erreur cote client HTTP Bifrost ("small read buffer" en lisant
les headers de reponse), cause exacte non confirmee dans les issues connues.
Les deux providers fonctionnent parfaitement en appel DIRECT (sans Bifrost),
verifie avec les memes cles.
---
## Solution validee : contournement direct, scope isole a onedrive_vec
`notes_vec` (mail, alimentee par `pipeline_processor.py`) et `onedrive_vec`
(OneDrive, alimentee par `embed_onedrive_docs.py`) sont deux tables
**separees**, toutes deux 768d/Google avant ce fix. Decision : ne toucher QUE
`onedrive_vec` -- `notes_vec` reste sur Google/Bifrost (768d), fonctionne deja,
aucune raison de la casser aujourd'hui.
**Modele choisi** : `nvidia/llama-nemotron-embed-vl-1b-v2` (2048d), disponible
IDENTIQUE (memes poids) sur NVIDIA NIM et sur OpenRouter (OpenRouter route ce
modele gratuit directement vers l'infra NVIDIA -- "hosted by one provider").
Consequence utile : les deux sources produisent le MEME espace vectoriel, donc
un vrai repli (pas deux embeddings incompatibles a ne jamais mixer).
**Code** (`embed_onedrive_docs.py` et nouvelle fonction `generate_onedrive_embedding`
dans `mcp_server.py`, strictement separee de `generate_gemini_embedding` qui
reste utilisee par `search_mail_memory`) :
```python
NVIDIA_NIM_API_KEY = os.getenv("NVIDIA_NIM_API_KEY", "")
OPENROUTER_API_KEY = os.getenv("OPENROUTER_API_KEY", "")
EMBEDDING_MODEL = "nvidia/llama-nemotron-embed-vl-1b-v2"
EMBEDDING_DIMENSIONS = 2048
def get_embedding(text):
text = text[:8000]
if NVIDIA_NIM_API_KEY:
try:
resp = httpx.post(
"https://integrate.api.nvidia.com/v1/embeddings",
headers={"Authorization": f"Bearer {NVIDIA_NIM_API_KEY}"},
json={"model": EMBEDDING_MODEL, "input": [text], "input_type": "passage"},
timeout=30,
)
resp.raise_for_status()
vec = resp.json()["data"][0]["embedding"]
if len(vec) == EMBEDDING_DIMENSIONS:
return vec
except Exception:
pass # repli OpenRouter
if OPENROUTER_API_KEY:
resp = httpx.post(
"https://openrouter.ai/api/v1/embeddings",
headers={"Authorization": f"Bearer {OPENROUTER_API_KEY}"},
json={"model": EMBEDDING_MODEL, "input": text},
timeout=30,
)
resp.raise_for_status()
return resp.json()["data"][0]["embedding"]
```
**Piege NVIDIA NIM specifique** : le parametre `input_type` (`"query"` ou
`"passage"`) est requis par leurs modeles NV-Embed*, absent chez OpenRouter --
mis uniquement sur l'appel NVIDIA direct.
**Migration schema** : `onedrive_vec` (`vec0`, dimension figee a la creation)
recree en 2048d, perte des 1781 vecteurs 768d existants (non recuperables,
mauvais espace vectoriel de toute facon) -- backfill relance depuis zero sur
6648 documents processed, rythme observe ~1/s (~2h estimees), aucune erreur
constatee sur le premier lot.
**Secrets** : cles dans `/volume1/docker/nyora-notes-tt/.env`
(`NVIDIA_NIM_API_KEY`, `OPENROUTER_API_KEY`) -- PAS via Bifrost pour cet usage
precis, contournement volontaire tant que #2356 n'est pas corrige upstream.
---
## Verification
```bash
docker exec nyora-notes-tt python3 -c "
import sqlean as sqlite3, sqlite_vec
c = sqlite3.connect('/app/nyora-notes-tt.db')
c.enable_load_extension(True); sqlite_vec.load(c); c.enable_load_extension(False)
print(c.execute('SELECT COUNT(*) FROM onedrive_vec').fetchone()[0])
"
```
---
## Reste a faire
- Laisser le backfill se terminer (~2h, tourne en arriere-plan via
`docker exec -d`, resumable si interrompu -- rescanner simplement au
redemarrage, la logique "deja embedde" se base sur les rowid presents).
- Reevaluer le retour a Bifrost si/quand #2356 est corrige upstream (verifier
changelog maximhq/bifrost).
- Auto-actualisation OneDrive (point 1) et ingestion mail continue (point 2) :
design discute mais pas implemente -- voir prompt de reprise en session
suivante.
## References
- Issue Bifrost NVIDIA NIM : https://github.com/maximhq/bifrost/issues/2356
- Runbook associe : `common/bifrost-google-provider-key-rotation.md`,
`hermes-tt/nyora-notes-tt-3-bugs-05-08-2026.md`