ITSkillsCenter
Intelligence Artificielle

Construire un RAG OHADA avec pgvector et embeddings open source — tutoriel 2026

12 min de lecture

Méta-description : Le droit OHADA, c’est 10 Actes Uniformes, 2 500 articles et des milliers de décisions de la CCJA. Un RAG bien construit transforme cette masse en assistant juridique conversationnel précis et souverain. Tutoriel pas-à-pas 2026 avec pgvector, sentence-transformers et Ollama sur Hetzner CX32.

Pourquoi un RAG OHADA en 2026 ?

L’Organisation pour l’Harmonisation en Afrique du Droit des Affaires (OHADA) régit l’essentiel du droit commercial dans 17 États membres, dont le Sénégal, la Côte d’Ivoire, le Burkina Faso, le Mali, la Guinée, le Cameroun et le Tchad. Les 10 Actes Uniformes couvrent le droit des sociétés, les sûretés, les procédures collectives, l’arbitrage, le droit comptable, les transports terrestres, le droit commercial général, les sociétés coopératives, les contrats de travail et la médiation. Cela représente plus de 2 500 articles et plusieurs milliers de décisions de la Cour Commune de Justice et d’Arbitrage (CCJA).

Un avocat à Dakar, un fiduciaire à Abidjan, un juriste d’entreprise à Bamako passe quotidiennement plusieurs heures à chercher l’article exact, la jurisprudence applicable, ou la procédure à suivre dans un dossier. Les outils existants sont soit payants et hors de prix (LexisNexis, Lamy), soit limités et imprécis (recherche par mot-clé sur des PDF). Un système RAG (Retrieval-Augmented Generation) bien construit change radicalement la donne : tu poses ta question en français naturel, le système retrouve les passages pertinents dans le corpus OHADA via embeddings vectoriels, et un LLM rédige une réponse synthétique citant ses sources. Le tout 100 % self-hosted, sans envoyer la moindre information confidentielle de tes dossiers vers OpenAI ou Anthropic.

Ce tutoriel s’inscrit dans le panorama IA et LLM pour PME francophones et complète notre guide général Bases de données modernes 2026. Tu vas y apprendre à constituer un corpus OHADA propre, générer des embeddings avec sentence-transformers, indexer dans pgvector, et orchestrer un pipeline RAG avec Ollama qui répond en moins de 3 secondes par question.

Prérequis

  • VPS Hetzner Cloud CX32 minimum (8 Go RAM, 80 Go SSD, ~5 200 F CFA/mois). Pour un usage cabinet d’avocats avec 10 utilisateurs simultanés, vise un CX42 (16 Go RAM).
  • Ubuntu 22.04 LTS ou 24.04 LTS.
  • Compétences Python intermédiaires et SQL de base.
  • Notion de PostgreSQL (utilisateurs, extensions). Si tu débutes, suis d’abord notre tutoriel TimescaleDB pour les fondamentaux d’admin Postgres.
  • Corpus OHADA en PDF ou texte. Les Actes Uniformes sont publics et disponibles sur le site officiel ohada.org.
  • Connexion stable pour télécharger les modèles (~2 Go au total).

Architecture du système RAG

Voici comment les composants s’articulent dans le pipeline final que tu vas construire. La phase d’indexation (one-shot, à refaire seulement quand le corpus évolue) prend en entrée les PDF des Actes Uniformes, les découpe en chunks de 500-800 tokens, génère un embedding vectoriel pour chaque chunk via sentence-transformers, et stocke embeddings + texte + métadonnées dans pgvector.

La phase de requête (à chaque question utilisateur) prend la question en entrée, génère son embedding avec le même modèle, lance une recherche de similarité cosine dans pgvector pour récupérer les 5 à 10 chunks les plus proches, construit un prompt qui combine la question et les chunks récupérés, envoie le tout à un LLM local (Ollama avec Mistral 7B ou Llama 3.1 8B), et retourne la réponse rédigée avec citations vers les articles sources. L’ensemble du pipeline tient sur un seul VPS et répond en 1 à 3 secondes.

Installation pas-à-pas

Étape 1 — PostgreSQL 16 + pgvector

# Sur le VPS Hetzner CX32
sudo sh -c 'echo "deb https://apt.postgresql.org/pub/repos/apt $(lsb_release -cs)-pgdg main" > /etc/apt/sources.list.d/pgdg.list'
curl -fsSL https://www.postgresql.org/media/keys/ACCC4CF8.asc | sudo gpg --dearmor -o /usr/share/keyrings/pgdg.gpg
sudo apt update
sudo apt install -y postgresql-16 postgresql-16-pgvector

