Skip to main content

ner-mcp-fr

CI PyPI Python License: MIT

Reconnaissance d'entités nommées (NER) en français, exposée comme serveur MCP — avec un CLI pour vérifier ce que le modèle fait réellement. Inférence ONNX, sans torch.

Quatre labels : PER (personne), LOC (lieu), ORG (organisation), MISC (divers).

Le modèle est CATIE-AQ/NERmembert-base-4entities (CamemBERT-base, 110 M de paramètres, fine-tuné sur frenchNER_4entities, licence MIT), exporté en ONNX fp16 et hébergé séparément des poids PyTorch.

⚠️ Ne pas utiliser NERmemberta-* ni NERmembert2-*. Ces modèles, pourtant marqués new_version par leurs auteurs, publient un tokenizer byte-level sans règles de fusion : chaque mot est découpé en lettres (Ġ S y l v a i n) et les prédictions sont du bruit. Constat vérifié et documenté dans SPECS.md §2.

Installation

Rien à installer globalement : uvx construit un environnement jetable à la volée.

uvx ner-mcp-fr info      # ne charge pas le modèle, sert de test de fumée
uvx ner-mcp-fr extract article.txt --format highlight

Empreinte : ~150 MB installés (onnxruntime, tokenizers, numpy, mcp), contre ~780 MB avec une pile PyTorch. Le premier appel télécharge les poids fp16 (210 MB) depuis Hugging Face, puis les garde en cache. Compromis assumé : ~70 ms par paragraphe sur CPU (contre ~16 ms avec torch + MPS sur Mac), pour un cinquième de la taille.

Tant que le paquet n'est pas publié sur PyPI, la même chose depuis GitHub :

uvx --from git+https://github.com/athoune/ner-mcp-fr ner-mcp-fr info

Pour développer :

git clone https://github.com/athoune/ner-mcp-fr
cd ner-mcp-fr
uv sync
uv run pytest

Le CLI : vérifier une analyse

# un fichier, rendu lisible avec les entités colorées
ner-mcp-fr extract article.txt --format highlight

# depuis STDIN
cat article.txt | ner-mcp-fr extract

# un paragraphe collé directement
pbpaste | ner-mcp-fr extract --format highlight --stats

Exemple de sortie --format text :

LABEL  SCORE   SPAN        TEXT
-----  ------  ----------  -------------------
MISC   0.9456  [36,38)     'JO'
LOC    0.9993  [75,84)     'Grand Rex'
PER    0.9989  [165,178)   'Sylvain Boyer'

Formats disponibles :

Format Usage
json schéma complet (défaut quand la sortie est redirigée)
jsonl une entité par ligne, pour jq
text tableau aligné (défaut sur un terminal)
highlight texte d'origine annoté, en couleur
markdown tableau + paragraphe annoté, pour un ticket

Options utiles :

ner-mcp-fr extract article.txt --labels PER,LOC      # filtre les labels
ner-mcp-fr extract article.txt --min-score 0.9       # exige de la confiance
ner-mcp-fr extract article.txt --keep-punctuation    # spans bruts du modèle
ner-mcp-fr extract article.txt --onnx ./model.onnx   # poids locaux, sans téléchargement
ner-mcp-fr extract article.txt --stats               # chunks/timing sur stderr
ner-mcp-fr extract article.txt --fail-on-empty       # code 3 si aucune entité

Codes de sortie : 0 succès, 1 erreur d'exécution, 2 erreur d'usage, 3 --fail-on-empty sans entité.

Serveur MCP

ner-mcp-fr sans argument (ou ner-mcp-fr mcp) démarre le serveur sur stdio. Configuration d'un hôte :

{
  "mcpServers": {
    "ner-fr": {
      "command": "uvx",
      "args": ["ner-mcp-fr"]
    }
  }
}

Quatre outils :

Outil Rôle
ner_extract un texte inline → entités
ner_extract_file un chemin → entités, fichier lu côté serveur
ner_batch jusqu'à 64 textes en une passe ; une entrée invalide n'annule pas le lot
ner_info modèle, précision, provider, contexte, statut — sans charger

