Saltar a contenido

Traducción automática

Este artículo se tradujo automáticamente a partir de la versión original en inglés.

La guía definitiva de NER en 2026: encoders, LLMs y la arquitectura de producción en 3 niveles

Hace dos años, elegir un enfoque de NER significaba escoger entre velocidad (modelos encoder) y precisión (LLMs). Ese trade-off ha desaparecido. Un GLiNER de 300M de parámetros iguala la precisión zero-shot de un UniNER de 13B mientras ejecuta 100x más rápido. Una variante bi-encoder más reciente escala a millones de tipos de entidad con una ventaja de throughput de 130x frente al cross-encoder original. El patrón de producción que ha emergido: usar LLMs para etiquetar datos, hacer fine-tuning de encoders compactos y desplegar con ONNX o Rust.

He construido el repo complementario y he benchmarkeado todos los enfoques principales. Los encoders ganaron el mercado de NER en producción. Los LLMs siguen siendo esenciales, pero como generadores de datos de entrenamiento en lugar de motores de inferencia. Esta guía cubre los papers, benchmarks y patrones de despliegue detrás de ese cambio.

Repo complementario: ner-field-guide — demos ejecutables para GLiNER, exportación a ONNX, pipeline LLM-as-teacher y extracción estructurada con Instructor.

TL;DR: Ya no necesitas construir modelos de NER desde cero. Para extracción zero-shot, GLiNER en CPU vía ONNX supera incluso a los LLMs más recientes con un coste casi nulo. Para tareas específicas de dominio, el pipeline LLM-as-teacher (LLM etiqueta → revisión → fine-tuning) produce encoders que alcanzan 90-93%+ de F1. Para casos que requieren razonamiento, usa Instructor u Outlines con una API de LLM — pero presupón \$2+/1K docs. La arquitectura de 3 niveles combina los tres.


Por qué NER importa más ahora: agentes, RAG e inteligencia documental

NER sigue significando lo mismo: encontrar spans nombrados en texto y clasificarlos. Lo que ha cambiado es dónde aparece. Antes era el último paso de un pipeline de NLP, la utilidad silenciosa sobre la que nadie escribía posts. Ahora es un bloque de construcción dentro de sistemas RAG, bucles de agentes y plataformas de procesamiento documental. Por eso la ola de investigación en NER de 2024-2026 importa más allá de los benchmarks académicos.

RAG: mejor recuperación mediante extracción de entidades

El RAG estándar — trocear texto, embebder, recuperar por similitud y esperar que salga bien — se rompe cuando los usuarios preguntan por entidades concretas. Si alguien pregunta "¿qué dijo Anthropic sobre seguridad del modelo en Q4 2024?", el sistema tiene que reconocer "Anthropic" y "Q4 2024" como filtros, no limitarse a depender de la similitud de embeddings.

Durante la indexación, extraes entidades de cada chunk y las almacenas como metadatos: {"organizations": ["Anthropic"], "dates": ["Q4 2024"], ...}. Esto permite filtrar por entidad antes de ejecutar la búsqueda vectorial. El knowledge graph RAG (GraphRAG, LlamaIndex property graphs) va más allá: NER más extracción de relaciones construyen un grafo que puede responder preguntas multi-hop que los embeddings planos no pueden.

En tiempo de consulta, las entidades extraídas de la pregunta del usuario dirigen el routing. Una pregunta que menciona el nombre de una empresa va a un índice financiero; otra que menciona nombres de fármacos va a una base de conocimiento clínica. GLiNER funciona bien aquí porque las entidades de consulta son impredecibles: no puedes reentrenar para cada nuevo tipo de entidad que los usuarios puedan preguntar.

Agentes de IA: convertir texto en hechos estructurados

Los agentes reciben texto no estructurado — páginas web, respuestas de API, mensajes de usuario — y necesitan actuar sobre ello. NER convierte ese texto en hechos estructurados sobre los que el agente puede razonar, almacenar o pasar a herramientas.

Importa sobre todo en dos sitios.

El primero es el routing de herramientas. Cuando un usuario dice "programa una reunión con Sarah Chen de Accenture el jueves a las 2pm", el agente necesita extraer PERSON: Sarah Chen, ORGANIZATION: Accenture y DATETIME: Thursday 2pm antes de llamar a la API del calendario. Un modelo encoder de NER hace esto en menos de 10ms. Un LLM añade 1-2 segundos por llamada, y ese retraso se acumula a lo largo de workflows multi-step hasta que un agente "instantáneo" deja de parecer instantáneo.