sudo -u postgres psql -c "CREATE DATABASE rag_ohada;"
sudo -u postgres psql -c "CREATE USER ragapp WITH PASSWORD 'mot-de-passe-fort';"
sudo -u postgres psql -c "GRANT ALL PRIVILEGES ON DATABASE rag_ohada TO ragapp;"
sudo -u postgres psql rag_ohada -c "CREATE EXTENSION IF NOT EXISTS vector;"

Étape 2 — Python + dépendances

sudo apt install -y python3.12 python3.12-venv python3-pip
mkdir -p ~/rag-ohada && cd ~/rag-ohada
python3.12 -m venv .venv
source .venv/bin/activate

pip install --upgrade pip
pip install psycopg sentence-transformers pypdf langchain-text-splitters tqdm requests fastapi uvicorn

Étape 3 — Ollama pour le LLM local

curl -fsSL https://ollama.com/install.sh | sh
ollama pull mistral:7b-instruct-q4_K_M
ollama serve &

Le modèle Mistral 7B quantifié en Q4 pèse ~4,3 Go et tient confortablement en RAM sur le CX32. Pour des réponses encore plus précises sur du juridique francophone, essaie aussi command-r:7b ou llama3.1:8b.

Schéma pgvector pour le corpus juridique

CREATE TABLE documents_ohada (
    id BIGSERIAL PRIMARY KEY,
    acte_uniforme TEXT NOT NULL,        -- ex: 'AUSCGIE', 'AUS', 'AUDCG'
    article_num TEXT,                    -- ex: '142', '142-1'
    titre_section TEXT,
    contenu TEXT NOT NULL,
    embedding vector(384),               -- dimension du modèle multilingue
    metadata JSONB DEFAULT '{}'::jsonb,
    created_at TIMESTAMPTZ DEFAULT NOW()
);

-- Index HNSW pour recherche vectorielle ultra-rapide
CREATE INDEX ON documents_ohada USING hnsw (embedding vector_cosine_ops);

-- Index B-tree classiques pour filtres SQL
CREATE INDEX ON documents_ohada (acte_uniforme);
CREATE INDEX ON documents_ohada (article_num);

-- Index GIN pour recherche full-text en complément
CREATE INDEX ON documents_ohada USING gin (to_tsvector('french', contenu));

Le choix de la dimension 384 correspond au modèle paraphrase-multilingual-MiniLM-L12-v2, un compromis idéal entre qualité et vitesse pour du français. Pour des cas plus exigeants (clauses contractuelles très techniques), passe à multilingual-e5-large en dimension 1024.

Ingestion du corpus OHADA

Le script Python ci-dessous télécharge un Acte Uniforme PDF depuis ohada.org, le découpe en chunks sémantiques cohérents avec les frontières d’articles, génère les embeddings et insère le tout dans pgvector :

from pypdf import PdfReader
from sentence_transformers import SentenceTransformer
from langchain_text_splitters import RecursiveCharacterTextSplitter
import psycopg
from tqdm import tqdm

# Modèle multilingue rapide et précis
model = SentenceTransformer('paraphrase-multilingual-MiniLM-L12-v2')

# Découpeur respectant la structure OHADA (Articles, Titres)
splitter = RecursiveCharacterTextSplitter(
    chunk_size=600,
    chunk_overlap=80,
    separators=['\nArticle ', '\nTITRE ', '\nCHAPITRE ', '\n\n', '\n', '. ']
)

def ingest_acte(pdf_path, acte_code):
    reader = PdfReader(pdf_path)
    full_text = '\n'.join(page.extract_text() for page in reader.pages)
    chunks = splitter.split_text(full_text)
    
    with psycopg.connect("postgresql://ragapp:mot-de-passe-fort@localhost/rag_ohada") as conn:
        with conn.cursor() as cur:
            for chunk in tqdm(chunks, desc=f"Indexation {acte_code}"):
                emb = model.encode(chunk).tolist()
                cur.execute(
                    "INSERT INTO documents_ohada (acte_uniforme, contenu, embedding) VALUES (%s, %s, %s)",
                    (acte_code, chunk, emb)
                )
            conn.commit()

ingest_acte('actes/AUSCGIE-2014.pdf', 'AUSCGIE')
ingest_acte('actes/AUS-2010.pdf', 'AUS')
# ... répéter pour les 10 Actes Uniformes