Pourquoi ner_extract_file existe : un texte de 200 kB collé dans ner_extract traverse le contexte du modèle deux fois (lecture + historique). Avec un chemin, il ne traverse jamais rien : le serveur lit le fichier en local. source dans la réponse est le chemin absolu résolu, pour tracer l'origine sans renvoyer le texte. NER_ALLOWED_DIRS restreint les chemins lisibles si le serveur ingère du contenu non fiable.

Réponse de ner_extract :

{
  "model": "CATIE-AQ/NERmembert-base-4entities",
  "precision": "fp16",
  "device": "CPUExecutionProvider",
  "entities": [
    { "text": "Paris", "label": "LOC", "start": 334, "end": 339, "score": 0.9991 }
  ],
  "source": "/Users/moi/article.txt",
  "text_length": 617,
  "chunks": 1,
  "truncated": false,
  "dropped_by_min_score": 0,
  "elapsed_ms": 214
}

Invariant : pour chaque entité, text[start:end] == entity.text. Les offsets sont des index de code points Unicode (sémantique Python). Si un client JavaScript manipule des offsets sur du texte contenant des emoji, préférer le champ text.

Configuration

Variable Défaut Effet
NER_MODEL_ID CATIE-AQ/NERmembert-base-4entities source du tokenizer et de la table de labels
NER_ARTIFACT_REPO athoune/ner-mcp-fr-onnx dépôt Hugging Face des poids ONNX
NER_ARTIFACT_FILE model-fp16.onnx fichier de poids dans ce dépôt
NER_ONNX_PATH — fichier ONNX local, court-circuite le téléchargement
NER_DEVICE auto auto, cpu, cuda (provider onnxruntime)
NER_MAX_INPUT_CHARS 200000 garde-fou de taille, aussi borne des fichiers
NER_BATCH_SIZE 8 fenêtres par passe
NER_MIN_SCORE 0.0 seuil de confiance par défaut
NER_CACHE_DIR — cache Hugging Face alternatif
NER_PRELOAD 0 charge le modèle au démarrage
NER_OFFLINE 0 1 = aucun accès réseau
NER_THREADS — threads onnxruntime
NER_LOG_LEVEL INFO logs sur stderr (stdout = protocole)
NER_ALLOWED_DIRS — répertoires autorisés pour ner_extract_file (:)

Limites connues

  • Français uniquement. Aucune détection de langue : sur de l'anglais, le modèle produit des entités plausibles mais non fiables.
  • Contexte 512 tokens (~350 mots). Au-delà, le texte est découpé en fenêtres avec chevauchement d'une phrase ; chunks l'indique. Rien n'est tronqué silencieusement.
  • CPU uniquement, sauf onnxruntime-gpu installé et NER_DEVICE=cuda. Le provider CoreML a été mesuré plus lent que le CPU sur ce graphe (29 nœuds accélérés sur 597).
  • fp16 : sortie identique au fp32 sur le corpus de référence, mais la quantization int8, elle, détruit le modèle (F1 0,53 en dynamique, 0,00 en statique). Ne pas la réintroduire sans mesure.
  • MISC est le label le plus faiblement performant (F1 ≈ 0,81) : attendez-vous à du bruit.
  • La ponctuation et le balisage Markdown de bord sont retirés des entités (Grand Rex. → Grand Rex, Ebenezer** → Ebenezer) ; --keep-punctuation rend les spans bruts.

Développement

uv run pytest        # tests unitaires (aucun modèle téléchargé)
uv run ruff check .

Re-exporter les poids (seule étape qui demande torch) :

uv run --group export python scripts/export_onnx.py
# écrit dist/onnx/model-fp16.onnx et affiche son SHA-256

Architecture : backend.py (session ONNX + tokenizer), artifacts.py (téléchargement, cache, vérification du SHA-256), engine.py (chunking, agrégation — sans MCP), cli.py + render.py (CLI), server.py (quatre outils MCP). Le contrat complet est dans SPECS.md.

Attribution

Modèles fine-tunés par CATIE-AQ sur le jeu frenchNER_4entities, publiés sous licence MIT. Le graphe ONNX est un export de NERmembert-base-4entities, distribué sous la même licence.

