Aller au contenu

Traduction automatique

Cet article a été traduit automatiquement depuis la version originale en anglais.

Le guide définitif du NER en 2026 : encodeurs, LLM et architecture de production en 3 niveaux

Il y a deux ans, choisir une approche NER revenait à choisir entre vitesse (modèles encodeurs) et précision (LLM). Ce compromis a disparu. Un modèle GLiNER de 300M de paramètres égale la précision zero-shot d’un UniNER 13B tout en étant 100x plus rapide. Une variante bi-encodeur plus récente passe à l’échelle jusqu’à des millions de types d’entités avec un avantage de débit de 130x par rapport au cross-encoder d’origine. Le pattern de production qui a émergé : utiliser les LLM pour labelliser les données, affiner des encodeurs compacts, puis déployer avec ONNX ou Rust.

J’ai construit le repo compagnon et benchmarké chaque approche majeure. Les encodeurs ont gagné le marché du NER en production. Les LLM restent essentiels, mais comme générateurs de données d’entraînement plutôt que comme moteurs d’inférence. Ce guide couvre les papiers, benchmarks et patterns de déploiement derrière ce basculement.

Repo compagnon : ner-field-guide — démos exécutables pour GLiNER, export ONNX, pipeline LLM-as-teacher et extraction structurée avec Instructor.

TL;DR : Vous n’avez plus besoin de construire des modèles NER from scratch. Pour l’extraction zero-shot, GLiNER sur CPU via ONNX bat même les LLM les plus récents pour un coût quasi nul. Pour les tâches spécifiques à un domaine, le pipeline LLM-as-teacher (LLM labels → review → fine-tune) produit des encodeurs qui atteignent 90-93%+ de F1. Pour les cas qui nécessitent du raisonnement, utilisez Instructor ou Outlines avec une API LLM — mais prévoyez \$2+/1K docs. L’architecture en 3 niveaux combine les trois.


Pourquoi le NER compte encore plus aujourd’hui : agents, RAG et document intelligence

Le NER signifie toujours la même chose : trouver des spans nommés dans du texte et les classifier. Ce qui a changé, c’est où il apparaît. Avant, c’était la dernière étape d’un pipeline NLP, un utilitaire discret sur lequel personne n’écrivait d’articles. Aujourd’hui, c’est un bloc de base dans les systèmes RAG, les boucles d’agents et les plateformes de traitement documentaire. C’est pourquoi la vague de recherche NER 2024-2026 compte au-delà des benchmarks académiques.

RAG : un meilleur retrieval grâce à l’extraction d’entités

Le RAG standard — découper le texte en chunks, embedder, récupérer par similarité, puis espérer que ça marche — s’effondre quand les utilisateurs posent des questions sur des entités spécifiques. Si quelqu’un demande « qu’a dit Anthropic sur la sécurité des modèles au T4 2024 ? », le système doit reconnaître « Anthropic » et « T4 2024 » comme des filtres, pas seulement s’appuyer sur la similarité d’embeddings.

Pendant l’indexation, vous extrayez les entités de chaque chunk et les stockez comme métadonnées : {"organizations": ["Anthropic"], "dates": ["Q4 2024"], ...}. Cela permet de filtrer par entité avant d’exécuter la recherche vectorielle. Le knowledge graph RAG (GraphRAG, property graphs de LlamaIndex) va plus loin : NER plus extraction de relations construit un graphe capable de répondre à des questions multi-hop que des embeddings plats ne peuvent pas traiter.

Au moment de la requête, les entités extraites de la question de l’utilisateur pilotent le routage. Une question mentionnant un nom d’entreprise va vers un index finance ; une autre mentionnant des noms de médicaments va vers une base de connaissance clinique. GLiNER fonctionne bien ici parce que les entités des requêtes sont imprévisibles — vous ne pouvez pas réentraîner pour chaque nouveau type d’entité que les utilisateurs pourraient demander.

Agents IA : transformer le texte en faits structurés

Les agents reçoivent du texte non structuré — pages web, réponses d’API, messages utilisateurs — et doivent agir dessus. Le NER convertit ce texte en faits structurés sur lesquels l’agent peut raisonner, qu’il peut stocker ou transmettre à des outils.

Deux endroits où c’est le plus important.

Le premier est le routage d’outils. Quand un utilisateur dit « planifie une réunion avec Sarah Chen de chez Accenture jeudi à 14h », l’agent doit extraire PERSON: Sarah Chen, ORGANIZATION: Accenture et DATETIME: Thursday 2pm avant d’appeler l’API calendrier. Un modèle NER encodeur fait cela en moins de 10 ms. Un LLM ajoute 1 à 2 secondes par appel, et ce délai s’accumule dans les workflows multi-étapes jusqu’à ce qu’un agent « instantané » ne paraisse plus instantané.

Le second est le suivi des entités au fil des conversations. Les systèmes de mémoire d’agents doivent savoir que « Sarah » au tour 3 et « Mme Chen » au tour 12 sont la même personne. Le NER identifie les spans ; l’entity linking les résout vers le même ID.

Dans les deux cas, la contrainte est la latence. Un appel NER de 200 ms dans une chaîne d’agent de 10 étapes ajoute 2 secondes de délai perçu. C’est pourquoi les modèles encodeurs, et non l’extraction basée sur LLM, sont le bon choix pour le travail sur les entités dans les boucles d’agents.