Le traitement complet des 10 Actes Uniformes prend ~30 minutes sur un CX32 et produit environ 8 000 chunks indexés.

Pipeline de requête RAG

Le cœur fonctionnel : prendre une question, retrouver les passages pertinents, générer la réponse :

import psycopg, requests
from sentence_transformers import SentenceTransformer

model = SentenceTransformer('paraphrase-multilingual-MiniLM-L12-v2')

def search_chunks(question, top_k=6):
    emb = model.encode(question).tolist()
    with psycopg.connect("postgresql://ragapp:mot-de-passe-fort@localhost/rag_ohada") as conn:
        with conn.cursor() as cur:
            cur.execute("""
                SELECT acte_uniforme, contenu, 1 - (embedding <=> %s::vector) AS similarity
                FROM documents_ohada
                ORDER BY embedding <=> %s::vector
                LIMIT %s
            """, (emb, emb, top_k))
            return cur.fetchall()

def ask_ohada(question):
    chunks = search_chunks(question)
    contexte = "\n\n".join(f"[{c[0]}] {c[1]}" for c in chunks)
    
    prompt = f"""Tu es un assistant juridique spécialisé en droit OHADA. Réponds à la question en t’appuyant exclusivement sur les passages fournis. Cite toujours l’Acte Uniforme source. Si l’information n’est pas dans les passages, dis-le clairement.

PASSAGES:
{contexte}

QUESTION: {question}

RÉPONSE:"""
    
    r = requests.post("http://localhost:11434/api/generate", json={
        "model": "mistral:7b-instruct-q4_K_M",
        "prompt": prompt,
        "stream": False
    })
    return r.json()["response"]

# Test
print(ask_ohada("Quelles sont les conditions de validité d'une SARL OHADA ?"))

Sur un CX32, la réponse complète arrive en 2 à 4 secondes. Pour un cabinet à Dakar ou Abidjan, c’est largement suffisant pour un usage interactif quotidien.

Exposer une API FastAPI pour l’équipe

Pour rendre l’outil accessible aux avocats, juristes et fiduciaires sans qu’ils ouvrent un terminal, expose une API REST FastAPI minimaliste :

from fastapi import FastAPI
from pydantic import BaseModel

app = FastAPI(title="RAG OHADA - ITSkillsCenter")

class Question(BaseModel):
    text: str
    top_k: int = 6

@app.post("/ask")
def ask(q: Question):
    chunks = search_chunks(q.text, q.top_k)
    return {
        "reponse": ask_ohada(q.text),
        "sources": [{"acte": c[0], "extrait": c[1][:200]} for c in chunks]
    }

# Lance avec : uvicorn app:app --host 0.0.0.0 --port 8000

Place un Caddy ou Nginx en reverse proxy avec authentification HTTP basic ou JWT, et tes collaborateurs peuvent interroger l’assistant depuis leur navigateur ou depuis une intégration Slack/Mattermost.

Adaptation au contexte ouest-africain

Le RAG OHADA self-hosted répond à des contraintes que les solutions SaaS commerciales ne couvrent pas. Premièrement, la confidentialité absolue : aucune information sur tes dossiers, tes clients ou tes consultations ne quitte ton VPS. Pour un cabinet d’avocats à Dakar qui gère des dossiers sensibles (contentieux fiscal, fusion-acquisition, propriété intellectuelle), c’est non négociable. Le secret professionnel impose ce niveau d’isolement.

Deuxièmement, la souveraineté législative : ton corpus reste à jour selon ta propre veille. Quand l’AUSCGIE est révisé en 2024 ou qu’un nouvel arrêt de la CCJA est rendu, tu mets à jour ton corpus quand tu l’as validé, pas quand un fournisseur étranger décide de le faire. Troisièmement, le coût marginal : 5 200 F CFA par mois pour un CX32 qui sert 10 collaborateurs simultanés, c’est 520 F CFA par utilisateur. Toutes les solutions commerciales équivalentes coûtent au minimum 50 USD par utilisateur et par mois.

Enfin, le RAG fonctionne même en cas de coupure internet. Si la connexion de ton cabinet à Bamako tombe, tes équipes peuvent toujours interroger l’assistant via le réseau local. Aucune dépendance à OpenAI ou Anthropic.

