# Intégration OpenRouter — Immbot AI ## Architecture ``` Navigateur ──(SSE, sans clé)── Next.js API ──(Bearer OPENROUTER_API_KEY)── openrouter.ai/api/v1 ``` La clé ne quitte **jamais** le serveur (`lib/openrouter/client.ts`, `registry.ts`). ## Registre dynamique (`lib/openrouter/registry.ts`) - `GET /models` → normalisation (prix $/M jetons, modalités d'entrée, `supported_parameters`) → **cache mémoire 15 min** (l'ancien cache sert de secours si l'API échoue). - Capacités détectées : images, fichiers, outils, raisonnement, sortie structurée, contexte max. - Palier de coût calculé (`économique` < 1 $/M pondéré ≤ `modéré` < 8 $/M ≤ `coûteux`) — les étudiants voient le palier, l'admin voit les prix exacts. - **Surcharges admin** (`model_overrides`) : activer/désactiver, favori, note. Un modèle désactivé est refusé côté serveur même si le client force son id. - **Préréglages** configurables (`settings.model_presets`) avec repli ordonné : le premier modèle disponible et activé de la liste est utilisé (`resolvePreset`). ## Appels de complétion (`lib/openrouter/client.ts`) - `streamChat` : SSE (`stream: true`, `usage: {include: true}`) relayé événement par événement au navigateur ; supporte `models: [principal, ...secours]` pour le repli fournisseur d'OpenRouter. - `completeChat` : non-streaming, `response_format: json_object` pour les générateurs (quiz, flashcards, résumés). - Multimodal : messages `content[]` avec `image_url` (data-URL base64) pour les images ; les documents texte (PDF/DOCX/XLSX extraits localement) sont injectés comme texte délimité. ## Suivi des coûts Chaque appel journalise jetons entrée/sortie, coût estimé (prix du registre × jetons), latence, succès/erreur (`usage_log`). Budgets appliqués **avant** chaque appel (`lib/usage.ts`) : par étudiant/jour, étudiant/mois, global/mois, requêtes/jour — configurables dans l'admin. ## Choix des modèles par tâche | Tâche | Préréglage utilisé | |---|---| | Chat étudiant | choix de l'étudiant (défaut : Recommandé) | | Génération de flashcards | Économique | | Résumés | Recommandé | | Titres/consolidation | (aucun appel — heuristiques locales) | ## Limites connues - OpenRouter n'offre pas d'endpoint d'embeddings → embeddings **locaux** (voir rag-architecture.md). - Les prix du registre sont indicatifs ; le coût facturé exact est visible dans le tableau de bord OpenRouter (l'endpoint `/generation` par requête est une évolution possible).