Metadata

Release files for ner-mcp-fr 0.2.0

For a detailed explanation of source distributions (sdists) and built distributions (wheels), please see the package formats documentation.

Source distribution (sdist)

Source distribution for ner-mcp-fr 0.2.0
File Size Uploaded Provenance Actions
ner_mcp_fr-0.2.0.tar.gz 40.0 kB With provenance Details for ner_mcp_fr-0.2.0.tar.gz

Built distribution (wheel)

Table of built distributions (wheels) for ner-mcp-fr 0.2.0
File Interpreter ABI Platform Actions
ner_mcp_fr-0.2.0-py3-none-any.whl Python 3 none any Details for ner_mcp_fr-0.2.0-py3-none-any.whl

Total release size: 70.2 kB

Release files / ner_mcp_fr-0.2.0.tar.gz

Download URL ner_mcp_fr-0.2.0.tar.gz
Size 40.0 kB
Tags Source
SHA-256 checksum
How to use checksums
629146214e0d0beb683d1d8ef201270b524509236a9ea37bf266b23a55965a9b
BLAKE2b-256 checksum
How to use checksums
905d2ff697359e0042b137acd02347377374729b0a64c5f9c09d084dcc1fd1ad
Upload date
Uploaded using Trusted Publishing?
What is trusted publishing?
Yes
Uploaded via twine/7.0.0 CPython/3.13.16

Provenance

Provenance describes where a file came from. On PyPI, provenance is shared via attestations, which provide a verifiable record of the build or publishing details. View details, limitations and caveats.

PyPI Publish Attestation

PyPI verified that this artifact, at this checksum, originated from the publisher listed below.

Signed by GitHub Actions, verified by PyPI on Nov 5, 2026.

Transparency log

Release files / ner_mcp_fr-0.2.0-py3-none-any.whl

Download URL ner_mcp_fr-0.2.0-py3-none-any.whl
Size 30.2 kB
Tags Python 3
SHA-256 checksum
How to use checksums
842ecb8601f070828ddd935ecf43448cdc5719803754d6f3aebadeab225f014a
BLAKE2b-256 checksum
How to use checksums
c851bd8ca678f6d1d62efdcead486f2a3d3c65499fede7d68cb08f5eadc24977
Upload date
Uploaded using Trusted Publishing?
What is trusted publishing?
Yes
Uploaded via twine/7.0.0 CPython/3.13.16

Provenance

Provenance describes where a file came from. On PyPI, provenance is shared via attestations, which provide a verifiable record of the build or publishing details. View details, limitations and caveats.

PyPI Publish Attestation

PyPI verified that this artifact, at this checksum, originated from the publisher listed below.

Signed by GitHub Actions, verified by PyPI on Nov 5, 2026.

Transparency log

Security for ner-mcp-fr 0.2.0

Provenance

Provenance describes where a file came from. On PyPI, provenance is shared via attestations, which provide a verifiable record of the build or publishing details. View details, limitations and caveats.

Full provenance

All 2 files in this release have been uploaded with provenance metadata.

Select from 2 files

Attestation for ner_mcp_fr-0.2.0.tar.gz

PyPI Publish Attestation

PyPI verified that this artifact, at this checksum, originated from the publisher listed below.

Signed by GitHub Actions, verified by PyPI on Nov 5, 2026.

Transparency log

A note on package security

PyPI is a repository for distributing packages, not a service for auditing them. While third-party security researchers and our staff do their best to detect and remove malicious packages, PyPI cannot guarantee the quality, security or suitability of any given package.

To learn more about protecting yourself from malicious actors, visit our package security documentation.

Release history Release notifications | RSS feed

This release

0.2.0 This release

2 release files Full provenance

Anthropic, PBC Visionary sponsor Bloomberg Visionary sponsor Hudson River Trading Visionary sponsor Meta Visionary sponsor NVIDIA Visionary sponsor Microsoft Sustainability sponsor Depot Continuous Integration AWS Cloud computing and Security Sponsor Datadog Monitoring Fastly CDN Google Download Analytics Sentry Error logging StatusPage Status page