Document intelligence : de l’image aux données structurées

L’OCR transforme des images en texte. Le NER transforme le texte en champs structurés. Ensemble, ils alimentent la numérisation documentaire à grande échelle.

Le pipeline standard : exécuter l’OCR (Tesseract, Azure Document Intelligence, AWS Textract) pour obtenir du texte et des bounding boxes, puis exécuter le NER pour extraire des champs structurés — invoice_number, vendor_name, line_items, total, due_date — à partir de ce qui n’était qu’un JPEG d’une facture papier. La même approche fonctionne pour les contrats, dossiers médicaux et dépôts réglementaires.

Les plateformes modernes combinent trois étapes : compréhension de mise en page (est-ce un en-tête ou une cellule de tableau ?), extraction d’entités (quel type a ce texte ?) et extraction de relations (quelles valeurs vont ensemble ?). GLiNER 2 gère les trois en une seule passe forward ; un seul appel de modèle peut renvoyer {vendor: "Acme Corp", amount: "\$4,200", due_date: "2026-04-15"} à partir d’une facture.

C’est là que le coût compte. Un cabinet comptable de taille moyenne traite des dizaines de milliers de factures par mois. Faire passer chacune d’elles par un LLM, même un modèle rentable comme GPT-5.4 Nano, coûte des centaines de dollars par jour. Un GLiNER fine-tuné sur CPU coûte quelques centimes. Votre CFO verra la différence. Le chemin : annoter 500 factures d’exemple avec un LLM, fine-tuner GLiNER sur les résultats, puis déployer sur CPU à \$0.10/heure.

Détection de PII et garde-fous pour LLM

Les réglementations sur la vie privée (GDPR, HIPAA, CCPA) exigent de trouver les données personnelles avant qu’elles n’atteignent les systèmes aval. Pour les déploiements LLM, cela signifie analyser les entrées avant qu’elles n’atteignent le modèle et les sorties avant qu’elles n’arrivent à l’utilisateur.

Le NER gère cela directement. Les modèles de désidentification trouvent les spans PERSON, SSN, PHONE, EMAIL, ADDRESS, puis les masquent ou les remplacent par des équivalents fictifs. Les modèles cliniques de John Snow Labs atteignent 96% de F1 sur la détection de PHI (contre Azure 91%, AWS 83%, GPT-4o 79%) tout en traitant plus de 100K notes cliniques par jour.

Pour les garde-fous LLM, le NER sert de couche de pré-screening : il scanne l’entrée utilisateur à la recherche de PII avant l’envoi à une API externe, puis bloque ou anonymise. C’est plus rapide et plus simple que de demander au LLM de s’auto-modérer. GLiNER est particulièrement utile ici parce que les catégories de PII varient selon les juridictions. Vous pouvez ajouter de nouveaux types d’entités comme « information génétique » dans le cadre d’une nouvelle réglementation sans réentraînement.


GLiNER réécrit l’économie du NER avec un modèle de 300M de paramètres

GLiNER (NAACL 2024, Zaratiana et al.) a rendu le NER basé sur encodeur compétitif face aux LLM pour une fraction du coût. Au lieu de traiter le NER comme du sequence labeling ou de la génération de texte, GLiNER le traite comme un problème d’appariement : scorer chaque span de texte candidat (chaque séquence contiguë de mots comme « Bill Gates » ou « Microsoft ») contre chaque label de type d’entité, puis garder les paires avec les scores élevés.

Le modèle prend les labels de type d’entité et le texte d’entrée comme une séquence unique : [ENT] person [ENT] organization [ENT] date [SEP] Bill Gates founded Microsoft.... Un transformer bidirectionnel (DeBERTa-v3) encode l’ensemble conjointement.

À partir de la sortie, le modèle construit deux ensembles de représentations : un pour les types d’entités (à partir des positions de tokens [ENT]) et un pour les spans de texte (en combinant les vecteurs de tokens de début et de fin via un petit FFN). Un produit scalaire entre une représentation de span et une représentation de type d’entité donne un score.

Appliquez sigmoid et vous obtenez la probabilité que le span du token \(i\) au token \(j\) appartienne au type d’entité \(t\) : \(\\phi(i, j, t) = \\sigma(S_{ij}^T \\cdot q_t)\), où \(S_{ij}\) est le vecteur de span produit par le FFN et \(q_t\) est l’embedding du type d’entité issu du token [ENT] correspondant (Zaratiana et al., 2024, Eq. 1). Les spans sont limités à 12 tokens pour garder de bonnes performances.

Architecture de GLiNER : les tokens de type d’entité et les tokens de texte sont encodés conjointement par DeBERTa, puis les représentations de spans sont scorées contre les embeddings de types d’entités via produit scalaire

En pratique, cela signifie que toute description en langage naturel fonctionne comme label au moment de l’inférence. Pas de réentraînement. Vous passez les types d’entités que vous voulez (« person », « adverse drug reaction », « financial instrument »), et le modèle score les spans par rapport à eux. Trois tailles sont disponibles : GLiNER-S (50M params), GLiNER-M (90M) et GLiNER-L (300M). Les données d’entraînement proviennent du dataset Pile-NER : 44 889 passages avec 240K spans d’entités sur 13K types d’entités, tous annotés par ChatGPT. L’entraînement de GLiNER-L prend environ 4 heures sur un seul A100 (Zaratiana et al., 2024).

