llm-memory-tool
by menoxz
README.md
# LLM Memory Tool
**Mémoire persistante, hybride et locale pour agents LLM** — serveur MCP + API REST + SDK Python.
LLM Memory Tool stocke les connaissances, décisions et conventions d'un projet, puis
fournit le contexte pertinent à injecter dans les prompts, sans jamais dépasser un
budget de tokens. Recherche hybride **vectorielle + BM25** avec fusion RRF, graphe de
connaissances, moteur de politiques (décroissance, rétention, renforcement) et serveur
**MCP** pour une intégration directe dans les assistants (VS Code, opencode, Claude…).
---
## Fonctionnalités
- **Recherche hybride** : similarité cosinus (vecteurs) + full-text BM25 + fusion RRF
- **4 types de mémoire** : `semantic`, `episodic`, `procedural`, `profile`
- **Injection pilotée par budget** : jamais au-delà du plafond de tokens configuré
- **Moteur de politiques** : décroissance de confiance, renforcement, rétention/élagage
- **Graphe de connaissances** : entités, relations typées, parcours, plus court chemin,
clustering (KMeans/DBSCAN) et extraction d'entités par NLP (spaCy)
- **Génération de skills** : transforme un cluster du graphe en fiche `SKILL.md`
- **API REST** : FastAPI + spec OpenAPI auto-générée sur `/docs`
- **SDK Python** : un appel `get_context(query, project_id)` pour le contexte de prompt
- **Serveur MCP** : 20+ outils exposés (`memory_store`, `memory_retrieve`, `graph_*`…)
- **Observabilité** : métriques Prometheus, logs structurés
- **Docker** : conteneur de production avec service d'embeddings (Ollama) intégré
---
## Architecture
```
┌──────────────┐ stdio / MCP ┌──────────────────┐ HTTP :8765 ┌──────────────────┐
│ Assistant │ ◄──────────────► │ Serveur MCP │ ─────────────► │ API REST │
│ (opencode, │ │ mcp_server/ │ (MEMORY_API_URL)│ memory_tool/ │
│ VS Code…) │ │ server.py │ ◄───────────── │ (FastAPI) │
└──────────────┘ └──────────────────┘ HTTP :8765 └────────┬─────────┘
│
┌───────┴────────┐
│ SQLite │
│ /data/memory.db│
└────────────────┘
┌──────────────────┐ HTTP :11434
│ Ollama │ ◄────── embeddings (nomic-embed-text)
│ (conteneur) │
└──────────────────┘
```
- **API** (`memory_tool/`) : FastAPI, port `8765`, endpoints sous `/api/v1`
- **Serveur MCP** (`mcp_server/`) : transport stdio, s'appuie sur l'API via `MEMORY_API_URL`
- **UI** : accessible sur `http://localhost:8766` (optionnelle, voir docker-compose)
---
## Prérequis
| Outil | Version minimum |
|---|---|
| Python | 3.11+ (3.13 testé) |
| Docker | 24+ (recommandé, avec plugin compose) |
| pip | 23+ |
---
## Installation
### Option A — Docker (recommandé)
```bash
cd memory_tool/
cp .env.example .env # définir MEMORY_API_KEY
docker compose up -d --build # démarre API :8765 + embeddings Ollama
curl http://localhost:8765/api/v1/health
```
Le service `embeddings` télécharge `nomic-embed-text` au premier démarrage.
### Option B — Local (pip)
```bash
cd memory_tool/
python -m venv .venv
source .venv/bin/activate # Windows : .venv\Scripts\activate
pip install -e ".[dev]"
# Pour le NLP (spaCy) : python -m spacy download en_core_web_sm
MEMORY_API_KEY=changeme MEMORY_EMBED_MODEL=mock uvicorn memory_tool.app:app --port 8765
```
---
## Configuration du serveur MCP
Ajoutez ce bloc à votre `opencode.json` (ou équivalent pour VS Code / Claude) :
```json
{
"mcp": {
"llm-memory-tool": {
"type": "local",
"command": ["python", "-m", "mcp_server.server"],
"environment": {
"MEMORY_API_URL": "http://localhost:8765/api/v1",
"MEMORY_API_KEY": "changeme",
"MEMORY_DEFAULT_PROJECT": "default"
},
"enabled": true
}
}
}
```
Le serveur MCP parle à l'API sur `MEMORY_API_URL` (défaut : `http://localhost:8765/api/v1`).
### Outils MCP exposés
| Outil | Rôle |
|---|---|
| `memory_health` | Vérifie que l'API est joignable |
| `memory_store` | Stocke une mémoire (type, tags, importance) |
| `memory_retrieve` | Récupère le contexte prêt à injecter (budget tokens) |
| `memory_retrieve_graph_augmented` | Recherche augmentée par le graphe de connaissances |
| `memory_list` / `memory_get` | Parcours et lecture des mémoires |
| `memory_update` / `memory_delete` | Mise à jour / suppression (soft ou hard) |
| `memory_consolidate` | Applique décroissance/rétention (dry-run par défaut) |
| `graph_entity_create` / `graph_entity_search` / `graph_entity_get` | Entités du graphe |
| `graph_edge_create` / `graph_edge_list` | Relations typées entre nœuds |
| `graph_traverse` / `graph_shortest_path` | Exploration du graphe (BFS, plus court chemin) |
| `graph_cluster` | Clustering KMeans/DBSCAN des entités |
| `graph_discover_entities` | Extraction d'entités par NLP (spaCy) |
| `graph_skill_sync` / `graph_skill_sync_all` | Génération de fiches `SKILL.md` |
---
## Utilisation rapide
### API REST
```bash
# Stocker une mémoire
curl -X POST http://localhost:8765/api/v1/memories \
-H "X-API-Key: changeme" \
-H "Content-Type: application/json" \
-d '{"project_id": "my-project",
"content": "On utilise FastAPI pour tous les endpoints REST, pydantic v2 pour la validation.",
"memory_type": "procedural",
"tags": ["architecture", "fastapi"]}'
# Récupérer le contexte
curl -X POST http://localhost:8765/api/v1/retrieve \
-H "X-API-Key: changeme" \
-H "Content-Type: application/json" \
-d '{"query": "quel framework pour les APIs ?", "project_id": "my-project", "token_budget": 600}'
```
### SDK Python
```python
from memory_tool.sdk import MemoryClient, get_context
client = MemoryClient(api_key="changeme")
client.create_memory(
project_id="my-project",
content="Convention : snake_case pour toutes les fonctions Python.",
tags=["conventions"],
)
context = get_context("conventions de nommage", project_id="my-project")
prompt = f"Contexte :\n{context}\n\nUtilisateur : {user_message}"
```
### Outils MCP (exemple de workflow)
1. `memory_retrieve` **d'abord** — injectez le contexte pertinent dans votre prompt ;
2. après une interaction utile, `memory_store` pour persister la nouvelle connaissance ;
3. `memory_consolidate` périodiquement pour appliquer les politiques.
---
## Configuration (variables d'environnement)
Toutes les réglages passent par des variables préfixées `MEMORY_` (fichier `.env` supporté) :
| Variable | Défaut | Description |
|---|---|---|
| `MEMORY_DB_PATH` | `/data/memory.db` | Chemin SQLite |
| `MEMORY_API_KEY` | `changeme` | **À changer en production** |
| `MEMORY_EMBED_MODEL` | `local` | `local` / `mock` |
| `MEMORY_EMBED_URL` | `http://localhost:11434` | URL Ollama / LM Studio |
| `MEMORY_EMBED_MODEL_NAME` | `nomic-embed-text` | Modèle d'embedding |
| `MEMORY_TOP_K` | `5` | k par défaut de la recherche |
| `MEMORY_MAX_TOKEN_BUDGET` | `1500` | Plafond de tokens injectés |
| `MEMORY_DECAY_DAYS` | `30` | Jours avant décroissance de confiance |
| `MEMORY_RETENTION_DAYS` | `90` | Rétention par défaut |
| `MEMORY_API_URL` | `http://localhost:8765/api/v1` | URL de l'API (côté MCP/SDK) |
| `MEMORY_DEFAULT_PROJECT` | `default` | Projet par défaut (MCP) |
---
## Tests
```bash
cd memory_tool/
pytest tests/ -q # 38 tests (SQLite en mémoire, aucun service externe requis)
# Avec couverture
pytest --cov=memory_tool --cov-report=term-missing
# Lint
ruff check memory_tool/
```
> Les tests utilisent une base SQLite en mémoire : aucune API Docker n'est nécessaire.
---
## Structure du projet
```
memory_tool/
├── mcp_server/ # Serveur MCP (stdio) : server.py, client.py
├── memory_tool/ # API FastAPI
│ ├── app.py # Point d'entrée FastAPI
│ ├── auth.py # Authentification par clé API
│ ├── config.py # Paramètres (pydantic-settings, env MEMORY_*)
│ ├── dependencies.py # Injection de dépendances
│ ├── sdk.py # Client SDK Python
│ ├── adapters/ # Embeddings (Ollama/mock), graphe
│ ├── db/ # Schéma SQLite + migrations + repository
│ ├── domain/ # Modèles métier purs + exceptions
│ ├── routers/ # Endpoints REST (memories, retrieve, admin, graph, infra)
│ └── services/ # mémoire, recherche hybride, politiques, NLP, clustering, skills
├── scripts/ # Synchronisation de l'index des skills, évaluation Recall@K
├── tests/ # Suite pytest
├── docs/ # Documentation (skill-index)
├── Dockerfile
├── docker-compose.yml # API :8765 + embeddings Ollama + UI :8766
├── pyproject.toml
└── requirements.txt
```
---
## Licence
[MIT](LICENSE) © 2026 Jean-Luc KOUMAGLO (menoxz)
This server cannot be deployed
Maintenance
ActivitySlowing
ResponsivenessNo issues