Intégration OpenRouter — Immbot AI
Architecture
text
Navigateur ──(SSE, sans clé)── Next.js API ──(Bearer OPENROUTER_API_KEY)── openrouter.ai/api/v1La 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 ; supportemodels: [principal, ...secours]pour le repli fournisseur d'OpenRouter.completeChat: non-streaming,response_format: json_objectpour les générateurs (quiz, flashcards, résumés).- Multimodal : messages
content[]avecimage_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
/generationpar requête est une évolution possible).