Résultats de benchmark

Résultats zero-shot de Zaratiana et al. (2024), tableaux 1 et 2 :

Model Params CrossNER F1 Avg (20 datasets)
GLiNER-L 300M 60.9% 47.8%
GoLLIE 7B 58.0% --
UniNER-13B 13B 55.6% --
GLiNER-M 90M 55.4% --
UniNER-7B 7B 53.7% 45.7%
GLiNER-S 50M 52.7% --
ChatGPT (GPT-3.5) -- 47.5% 36.5%

GLiNER-M avec 90M de paramètres égale presque UniNER-13B (55.4% vs 55.6% F1) tout en étant 140x plus petit. Même le minuscule GLiNER-S 50M bat ChatGPT (GPT-3.5) de 5 points de F1. La variante multilingue — entraînée uniquement sur des données anglaises — bat ChatGPT dans 8 langues non anglaises sur 10 (Zaratiana et al., 2024). Note : des LLM plus récents (GPT-5.4, Claude 4.6) obtiendraient probablement de meilleurs scores sur ces benchmarks, mais l’écart de coût n’a fait que s’élargir — ces modèles restent plusieurs ordres de grandeur plus chers qu’un encodeur 90M sur CPU.

L’écosystème est vaste : 280+ modèles compatibles GLiNER sur HuggingFace, ~350 000 téléchargements PyPI par mois, ~2 800 étoiles GitHub. Les variantes couvrent le biomédical, la détection de PII, l’actualité et le support multilingue.

Depuis quickstart.py :

from gliner import GLiNER

model = GLiNER.from_pretrained("urchade/gliner_medium-v2.1")
text = "Bill Gates founded Microsoft on April 4, 1975."
labels = ["person", "organization", "date"]
entities = model.predict_entities(text, labels, threshold=0.5)

for entity in entities:
    print(f"  {entity['text']} => {entity['label']} ({entity['score']:.3f})")
# Bill Gates => person (0.987)
# Microsoft => organization (0.991)
# April 4, 1975 => date (0.974)

Comment GLiNER se compare à spaCy

Tout guide sur le NER serait incomplet sans spaCy~21M de téléchargements par mois, et l’une des bibliothèques NLP les plus durables en production. Mais spaCy résout un problème différent de GLiNER.

Les pipelines spaCy (en_core_web_sm, en_core_web_trf) font du NER à vocabulaire fermé : un ensemble fixe de types d’entités (PERSON, ORG, GPE, DATE, etc.) défini au moment de l’entraînement. Vous voulez un nouveau type d’entité ? Il faut collecter des données annotées et réentraîner. Le modèle en_core_web_trf basé sur transformer atteint 89.8% de F1 sur OntoNotes 5.0, mais uniquement pour ses 18 types prédéfinis.

GLiNER fait du NER à vocabulaire ouvert : n’importe quel label fonctionne au moment de l’inférence, sans réentraînement. Cela en fait le meilleur choix quand les types d’entités ne sont pas connus à l’avance, changent souvent ou sont spécifiques à un domaine (« adverse drug reaction », « financial instrument », « threat indicator »).

Ma recommandation : utilisez spaCy pour les types d’entités standard quand les pipelines préentraînés sont bien validés. Utilisez GLiNER quand vous avez besoin de types flexibles en zero-shot ou quand votre pipeline doit s’adapter sans réentraînement. Les deux se combinent bien — spaCy gère la tokenization et le découpage en phrases, GLiNER gère l’extraction d’entités.


UniNER et NuNER : jusqu’où peut-on descendre ?

UniNER (ICLR 2024, Zhou et al.) et NuNER (EMNLP 2024, Bogdanov et al.) distillent tous deux des annotations LLM dans des modèles NER plus petits — mais ils ne sont pas d’accord sur la taille minimale viable.

UniNER : la voie maximaliste

UniNER fine-tune LLaMA-7B/13B sur 44 889 paires NER (240K entités, 13K types) générées par ChatGPT. Pour chaque type d’entité, le modèle répond à « What describes [type] in the text? » et sort des listes JSON. Une astuce d’entraînement clé : le frequency-based negative sampling fait passer le F1 de 31.5% à 53.4% (Zhou et al., 2024).

UniNER-7B atteint 41.7% de F1 zero-shot sur 43 datasets — battant les 34.9% de ChatGPT de 7 points. La variante 13B atteint 43.4%, soit seulement 1.7 point de plus pour presque le double de calcul (Zhou et al., 2024).

Le problème en production : en tant que modèle autoregressif 7B, UniNER nécessite N passes forward pour N types d’entités, demande 14GB+ de VRAM (donc votre budget GPU est déjà parti avant midi), et a une licence restrictive CC BY-NC 4.0.

NuNER : la voie minimaliste

NuNER part de RoBERTa-base (125M de paramètres) et utilise un entraînement contrastif avec 4.38 millions d’annotations GPT-3.5 sur 200K concepts — pour un coût total d’annotation inférieur à \$500. Après entraînement, l’encodeur de concepts est jeté ; l’encodeur de texte s’insère dans n’importe quel pipeline NER standard comme remplaçant de RoBERTa (Bogdanov et al., 2024).

