Système de Mémoire Cognitive Modulaire pour LLM Local Architecture RAG avancée avec Boucle de Réflexion, Graphe Obsidian et Contradiction Engine
Multi-RAG Obsidian transforme un vault Obsidian en mémoire cognitive active pour un LLM local.
Le projet ne se limite pas à faire de la recherche documentaire. Il vise à créer un système de raisonnement augmenté, capable de :
- récupérer des informations depuis plusieurs bases de connaissances spécialisées ;
- toujours intégrer le contexte utilisateur (RAG_USER obligatoire) ;
- explorer les liens Obsidian comme un graphe de pensée ;
- filtrer, classer et synthétiser les informations ;
- détecter les contradictions entre sources ;
- produire des réponses personnalisées, sourcées et évolutives ;
- sauvegarder automatiquement les raisonnements dans Obsidian.
Question classique : Question → Recherche → Réponse
Multi-RAG Obsidian : Question
→ analyse de l'intention
→ sélection des mémoires pertinentes
→ exploration du graphe Obsidian
→ recherche vectorielle hybride
→ reranking + pruning
→ vérification des contradictions
→ synthèse personnalisée
→ sauvegarde dans la mémoire utilisateur
| Fonctionnalité | Description |
|---|---|
| Multi-RAG par domaine | Chaque domaine a son propre espace vectoriel Qdrant |
| RAG_USER obligatoire | Le contexte utilisateur est systématiquement inclus |
| Boucle de réflexion | Génération d'axes → Exploration graphe → Fusion → Synthèse |
| Graphe Obsidian | Exploration BFS des wikilinks avec profondeur contrôlée |
| Recherche hybride | Vectorielle + BM25 + graphe |
| Reranking pondéré | Score composite multi-critères |
| Contradiction Engine | Détection et arbitrage des conflits entre sources |
| Indexation automatique | Watcher watchdog en temps réel |
| Mémoire cognitive | Working, Session, User, Semantic, Episodic, Meta, Archived |
| Notes auto | Sauvegarde structurée dans USER_DATA/auto-generated/ |
┌─────────────────────┐
│ Obsidian Vault │
│ Markdown + Wikilinks│
└──────────┬──────────┘
│
▼
┌──────────────────┐
│ Watcher Indexer │
│ watchdog │
└────────┬─────────┘
│
▼
┌──────────────────────────┐
│ Parser Markdown/YAML │
│ chunks + metadata │
└───────────┬──────────────┘
│
▼
┌──────────────────────────┐
│ Embedding Model │
│ YOUR_EMBEDDING_MODEL │
└───────────┬──────────────┘
│
▼
┌──────────────────────────┐
│ Qdrant Vector Store │
│ collections par RAG │
└───────────┬──────────────┘
│
▼
┌──────────────────────────────────────────────────────┐
│ FastAPI Backend │
│ Query Analyzer → RAG Selector → Graph Explorer │
│ Hybrid Retriever → Reranker → Contradiction Engine │
│ LLM Synthesizer → Memory Writer │
└──────────────────────────────────────────────────────┘
│
▼
┌──────────────────────────┐
│ Ollama / YOUR_LLM / LLM │
└──────────────────────────┘
| Composant | Technologie |
|---|---|
| LLM | Ollama — YOUR_PREFERRED_MODEL / mistral-nemo / llama3.1 / qwen2.5 |
| Vector DB | Qdrant |
| Embeddings | Ollama — YOUR_EMBEDDING_MODEL (recommandé) |
| Backend API | FastAPI + Uvicorn |
| CLI | Typer |
| Graphe | NetworkX |
| Watcher | watchdog |
| Config | Pydantic + YAML |
| Logging | structlog |
| DB locale | SQLite (logs, feedback, sessions) |
| Cache | Redis (optionnel) |
Embeddings (via Ollama - recommandé) :
YOUR_EMBEDDING_MODEL → Recommandé (ex: nomic-embed-text-v2-moe:latest)
nomic-embed-text:latest → Bon compromis (768d, plus léger)
Embeddings (via SentenceTransformers - alternative) :
bge-m3 → Alternative (768d, multilingue)
multilingual-e5-large → Bon compromis
paraphrase-multilingual-mpnet-base-v2 → Alternative
all-MiniLM-L6-v2 → Prototype léger uniquement
LLM local via Ollama :
YOUR_PREFERRED_MODEL:7b → Réflexion légère, analyse d'intention
llama3.1:8b / mistral-nemo → Synthèse poussée
qwen2.5:14b → Production optimale
✨ Configuration actuelle : Le système utilise
YOUR_EMBEDDING_MODELvia Ollama pour éviter les problèmes de cache de fichiers.
multi-rag-obsidian/
│
├── README.md
├── CUSTOMIZATION.md # Guide de personnalisation
├── LICENSE
├── docker-compose.yml
├── requirements.txt
├── requirements-dev.txt
├── .env.example
│
├── config/
│ ├── settings.yaml
│ ├── rag_config.yaml # Configuration des bases de connaissances
│ ├── prompts.yaml
│ └── scoring.yaml
│
├── app/
│ ├── main.py
│ ├── api/
│ │ ├── routes_query.py
│ │ ├── routes_index.py
│ │ ├── routes_feedback.py
│ │ └── routes_health.py
│ ├── core/
│ │ ├── config.py
│ │ ├── logging.py
│ │ └── security.py
│ ├── indexing/
│ │ ├── watcher.py
│ │ ├── markdown_parser.py
│ │ ├── chunker.py
│ │ ├── frontmatter.py
│ │ └── indexer.py
│ ├── retrieval/
│ │ ├── rag_selector.py
│ │ ├── vector_retriever.py
│ │ ├── bm25_retriever.py
│ │ ├── graph_retriever.py
│ │ ├── hybrid_retriever.py
│ │ ├── reranker.py
│ │ └── fusion.py
│ ├── reasoning/
│ │ ├── query_analyzer.py
│ │ ├── reflection_loop.py
│ │ ├── contradiction_checker.py
│ │ ├── confidence.py
│ │ └── synthesizer.py
│ ├── memory/
│ │ ├── user_memory.py
│ │ ├── meta_memory.py
│ │ ├── session_memory.py
│ │ └── memory_writer.py
│ ├── obsidian/
│ │ ├── vault.py
│ │ ├── wikilinks.py
│ │ ├── graph.py
│ │ └── note_creator.py
│ ├── llm/
│ │ ├── ollama_client.py
│ │ └── prompts.py
│ └── db/
│ ├── qdrant.py
│ ├── sqlite.py
│ └── cache.py
│
├── cli/
│ └── main.py
├── scripts/
│ ├── setup_qdrant.py
│ ├── index_obsidian.py
│ └── create_sample_notes.py
├── tests/
│ ├── test_indexing.py
│ ├── test_retrieval.py
│ ├── test_graph.py
│ ├── test_query.py
│ ├── test_llm.py
│ ├── test_rag.py
│ ├── test_obsidian.py
│ └── test_reflection.py
└── vault_example/
├── USER_DATA/ # Vos données utilisateur (obligatoire)
│ └── auto-generated/
├── BASE_1/ # Base de connaissances #1 (ex: documentation technique)
├── BASE_2/ # Base de connaissances #2 (ex: projets)
└── BASE_3/ # Base de connaissances #3 (ex: ressources)
Ce fichier configure vos bases de connaissances. Personnalisez-le avec vos propres noms et chemins.
rags:
USER_DATA:
path: "vault_example/USER_DATA"
collection: "rag_user_data"
required: true
base_weight: 2.0
trust_score: 0.9
description: "Mémoire personnelle utilisateur - TOUJOURS inclus"
color: "#4CAF50"
icon: "👤"
BASE_1:
path: "vault_example/BASE_1"
collection: "rag_base_1"
required: false
base_weight: 1.2
trust_score: 0.95
description: "Votre première base de connaissances (ex: documentation technique)"
color: "#FF5722"
icon: "📚"
BASE_2:
path: "vault_example/BASE_2"
collection: "rag_base_2"
required: false
base_weight: 1.0
trust_score: 0.85
description: "Votre deuxième base de connaissances (ex: projets)"
color: "#9C27B0"
icon: "🗂️"
BASE_3:
path: "vault_example/BASE_3"
collection: "rag_base_3"
required: false
base_weight: 1.0
trust_score: 0.8
description: "Votre troisième base de connaissances (ex: ressources)"
color: "#2196F3"
icon: "📖"
BASE_4:
path: "vault_example/USER_DATA/meta"
collection: "rag_meta"
required: false
base_weight: 0.7
trust_score: 0.75
description: "Métadonnées du système (ex: raisonnements, logs)"
color: "#607D8B"
icon: "📊"
# Mapping des domaines vers les bases à interroger
domain_rags:
default: ["USER_DATA", "BASE_1", "BASE_2", "BASE_3"]
# Priorités de sélection
selection_priority:
- BASE_1
- BASE_2
- BASE_3
- BASE_4
⚠️ IMPORTANT : Modifiez les chemins et les noms pour correspondre à votre structure de fichiers.
app:
name: "Multi-RAG Obsidian"
environment: "local"
debug: true
vault:
path: "./vault_example"
auto_generated_path: "./vault_example/USER_DATA/auto-generated"
supported_extensions: [".md"]
qdrant:
host: "localhost"
port: 6333
storage_path: "./data/qdrant"
ollama:
host: "http://localhost:11434"
default_model: "YOUR_PREFERRED_MODEL" # Ex: "mistral", "llama3.1:8b"
reflection_model: "YOUR_PREFERRED_MODEL"
synthesis_model: "YOUR_PREFERRED_MODEL"
embeddings:
model: "YOUR_EMBEDDING_MODEL" # Ex: "nomic-embed-text:latest"
use_ollama: true
batch_size: 32
cache_size: 2000
chunking:
chunk_size: 800
chunk_overlap: 120
retrieval:
top_k_per_rag: 8
final_top_k: 12
use_bm25: true
use_vector: true
use_graph: true
use_reranker: true
graph:
max_depth: 2
max_nodes: 25
reflection:
enabled: true
max_axes: 4
contradiction_check: true
auto_save_answer: true
memory:
session_enabled: true
auto_generate_notes: true
deduplicate_questions: true
modes:
fast:
reflection: false
graph_depth: 0
top_k: 6
balanced:
reflection: true
graph_depth: 1
top_k: 10
deep:
reflection: true
graph_depth: 2
contradiction_check: true
top_k: 16{
"intent": "knowledge_retrieval",
"domains": ["BASE_1", "BASE_2", "USER_DATA"],
"requires_user_context": true,
"requires_graph_exploration": true,
"requires_contradiction_check": true,
"complexity": "medium"
}BASE_USER_DATA → obligatoire (weight: 2.0)
BASE_1 → prioritaire (ex: votre documentation technique)
BASE_2 → secondaire (ex: vos projets)
BASE_3 → support (ex: vos ressources)
BASE_4 → métadonnées (optionnel)
{
"axes": [
{"name": "Contexte utilisateur", "keywords": ["USER_DATA", "personnalisation"], "bases": ["USER_DATA"]},
{"name": "Documentation technique", "keywords": ["architecture", "implémentation"], "bases": ["BASE_1", "BASE_3"]},
{"name": "Projets", "keywords": ["roadmap", "spécifications"], "bases": ["BASE_2"]}
]
}Chaque axe déclenche en parallèle : recherche vectorielle + BM25 + exploration graphe BFS.
score_final =
score_vectoriel * 0.35
+ score_bm25 * 0.15
+ score_graphe * 0.15
+ score_base * 0.15
+ score_importance * 0.10
+ score_recence * 0.05
+ score_feedback * 0.05
Source A (BASE_1, trust=0.95) : information technique
Source B (USER_DATA, trust=0.90) : information personnelle (plus récent)
→ Arbitrage : exposer les deux versions avec explication
Réponse sauvegardée dans USER_DATA/auto-generated/ :
---
type: rag_answer
auto: true
created: 2025-01-01
question_hash: "a92fd1"
bases_used: [USER_DATA, BASE_1, BASE_2]
confidence: 0.82
feedback: null
---| Type | Rôle | Base associée |
|---|---|---|
| Working Memory | Contexte immédiat de la conversation | - |
| Session Memory | Mémoire temporaire de la session | - |
| User Memory | Préférences et historique utilisateur | USER_DATA |
| Semantic Memory | Connaissances stables par domaine | BASE_1, BASE_2, BASE_3 |
| Episodic Memory | Événements et interactions passées | USER_DATA |
| Meta Memory | Raisonnements, erreurs, corrections | BASE_4 |
| Archived Memory | Anciennes notes compressées | USER_DATA |
---
type: concept
domain: BASE_1 # ou BASE_2, BASE_3, etc.
status: canonical
importance_score: 0.8
trust_score: 0.95
recency_score: 0.6
usage_frequency: 12
contradiction_score: 0.1
last_indexed: 2025-01-01
---# Cloner le dépôt
git clone https://github.com/YOUR_USERNAME/multi-rag-obsidian.git
cd multi-rag-obsidian
# Créer l'environnement virtuel
python -m venv .venv
source .venv/bin/activate # Linux/Mac
# .\.venv\Scripts\activate # Windows
# Installer les dépendances
pip install -r requirements.txt
# Configurer l'environnement
cp .env.example .env
# Démarrer Qdrant avec Docker
docker run -d -p 6333:6333 -v "$(pwd)/data/qdrant:/qdrant/storage" qdrant/qdrant
# Configurer les collections et indexer le vault
PYTHONPATH=. python scripts/setup_qdrant.py
PYTHONPATH=. python scripts/index_obsidian.py ./vault_example
# Démarrer l'API
uvicorn app.main:app --reload --host 0.0.0.0 --port 8000# Démarrer une session de chat
python -m app.main chat
# Poser une question directe
python -m app.main query "Quelle est l'architecture de ce système ?"
# Poser une question en mode profond
python -m app.main query --mode deep "Expliquez le fonctionnement du Contradiction Engine"
# Réindexer le vault
python -m app.main index rebuild
# Statistiques du graphe
python -m app.main graph stats
# Envoyer un feedback
python -m app.main feedback a92fd1 up| Méthode | Endpoint | Description |
|---|---|---|
| GET | /health |
État du système |
| POST | /query |
Requête complète avec réflexion |
| POST | /rags/search |
Recherche directe dans les bases |
| GET | /graph/explore |
Explorer les wikilinks |
| POST | /index/rebuild |
Réindexer le vault |
| POST | /feedback |
Envoyer un feedback |
| GET | /docs |
Documentation Swagger |
| GET | /redoc |
Documentation ReDoc |
curl -X POST http://localhost:8000/api/query \
-H "Content-Type: application/json" \
-d '{
"question": "Quelle est l\'architecture de ce projet Multi-RAG ?",
"mode": "balanced",
"bases": ["USER_DATA", "BASE_1", "BASE_2"]
}'{
"answer": "Ce projet utilise une architecture Multi-RAG avec 4 modules...",
"sources": [
{
"text": "Le système Multi-RAG Obsidian combine...",
"path": "vault_example/BASE_1/architecture.md",
"score": 0.92,
"base": "BASE_1"
},
{
"text": "Les modules sont : Memory, Reason...",
"path": "vault_example/BASE_2/docs.md",
"score": 0.85,
"base": "BASE_2"
}
],
"confidence": 0.95,
"bases_used": ["USER_DATA", "BASE_1", "BASE_2"],
"query": "Quelle est l'architecture de ce projet Multi-RAG ?",
"mode": "balanced"
}version: "3.9"
services:
qdrant:
image: qdrant/qdrant:latest
ports: ["6333:6333"]
volumes: ["./data/qdrant:/qdrant/storage"]
api:
build: .
ports: ["8000:8000"]
volumes: ["./vault_example:/app/vault_example", "./config:/app/config"]
environment: ["OLLAMA_HOST=http://host.docker.internal:11434"]
depends_on: [qdrant]Consultez le fichier CUSTOMIZATION.md pour un guide détaillé sur :
- ✅ Comment ajouter vos propres bases de connaissances
- ✅ Comment configurer vos modèles LLM préférés (Ollama)
- ✅ Comment structurer vos notes Obsidian pour une indexation optimale
- ✅ Comment adapter les poids et scores des bases
- ✅ Comment créer des modes de recherche personnalisés
| Risque | Mitigation |
|---|---|
| Trop de contexte | Retrieval → Ranking → Pruning → Contradiction → Synthesis |
| Latence excessive | Cache Redis, modes fast/balanced/deep, modèles spécialisés |
| Surpondération USER_DATA | Poids dynamique, scoring de fraîcheur |
| Dérive sémantique | Hash + date de modif → réindexation incrémentale |
| Contamination sémantique | Collections Qdrant strictement isolées |
| Version | Objectif |
|---|---|
| v0.1 | MVP — Indexation + Query + USER_DATA |
| v0.2 | Multi-RAG propre + Fusion RRF + CLI |
| v0.3 | Graphe Obsidian + BFS |
| v0.4 | Boucle de réflexion + sauvegarde auto |
| v0.5 | Mémoire cognitive + feedback |
| v0.6 | Contradiction Engine |
| v1.0 | Assistant stable + tests + docs |
| v1.1+ | Interface web, multi-utilisateurs, plugin Obsidian |
Les contributions sont les bienvenues ! Ouvrez une Pull Request pour :
- Corriger des bugs
- Ajouter des fonctionnalités génériques (non liées à un cas d'usage spécifique)
- Améliorer la documentation
- Optimiser les performances
GNU Affero General Public License v3.0 (AGPL-3.0)
Copyright (C) 2025 Multi-RAG Obsidian Contributors
Ce projet est distribué sous la licence AGPL-3.0, une licence copyleft forte qui garantit :
- La liberté d'utiliser, modifier et distribuer le logiciel
- L'obligation de partager le code source des versions modifiées
- La protection contre l'appropriation privée (trou de la licence AGPL)
Pour plus de détails, consulter : Licence AGPL-3.0 complète
⚠️ Restriction commerciale
Toute utilisation commerciale de ce logiciel générant un chiffre d'affaires annuel supérieur à 50 000€ doit faire l'objet d'un accord écrit préalable avec l'auteur original.
Contact : Pour les questions de licence commerciale, contactez l'auteur original via les informations fournies dans le fichier LICENSE.
Cette restriction s'ajoute aux obligations de la licence AGPL-3.0 et ne limite pas les usages personnels, éducatifs ou les utilisations commerciales à faible volume.
Documentation générée pour Multi-RAG Obsidian Dernière mise à jour : 2025-05-10