El segundo es el seguimiento de entidades a lo largo de conversaciones. Los sistemas de memoria de agentes necesitan saber que "Sarah" en el turno 3 y "Ms. Chen" en el turno 12 son la misma persona. NER identifica los spans; el entity linking los resuelve al mismo ID.

La restricción en ambos casos es la latencia. Una llamada de NER de 200ms dentro de una cadena de agente de 10 pasos añade 2 segundos de retraso percibido. Por eso los modelos encoder, y no la extracción basada en LLMs, son la opción correcta para el trabajo con entidades dentro de bucles de agentes.

Inteligencia documental: de imágenes a datos estructurados

OCR convierte imágenes en texto. NER convierte texto en campos estructurados. Juntos, impulsan la digitalización documental a escala.

El pipeline estándar: ejecutar OCR (Tesseract, Azure Document Intelligence, AWS Textract) para obtener texto y bounding boxes, y después ejecutar NER para extraer campos estructurados — invoice_number, vendor_name, line_items, total, due_date — de lo que antes era un JPEG de una factura en papel. El mismo enfoque funciona para contratos, historiales médicos y filings regulatorios.

Las plataformas modernas combinan tres pasos: comprensión de layout (¿es esto una cabecera o una celda de tabla?), extracción de entidades (¿qué tipo es este texto?) y extracción de relaciones (¿qué valores van juntos?). GLiNER 2 gestiona los tres en una sola pasada forward; una única llamada al modelo puede devolver {vendor: "Acme Corp", amount: "\$4,200", due_date: "2026-04-15"} de una factura.

Aquí es donde importa el coste. Una asesoría contable mediana procesa decenas de miles de facturas al mes. Enviar cada una a través de un LLM, incluso un modelo eficiente en costes como GPT-5.4 Nano, cuesta cientos de dólares al día. Un GLiNER ajustado por fine-tuning en CPU cuesta céntimos. Tu CFO notará la diferencia. La ruta: anotar 500 facturas de ejemplo con un LLM, hacer fine-tuning de GLiNER con los resultados y desplegar en CPU a \$0.10/hora.

Detección de PII y guardrails para LLMs

Las regulaciones de privacidad (GDPR, HIPAA, CCPA) obligan a encontrar datos personales antes de que lleguen a sistemas downstream. En despliegues de LLMs, eso significa escanear inputs antes de que lleguen al modelo y outputs antes de que lleguen al usuario.

NER gestiona esto de forma directa. Los modelos de de-identification encuentran spans de PERSON, SSN, PHONE, EMAIL, ADDRESS y los redactan o los sustituyen por equivalentes falsos. Los modelos clínicos de John Snow Labs alcanzan 96% de F1 en detección de PHI (frente a Azure 91%, AWS 83%, GPT-4o 79%) mientras procesan más de 100K notas clínicas al día.

Para guardrails de LLMs, NER funciona como una capa de pre-screening: escanea la entrada del usuario en busca de PII antes de enviarla a una API externa, y después bloquea o anonimiza. Esto es más rápido y más simple que pedir al LLM que se automodere. GLiNER es especialmente útil aquí porque las categorías de PII varían según la jurisdicción. Puedes añadir nuevos tipos de entidad como "información genética" bajo una nueva regulación sin reentrenar.


GLiNER reescribe la economía de NER con un modelo de 300M de parámetros

GLiNER (NAACL 2024, Zaratiana et al.) hizo que el NER basado en encoders fuese competitivo con los LLMs a una fracción del coste. En lugar de tratar NER como etiquetado de secuencias o generación de texto, GLiNER lo trata como un problema de matching: puntúa cada span candidato de texto (cada secuencia contigua de palabras como "Bill Gates" o "Microsoft") frente a cada etiqueta de tipo de entidad, y luego se queda con los pares de alta puntuación.

El modelo toma las etiquetas de tipo de entidad y el texto de entrada como una sola secuencia: [ENT] person [ENT] organization [ENT] date [SEP] Bill Gates founded Microsoft.... Un transformer bidireccional (DeBERTa-v3) codifica todo conjuntamente.

A partir del output, el modelo construye dos conjuntos de representaciones: uno para los tipos de entidad (desde posiciones de token [ENT]) y otro para los spans de texto (combinando vectores de token inicial y final mediante una pequeña FFN). Un producto escalar entre una representación de span y una representación de tipo de entidad da una puntuación.

