Skip to content

cmer81/fiscal-rag

Folders and files

NameName
Last commit message
Last commit date

Latest commit

 

History

7 Commits
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 

Repository files navigation

bofip-rag

Stack RAG (Retrieval-Augmented Generation) pour interroger le BOFiP (Bulletin Officiel des Finances Publiques - Impôts) en langage naturel.

Basé sur le modèle louisbrulenaudet/lemone-embed-pro fine-tuné sur la doctrine fiscale française, PostgreSQL + pgvector pour la recherche vectorielle, et FastAPI pour l'exposition de l'API.


Architecture

┌─────────────────────────────────────────────────┐
│                  embedding-api                   │
│           FastAPI · Uvicorn · port 8000          │
│     louisbrulenaudet/lemone-embed-pro (768d)     │
└───────────────────┬─────────────────────────────┘
                    │
┌───────────────────▼─────────────────────────────┐
│                   postgres                       │
│         pgvector/pgvector:pg17 · port 5432       │
│         HNSW index · cosine similarity           │
└─────────────────────────────────────────────────┘

Le service ingest (profil Docker Compose séparé) télécharge les documents depuis l'API officielle data.economie.gouv.fr, les découpe en chunks et les vectorise.


Prérequis


Démarrage rapide

# 1. Configuration
cp .env.example .env

# 2. Démarrer l'API + PostgreSQL
docker compose up -d

# 3. Ingérer le BOFiP (one-shot, ~30 min sur CPU / ~5 min sur GPU)
docker compose --profile ingest run ingest

# 4. Tester
curl http://localhost:8000/health

API

POST /search

Recherche sémantique dans le BOFiP.

curl -X POST http://localhost:8000/search \
  -H "Content-Type: application/json" \
  -d '{
    "query": "TVA intracommunautaire livraison de biens",
    "k": 5,
    "serie": "TVA"
  }'

Paramètres :

Champ Type Description
query string Question en langage naturel
k int Nombre de résultats (défaut : 5)
serie string Filtrer par série : IR, IS, TVA, BIC, BNC
doc_type string Filtrer par type : Contenu, Barème

Réponse :

{
  "results": [
    {
      "id": 18671,
      "boi_id": "BOI-TVA-CHAMP-10-10-40-20",
      "title": "TVA - Champ d'application...",
      "serie": "TVA",
      "doc_type": "Contenu",
      "published_at": "2022-01-19",
      "chunk_index": 3,
      "content": "...",
      "score": 0.73
    }
  ]
}

POST /embed

Vectorise une liste de textes (documents).

curl -X POST http://localhost:8000/embed \
  -H "Content-Type: application/json" \
  -d '{"texts": ["texte à embedder"]}'

POST /embed/query

Vectorise une liste de textes (requêtes de recherche).

POST /documents

Stocke des textes avec leurs embeddings en base.

curl -X POST http://localhost:8000/documents \
  -H "Content-Type: application/json" \
  -d '{
    "texts": ["contenu du document"],
    "metadata": [{"source": "custom"}]
  }'

GET /health

{ "status": "ok", "model": "louisbrulenaudet/lemone-embed-pro" }

Ingestion BOFiP

Le script d'ingestion consomme l'API ODS officielle du ministère de l'Économie.

Dataset : bofip-vigueur — 6 309 documents Contenu à jour (màj hebdomadaire)

Séries disponibles : BIC · TVA · IS · IF · IR · ENR · INT · RPPM · RSA · CF · RFPI · BA · REC · CTX · PAT · BNC…

# Ingestion standard (Contenu uniquement)
docker compose --profile ingest run ingest

# Filtrer sur une série pour tester
API_FILTER='type="Contenu" AND serie="TVA"' \
docker compose --profile ingest run ingest

# Suivre les logs
docker logs -f <container_id>

L'ingestion est idempotente : les documents déjà présents en base (par boi_id) sont ignorés.


Variables d'environnement

