Flux d'une question (RAG complet)
Flux d'une question (RAG complet)
Dernière mise à jour : 2026-05-10
Source de vérité : ARCHITECTURE.md § "Flux principal (question)". Cette page reformule pour vue rapide.
9 étapes
POST /api/ask/stream { gameId, question, extensions, history, cardMentions, stickyCardMentions }
│
1. Validation Zod (askStreamSchema) — UUID, question ≤500 chars, history ≤5
│
2. Résolution extensions (IDs → noms via gamesRepo.getById)
│
3. Résolution cartes @-citées (resolveMentions) — fresh + sticky
│
4. Classification question (classify.ts via Haiku, en parallèle du retrieval)
├─ Output: 'rules' | 'synergy' | 'meta' | 'deckbuilding'
└─ Si timeout → fallback 'rules'
│
5. RETRIEVAL (orchestrator.ts retrieveChunks)
│
├─ Étape 0 — Embeddings question
│ ├─ Question brute → TEI bge-m3 (1024 dense)
│ └─ HyDE → Haiku passage hypothétique → TEI bge-m3
│ (timeout 25s, fallback : query brute seule)
│
├─ Étape 1 — Recherches hybrides parallèles
│ ├─ Pour chaque collection (base + extensions cochées) :
│ │ ├─ Dense bge-m3 (cosine)
│ │ └─ Sparse BM25 natif Qdrant (keyword match)
│ │
│ ├─ Fusion RRF v2 (RAG_FUSION_V2_ENABLED)
│ │ ├─ Score = 2/(rank_dense+2) + 1/(rank_bm25+2) ← question×2 vs HyDE×1
│ │ ├─ Top-rank bonus : +0.05 si rank=0, +0.02 si rank ∈ {1,2}
│ │ └─ Dedup par pointId
│ │
│ ├─ [Si intent=meta] meta-retrieval
│ │ └─ Recherche chunks 17Lands / MTGGoldfish / etc. (filter meta_format)
│ │
│ └─ [Si MTG/FAB/Riftbound] synergy-expansion
│ ├─ decompose-query (Haiku) → JSON {couleurs, format, types, themes}
│ ├─ Filters Qdrant natifs (payload matching)
│ ├─ Multi-query TCG (synonymes/variantes)
│ └─ set-matcher : "Strixhaven" → "STX"
│
└─ Étape 2 — Reranking cross-encoder (bge-reranker-v2-m3)
├─ Re-classe top-50 candidats RRF
└─ Blending position-aware
├─ Top 1-3 : 75% RRF + 25% rerank (préserve exact-match)
├─ Top 4-10 : 60/40
└─ Top 11+ : 40/60
│
6. Enrichissement contexte (answer.ts)
├─ BGG metadata (mechanics, categories) si dispo
├─ Image PNG : 1 page max (resolvePageImageFile)
│ └─ Granularité (livret, page) — pas seulement page
├─ Cartes @-mentionnées (bloc CARTES CITÉES PAR LE JOUEUR (ce tour))
├─ Sticky cards (bloc CARTES ÉVOQUÉES DANS LA CONVERSATION, format abrégé ~100 tokens)
└─ Historique (≤5 turns)
│
7. Génération réponse Claude (claude-ssh.ts promptStream)
├─ Construction userPrompt (chunks + cartes + image + historique)
├─ SSH oracle@VM : claude -p --append-system-prompt ... --output-format stream-json
│ └─ ⚠️ --append (pas --system-prompt) : préserve le contrat outils (Read, etc.)
├─ withTimeout HYDE_TIMEOUT_MS, fallback Haiku/Opus
└─ Stream JSON verbose → yield tokens (event.type='assistant')
│
8. Événements SSE streamés au client
├─ meta — questionId (1er event, pour fallback polling)
├─ phase — "L'Oracle pèse votre question", "plonge dans le grimoire", etc.
├─ context — chunks retrouvés + scores + mentionedCards + stickyMentionedCards
├─ token — streaming réponse
├─ heartbeat — toutes les 8s (anti idle-timeout NPM)
├─ diagnostics — {chunks, hyde, timings, bestScore}
└─ done — {fullAnswer, questionId, bestScore}
│
9. Persistance (questionsRepo.updateAnswer)
└─ {answer, bestScore, diagnostics}
Optimisations notables
- Parallélisation Qdrant (commit
95229af) : dense + sparse en parallèle, pas séquentiel withTimeoutpartout (8 sites) : évite blocages de boot et de RAG- Fusion RRF v2 : pondération question brute ×2, blending position-aware (cf. ADR-005)
- Sticky mentions : maîtrise tokens sur multi-tours (cap FIFO 20 / 80 si deck)
- Vision 1 image max : ~30s par image lue par Claude — passer à 2-3 doublait la latence pour gain marginal
Fallback connexion SSE
Si la connexion SSE casse mais qu'on a déjà reçu meta.questionId :
- Le frontend bascule sur polling
GET /api/ask/:questionId(3s × 15 = 45s max) - La réponse est récupérée depuis la BDD telle qu'elle a été persistée
- L'UI affiche "L'Oracle finalise hors-ligne…" pendant la récupération
- Si rien après 45s, erreur user-visible
Pattern réutilisable pour tout endpoint streamSSE : exposer GET /api/<resource>/:id retournant 200 (prêt) / 202 (pending) / 404.
No comments to display
No comments to display