Docs: show VPS vs mini PC RAG flow (Discourse lives on the VPS)
The old README diagram stacked Discourse above the mini PC and left the VPS as an orphan column. Rewrite is also the resident 30B MoE, not a small dedicated model. Co-authored-by: Cursor <cursoragent@cursor.com>
This commit is contained in:
parent
62d29468d4
commit
83805bf9cd
5 changed files with 100 additions and 47 deletions
57
README.fr.md
57
README.fr.md
|
|
@ -8,19 +8,21 @@
|
|||
> publiée.
|
||||
|
||||
Un plugin **Discourse** + un pipeline RAG auto-hébergé, conçu pour un forum
|
||||
associatif francophone (Depiedencap — souliers pour homme, ~428k messages).
|
||||
Principe produit : **le bot oriente vers les fils existants, il ne répond
|
||||
pas à la place des membres.**
|
||||
associatif francophone (Depiedencap — souliers pour homme, 424 835 messages
|
||||
/ 22 230 sujets). Principe produit : **le bot oriente vers les fils
|
||||
existants, il ne répond pas à la place des membres.**
|
||||
|
||||
## Ce que fait le plugin
|
||||
|
||||
- Retrieval au **grain post** (et non au grain topic) : embeddings `bge-m3`
|
||||
dans `ai_posts_embeddings` (pgvector dans la Postgres du forum), top-25
|
||||
par cosine puis **rerank cross-encoder** (TEI), déduplication par fil.
|
||||
dans `ai_posts_embeddings` (pgvector dans la Postgres du forum, **sur le
|
||||
VPS**), top-25 par cosine puis **rerank cross-encoder** (TEI **sur le mini
|
||||
PC**), déduplication par fil.
|
||||
- **Réécriture de requête multi-tour** : le dernier message + les tours
|
||||
précédents sont condensés en une requête autonome par un petit modèle
|
||||
dédié avant retrieval (pattern *condense question* / history-aware
|
||||
retriever).
|
||||
précédents sont condensés en une requête autonome (pattern *condense
|
||||
question* / history-aware retriever). Même modèle résident que la
|
||||
génération : `qwen3:30b-a3b-q6k` (MoE, ~3B actifs, `think:false`) — plus
|
||||
de petit modèle dédié à la réécriture.
|
||||
- **Citations vérifiées côté serveur** : le LLM n'écrit que des marqueurs
|
||||
`[[n]]` ; le plugin les transforme en liens `/t/slug/id/post_number` et
|
||||
jette tout lien qui n'existe pas réellement en base (whitelist Postgres,
|
||||
|
|
@ -33,18 +35,41 @@ pas à la place des membres.**
|
|||
|
||||
## Architecture
|
||||
|
||||
Le plugin tourne **dans Discourse, sur le VPS**. Le mini PC n'est que le
|
||||
backend d'inférence (Ollama + TEI), joignable via Tailscale. Le gate,
|
||||
pgvector et le sanitizer de citations ne quittent jamais le VPS.
|
||||
|
||||
```
|
||||
Discourse (plugin Ruby, dans le process du forum)
|
||||
│ question → gate → réécriture (modèle léger) → embed → pgvector → rerank → LLM → sanitizer
|
||||
Question membre
|
||||
│
|
||||
▼
|
||||
Mini PC auto-hébergé (k3s) VPS
|
||||
Ollama : bge-m3 (embeddings) Discourse + Postgres/pgvector
|
||||
qwen3 30B MoE (~3B actifs) (~428k posts embeddés)
|
||||
— génération ET réécriture de
|
||||
requête (un seul modèle résident)
|
||||
TEI : cross-encoder mmarco-mMiniLMv2 (rerank)
|
||||
[VPS] Discourse + ce plugin Ruby
|
||||
│
|
||||
├─ 1. gate regex locale, 0 LLM
|
||||
│
|
||||
├─ 2. réécriture ──Tailscale──► [mini PC] Ollama qwen3:30b-a3b-q6k
|
||||
│
|
||||
├─ 3. embed ──Tailscale──► [mini PC] Ollama bge-m3
|
||||
│
|
||||
├─ 4. pgvector Postgres locale, 424 835 posts, cosine top-25
|
||||
│
|
||||
├─ 5. rerank ──Tailscale──► [mini PC] TEI mmarco-mMiniLMv2
|
||||
│
|
||||
├─ 6. génération ──Tailscale──► [mini PC] Ollama qwen3:30b-a3b-q6k
|
||||
│
|
||||
└─ 7. sanitizer whitelist URL, Postgres locale
|
||||
│
|
||||
▼
|
||||
réponse + liens /t/slug/id/post_number
|
||||
```
|
||||
|
||||
| Sur le VPS | Sur le mini PC (k3s, iGPU) |
|
||||
|---|---|
|
||||
| Discourse, ce plugin, Postgres/pgvector | Ollama (`bge-m3` + `qwen3:30b-a3b-q6k`) et TEI (`mmarco`) |
|
||||
|
||||
`qwen3:30b-a3b-q6k` est un seul MoE résident (~3B actifs) pour la
|
||||
réécriture (`think:false`) **et** la génération.
|
||||
|
||||
Le choix délibéré : **pas de framework RAG** (LangChain & co.) — pipeline
|
||||
linéaire en code direct, instrumenté pour l'évaluation. Le raisonnement
|
||||
complet : [`docs/rag/DESIGN.md`](docs/rag/DESIGN.md) §9.
|
||||
|
|
|
|||
56
README.md
56
README.md
|
|
@ -7,18 +7,21 @@
|
|||
> This repository documents the work — no demo URL is published.
|
||||
|
||||
A **Discourse plugin** + a self-hosted RAG pipeline, built for a French
|
||||
community forum (Depiedencap — men's shoes, ~428k posts). Product
|
||||
principle: **the bot points members to existing threads instead of
|
||||
answering in their place.**
|
||||
community forum (Depiedencap — men's shoes, 424 835 posts / 22 230
|
||||
topics). Product principle: **the bot points members to existing threads
|
||||
instead of answering in their place.**
|
||||
|
||||
## What it does
|
||||
|
||||
- **Post-grain retrieval** (not topic-grain): `bge-m3` embeddings in
|
||||
`ai_posts_embeddings` (pgvector inside the forum's Postgres), top-25 by
|
||||
cosine then **cross-encoder rerank** (TEI), per-thread dedup.
|
||||
`ai_posts_embeddings` (pgvector inside the forum's Postgres on the VPS),
|
||||
top-25 by cosine then **cross-encoder rerank** (TEI on the mini PC),
|
||||
per-thread dedup.
|
||||
- **Multi-turn query rewriting**: the latest message plus earlier turns
|
||||
are condensed into a standalone query by a small dedicated model before
|
||||
retrieval (*condense question* / history-aware retriever pattern).
|
||||
are condensed into a standalone query (*condense question* /
|
||||
history-aware retriever). Same resident model as generation:
|
||||
`qwen3:30b-a3b-q6k` (MoE, ~3B active, `think:false`) — not a separate
|
||||
small rewriter.
|
||||
- **Server-side verified citations**: the LLM only emits bare `[[n]]`
|
||||
markers; the plugin maps them to `/t/slug/id/post_number` links and
|
||||
discards any link that does not actually exist in Postgres (URL
|
||||
|
|
@ -31,18 +34,41 @@ answering in their place.**
|
|||
|
||||
## Architecture
|
||||
|
||||
The plugin runs **inside Discourse on the VPS**. The mini PC is only the
|
||||
inference backend (Ollama + TEI), reached over Tailscale. Gate, pgvector
|
||||
and the citation sanitizer never leave the VPS.
|
||||
|
||||
```
|
||||
Discourse (Ruby plugin, inside the forum process)
|
||||
│ question → gate → rewrite (small model) → embed → pgvector → rerank → LLM → sanitizer
|
||||
Member question
|
||||
│
|
||||
▼
|
||||
Self-hosted mini PC (k3s) VPS
|
||||
Ollama : bge-m3 (embeddings) Discourse + Postgres/pgvector
|
||||
qwen3 30B MoE (~3B active) (~428k embedded posts)
|
||||
— generation AND query rewriting
|
||||
(single resident model)
|
||||
TEI : mmarco-mMiniLMv2 cross-encoder (rerank)
|
||||
[VPS] Discourse + this Ruby plugin
|
||||
│
|
||||
├─ 1. gate regex, local, 0 LLM
|
||||
│
|
||||
├─ 2. rewrite ──Tailscale──► [mini PC] Ollama qwen3:30b-a3b-q6k
|
||||
│
|
||||
├─ 3. embed ──Tailscale──► [mini PC] Ollama bge-m3
|
||||
│
|
||||
├─ 4. pgvector Postgres local, 424 835 posts, cosine top-25
|
||||
│
|
||||
├─ 5. rerank ──Tailscale──► [mini PC] TEI mmarco-mMiniLMv2
|
||||
│
|
||||
├─ 6. generate ──Tailscale──► [mini PC] Ollama qwen3:30b-a3b-q6k
|
||||
│
|
||||
└─ 7. sanitizer URL whitelist, local Postgres
|
||||
│
|
||||
▼
|
||||
answer + /t/slug/id/post_number links
|
||||
```
|
||||
|
||||
| Lives on the VPS | Lives on the mini PC (k3s, iGPU) |
|
||||
|---|---|
|
||||
| Discourse, this plugin, Postgres/pgvector | Ollama (`bge-m3` + `qwen3:30b-a3b-q6k`) and TEI (`mmarco`) |
|
||||
|
||||
`qwen3:30b-a3b-q6k` is a single resident MoE (~3B active) used for both
|
||||
rewrite (`think:false`) and generation.
|
||||
|
||||
Deliberate choice: **no RAG framework** (LangChain & co.) — a linear
|
||||
pipeline in direct code, instrumented for evaluation. Full reasoning:
|
||||
[`docs/rag/DESIGN.md`](docs/rag/DESIGN.md) §9.
|
||||
|
|
|
|||
|
|
@ -1,11 +1,12 @@
|
|||
# Design — RAG grain post (Depiedencap)
|
||||
|
||||
> **Dernière màj** : 14/09/2026 · **Statut** : toutes les configs A-G
|
||||
> mesurées, config gagnante identifiée (E : posts natifs + rerank),
|
||||
> sécurité testée à l'échelle. **Rien déployé en prod.**
|
||||
> **Dernière màj** : 17/09/2026 · **Statut** : config gagnante (E : posts
|
||||
> natifs + rerank) mesurée ; code en prod sur le VPS, flags membre encore
|
||||
> **OFF**, agent limité à un groupe démo. Le §0 ci-dessous est un
|
||||
> **instantané historique** (grain topic) — l'architecture actuelle :
|
||||
> [`README.md`](../../README.md) · [`PIPELINE.md`](PIPELINE.md).
|
||||
> Résultats : [`EVAL.md`](EVAL.md) · Sécurité : [`SAFETY.md`](SAFETY.md) ·
|
||||
> Architecture : [`PIPELINE.md`](PIPELINE.md)
|
||||
> Références techniques : [`REFERENCES.md`](REFERENCES.md)
|
||||
> Références : [`REFERENCES.md`](REFERENCES.md)
|
||||
|
||||
## 0. État actuel (rappel)
|
||||
|
||||
|
|
|
|||
|
|
@ -1,11 +1,12 @@
|
|||
# Chantier RAG — granularité post, retrieval avancé, évaluation
|
||||
|
||||
> **Statut (15/09/2026)** : **déploiement prod en cours**, flags encore **OFF**
|
||||
> (comportement live inchangé). Code v2 déployé, reranker en service, backfill
|
||||
> natif posts en cours sur le VPS. Reprise / prochaine étape exacte :
|
||||
> [`PLAN_RAG_PROD_VPS.md`](../PLAN_RAG_PROD_VPS.md) § « Reprise session » (tout en haut).
|
||||
> Éval locale : config gagnante mesurée (posts+rerank, Hit@5 0.97), sécurité
|
||||
> testée (red-team + gate + clause) — `EVAL.md` / `SAFETY.md`.
|
||||
> **Statut (17/09/2026)** : plugin + pipeline en prod sur le **VPS**
|
||||
> (Discourse + Postgres/pgvector, 424 835 posts). Inférence sur le **mini
|
||||
> PC** (Ollama `bge-m3` + `qwen3:30b-a3b-q6k`, TEI mmarco) via Tailscale.
|
||||
> Flags membre encore **OFF** ; agent limité à un groupe démo. Schéma
|
||||
> public : [`README.md`](../../README.md). Reprise :
|
||||
> [`PLAN_RAG_PROD_VPS.md`](../PLAN_RAG_PROD_VPS.md) § « Reprise session ».
|
||||
> Éval : posts+rerank, Hit@5 0.97 — `EVAL.md` / `SAFETY.md`.
|
||||
|
||||
## Pourquoi ce chantier
|
||||
|
||||
|
|
|
|||
|
|
@ -25,9 +25,9 @@ module DepiedencapAiCitations
|
|||
RERANK_READ_TIMEOUT = 4
|
||||
POSTS_SQL_LIMIT = 25
|
||||
|
||||
# Réécriture de requête multi-tour (condense_query) — modèle léger dédié,
|
||||
# distinct du LLM de génération (Qwen 30B) : latence courte (~2-3s mesurées),
|
||||
# pas de mode "thinking" à filtrer (contrairement à qwen3:4b sur ce serving).
|
||||
# Réécriture de requête multi-tour (condense_query) — même LLM résident
|
||||
# que la génération (qwen3:30b-a3b-q6k, MoE ~3B actifs, ~1 s à chaud).
|
||||
# think:false pour éviter le budget englouti dans reasoning (vu sur qwen3:4b).
|
||||
HISTORY_TURNS = 3
|
||||
CONDENSE_MAX_TOKENS = 80
|
||||
CONDENSE_OPEN_TIMEOUT = 2
|
||||
|
|
|
|||
Loading…
Add table
Reference in a new issue