Skip to main content
Glama
theojoly2

GlossaryAI MCP Server

by theojoly2
README.md
# GlossaryAI — Serveur MCP

Serveur MCP (Model Context Protocol) pour **GlossaryAI**, un assistant IA spécialisé en vocabulaires, glossaires et textes juridiques/réglementaires. Il expose des outils de recherche vectorielle, de planification, de résolution de liens juridiques et de comparaison de concepts, alimentés par une base Qdrant et un LLM OpenAI-compatible.

---

## Overview

Le serveur est construit avec **FastMCP** et exécuté via **Uvicorn**. Il est appelé par le client Streamlit `AI4Semantics-MCP-client-fr` pour :

1. Planifier la réponse à une question utilisateur (`plan_workflow_with_tools`).
2. Rechercher dans les documents indexés (`retrieve_documents`).
3. Lister les sources disponibles (`get_available_tags`).
4. Résoudre les liens juridiques et RDF mentionnés dans les chunks (`resolve_links`).
5. Comparer/converger plusieurs termes (`compare_concepts`).

---

## Requirements

- Python 3.10 ou supérieur
- Docker (pour Qdrant via `docker-compose.yml`)
- Un GPU est recommandé pour le reranker local ; sinon le serveur bascule automatiquement sur ONNX CPU.
- Une clé API pour le LLM (`LLM_API_KEY` / `URL_LLM_API`) et éventuellement pour Albert (`ALBERT_API_KEY`) si le reranker API est activé.

---

## Setup

### 1. Cloner le dépôt

```bash
git clone https://github.com/pwc-be-adv-tc-cd/AI4semantics
cd AI4semantics/AI4Semantics-MCP-server-fr
```

### 2. Créer et activer un environnement virtuel

```bash
python -m venv venv
source venv/bin/activate  # Windows: venv\Scripts\activate
```

### 3. Installer les dépendances

```bash
pip install -r requirements.txt
```

### 4. Configurer les variables d'environnement

Copier `.env.sample` vers `.env` et renseigner les valeurs :

```bash
cp .env.sample .env
```

| Variable | Description |
|---|---|
| `SERVER_HOST` | Hôte Qdrant (`qdrant` en Docker, `localhost` en local) |
| `SERVER_PORT` | Port Qdrant (`6333`) |
| `QDRANT_API_KEY` | Clé API Qdrant (laisser vide si aucune) |
| `URL_LLM_API` | Endpoint OpenAI-compatible du LLM |
| `LLM_API_KEY` | Clé API du LLM |
| `LLM_MODEL` | Nom du modèle LLM |
| `ALBERT_API_KEY` | Clé pour le reranker Albert (si `reranker_api.enabled: true`) |

### 5. Démarrer Qdrant

```bash
docker-compose up -d
```

Qdrant est alors accessible sur `localhost:6333` avec un volume persistant dans `./data/qdrant`.

### 6. Indexer les documents

Placer les documents dans `tools/index_search/load_documents/documents/` puis lancer :

```bash
python tools/index_search/load_documents/load.py
```

Le script supporte de nombreux formats : PDF, HTML, TXT, CSV, JSON, XML/RDF/SKOS, Excel, Markdown, RTF, etc. Les fichiers HTML Eur-Lex (par exemple `Data-Act.html`) sont automatiquement découpés par articles/chapitres.

Pour tester la recherche :

```bash
python tools/index_search/load_documents/retrieve.py
```

### 7. Démarrer le serveur MCP

```bash
python -m server
```

Le serveur écoute par défaut sur `0.0.0.0:8001`.

---

## Tools

| Tool | Fichier | Description |
|---|---|---|
| `plan_workflow_with_tools` | `tools/planning_orchestrator/plan_workflow_with_tools.py` | Planifie l'enchaînement des outils pour répondre à la question utilisateur. |
| `retrieve_documents` | `tools/index_search/retrieve_documents.py` | Recherche hybride dense/sparse dans Qdrant, reranking, retour de chunks et de fenêtres de documents. |
| `get_available_tags` | `tools/index_search/get_available_tags.py` | Liste les tags de sources présents dans la collection Qdrant. |
| `resolve_links` | `tools/legal_link_resolver/resolve_links.py` | Détecte les références à articles juridiques et les liens RDF/SKOS, puis remonte les chunks liés. |
| `compare_concepts` | `tools/concept_comparator/compare_concepts.py` | Compare plusieurs termes via recherche vectorielle et propose une définition convergente via LLM. |