Aplicando sigmoid obtienes la probabilidad de que el span desde el token \(i\) hasta el token \(j\) pertenezca al tipo de entidad \(t\): \(\\phi(i, j, t) = \\sigma(S_{ij}^T \\cdot q_t)\), donde \(S_{ij}\) es el vector de span producido por la FFN y \(q_t\) es el embedding del tipo de entidad del token [ENT] correspondiente (Zaratiana et al., 2024, Ec. 1). Los spans se limitan a 12 tokens para mantener la velocidad.

Arquitectura de GLiNER: los tokens de tipo de entidad y los tokens de texto se codifican conjuntamente con DeBERTa, y después las representaciones de span se puntúan frente a embeddings de tipo de entidad mediante producto escalar

En la práctica, eso significa que cualquier descripción en lenguaje natural funciona como etiqueta en tiempo de inferencia. Sin reentrenamiento. Pasas los tipos de entidad que quieras ("person", "adverse drug reaction", "financial instrument"), y el modelo puntúa spans frente a ellos. Hay tres tamaños disponibles: GLiNER-S (50M params), GLiNER-M (90M) y GLiNER-L (300M). Los datos de entrenamiento proceden del dataset Pile-NER: 44.889 pasajes con 240K spans de entidad en 13K tipos de entidad, todos etiquetados por ChatGPT. Entrenar GLiNER-L lleva unas 4 horas en una sola A100 (Zaratiana et al., 2024).

Resultados de benchmark

Resultados zero-shot de Zaratiana et al. (2024), tablas 1 y 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 con 90M de parámetros casi iguala a UniNER-13B (55.4% frente a 55.6% F1) siendo 140x más pequeño. Incluso el diminuto GLiNER-S de 50M supera a ChatGPT (GPT-3.5) por 5 puntos de F1. La variante multilingüe — entrenada solo con datos en inglés — supera a ChatGPT en 8 de 10 lenguas no inglesas (Zaratiana et al., 2024). Nota: LLMs más recientes (GPT-5.4, Claude 4.6) probablemente puntúan más alto en estos benchmarks, pero la brecha de coste no ha hecho más que ampliarse — estos modelos siguen siendo órdenes de magnitud más caros que un encoder de 90M en CPU.

El ecosistema es grande: 280+ modelos compatibles con GLiNER en HuggingFace, ~350.000 descargas mensuales en PyPI, ~2.800 estrellas en GitHub. Hay variantes para texto biomédico, detección de PII, noticias y soporte multilingüe.

De 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)

Cómo se compara GLiNER con spaCy

Cualquier guía de NER estaría incompleta sin spaCy~21M de descargas al mes, y una de las librerías de NLP más duraderas en producción. Pero resuelve un problema distinto al de GLiNER.

Los pipelines de spaCy (en_core_web_sm, en_core_web_trf) hacen NER de vocabulario cerrado: un conjunto fijo de tipos de entidad (PERSON, ORG, GPE, DATE, etc.) definido en tiempo de entrenamiento. ¿Quieres un tipo de entidad nuevo? Recoge datos etiquetados y reentrena. El en_core_web_trf respaldado por transformer alcanza 89.8% de F1 en OntoNotes 5.0, pero solo para sus 18 tipos predefinidos.

GLiNER hace NER de vocabulario abierto: cualquier etiqueta funciona en tiempo de inferencia, sin necesidad de reentrenar. Esto lo convierte en la mejor opción cuando los tipos de entidad no se conocen de antemano, cambian a menudo o son específicos de dominio ("adverse drug reaction", "financial instrument", "threat indicator").

Mi recomendación: usa spaCy para tipos de entidad estándar donde los pipelines preentrenados están bien validados. Usa GLiNER cuando necesites tipos flexibles, zero-shot o cuando tu pipeline deba adaptarse sin reentrenar. Funcionan bien juntos — spaCy gestiona tokenización y segmentación en frases, GLiNER gestiona la extracción de entidades.


UniNER y NuNER: ¿hasta qué punto se puede reducir?

UniNER (ICLR 2024, Zhou et al.) y NuNER (EMNLP 2024, Bogdanov et al.) destilan ambos anotaciones de LLMs en modelos NER más pequeños — pero discrepan en cuánto se puede reducir.

UniNER: la vía maximalista

UniNER hace fine-tuning de LLaMA-7B/13B sobre 44.889 pares NER (240K entidades, 13K tipos) generados por ChatGPT. Para cada tipo de entidad, el modelo responde "What describes [type] in the text?" y produce listas JSON. Un truco de entrenamiento clave: el frequency-based negative sampling eleva el F1 de 31.5% a 53.4% (Zhou et al., 2024).