Erreurs fréquentes à éviter

  • Chunks trop gros ou trop petits — < 200 tokens : perte de contexte ; > 1000 tokens : embedding moins discriminant. Vise 400-800 tokens avec overlap 10-15 %.
  • Choix d’un modèle d’embedding inadapté au français — beaucoup de modèles populaires (all-MiniLM-L6-v2) sont anglais. Utilise paraphrase-multilingual ou e5-multilingual.
  • Index HNSW mal configuré — sur 8 000 chunks, les paramètres par défaut sont OK. Sur 1 million+, ajuste m et ef_construction.
  • Prompt trop court — explique au LLM qu’il doit citer les sources et refuser de répondre hors contexte. Sans ça, il hallucine.
  • Pas de retour utilisateur — implémente un système de pouce haut/bas sur chaque réponse pour identifier les questions mal traitées et améliorer le corpus.
  • Oublier la jurisprudence CCJA — le corpus OHADA, c’est aussi 4 000+ arrêts de la CCJA. Indexe-les en complément.

Trois cas d’usage concrets

  1. Cabinet d’avocats à Dakar (8 collaborateurs) — RAG OHADA + corpus interne (mémos, plaidoiries anonymisées). Gain mesuré : 40 % du temps de recherche documentaire économisé. Investissement : 5 200 F CFA infra/mois + 3 jours de mise en place.
  2. Fiduciaire à Abidjan (4 experts-comptables) — RAG sur Acte Uniforme Comptable + textes fiscaux ivoiriens. Réponse instantanée aux questions clients sur amortissements, TVA, IRPP. ROI : 2 mois.
  3. Direction juridique d’une banque à Ouagadougou — RAG sur AUSCGIE, droit bancaire UEMOA, jurisprudence locale. Couplé à Mattermost en self-hosted, les juristes interrogent l’assistant depuis leur poste. Adoption massive en 2 semaines.

Checklist post-déploiement

  • ✅ PostgreSQL 16 + extension pgvector active
  • ✅ Index HNSW créé sur la colonne embedding
  • ✅ Au moins 5 000 chunks indexés couvrant les 10 Actes Uniformes
  • ✅ Modèle Ollama (Mistral 7B ou Llama 3.1 8B) téléchargé et serveur lancé
  • ✅ Test de bout en bout : question → réponse avec citations en moins de 5 secondes
  • ✅ API FastAPI exposée derrière un reverse proxy avec authentification
  • ✅ Backup quotidien de la base PostgreSQL vers Hetzner Object Storage
  • ✅ Procédure de mise à jour du corpus documentée (révisions Actes, nouveaux arrêts)
  • ✅ Système de feedback utilisateur (👍/👎) implémenté
  • ✅ Formation initiale des 5-10 utilisateurs principaux

FAQ

Le RAG remplace-t-il un avocat ?

Absolument pas. C’est un outil d’aide à la recherche documentaire, pas un conseil juridique. La responsabilité professionnelle reste entière chez l’avocat ou le juriste qui valide la réponse.

Quelle est la qualité par rapport à ChatGPT ?

Sur du droit OHADA, ton RAG self-hosted bat largement ChatGPT car ce dernier hallucine fréquemment des numéros d’articles. Avec un corpus précis et des sources citées, ton RAG est traçable et fiable.

Comment garder le corpus à jour ?

Mets en place un cron mensuel qui scrape ohada.org pour détecter les nouvelles publications. Pour la jurisprudence CCJA, abonnement à un agrégateur ou veille manuelle.

Est-il licite d’indexer les Actes Uniformes ?

Oui, les Actes Uniformes sont des textes publics. Pour la jurisprudence et la doctrine, vérifie les conditions des sources que tu utilises.

Pour aller plus loin

Besoin d’accompagnement sur ton RAG juridique ?

Tu es avocat, fiduciaire, juriste d’entreprise ou DSI d’un cabinet et tu veux mettre en place un assistant RAG sur ton corpus ? ITSkillsCenter propose un audit gratuit de 30 minutes pour cadrer le périmètre technique et estimer ton ROI. Contacte-nous via WhatsApp +221 78 226 83 77 ou demande directement ton audit gratuit en ligne.


[ITS] ITSkillsCenter — formations IT et conseil pour PME d’Afrique de l’Ouest. Dakar · Abidjan · Ouagadougou · Bamako · Conakry. Tous nos contenus sont audités selon notre charte éditoriale Ahl-Sunna.

Besoin d'un site web ?

Confiez-nous la Création de Votre Site Web

Site vitrine, e-commerce ou application web — nous transformons votre vision en réalité digitale. Accompagnement personnalisé de A à Z.

À partir de 250.000 FCFA
Parlons de Votre Projet
Publicité