---

## File Structure

```
.
├── server.py                       # Point d'entrée FastMCP + Uvicorn
├── config.py                       # Chargement centralisé de la configuration
├── config.yaml                     # Paramètres de chunking, recherche, reranker, comparateur
├── docker-compose.yml              # Service Qdrant
├── .env.sample                     # Variables d'environnement requises
├── requirements.txt                # Dépendances Python
│
└── tools/
    ├── __init__.py                 # Export des outils enregistrés dans le serveur
    │
    ├── concept_comparator/
    │   └── compare_concepts.py     # Comparaison/convergence de termes
    │
    ├── index_search/
    │   ├── retrieve_documents.py           # Wrapper de recherche pour le serveur
    │   ├── retrieve_search_documents.py    # Logique de recherche hybride et aggregation
    │   ├── get_available_tags.py           # Liste des tags indexés
    │   ├── init_qdrant_no_vocs.py          # (legacy) initialisation sans vocabulaires
    │   ├── init_qdrant_vocs.py             # (legacy) initialisation avec vocabulaires
    │   ├── old_init.py                     # (legacy)
    │   └── load_documents/
    │       ├── load.py             # Indexation complète (parse, chunk, embed, upsert)
    │       ├── retrieve.py         # Script de test de recherche
    │       ├── config.py           # Client Qdrant, modèle d'embedding, rerankers
    │       ├── config.yaml         # Configuration de Qdrant, chunking, reranker
    │       └── documents/          # Dossier contenant les documents à indexer
    │           ├── AGIT/
    │           ├── EU/
    │           ├── FranceTerme/
    │           ├── Legifrance/
    │           ├── OFB/
    │           └── OiEau/
    │
    ├── legal_link_resolver/
    │   └── resolve_links.py        # Résolution de liens juridiques et RDF
    │
    └── planning_orchestrator/
        ├── plan_workflow_with_tools.py  # Planner agent
        └── prompts.py                   # Prompt système du planner
```

---

## Architecture de recherche

1. **Parsing** : `load.py` extrait le texte de nombreux formats.
2. **Chunking** : découpage par taille avec chevauchement. Les HTML Eur-Lex sont chunkés par articles/chapitres.
3. **Embeddings** : modèle `BAAI/bge-m3` (dense + sparse via la même API de modèle).
4. **Indexation** : upsert dans Qdrant avec métadonnées (tag, filename, chunk_index, article, concept_uri, etc.).
5. **Recherche** : recherche hybride dense/sparse, reranking local (bge-reranker-v2-m3) ou via API Albert, agrégation par document, retour des meilleurs chunks avec possibilité de fenêtre.

Les paramètres de recherche sont centralisés dans `tools/index_search/load_documents/config.yaml` :

| Paramètre | Description |
|---|---|
| `search.limit` | Nombre de résultats finaux retournés |
| `search.min_candidates` | Taille du pool initial de candidats |
| `search.rerank_pool_size` | Nombre de candidats rerankés |
| `search.hybrid_dense_weight` | Poids de la recherche dense vs sparse |
| `search.max_chunks_per_document` | Nombre de chunks maximum par document dans les résultats |
| `chunking.chunk_size` | Taille d'un chunk |
| `chunking.chunk_overlap` | Chevauchement entre chunks |

---

## Configuration

- `config.yaml` (racine) : paramètres pour le résolveur de liens (`link_resolver`) et le comparateur de concepts (`concept_comparator`).
- `tools/index_search/load_documents/config.yaml` : configuration Qdrant, modèles, chunking, reranker, recherche.
- `.env` : secrets et endpoints.

---

## Démarrage rapide

```bash
# 1. Démarrer Qdrant
docker-compose up -d

# 2. Indexer les documents
python tools/index_search/load_documents/load.py

# 3. Lancer le serveur MCP
python -m server
```

Puis lancer le client Streamlit `AI4Semantics-MCP-client-fr`.

---

## Notes importantes

- Le serveur utilise un `ThreadPoolExecutor(max_workers=2)` pour exécuter les recherches lourdes sans bloquer la boucle asyncio.
- `TOKENIZERS_PARALLELISM` est désactivé pour éviter les deadlocks du tokenizer HuggingFace.
- Le reranker local peut être remplacé par l'API Albert si `reranker_api.enabled` est à `true` dans `config.yaml`.

Pour plus de détails, consulter les commentaires dans chaque module.