UniNER-7B alcanza 41.7% de F1 zero-shot en 43 datasets — superando el 34.9% de ChatGPT por 7 puntos. La variante de 13B llega a 43.4%, solo 1.7 puntos más a cambio de casi doblar el cómputo (Zhou et al., 2024).

El problema en producción: como modelo autoregresivo de 7B, UniNER necesita N forward passes para N tipos de entidad, requiere 14GB+ de VRAM (ahí se va tu presupuesto de GPU antes del almuerzo) y tiene una licencia restrictiva CC BY-NC 4.0.

NuNER: la vía minimalista

NuNER parte de RoBERTa-base (125M de parámetros) y usa entrenamiento contrastivo con 4,38 millones de anotaciones de GPT-3.5 sobre 200K conceptos — coste total de anotación por debajo de \$500. Tras el entrenamiento, el encoder de conceptos se descarta; el encoder de texto encaja en cualquier pipeline NER estándar como sustituto de RoBERTa (Bogdanov et al., 2024).

Los resultados: NuNER supera a RoBERTa plano por 6-15 puntos de F1 en todos los tamaños few-shot. Con solo una docena de ejemplos por tipo de entidad, NuNER iguala a UniNER-7B pese a ser 56x más pequeño (Bogdanov et al., 2024).

Ambos papers muestran lo mismo: destilar anotaciones de LLMs en modelos más pequeños produce un NER que supera al profesor. Y no necesitas 7B de parámetros — 125M bastan cuando hay datos de fine-tuning disponibles, con licencia MIT e inferencia amigable para CPU.


GLiNER 2: un modelo, cuatro tareas

El ecosistema original de GLiNER tenía un problema creciente: modelos separados para NER (GLiNER), extracción de relaciones (GLiREL), clasificación (GLiClass) y RE a nivel de documento (GLiDRE) — cada uno con su propio despliegue, contenedor Docker, monitorización y modos de fallo. GLiNER 2 (EMNLP 2025, Zaratiana et al.) fusiona los cuatro en un único modelo de 205M de parámetros con una interfaz guiada por esquema.

La arquitectura mantiene el diseño cross-encoder, pero amplía el contexto a 2.048 tokens (4x el original) y añade esquemas declarativos para definir tareas de extracción. El entrenamiento usa 135.698 documentos reales anotados con GPT-4o más 118.636 ejemplos sintéticos (Zaratiana et al., 2025).

En CrossNER zero-shot, GLiNER 2 obtiene 0.590 F1 — cerca del 0.599 de GPT-4o según el benchmark del paper (mediados de 2025). Modelos más recientes como GPT-5.4 probablemente puntúan más alto, pero a una fracción de la velocidad y el coste de GLiNER 2. En clasificación, alcanza 0.72 de media en 7 benchmarks, superando a DeBERTa-v3-large (0.69). En CPU, GLiNER 2 ejecuta clasificación en 130-208ms independientemente del número de etiquetas. DeBERTa escala linealmente: 1.714ms para 5 etiquetas, 16.897ms para 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 único despliegue de modelo sustituye a cuatro. Infraestructura más simple, precisión competitiva.


El bi-encoder: escalando NER a millones de etiquetas

El GLiNER original codifica etiquetas y texto conjuntamente — lo que crea un cuello de botella. Más tipos de entidad significan una secuencia de entrada más larga, y el rendimiento cae rápido más allá de ~30 tipos. El bi-encoder de GLiNER (febrero de 2026, Stepanov et al.; arXiv 2602.18487) corrige esto separando la codificación de texto y etiquetas en dos transformers independientes.

Cross-encoder frente a bi-encoder: el cross-encoder codifica conjuntamente etiquetas y texto, mientras que el bi-encoder usa encoders separados con embeddings de etiqueta precalculados

El encoder de texto usa ModernBERT (familia Ettin), el encoder de etiquetas usa sentence transformers (BGE o MiniLM). Los spans y las etiquetas se puntúan mediante producto escalar. El truco: los embeddings de tipo de entidad pueden precalcularse una vez y cachearse. En inferencia, solo hace falta codificar el texto — la búsqueda de etiquetas es instantánea.

