Retour aux projets
2026 – Aujourd'hui

Nexus

Plateforme locale d'exploration de corpus multimodal — alternative open-source à Palantir & Maltego

Python FastAPI React Elasticsearch Neo4j LLM / RAG
Ce que ça démontre
  • Conception d'un système IA complet (NLP, search, graph, RAG) de bout en bout
  • Vraie profondeur sur les sujets corpus / knowledge systems / retrieval
  • Capacité à construire un produit complexe en autonomie complète
Aperçu de Nexus

Contexte

Les outils d'analyse de corpus documentaire de référence (Palantir, Maltego, i2 Analyst's Notebook) sont onéreux, propriétaires, et nécessitent l'envoi de données vers des serveurs tiers — incompatible avec des corpus sensibles (judiciaire, journalisme d'investigation, renseignement open-source).

L'objectif de Nexus est de reproduire ces capacités dans un environnement 100 % local, open-source, tournant sur une machine personnelle avec GPU grand public (RTX 3070, 8 Go VRAM). Le projet couvre l'intégralité de la chaîne : ingestion de documents bruts → extraction automatique → analyse sémantique et graphique → interrogation en langage naturel.

Type : Projet personnel
Rôle : Développeur fullstack unique
Statut : Fonctionnel sur plusieurs centaines de documents
Contrainte : 100 % local — 16 Go RAM, 8 Go VRAM

Démo

Fonctionnalités

Ingestion multimodale

  • Import de PDF, DOCX, TXT, HTML, CSV, JSON, emails (.eml/.mbox), images, audio et vidéo
  • Support des archives ZIP/TAR avec extraction récursive
  • Dédoublonnage automatique en 3 passes : hash exact (SHA-256) → MinHash LSH → similarité sémantique

Extraction et NLP automatique

  • OCR en cascade : PyMuPDF → Tesseract → PaddleOCR (fallback automatique selon la qualité)
  • Transcription audio/vidéo via Whisper
  • Classification zero-shot des documents (BART-large-MNLI, 12 catégories)
  • NER hybride : spaCy (fr/en) + GLiNER + règles regex — Personne, Organisation, Lieu, Date, Email, Téléphone, URL, Événement
  • Résolution d'entités : fusion des mentions, normalisation des noms canoniques
  • Embeddings multilingues BAAI/bge-m3 (1024 dimensions)

Recherche

  • Recherche plein texte (BM25 Elasticsearch)
  • Recherche sémantique (kNN sur vecteurs denses)
  • Recherche hybride BM25 + kNN avec re-ranking cross-encoder
  • Filtres : type de document, entité, langue, plage de dates

Graphe de connaissances

  • Construction automatique d'un graphe Neo4j lors du traitement
  • Visualisation interactive (vis-network) avec simulation physique
  • Analyse de centralité (betweenness, closeness via GDS)
  • Détection de communautés / composantes connexes
  • Recherche du chemin le plus court entre deux entités
  • Fusion d'entités avec recalcul automatique du graphe

Assistant LLM (RAG)

  • Standard — recherche vectorielle + LLM local (Ollama)
  • Graph — contexte enrichi par le voisinage Neo4j
  • Complex — décomposition en sous-questions (SubQuestionQueryEngine)
  • Agent — agent ReAct avec 4 outils (recherche corpus, graphe, lecture document, statistiques)
  • Génération de rapports structurés, synthèse multi-documents, conversation multi-tours, réponses en streaming

Autres fonctionnalités

  • Clustering de documents (K-means / HDBSCAN sur embeddings)
  • Détection d'anomalies (Isolation Forest)
  • Fiches personnes — profils structurés enrichis depuis l'Infobox Wikipedia, timeline personnelle
  • Timeline interactif des événements extraits, carte géographique des localisations
  • Export PDF : rapports corpus, entité, document
  • Multi-tenant avec rôles (Viewer, Analyst, Admin), i18n français / anglais

Stack technique

CoucheTechnologie
Backend APIFastAPI 0.115 + Uvicorn, Python 3.11
Workers asynchronesCelery 5.4 + Redis 7
RechercheElasticsearch 8.12 (BM25 + kNN dense_vector)
GrapheNeo4j 5 Community + GDS Plugin
Stockage objetsMinIO (S3-compatible)
FrontendReact 18 + MUI 6 (dark theme) + vis-network 9
LLMLlamaIndex 0.12 + Ollama (local, modèle configurable)
MonitoringPrometheus + Grafana
OrchestrationDocker Compose (10 conteneurs)

Modèles ML embarqués

ModèleRôle
BAAI/bge-m3Embeddings multilingues (1024 dim)
facebook/bart-large-mnliClassification zero-shot
fr_core_news_lg / en_core_web_trfNER statistique + transformer
GLiNERNER généraliste contextuel
OpenAI Whisper (base)Transcription audio/vidéo
PaddleOCROCR multilingue
cross-encoder/ms-marco-MiniLMRe-ranking sémantique

Pipeline de traitement