Les résultats : NuNER bat RoBERTa standard de 6 à 15 points de F1 sur toutes les tailles few-shot. Avec seulement une douzaine d’exemples par type d’entité, NuNER égale UniNER-7B tout en étant 56x plus petit (Bogdanov et al., 2024).

Les deux papiers montrent la même chose : distiller des annotations LLM dans des modèles plus petits produit un NER qui bat l’enseignant. Et vous n’avez pas besoin de 7B de paramètres — 125M suffisent quand des données de fine-tuning sont disponibles, avec une licence MIT et une inférence compatible CPU.


GLiNER 2 : un modèle, quatre tâches

L’écosystème GLiNER d’origine avait un problème croissant : des modèles séparés pour le NER (GLiNER), l’extraction de relations (GLiREL), la classification (GLiClass) et la RE au niveau document (GLiDRE) — chacun nécessitant son propre déploiement, son propre conteneur Docker, sa propre supervision et ses propres modes de défaillance. GLiNER 2 (EMNLP 2025, Zaratiana et al.) fusionne les quatre dans un seul modèle de 205M de paramètres avec une interface pilotée par schéma.

L’architecture conserve le design cross-encoder mais étend le contexte à 2 048 tokens (4x l’original) et ajoute des schémas déclaratifs pour définir les tâches d’extraction. L’entraînement utilise 135 698 documents réels annotés avec GPT-4o plus 118 636 exemples synthétiques (Zaratiana et al., 2025).

En zero-shot sur CrossNER, GLiNER 2 atteint 0.590 de F1 — proche des 0.599 de GPT-4o selon le benchmark du papier (mi-2025). Des modèles plus récents comme GPT-5.4 obtiendraient probablement de meilleurs scores, mais à une fraction de la vitesse et du coût de GLiNER 2. En classification, il atteint 0.72 de moyenne sur 7 benchmarks, battant DeBERTa-v3-large (0.69). Sur CPU, GLiNER 2 exécute la classification en 130-208ms quel que soit le nombre de labels. DeBERTa passe à l’échelle linéairement : 1 714ms pour 5 labels, 16 897ms pour 50 (Zaratiana et al., 2025).

from gliner2 import GLiNER2
extractor = GLiNER2.from_pretrained("fastino/gliner2-base-v1")

# Multi-task composition in ONE forward pass
schema = (extractor.create_schema()
    .entities({"person": "Names of people", "company": "Organization names"})
    .classification("sentiment", ["positive", "negative", "neutral"])
    .relations(["works_for", "founded", "located_in"])
    .structure("product_info")
        .field("name", dtype="str")
        .field("price", dtype="str"))
results = extractor.extract(text, schema)

Un seul déploiement de modèle en remplace quatre. Une infrastructure plus simple, une précision compétitive.


Le bi-encodeur : passer à l’échelle du NER à un million de labels

Le GLiNER d’origine encode labels et texte ensemble — ce qui crée un goulot d’étranglement. Plus de types d’entités signifie une séquence d’entrée plus longue, et les performances chutent vite au-delà d’environ 30 types. Le bi-encodeur GLiNER (février 2026, Stepanov et al. ; arXiv 2602.18487) corrige cela en séparant l’encodage du texte et des labels en deux transformers distincts.

Cross-encoder vs bi-encoder : le cross-encoder encode conjointement labels et texte, tandis que le bi-encodeur utilise des encodeurs séparés avec des embeddings de labels pré-calculés

L’encodeur de texte utilise ModernBERT (famille Ettin), l’encodeur de labels utilise des sentence transformers (BGE ou MiniLM). Les spans et les labels sont scorés via produit scalaire. L’astuce : les embeddings de types d’entités peuvent être pré-calculés une seule fois et mis en cache. À l’inférence, seul le texte doit être encodé — la recherche des labels est instantanée.

Quatre tailles de modèle sont disponibles, toutes benchmarkées sur CrossNER (Stepanov et al., 2026, tableau 1) :

Model Parameters CrossNER F1 Throughput (H100) With Pre-computed Labels
bi-edge-v2.0 60M 54.0% 13.64 ex/s 24.62 ex/s
bi-small-v2.0 108M 57.2% 7.99 ex/s 15.22 ex/s
bi-base-v2.0 194M 60.3% 5.91 ex/s 9.51 ex/s
bi-large-v2.0 530M 61.5% 2.68 ex/s 3.60 ex/s

À 1 024 types d’entités, le bi-encodeur (edge, pré-calculé) ne perd que 5.2% de débit par rapport à un seul label. Le cross-encoder en perd 98.7% (10.7 → 0.14 ex/s). C’est un avantage de débit de 130x à grande échelle. Avec 100 types d’entités sur un seul H100, le bi-encodeur traite 1.96 million de prédictions par jour contre 368K pour le cross-encoder (Stepanov et al., 2026).

La précision tient aussi. Bi-encoder-large atteint 61.5% de F1 sur CrossNER, légèrement au-dessus des 60.9% du cross-encoder. Les auteurs recommandent bi-base-v2.0 (194M) comme meilleur compromis, atteignant 98% de la précision du grand modèle à 2.6x la vitesse (Stepanov et al., 2026).

from gliner import GLiNER

