TypeScript 98.3%
CSS 0.9%
Shell 0.7%
1# Architecture technique — Immbot AI23## Pile retenue45| Couche | Choix | Justification |6|---|---|---|7| Framework | **Next.js 15 (App Router) + React 19 + TypeScript strict** | Full-stack unifié, streaming natif, RSC pour la vitesse |8| UI | **Tailwind CSS v4** + composants maison de style shadcn/ui + animations CSS discrètes | Contrôle total de l'identité, thèmes clair/sombre/système |9| Rendu chat | react-markdown + remark-gfm + remark-math + rehype-katex | Markdown, tableaux, LaTeX |10| BD | **SQLite via `node:sqlite`** (natif Node 25, FTS5 vérifié avec `remove_diacritics 2`) | Zéro dépendance native fragile, parfait pour un déploiement mono-nœud ; chemin PostgreSQL + pgvector documenté pour une montée en charge (docs/deployment.md) |11| Accès BD | Couche `lib/db` SQL typée (requêtes préparées) | Simplicité, contrôle des index, FTS5 et blobs vecteurs sans friction ORM |12| Embeddings | **Local : `@huggingface/transformers`, modèle `Xenova/multilingual-e5-small`** (384 dims) | OpenRouter n'offre pas d'endpoint d'embeddings ; local = gratuit, privé, hors-ligne, excellent en français |13| Recherche | Hybride : FTS5 (BM25) + cosinus vectoriel en mémoire + filtres de métadonnées + RRF | Corpus ~2-3k fragments → recherche en mémoire < 10 ms |14| LLM | **OpenRouter** (`/api/v1/models` + `/api/v1/chat/completions`, streaming SSE) | Registre dynamique, multimodalité, coûts |15| Auth | Sessions serveur (cookie httpOnly + table sessions), bcryptjs, rate limiting | Voir security-model.md |16| Fichiers | Stockage local `data/uploads/` (dev) ; interface compatible S3/MinIO documentée | |17| Tests | Vitest (unitaires + intégration) | |1819**Décisions documentées** (hypothèses raisonnables adoptées) :20- SQLite plutôt que PostgreSQL en v1 : un seul professeur héberge la plateforme ; `node:sqlite` en21 mode WAL supporte largement une cohorte de cours. Le schéma n'utilise rien d'exclusif à SQLite22 (migration Postgres documentée). pgvector devient utile au-delà de ~100k fragments — on en est loin.23- Pas de Redis/file de tâches en v1 : l'ingestion (~30 documents LaTeX) prend quelques minutes et24 tourne comme script ou tâche serveur avec journal de progression en BD.2526## Structure du projet2728```29immbot-ai/30├── app/ # Next.js App Router31│ ├── (public)/ # accueil, connexion, inscription32│ ├── (app)/ # chat, apprendre/*, bibliothèque, paramètres (auth requise)33│ ├── (admin)/admin/* # tableau de bord professeur34│ └── api/ # routes API (auth, chat SSE, rag, learning, admin, uploads)35├── components/ # UI (ui/ primitives, chat/, learning/, admin/)36├── lib/37│ ├── db/ # connexion node:sqlite, schéma, migrations, requêtes38│ ├── auth/ # sessions, mots de passe, permissions, rate-limit39│ ├── openrouter/ # registre de modèles, client streaming, coûts, presets40│ ├── rag/ # parseur LaTeX, chunker, embeddings, recherche hybride, citations41│ ├── learning/ # SM-2, maîtrise, quiz adaptatif, examens, plan d'étude, recommandations42│ ├── analytics/ # événements, agrégats anonymisés43│ └── security/ # validation, sanitisation44├── prompts/ # prompts système modulaires versionnés (fichiers .md)45├── scripts/ # setup, dev, build, seed-admin, ingest-courses, reindex, test, verify, backup46├── tests/ # vitest47├── evaluation/ # jeux de test RAG + rapport48├── docs/ # la présente documentation49├── data/ # immbot.db, uploads/, cache modèles (gitignoré)50└── public/ # logo SVG, actifs51```5253## Flux principaux5455### Chat RAG (mode « Cours uniquement »)561. POST `/api/chat` (auth + vérification d'accès au cours + budget).572. Analyse de la question → détection du sujet ; embedding local de la requête.583. Recherche hybride dans l'espace du cours choisi : FTS5 (BM25) + cosinus, fusion RRF,59 filtres métadonnées, expansion aux fragments voisins, dédoublonnage → top-k équilibré.604. Construction du contexte : fragments numérotés `[S1]…[Sn]` avec métadonnées (séance,61 diapositive) + prompt système assemblé (base + rag-grounding + citation-policy + cours + mode).625. Appel OpenRouter en streaming, relayé au client en SSE ; le modèle cite `[S3]`.636. Post-validation : toute référence `[Sx]` absente du contexte est neutralisée ; les citations64 valides sont résolues en objets cliquables (document, séance, diapositive, extrait).657. Journalisation : jetons, coût, latence, fragments servis (pour l'évaluation RAG).6667### Ingestion68`scripts/ingest-courses.ts` (ou bouton admin) : scan des dossiers de cours → détection de type →69somme de contrôle (réingestion incrémentale) → parseur LaTeX (frames beamer numérotées en70diapositives, sections, boîtes sémantiques, équations, tableaux) → fragments structurés avec71métadonnées complètes → FTS5 + embeddings par lots → rapport (docs/ingestion-report.md + table72`ingestion_runs`).7374### Moteur de maîtrise75Chaque interaction évaluable (carte, question de quiz, item d'examen) émet un événement76`(concept, correct, difficulté, autonomie, confiance)` ; la maîtrise par concept est un score77composite à décroissance temporelle (voir learning-science-strategy.md), agrégé par thème et cours.7879## Performance80RSC par défaut, composants client uniquement où nécessaire (chat, cartes interactives) ·81embeddings et registre de modèles en cache mémoire avec TTL · requêtes préparées réutilisées ·82index SQL sur toutes les clés de recherche · streaming immédiat (TTFB < 1 s hors latence modèle).83