SPB Git

spb/uqo-chat

Public
4.8 KB · 75 lines markdown
1# UQO-Chat23**Tuteur IA pour les cours IMM1003 — Éléments d'évaluation immobilière et IMM1033 — Méthodes du coût (UQO).**4Production : https://www.uqo-chat.app · Spécification complète : [`CLAUDE.md`](CLAUDE.md).56Le tuteur explique la matière en citant les notes de cours officielles (RAG), exécute du Python7dans un bac à sable isolé, produit des classeurs Excel à formules vivantes, cherche des données8de marché actuelles (Firecrawl), analyse les fichiers déposés et génère des quiz interactifs.9Tous les modèles (Claude, GPT) passent par OpenRouter avec repli automatique.1011## Architecture (déploiement MacLustr)1213```14Internet ── ngrok (www.uqo-chat.app) ──► uqo-chat-api  :8190  FastAPI + SSE + SPA React (PM2)15                                              │16                                              ├──► uqo-chat-sandbox :8191  (PM2, sandbox-exec : sans réseau)17                                              ├──► SQLite  data/uqochat.db  (index BM25 en mémoire)18                                              ├──► fichiers data/files/ (TTL 7 j / 30 j épinglés)19                                              └──► OpenRouter · Firecrawl (HTTPS sortant)20```2122Les manifestes Kubernetes (`k8s/`) et `docker-compose.yml` reproduisent la cible décrite dans la23spécification (Postgres + pgvector, Redis, MinIO, sandbox durci) pour un futur cluster ; la24production actuelle tourne sur un nœud Mac du cluster via `mld` (voir `deploy/`).2526## Démarrage local2728```bash29cp .env.example .env            # OPENROUTER_API_KEY, FIRECRAWL_API_KEY, RESEND_API_KEY…30make setup                      # venvs uv (backend, sandbox) + npm install31make sandbox &                  # :819132make api &                      # :8190 (sert frontend/dist s'il existe)33make web                        # :5173 avec proxy /api34make ingest COURSE=imm1033 SITE=~/Desktop/Academique/UQO/UQO_COURS/_Site_web/dist/imm103335make test && make lint36```3738Connexion : le professeur inscrit les courriels des étudiant·es (onglet **Étudiants**) ; chacun·e reçoit39un courriel Resend « Bienvenue sur UQO-Chat » avec un lien `/mot-de-passe?token=…` (valide40`INVITE_TTL_DAYS`) pour choisir son mot de passe, puis se connecte avec courriel + mot de passe.41« Première connexion ou mot de passe oublié » renvoie un lien (`RESET_TTL_MINUTES`). Seules les adresses42inscrites (ou listées dans `PROFESSOR_EMAILS` / `ADMIN_EMAILS` / `INVITED_EMAILS`) peuvent demander un lien.43Sans `RESEND_API_KEY` (ni SMTP), les liens sont affichés dans le tableau de bord pour être copiés ; en dev,44`/auth/forgot` renvoie `dev_link`.4546## Déploiement4748```bash49make build                                       # frontend/dist50~/Desktop/cluster-skill/mld stage $PWD uqo-chat  # laptop → passerelle51~/Desktop/cluster-skill/mld deploy uqo-chat      # nœud choisi par score (--node X pour forcer)52```5354Le manifeste de production (`M1M32:~/dispatch/apps/uqo-chat.json`) contient les secrets ; la copie55du dépôt (`deploy/uqo-chat.manifest.json`) n'a que des gabarits. Après un premier déploiement,56ingérer le matériel de cours sur le nœud :5758```bash59scp -r ~/Desktop/Academique/UQO/UQO_COURS/_Site_web/dist/imm10{03,33} <nœud>:~/apps/uqo-chat/content/60ssh <nœud> 'cd ~/apps/uqo-chat/backend && for c in imm1003 imm1033; do \61  DATA_DIR=~/apps/uqo-chat/data .venv/bin/python -m scripts.ingest --course $c --site ../content/$c; done'62pm2 restart uqo-chat-api63```6465## Écarts assumés par rapport à la spécification6667| Spécification | Réalisation actuelle | Pourquoi |68|---|---|---|69| PostgreSQL + pgvector, Redis, MinIO, arq | SQLite (SQLAlchemy async), cache/limiteur en mémoire, fichiers sur disque, tâches asyncio | Déploiement mono-nœud sans dépendances ; `DATABASE_URL` accepte déjà Postgres, `k8s/` décrit la cible complète |70| Embeddings `openai/text-embedding-3-large` via OpenRouter | BM25 (index en mémoire) + embeddings optionnels via un endpoint OpenAI-compatible (`EMBEDDINGS_BASE_URL`) | OpenRouter n'expose aucun modèle d'embeddings (vérifié 2026-09-05) |71| Lien magique SMTP à chaque connexion | Invitation Resend → mot de passe choisi par l'étudiant·e (PBKDF2), « mot de passe oublié » par courriel ; liste blanche gérée par le professeur | Une seule étape par courriel, puis connexion classique ; Resend (`RESEND_API_KEY`) plutôt qu'un SMTP UQO |72| Pods sandbox gVisor / Job k8s | Service `sandbox-runner` séparé, `sandbox-exec` macOS (réseau interdit, écriture confinée) + rlimits + timeout | Équivalent local ; `sandbox-runner/Dockerfile` + NetworkPolicy prêts pour k8s |73| Alembic | `create_all` au démarrage | Une migration initiale sera ajoutée au premier changement de schéma |74| Export PDF de conversation, mode hors-ligne complet | Non faits (PWA : app shell + cache lecture) | Phase 2/3 |75
Files · f7b72d80f2bbde2540a0689dd9a0bffc67e6a1b6
Menu

Theme