model = GLiNER.from_pretrained("knowledgator/gliner-bi-base-v2.0")

# Pre-compute embeddings for massive label sets — encode once, use forever
entity_types = ["person", "organization", "date"]  # Can be thousands or millions
entity_embeddings = model.encode_labels(entity_types, batch_size=8)

# Inference only encodes text — labels are a cached lookup
outputs = model.batch_predict_with_embeds(texts, entity_embeddings, entity_types)

Les applications incluent le NER biomédical sur l’ontologie UMLS (4M+ concepts), des taxonomies d’entreprise qui évoluent sans réentraînement du modèle, et l’entity linking via le framework compagnon GLiNKER.


Les LLM comme enseignants : le pipeline à \\(70 qui bat le modèle à \\\)8/heure

Le pattern LLM-as-teacher est devenu un pipeline de production standard. Trois études montrent ce qu’il coûte et ce qu’il apporte.

Le pipeline LLM-as-teacher : le LLM annote les données brutes, des humains en révisent un sous-ensemble, puis l’encodeur est fine-tuné et déployé à un coût 80x inférieur

L’étude de cas CFM

Capital Fund Management extrayait des noms d’entreprises à partir d’environ 900K titres de news financières. GLiNER en zero-shot obtenait 87.0% de F1. Ils ont utilisé Llama 3.1-70b (le meilleur modèle ouvert à l’époque) pour annoter l’ensemble du dataset en ~8 heures pour ~\$70, puis ont fait réviser 2 714 échantillons par des humains via Argilla en 8 heures supplémentaires.

Le fine-tuning de GLiNER sur ces données a porté les performances à 93.4% de F1 — battant même les 92.7% de F1 de l’enseignant Llama 70b. Le modèle fine-tuné tourne à \\(0.10/heure sur CPU** contre \\\)8/heure pour l’enseignant — 80x moins cher** avec une meilleure précision (Étude de cas CFM). Aujourd’hui, vous obtiendriez des annotations enseignant encore meilleures avec Llama 4 Maverick ou GPT-5.4 Mini à coût similaire ou inférieur.

L’étude Refuel AI

Refuel AI a benchmarké l’annotation par LLM sur 8 datasets NLP, dont CoNLL-2003. GPT-4 (mars 2023) a atteint 88.4% d’accord avec la vérité terrain — au-dessus des 86.2% des annotateurs humains qualifiés. Les LLM étaient 20x plus rapides et 7x moins chers. Leur approche d’ensembling — modèles bon marché pour les exemples faciles, GPT-4 pour les exemples difficiles — a atteint 95%+ d’accord tout en maintenant les coûts bas (Rapport technique Refuel AI). Avec GPT-5.4 et Claude 4.6 disponibles aujourd’hui, la qualité de l’enseignant n’a fait que progresser.

Tonic.ai Clinical NER

Tonic.ai a montré que le pattern fonctionne aussi pour le NER clinique. Les annotations LLM seules ont permis d’entraîner un modèle RoBERTa LoRA à 0.70 de F1 sur le NCBI Disease Corpus (contre 0.81 avec des labels humains complets). Sur l’extraction d’identifiants de santé, il a atteint 0.947 de F1 — au-dessus du seuil de production de 0.914 — sans aucune donnée annotée par des humains.

Le pipeline standard

La recette de production s’est stabilisée en six étapes :

  1. Rédiger des guidelines d’annotation en langage naturel
  2. Créer un petit jeu de validation annoté par des humains (50-200 documents)
  3. Utiliser un LLM (GPT-5.4 Mini, Llama 4 Maverick ou Qwen3.5) pour labelliser les données d’entraînement en masse
  4. Réviser un sous-ensemble via Argilla ou Label Studio
  5. Fine-tuner un encodeur compact (GLiNER, SpanMarker, RoBERTa)
  6. Déployer avec un coût d’inférence 16 à 80x inférieur

Le coût du NER n’est plus « annoter toutes vos données d’entraînement en embauchant une armée d’étudiants ». C’est « construire un bon jeu de validation, écrire des guidelines claires, et laisser le LLM faire le reste ».


Là où GLiNER échoue et où les LLM restent essentiels

Le benchmark Sease (octobre 2025) a testé GLiNER face à GPT-4.1-mini sur 30 tâches de query parsing. GPT-4.1-mini a obtenu 100% entièrement correct. GLiNER a obtenu 53% (16 sur 30). Mais GLiNER a répondu en 0.08 seconde contre 1.21 seconde pour le LLM — 15x plus rapide.

GLiNER échoue selon trois patterns précis :

  1. Entités implicites : extraire « event » depuis « Elton John performed at Madison Square Garden » — rien dans le texte ne dit littéralement « event », mais le LLM infère « concert »
  2. Sensibilité à la formulation du label : « 2022 » obtient un score de 0.388 contre « date » mais 0.958 contre « year » — de petits changements de label causent de fortes variations de score
  3. Mapping de valeur : GLiNER renvoie le texte de surface exact (« family houses ») au lieu de la valeur canonique (« Single family house ») — les LLM le font naturellement

Entités imbriquées et chevauchantes