Hay cuatro tamaños de modelo disponibles, todos benchmarkeados en CrossNER (Stepanov et al., 2026, tabla 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

Con 1.024 tipos de entidad, el bi-encoder (edge, precalculado) pierde solo 5.2% de throughput frente a una sola etiqueta. El cross-encoder pierde 98.7% (10.7 → 0.14 ex/s). Eso supone una ventaja de throughput de 130x a escala. Con 100 tipos de entidad en una sola H100, el bi-encoder procesa 1,96 millones de predicciones al día frente a 368K del cross-encoder (Stepanov et al., 2026).

La precisión también aguanta. Bi-encoder-large alcanza 61.5% de F1 en CrossNER, ligeramente por delante del 60.9% del cross-encoder. Los autores recomiendan bi-base-v2.0 (194M) como punto óptimo, alcanzando el 98% de la precisión del modelo large a 2.6x la velocidad (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)

Las aplicaciones incluyen NER biomédico contra la ontología UMLS (más de 4M conceptos), taxonomías empresariales que evolucionan sin reentrenar el modelo, y entity linking mediante el framework complementario GLiNKER.


LLMs como profesores: el pipeline de \\(70 que supera al modelo de \\\)8/hora

El patrón LLM-as-teacher se ha convertido en un pipeline estándar de producción. Tres estudios muestran cuánto cuesta y qué obtienes.

El pipeline LLM-as-teacher: el LLM etiqueta datos brutos, humanos revisan un subconjunto, el encoder se ajusta por fine-tuning y se despliega con un coste 80x menor

El caso de estudio de CFM

Capital Fund Management extrajo nombres de empresas de ~900K titulares de noticias financieras. GLiNER zero-shot obtuvo 87.0% de F1. Usaron Llama 3.1-70b (el modelo abierto más fuerte en ese momento) para anotar el dataset completo en ~8 horas por ~\$70, y luego revisaron manualmente 2.714 muestras con Argilla en otras 8 horas.

El fine-tuning de GLiNER con esos datos llevó el rendimiento a 93.4% de F1 — superando incluso el 92.7% del profesor Llama 70b. El modelo afinado ejecuta a \\(0.10/hora en CPU** frente a \\\)8/hora del profesor — 80x más barato** con mejor precisión (CFM Case Study). Hoy obtendrías anotaciones profesor todavía mejores con Llama 4 Maverick o GPT-5.4 Mini a coste similar o menor.

El estudio de Refuel AI

Refuel AI benchmarkeó el etiquetado con LLMs en 8 datasets de NLP, incluido CoNLL-2003. GPT-4 (marzo de 2023) alcanzó 88.4% de acuerdo con ground truth — por encima del 86.2% de anotadores humanos cualificados. Los LLMs fueron 20x más rápidos y 7x más baratos. Su enfoque de ensemble — modelos baratos para ejemplos fáciles, GPT-4 para los difíciles — llegó a 95%+ de acuerdo manteniendo los costes bajos (Refuel AI Technical Report). Con GPT-5.4 y Claude 4.6 ya disponibles, la calidad del profesor no ha hecho más que mejorar.

NER clínico en Tonic.ai

Tonic.ai mostró que el patrón funciona también para NER clínico. Solo con anotaciones de LLM se entrenó un modelo RoBERTa LoRA hasta 0.70 F1 en el NCBI Disease Corpus (frente a 0.81 con etiquetas humanas completas). En extracción de IDs sanitarios alcanzó 0.947 F1 — por encima del umbral de producción de 0.914 — sin datos etiquetados por humanos.

El pipeline estándar

La receta de producción se ha asentado en seis pasos:

  1. Escribir guías de anotación en lenguaje natural
  2. Crear un conjunto de validación pequeño etiquetado por humanos (50-200 documentos)
  3. Usar un LLM (GPT-5.4 Mini, Llama 4 Maverick o Qwen3.5) para etiquetar datos de entrenamiento a gran escala
  4. Revisar un subconjunto mediante Argilla o Label Studio
  5. Hacer fine-tuning de un encoder compacto (GLiNER, SpanMarker, RoBERTa)
  6. Desplegar con un coste de inferencia 16-80x menor

El coste del NER ya no es "anota todos tus datos de entrenamiento contratando un ejército de estudiantes". Ahora es "construye un buen conjunto de validación, escribe guías claras y deja que el LLM haga el resto".


Dónde falla GLiNER y por qué los LLMs siguen siendo esenciales

El benchmark de Sease (octubre de 2025) probó GLiNER frente a GPT-4.1-mini en 30 tareas de parsing de consultas. GPT-4.1-mini obtuvo 100% totalmente correcto. GLiNER obtuvo 53% (16 de 30). Pero GLiNER respondió en 0.08 segundos frente a los 1.21 segundos del LLM — 15x más rápido.

GLiNER falla en tres patrones concretos:

  1. Entidades implícitas: extraer "event" de "Elton John performed at Madison Square Garden" — ningún texto dice literalmente "event", pero el LLM infiere "concert"
  2. Sensibilidad al phrasing de la etiqueta: "2022" puntúa 0.388 frente a "date" pero 0.958 frente a "year" — pequeños cambios en la etiqueta provocan grandes variaciones en la puntuación
  3. Value mapping: GLiNER devuelve el texto superficial exacto ("family houses") en lugar del valor canónico ("Single family house") — los LLMs hacen esto de forma natural

Entidades anidadas y solapadas

GLiNER también tiene dificultades con las entidades anidadas. En "New York University", un humano podría etiquetar tanto "New York" (LOCATION) como "New York University" (ORGANIZATION). GLiNER escoge solo el span con mayor puntuación. Esto importa en texto biomédico ("acute myeloid leukemia" contiene tanto una enfermedad como un modificador) y texto legal (jerarquías organizativas anidadas). Los modelos especializados gestionan el anidamiento, pero el diseño de spans planos de GLiNER no.

En la práctica: GLiNER resuelve la extracción explícita de entidades — el núcleo del NER en producción. Los LLMs entran cuando la extracción requiere inferencia, razonamiento o mapping a ontologías predefinidas. Usa ambos.


Evaluar NER: métricas, trampas y construcción de conjuntos de test

He visto equipos desplegar modelos con 95% de F1 en su test set que fallaban en producción porque el test set no reflejaba la distribución real de documentos. Tu test set no es tus datos de producción. Este modo de fallo es lo bastante común como para planificarlo.

Las métricas básicas

  • F1 a nivel de entidad: la métrica estándar. Una predicción es correcta solo si tanto los límites del span como el tipo coinciden exactamente con el ground truth. Es lo que reporta la mayoría de papers.
  • F1 a nivel de token: puntúa cada token de forma independiente. Infla resultados porque acertar la mayor parte de una entidad larga da crédito parcial. Prefiere F1 a nivel de entidad.
  • Precision frente a recall: suelen tener costes asimétricos. En de-identification, recall importa más — omitir un nombre es peor que redacted de más. En extracción para base de datos, precision importa más — entradas falsas corrompen el análisis downstream.

Trampas habituales en evaluación

  1. Inflación por partial match: extraer "Bill" cuando la etiqueta gold es "Bill Gates" — algunos scripts cuentan esto como acierto parcial. Usa matching exacto de spans salvo que tengas una razón para no hacerlo.
  2. Confusión de tipos: "Microsoft" identificado correctamente como span pero etiquetado PERSON en lugar de ORG debe puntuar cero. Comprueba que tu código de evaluación lo maneja.
  3. Fuga del test set: si las entidades del test se solapan con las del entrenamiento, las puntuaciones se inflan. Los benchmarks zero-shot (CrossNER, Few-NERD) existen para probar generalización.

Cómo construir un test set de dominio

Para evaluación en producción, recomiendo:

  1. Muestrear desde datos de producción, no desde ejemplos curados. Incluye los documentos sucios que tu modelo verá de verdad.
  2. 200-500 documentos anotados proporcionan estimaciones estables de F1. Por debajo de 100, los intervalos de confianza son demasiado amplios.
  3. Mínimo dos anotadores, con acuerdo interanotador (kappa de Cohen > 0.8). Si los humanos discrepan, tu modelo no puede hacerlo mejor.
  4. Estratificar por dificultad — casos fáciles (texto limpio, tipos estándar) y casos difíciles (entidades ambiguas, jerga, texto ruidoso).

NER en producción en cuatro industrias

Estas son las implementaciones de NER más maduras que he encontrado, con cifras concretas.

Sanidad

Sanidad tiene el tooling de NER más maduro. John Snow Labs tiene más de 2.500 modelos preentrenados, incluidos más de 1.200 para healthcare, que cubren más de 400 tipos de entidad clínica mapeados a ICD-10, SNOMED CT, LOINC y RxNorm. Sus modelos de de-identification alcanzan 96% de F1 (frente a Azure 91%, AWS 83%, GPT-4o 79%), con Providence St. Joseph Health procesando 100K-500K notas clínicas diarias.

El proyecto open-source OpenMed project ofrece más de 380 modelos de NER biomédico con 29.7M de descargas en HuggingFace, estableciendo un nuevo state-of-the-art en 10 de 12 benchmarks biomédicos públicos.

NER financiero

El principal caso de uso: extracción de filings de la SEC. Finance NLP de John Snow Labs extrae más de 11 tipos de entidad de filings 10-K/10-Q (direcciones, tickers, años fiscales, bolsas). Las variantes de FinBERT-MRC alcanzan 0.87-0.93 F1 en tareas de entidades financieras. El reto clave: documentos largos y entidades anidadas en instrumentos financieros complejos.

E-commerce

NER a escala masiva. El sistema EAMT de Walmart (KDD 2023) entrena con 965 millones de consultas y ~60 etiquetas de entidad, logrando una subida del 0.51% en GMV en tests A/B — millones en ingresos incrementales. El framework TripleLearn de Home Depot (AAAI 2021) elevó el F1 de NER de 69.5 a 93.3 mediante entrenamiento iterativo.

Ciberseguridad

El sistema iACE (CCS 2016) procesó 71.000 artículos de 45 blogs de seguridad, extrayendo 900K elementos IOC con 98% de precision y 93% de recall. Sistemas modernos como CyNER combinan DeBERTa (F1 >91%) con heurísticas IOC basadas en regex. El dataset unificado CyberNER (2025) armoniza cuatro datasets en 21 tipos de entidad alineados con STIX 2.1, con RoBERTa alcanzando 0.736 F1.


Optimización de despliegue: de Python a inferencia sub-milisegundo

Probé tres formas de acelerar GLiNER para producción en el repo complementario.

Exportación a ONNX

GLiNER tiene conversión nativa a ONNX, y existen modelos ya convertidos en HuggingFace (onnx-community/gliner_small-v2.1). ONNX Runtime ofrece 1.5-3x de aceleración en CPU frente a PyTorch, con cuatro niveles de optimización, desde básico hasta mixed-precision.

De 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)

