SPB Git forge

spb/immbot-ai

Public
1commits 1branches 0releases
1.5 MBsize
maindefault branch
20 days agolast push
TypeScript 98.3% CSS 0.9% Shell 0.7%
5.8 KB · 83 lines markdown
Rendered Raw Blame History
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