GLiNER a aussi du mal avec les entités imbriquées. Dans « New York University », un humain pourrait annoter à la fois « New York » (LOCATION) et « New York University » (ORGANIZATION). GLiNER ne garde que le span au score le plus élevé. Cela compte dans le biomédical (« acute myeloid leukemia » contient à la fois une maladie et un modificateur) et dans le juridique (hiérarchies organisationnelles imbriquées). Des modèles spécialisés gèrent l’imbrication, mais le design à spans plats de GLiNER ne le permet pas.

En pratique : GLiNER gère l’extraction d’entités explicites — le cœur du NER en production. Les LLM interviennent quand l’extraction requiert inférence, raisonnement ou mapping vers des ontologies prédéfinies. Utilisez les deux.


Évaluer le NER : métriques, pièges et construction de jeux de test

J’ai vu des équipes livrer des modèles à 95% de F1 sur leur jeu de test qui échouaient en production parce que le jeu de test ne reflétait pas la distribution réelle des documents. Votre jeu de test n’est pas vos données de production. Ce mode d’échec est assez courant pour être anticipé.

Les métriques de base

  • F1 au niveau entité : la métrique standard. Une prédiction est correcte uniquement si les bornes du span et le type correspondent exactement à la vérité terrain. C’est ce que rapportent la plupart des papiers.
  • F1 au niveau token : score chaque token indépendamment. Gonfle les résultats parce qu’obtenir la majeure partie d’une longue entité donne un crédit partiel. Préférez le F1 au niveau entité.
  • Précision vs rappel : ils ont souvent des coûts asymétriques. Pour la désidentification, le rappel compte davantage — rater un nom est pire que sur-masquer. Pour l’extraction vers une base de données, la précision compte davantage — les faux positifs corrompent l’analyse aval.

Pièges fréquents en évaluation

  1. Inflation par correspondance partielle : « Bill » extrait alors que le label gold est « Bill Gates » — certains scripts comptent cela comme une correspondance partielle. Utilisez une correspondance exacte des spans, sauf raison contraire.
  2. Confusion de type : « Microsoft » correctement identifié comme span mais étiqueté PERSON au lieu de ORG doit valoir zéro. Vérifiez que votre code d’évaluation le gère.
  3. Fuite du jeu de test : si les entités du test chevauchent celles de l’entraînement, les scores sont gonflés. Les benchmarks zero-shot (CrossNER, Few-NERD) existent pour tester la généralisation.

Construire un jeu de test de domaine

Pour l’évaluation en production, je recommande :

  1. Échantillonner à partir des données de production, pas d’exemples sélectionnés. Incluez les documents bruités que votre modèle verra réellement.
  2. 200 à 500 documents annotés donnent des estimations de F1 stables. En dessous de 100, les intervalles de confiance sont trop larges.
  3. Deux annotateurs minimum, avec accord inter-annotateurs (kappa de Cohen > 0.8). Si les humains ne sont pas d’accord, votre modèle ne peut pas faire mieux.
  4. Stratifier par difficulté — cas faciles (texte propre, types standard) et cas difficiles (entités ambiguës, jargon, texte bruité).

Le NER en production dans quatre industries

Voici les déploiements NER les plus matures que j’ai trouvés, avec des chiffres précis.

Santé

La santé dispose des outils NER les plus matures. John Snow Labs propose plus de 2 500 modèles préentraînés, dont plus de 1 200 pour la santé, couvrant plus de 400 types d’entités cliniques mappés vers ICD-10, SNOMED CT, LOINC et RxNorm. Leurs modèles de désidentification atteignent 96% de F1 (contre Azure 91%, AWS 83%, GPT-4o 79%), avec Providence St. Joseph Health traitant 100K-500K notes cliniques par jour.

Le projet OpenMed open source propose plus de 380 modèles NER biomédicaux avec 29.7M de téléchargements sur HuggingFace, établissant un nouvel état de l’art sur 10 des 12 benchmarks biomédicaux publics.

NER financier

Le principal cas d’usage : l’extraction des dépôts SEC. Le Finance NLP de John Snow Labs extrait plus de 11 types d’entités à partir des formulaires 10-K/10-Q (adresses, tickers, exercices fiscaux, bourses). Les variantes FinBERT-MRC atteignent 0.87-0.93 de F1 sur les tâches d’entités financières. Le principal défi : les documents longs et les entités imbriquées dans des instruments financiers complexes.

E-commerce

Du NER à très grande échelle. Le système EAMT de Walmart (KDD 2023) s’entraîne sur 965 millions de requêtes avec ~60 labels d’entités, et génère un gain de GMV de 0.51% en tests A/B — soit des millions de revenus incrémentaux. Le framework TripleLearn de Home Depot (AAAI 2021) a fait passer le F1 NER de 69.5 à 93.3 via un entraînement itératif.

Cybersécurité

Le système iACE (CCS 2016) a traité 71 000 articles issus de 45 blogs de sécurité, extrayant 900K IOC avec 98% de précision et 93% de rappel. Les systèmes modernes comme CyNER combinent DeBERTa (F1 >91%) avec des heuristiques IOC à base de regex. Le dataset unifié CyberNER (2025) harmonise quatre datasets en 21 types d’entités alignés sur STIX 2.1, avec RoBERTa atteignant 0.736 de F1.


Optimisation du déploiement : de Python à une inférence sous la milliseconde

J’ai testé trois façons d’accélérer GLiNER pour la production dans le repo compagnon.

Export ONNX