Cuantización INT8

La cuantización dinámica reduce los modelos 2.4x (438MB → 181MB) con menos de 0.6% de pérdida de F1. La velocidad mejora 1.8x en CPU. En CPUs Intel VNNI con ONNX Runtime, INT8 alcanza hasta 6x de aceleración frente a 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: reimplementación en Rust

gline-rs (Apache 2.0) elimina la sobrecarga de Python. En CPU: 6.67 seq/s frente a 1.61 de Python — una aceleración de 4.1x. En una RTX 4080: 248.75 seq/s (benchmarks de gline-rs). Soporta modelos de spans y de tokens, GPU/NPU vía ONNX Runtime, y se distribuye como crate en 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%)

El paquete fast-gliner ofrece bindings de Python vía PyO3 — velocidad de Rust con ergonomía de Python.

Resumen del stack de optimización

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

Extracción estructurada: Instructor frente a Outlines

Cuando necesitas más flexibilidad de la que ofrecen los modelos encoder — entidades implícitas, razonamiento, mapping de ontologías — dos librerías manejan la extracción estructurada con LLMs.

Instructor (~12.600 estrellas en GitHub, ~8.8M de descargas/mes a marzo de 2026), de Jason Liu, parchea SDKs de LLM para aceptar modelos de respuesta Pydantic, con reintento automático en caso de fallo de validación. Soporta más de 15 proveedores e inspiró la funcionalidad nativa de structured output de OpenAI.

