From 754226c7b68e67fa331550cfebb45d857cdd324a Mon Sep 17 00:00:00 2001 From: bolbol Date: Wed, 5 Aug 2026 21:06:36 +0000 Subject: [PATCH] runbook : contournement direct NVIDIA NIM/OpenRouter pour onedrive_vec --- ...yora-notes-tt-embeddings-bypass-bifrost.md | 127 ++++++++++++++++++ 1 file changed, 127 insertions(+) create mode 100644 hermes-tt/nyora-notes-tt-embeddings-bypass-bifrost.md diff --git a/hermes-tt/nyora-notes-tt-embeddings-bypass-bifrost.md b/hermes-tt/nyora-notes-tt-embeddings-bypass-bifrost.md new file mode 100644 index 0000000..2e4859f --- /dev/null +++ b/hermes-tt/nyora-notes-tt-embeddings-bypass-bifrost.md @@ -0,0 +1,127 @@ +# 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`