GLiNER dispose d’une conversion ONNX native, et des modèles déjà convertis existent sur HuggingFace (onnx-community/gliner_small-v2.1). ONNX Runtime apporte 1.5 à 3x d’accélération sur CPU par rapport à PyTorch, avec quatre niveaux d’optimisation allant du basique à la précision mixte.

Depuis onnx_export.py :

# Export with quantization
# python convert_to_onnx.py --model_path model/ --save_path onnx/ --quantize True

# Load ONNX model — same API, faster inference
from gliner import GLiNER
model = GLiNER.from_pretrained("path/to/model", load_onnx_model=True)

# Same predict_entities call, 1.5-3x faster on CPU
entities = model.predict_entities(text, labels, threshold=0.5)

Quantification INT8

La quantification dynamique réduit la taille des modèles de 2.4x (438MB → 181MB) avec moins de 0.6% de perte de F1. La vitesse s’améliore de 1.8x sur CPU. Sur les CPU Intel VNNI avec ONNX Runtime, INT8 atteint jusqu’à 6x d’accélération par rapport à PyTorch FP32.

from onnxruntime.quantization import quantize_dynamic, QuantType

# One-line quantization — 2.4x smaller, <1% F1 loss
quantize_dynamic("gliner.onnx", "gliner_int8.onnx", weight_type=QuantType.QInt8)

gline-rs : réimplémentation Rust

gline-rs (Apache 2.0) élimine l’overhead Python. Sur CPU : 6.67 seq/s contre 1.61 pour Python — soit une accélération de 4.1x. Sur une RTX 4080 : 248.75 seq/s (benchmarks gline-rs). Il prend en charge les modèles à spans et à tokens, GPU/NPU via ONNX Runtime, et est distribué comme crate sur crates.io.

use gliner::{GLiNER, TokenMode, Parameters, RuntimeParameters, TextInput};

let model = GLiNER::<TokenMode>::new(
    Parameters::default(), RuntimeParameters::default(),
    "tokenizer.json", "model.onnx")?;

let input = TextInput::from_str(
    &["My name is James Bond."], &["person", "vehicle"])?;
let output = model.inference(input)?;
// => "James Bond" : "person" (99.7%)

Le package fast-gliner fournit des bindings Python via PyO3 — vitesse Rust avec ergonomie Python.

Résumé de la pile d’optimisation

Optimization Speedup vs PyTorch Model Size F1 Impact Best For
ONNX Runtime 1.5-3x Same None Quick win, any hardware
INT8 Quantization 3-6x 2.4x smaller <0.6% loss CPU deployment, memory-constrained
gline-rs (Rust) 4.1x (CPU) ONNX format None High-throughput, latency-critical
gline-rs + INT8 4-8x 2.4x smaller <1% loss Production at scale

Extraction structurée : Instructor vs Outlines

Quand vous avez besoin de plus de flexibilité que ce que permettent les modèles encodeurs — entités implicites, raisonnement, mapping ontologique — deux bibliothèques gèrent l’extraction structurée avec des LLM.

Instructor (~12 600 étoiles GitHub, ~8.8M téléchargements/mois en mars 2026) par Jason Liu patch les SDK LLM pour accepter des modèles de réponse Pydantic, avec retry automatique en cas d’échec de validation. Il prend en charge plus de 15 providers et a inspiré la fonctionnalité native de structured output d’OpenAI.

Depuis structured_extraction.py :

import instructor
from pydantic import BaseModel
from typing import List, Literal
from openai import OpenAI

class Entity(BaseModel):
    name: str
    label: Literal["PERSON", "ORGANIZATION", "LOCATION"]

class ExtractEntities(BaseModel):
    entities: List[Entity]

client = instructor.from_openai(OpenAI())
result = client.chat.completions.create(
    model="gpt-5.4-mini", temperature=0.0,
    response_model=ExtractEntities,
    messages=[{"role": "user", "content": "BioNTech SE acquired InstaDeep in the U.K."}])
# entities=[Entity(name='BioNTech SE', label='ORGANIZATION'), ...]

Outlines (~13 600 étoiles GitHub) par dottxt adopte une autre approche : génération de tokens contrainte via machines à états finis. Au lieu de générer une sortie puis de retry en cas d’échec de validation, Outlines empêche tout simplement la génération de tokens invalides — 100% de conformité au schéma, zéro retry. Les benchmarks AWS montrent 98% d’adhérence au schéma contre 76% pour la validation post-génération, avec une génération 5x plus rapide par rapport à la génération non contrainte avec retries de post-validation.

import outlines

model = outlines.models.transformers("microsoft/Phi-3-mini-128k-instruct")
generator = outlines.generate.json(model, ExtractEntities)
result = generator("Extract entities from: BioNTech SE acquired InstaDeep in the U.K.")

Le choix dépend de l’endroit où vous exécutez vos modèles. Instructor est le meilleur choix pour les API LLM cloud — prototypage rapide, support multi-provider, patterns Pydantic familiers. Outlines l’emporte pour les modèles locaux quand vous avez besoin de garanties de format sans dépendances externes. Les deux fonctionnent bien pour une extraction de type NER, mais aucun n’égale le débit des encodeurs : Instructor ajoute 200ms à 2s de latence API par appel, et Outlines dépend de la vitesse du modèle local. Pour le NER à haut débit, les encodeurs restent 10 à 100x plus rapides.