Variable Défaut Description
MODEL_NAME louisbrulenaudet/lemone-embed-pro Modèle HuggingFace
MAX_BATCH_SIZE 64 Batch max pour l'API embedding
POSTGRES_DB embeddings Nom de la base
POSTGRES_USER embeduser Utilisateur PostgreSQL
POSTGRES_PASSWORD embedpass Mot de passe PostgreSQL
API_FILTER type="Contenu" Filtre ODS (exclut les Actualités)
CHUNK_WORDS 400 Taille des chunks en mots (~500 tokens)
CHUNK_OVERLAP 50 Overlap entre chunks en mots
EMBED_BATCH 32 Batch d'embedding pendant l'ingestion

Schéma de la base

CREATE TABLE documents (
    id           BIGSERIAL PRIMARY KEY,
    boi_id       TEXT,          -- ex: BOI-TVA-CHAMP-10-10-40-20
    title        TEXT,
    doc_type     TEXT,          -- Contenu, Barème, Formulaire…
    serie        TEXT,          -- IR, IS, TVA, BIC…
    published_at DATE,
    chunk_index  INTEGER NOT NULL DEFAULT 0,
    content      TEXT NOT NULL,
    embedding    VECTOR(768),   -- lemone-embed-pro (gte-multilingual-base)
    metadata     JSONB DEFAULT '{}',
    created_at   TIMESTAMPTZ DEFAULT NOW()
);

Index : boi_id · serie · HNSW cosine sur embedding


Intégration n8n (RAG)

Le workflow n8n est disponible dans n8n/fiscal-rag.json.

Architecture du workflow

Chat Trigger → AI Agent ──┬── OpenRouter (mistral-small-2603)
                           ├── Simple Memory (buffer window)
                           └── search_bofip (HTTP Tool → POST /search)

Composants

Nœud Type Rôle
Chat Trigger chatTrigger Interface chat publique avec streaming
AI Agent agent Orchestre les appels à search_bofip et formule la réponse
OpenRouter Chat Model lmChatOpenRouter LLM : mistralai/mistral-small-2603
Simple Memory memoryBufferWindow Mémoire conversationnelle
search_bofip httpRequestTool Appelle POST /search avec k=5

Import du workflow

  1. Dans n8n, aller dans Workflows → Import from file
  2. Sélectionner n8n/fiscal-rag.json
  3. Configurer les credentials OpenRouter (openRouterApi)
  4. Mettre à jour l'URL de search_bofip pour pointer vers votre instance (http://<host>:8000/search)

Structure du projet

.
├── Dockerfile              # Image API (Python 3.11 + torch CPU)
├── docker-compose.yml      # Stack complète (api + postgres + ingest)
├── preload_model.py        # Préchargement du modèle au build
├── .env.example
├── app/
│   ├── main.py             # FastAPI — endpoints embedding + recherche
│   └── requirements.txt
├── ingest/
│   ├── ingest.py           # Pipeline d'ingestion BOFiP
│   └── requirements.txt
├── docker/
│   └── init.sql            # Schéma PostgreSQL + pgvector
└── n8n/
    └── fiscal-rag.json     # Workflow n8n (chat RAG fiscal)

Commandes utiles

# Démarrer
docker compose up -d

# Rebuild après modification
docker compose up -d --build

# Logs de l'API
docker compose logs -f embedding-api

# Reset complet (supprime les données)
docker compose down -v

# Accès psql
docker exec -it embedding-postgres psql -U embeduser -d embeddings

# Nombre de chunks en base
docker exec embedding-postgres psql -U embeduser -d embeddings \
  -c "SELECT serie, count(*) FROM documents GROUP BY serie ORDER BY count DESC;"

Licence

MIT

About

Stack RAG pour interroger le BOFiP (droit fiscal français) en langage naturel — pgvector + FastAPI + n8n

Topics

Resources

Stars

1 star

Watchers

0 watching

Forks

Releases

No releases published

Contributors