De 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 estrellas en GitHub), de dottxt, adopta otro enfoque: generación de tokens restringida mediante máquinas de estados finitos. En lugar de generar una salida y reintentar cuando falla la validación, Outlines evita que se generen tokens inválidos — 100% de cumplimiento del esquema, cero reintentos. Los benchmarks de AWS muestran 98% de adherencia al esquema frente a 76% para validación posterior a la generación, con 5x mayor velocidad de generación frente a generación no restringida con reintentos de post-validación.

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.")

La elección depende de dónde ejecutes tus modelos. Instructor es mejor para APIs cloud de LLM — prototipado rápido, soporte multi-provider, patrones familiares de Pydantic. Outlines gana para modelos locales donde necesitas garantías de formato sin dependencias externas. Ambos funcionan bien para extracción tipo NER, pero ninguno iguala el throughput de los encoders: Instructor añade 200ms-2s de latencia de API por llamada, y Outlines depende de la velocidad del modelo local. Para NER de alto throughput, los encoders siguen siendo 10-100x más rápidos.


La arquitectura de producción en 3 niveles

Así es como yo uniría todo esto para NER en producción.

La arquitectura en 3 niveles: los modelos encoder manejan más del 90% del volumen a bajo coste, GLiNER 2 gestiona extracción multi-tarea, y los LLMs gestionan el 10% más difícil mientras también entrenan los modelos del nivel 1