L’architecture de production en 3 niveaux

Voici comment j’assemblerais tout cela pour du NER en production.

L’architecture en 3 niveaux : les modèles encodeurs traitent 90%+ du volume à faible coût, GLiNER 2 gère l’extraction multi-tâches, et les LLM traitent les 10% les plus difficiles tout en entraînant aussi les modèles du niveau 1

Niveau 1 — Modèles encodeurs pour les types d’entités connus. GLiNER (cross-encoder pour <30 types, bi-encodeur pour 30+), fine-tunés via le pipeline LLM-as-teacher. Déployez avec ONNX + INT8 ou gline-rs. Gère >90% du volume avec une latence sous 50 ms et un coût quasi nul. Le bi-encodeur passe à l’échelle jusqu’à des millions de types d’entités avec des embeddings pré-calculés.

Niveau 2 — GLiNER 2 pour l’extraction multi-tâches. Quand une requête nécessite NER + classification + extraction de relations + données structurées, le modèle 205M de paramètres de GLiNER 2 remplace quatre déploiements. Il tourne sur CPU en 130-208ms quel que soit le nombre de labels — bon choix pour les pipelines documentaires qui nécessitent plusieurs tâches d’extraction en une passe.

Niveau 3 — LLM pour l’extraction riche en raisonnement. Quand les entités sont implicites, nécessitent une inférence contextuelle ou un mapping ontologique, routez vers un LLM (GPT-5.4 Mini, Claude Sonnet 4.6, Llama 4 Maverick) via Instructor (cloud) ou Outlines (local). Cela gère les ~10% de requêtes que les encodeurs ratent. Les mêmes LLM génèrent aussi les données d’entraînement du niveau 1.

Combien cela coûte-t-il ? Un GLiNER fine-tuné atteint 93.4% de F1 à \\(0.10/heure sur CPU**, égalant les **92.7% de F1** de son enseignant Llama-70b à **\\\)8/heure — 80x moins cher.


Compromis et limites

Les systèmes ML impliquent toujours des compromis. La vraie question est où se situe le compromis et si vous pouvez le mesurer avant le déploiement.

Les erreurs du LLM-as-teacher se propagent. Si le LLM se trompe systématiquement sur un type d’entité donné (par exemple en confondant des noms de filiales avec des maisons mères), l’encodeur fine-tuné héritera de ce biais. La correction consiste à faire une revue humaine ciblée — concentrez l’effort sur les types d’entités où la confiance du LLM est faible ou incohérente, pas sur un échantillonnage aléatoire.

Les pertes dues à la quantification ne sont pas uniformes. La perte moyenne d’environ 0.6% de F1 en INT8 peut être plus importante sur des types d’entités rares avec des motifs de frontières subtils (composés chimiques, abréviations multi-mots). Benchmarkez toujours les modèles quantifiés sur vos types d’entités spécifiques, pas seulement sur le F1 agrégé.

Quand l’architecture en 3 niveaux est excessive. Un seul domaine, des types d’entités bien définis, plus de 500 exemples annotés ? Un pipeline RoBERTa ou spaCy fine-tuné est plus simple et suffit. Le pattern en 3 niveaux devient rentable avec (a) plusieurs domaines, (b) des types d’entités évolutifs, ou (c) un mélange de tâches d’extraction faciles et difficiles. Si vous extrayez seulement des noms et des dates depuis des factures, le niveau 1 seul suffit.

Plafond de qualité du bi-encodeur. Le bi-encodeur échange l’attention conjointe contre du débit. Quand la sémantique des labels interagit avec le contexte textuel (« date » vs « year » vs « period » pour le même span), le cross-encoder garde l’avantage. Utilisez le cross-encoder pour les tâches critiques avec peu de labels ; le bi-encodeur pour la largeur de couverture.


Points clés à retenir

  1. Les encodeurs ont gagné. GLiNER et les variantes bi-encodeur battent les LLM sur les benchmarks NER standard pour un coût 80 à 130x inférieur. Même avec GPT-5.4 Nano et Llama 4 qui font baisser les prix, exécuter un LLM pour chaque requête NER n’est plus justifié.
  2. Les LLM sont essentiels — comme enseignants. Ils annotent les données d’entraînement pour \$70 là où une annotation humaine coûterait des milliers, et l’encodeur fine-tuné finit généralement par battre le LLM qui l’a formé.
  3. Le bi-encodeur débloque l’échelle du million de labels. Les embeddings pré-calculés résolvent le problème de complexité quadratique, avec seulement 5.2% de perte de débit à 1 024 labels.
  4. GLiNER 2 consolide l’extraction multi-tâches. Un seul modèle 205M pour NER + classification + RE + extraction structurée.
  5. Évaluez sur vos données. Utilisez le F1 au niveau entité, construisez des jeux de test à partir de documents de production, et benchmarkez les modèles quantifiés sur vos types d’entités spécifiques.
  6. Utilisez le pattern hybride. Niveaux 1/2 pour l’extraction rapide, niveau 3 pour le raisonnement. Les mêmes LLM qui gèrent les 10% les plus difficiles génèrent aussi les données d’entraînement pour les 90%.

Références

Articles

Articles industriels

Études de cas

Outils et frameworks