1
Upload & extraction

Détection du format, extraction du contenu brut (PDF, DOCX, audio, vidéo, email…)

2
Dédoublonnage exact

Hash SHA-256 — rejet immédiat des doublons binaires

3
OCR

PyMuPDF → Tesseract → PaddleOCR, sélection automatique selon la qualité

4
Transcription

Whisper pour les fichiers audio et vidéo

5
Dédoublonnage fuzzy

MinHash LSH (seuil 0.9) — élimination des quasi-doublons

6
Détection de langue

Identification automatique de la langue du document

7
Classification zero-shot

BART-large-MNLI — 12 catégories thématiques

8
NER hybride

spaCy + GLiNER + regex — extraction de 8 types d'entités

9
Résolution d'entités

Fusion des mentions, normalisation des noms canoniques

10
Chunking sémantique

Découpage avec préfixe de contexte pour la RAG

11
Embedding

BAAI/bge-m3 — vecteurs de 1024 dimensions par chunk

12
Indexation Elasticsearch

BM25 + index kNN dense_vector

13
Construction du graphe Neo4j

Nœuds entités + relations MENTIONED_IN, APPEARS_WITH, liens structurels

Chaque étape est une tâche Celery indépendante avec gestion des erreurs transitoires (retry) et permanentes. Le pipeline est repris depuis n'importe quelle étape.

Architecture

CorpusExplorer/
├── backend/
│   ├── app/
│   │   ├── api/routes/          # 15 modules de routes (auth, documents, search, graph, llm…)
│   │   ├── models/              # Pydantic v2 (Document, Entity, Person, User…)
│   │   ├── services/
│   │   │   ├── ingestion/       # IngestService, extracteurs par format
│   │   │   ├── processing/      # NER, OCR, embeddings, chunker, dedup, classification
│   │   │   ├── search/          # ElasticsearchService, SemanticSearch, cache
│   │   │   ├── graph/           # GraphBuilder (Neo4j), PathFinder
│   │   │   ├── llm/             # RAGService, LlamaIndex adapters, LLMService (Ollama)
│   │   │   ├── profile/         # PersonProfileService, ProfileGenerator
│   │   │   └── auth/            # JWT, RBAC, audit
│   │   └── workers/
│   │       └── tasks.py         # Pipeline Celery (~1 000 lignes)
├── frontend/
│   └── src/
│       ├── components/          # 27 pages et composants React
│       ├── services/api.js      # Client Axios centralisé
│       └── locales/             # i18n fr/en
└── docker-compose.yml           # 10 services orchestrés

Défis techniques résolus

Asyncio en contexte multi-thread

FastAPI tourne sur une boucle asyncio principale. Les tâches LlamaIndex (synchrones) sont déléguées à un ThreadPoolExecutor. Le problème : les composants appelaient asyncio.run() depuis ce thread, créant des boucles imbriquées et corrompant le client Elasticsearch async partagé.

Solution : réécriture intégrale de NexusElasticsearchVectorStore et NexusGraphRetriever en mode fully-synchronous, avec des clients Elasticsearch sync dédiés — zéro asyncio dans les threads.

État LSH in-memory dans le worker Celery

Le DeduplicationService maintient un index MinHash LSH en mémoire. Un purge de la base vidait Redis mais laissait la LSH stale → faux quasi-doublons sur les ré-imports.

Solution : tâche Celery dédiée reset_dedup_state_task() dispatchée après purge Redis pour reconstruire l'index depuis un état vide.

OOM du frontend sous Docker

Le build webpack consomme plus de 1 Go de heap Node.js, provoquant des OOM kills en conteneur.

Solution : mem_limit: 1536m + NODE_OPTIONS=--max-old-space-size=1024 sur le conteneur frontend.

Merge d'entités avec types de relations hétérogènes

Le merge de deux nœuds Neo4j devait rediriger toutes leurs relations, mais les types (MENTIONED_IN, APPEARS_WITH, SPOUSE_OF…) ne sont pas connus à l'avance.

Solution : réécriture du merge en Cypher générique avec CALL {} subqueries dynamiques couvrant tous les types de relations via fallback APOC-free.

Chiffres clés

13Étapes de pipeline
7Modèles ML embarqués
10Conteneurs Docker
27Composants React
15Modules de routes API
4Modes RAG
8Types d'entités NER
12Formats d'ingestion

Pourquoi ce projet compte

Ce projet illustre ma capacité à concevoir et construire un système IA complet de bout en bout — de l'ingestion documentaire à l'assistant conversationnel, en passant par la structuration, la recherche hybride et le graphe de connaissances. C'est le projet qui correspond le mieux aux problématiques que je traite au quotidien chez ChapsVision, transposées dans un contexte 100 % open-source et local, sans aucune contrainte externe.

Il démontre à la fois la profondeur technique (NLP, RAG, vector search, graph, orchestration) et la capacité à livrer un produit utilisable avec une vraie interface, un vrai pipeline et une vraie architecture — pas un notebook ou un POC.