Nivel 1 — Modelos encoder para tipos de entidad conocidos. GLiNER (cross-encoder para <30 tipos, bi-encoder para 30+), afinado con el pipeline LLM-as-teacher. Despliega con ONNX + INT8 o gline-rs. Maneja >90% del volumen con latencia sub-50ms y coste casi nulo. El bi-encoder escala a millones de tipos de entidad con embeddings precalculados.

Nivel 2 — GLiNER 2 para extracción multi-tarea. Cuando una petición necesita NER + clasificación + extracción de relaciones + datos estructurados, el modelo de 205M de parámetros de GLiNER 2 sustituye cuatro despliegues. Ejecuta en CPU en 130-208ms independientemente del número de etiquetas — útil para pipelines documentales que necesitan varias tareas de extracción en una sola pasada.

Nivel 3 — LLMs para extracción con razonamiento intensivo. Cuando las entidades son implícitas, necesitan inferencia contextual o requieren mapping a ontologías, enruta a un LLM (GPT-5.4 Mini, Claude Sonnet 4.6, Llama 4 Maverick) vía Instructor (cloud) u Outlines (local). Esto maneja el ~10% de consultas que los encoders no cubren. Los mismos LLMs también generan datos de entrenamiento para el Nivel 1.

¿Cuánto cuesta esto? Un GLiNER afinado por fine-tuning alcanza 93.4% de F1 a \\(0.10/hora en CPU**, igualando el **92.7% de F1** de su profesor Llama-70b a **\\\)8/hora — 80x más barato.


Trade-offs y limitaciones

Los sistemas de ML siempre tienen trade-offs. La pregunta importante es dónde aparece ese trade-off y si puedes medirlo antes del despliegue.

Los errores del LLM-as-teacher se propagan. Si el LLM se equivoca sistemáticamente con un tipo de entidad concreto (por ejemplo, confundir nombres de filiales con empresas matriz), el encoder afinado hereda ese sesgo. La solución es revisión humana dirigida — centra el esfuerzo en tipos de entidad donde la confianza del LLM es baja o inconsistente, no en muestreo aleatorio.

Las pérdidas por cuantización no son uniformes. La pérdida media de ~0.6% de F1 con INT8 puede ser mayor en tipos de entidad raros con patrones de límites sutiles (compuestos químicos, abreviaturas multi-palabra). Haz siempre benchmark de los modelos cuantizados sobre tus tipos de entidad específicos, no solo sobre el F1 agregado.

Cuándo la arquitectura en 3 niveles es excesiva. Un único dominio, tipos de entidad bien definidos, más de 500 ejemplos etiquetados? Un pipeline de RoBERTa o spaCy ajustado por fine-tuning es más simple y suficiente. El patrón de 3 niveles compensa con (a) múltiples dominios, (b) tipos de entidad cambiantes o (c) una mezcla de tareas de extracción fáciles y difíciles. Si solo estás extrayendo nombres y fechas de facturas, el Nivel 1 basta.

Techo de calidad del bi-encoder. El bi-encoder intercambia atención conjunta por throughput. Cuando la semántica de la etiqueta interactúa con el contexto del texto ("date" frente a "year" frente a "period" para el mismo span), el cross-encoder sigue ganando. Usa cross-encoder para tareas críticas con pocas etiquetas; bi-encoder para amplitud.


Ideas clave

  1. Los encoders ganaron. GLiNER y las variantes bi-encoder superan a los LLMs en benchmarks estándar de NER con un coste 80-130x menor. Incluso con GPT-5.4 Nano y Llama 4 bajando precios, ejecutar un LLM para cada consulta de NER ya no está justificado.
  2. Los LLMs son esenciales — como profesores. Etiquetan datos de entrenamiento por \$70 que costarían miles en anotación humana, y el encoder afinado suele acabar superando al LLM que lo enseñó.
  3. El bi-encoder desbloquea la escala de millones de etiquetas. Los embeddings precalculados resuelven el problema de complejidad cuadrática, con solo un 5.2% de pérdida de throughput en 1.024 etiquetas.
  4. GLiNER 2 consolida la extracción multi-tarea. Un modelo de 205M para NER + clasificación + RE + extracción estructurada.
  5. Evalúa con tus datos. Usa F1 a nivel de entidad, construye test sets a partir de documentos de producción y benchmarkea modelos cuantizados con tus tipos de entidad concretos.
  6. Usa el patrón híbrido. Nivel 1/2 para extracción rápida, Nivel 3 para razonamiento. Los mismos LLMs que manejan el 10% más difícil generan los datos de entrenamiento para el 90%.

Referencias

Papers

Papers de industria

Casos de estudio

Herramientas y frameworks