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 capas
Hace dos años, elegir un enfoque de NER implicaba 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 se 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.
Construí el repo complementario y comparé en benchmarks todos los enfoques principales. Los encoders ganaron el mercado del NER en producción. Los LLMs siguen siendo esenciales, pero como generadores de datos de entrenamiento más que como 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 de LLM-como-profesor 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-como-profesor (LLM etiqueta → revisión → fine-tuning) produce encoders que alcanzan 90-93%+ de F1. Para casos que requieren razonamiento, usa Instructor o Outlines con una API de LLM — pero presupón \$2+/1K docs. La arquitectura en 3 capas combina los tres.
Por qué NER importa más ahora: agentes, RAG e inteligencia documental
NER sigue significando lo mismo: encontrar spans nominales 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 oleada 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, embebido, 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 de modelos en Q4 2024?”, el sistema necesita reconocer “Anthropic” y “Q4 2024” como filtros, no limitarse a la similitud de embeddings.
Durante el indexado, extraes entidades de cada chunk y las almacenas como metadatos: {"organizations": ["Anthropic"], "dates": ["Q4 2024"], ...}. Esto permite filtrar por entidad antes de lanzar la búsqueda vectorial. El RAG con grafos de conocimiento (GraphRAG, property graphs de LlamaIndex) va más allá: NER más extracción de relaciones construyen un grafo capaz de responder preguntas multi-hop que los embeddings planos no pueden resolver.
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; una 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 él. NER convierte ese texto en hechos estructurados sobre los que el agente puede razonar, almacenar o pasar a herramientas.
Hay dos puntos donde más importa.
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 eso se acumula a lo largo de workflows de varios pasos hasta que tu agente “instantáneo” parece ejecutarse con una carrera de filosofía.
El segundo es el seguimiento de entidades a lo largo de la conversación. Los sistemas de memoria de agentes necesitan saber que “Sarah” en el turno 3 y “Sra. Chen” en el turno 12 son la misma persona. NER identifica los spans; 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, no la extracción basada en LLMs, son la elección correcta para 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 de texto es esto?) y extracción de relaciones (¿qué valores pertenecen entre sí?). GLiNER 2 maneja 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 el coste importa. Un despacho contable de tamaño medio procesa decenas de miles de facturas al mes. Enrutar 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 afinado en CPU cuesta céntimos. Tu CFO notará la diferencia. El camino: anotar 500 facturas de muestra 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) exigen encontrar datos personales antes de que lleguen a sistemas downstream. En despliegues de LLMs, eso significa escanear las entradas antes de que lleguen al modelo y las salidas antes de que lleguen al usuario.
NER lo resuelve directamente. Los modelos de desidentificación encuentran spans de PERSON, SSN, PHONE, EMAIL y 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 LLM, 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 luego 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 del NER con un modelo de 300M de parámetros
GLiNER (NAACL 2024, Zaratiana et al.) hizo que el NER basado en encoder 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: puntuar cada span de texto candidato (cada secuencia contigua de palabras como “Bill Gates” o “Microsoft”) frente a cada etiqueta de tipo de entidad, y quedarse con los pares de alta puntuación.
El modelo toma las etiquetas de tipo de entidad y el texto de entrada como una única secuencia: [ENT] person [ENT] organization [ENT] date [SEP] Bill Gates founded Microsoft.... Un transformer bidireccional (DeBERTa-v3) codifica todo conjuntamente.
A partir de la salida, el modelo construye dos conjuntos de representaciones: uno para tipos de entidad (a partir de las posiciones de token [ENT]) y otro para spans de texto (combinando los 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.
Aplica sigmoid y 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 del 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.
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 contra ellos. Hay tres tamaños disponibles: GLiNER-S (50M parámetros), GLiNER-M (90M) y GLiNER-L (300M). Los datos de entrenamiento vienen del dataset Pile-NER: 44.889 pasajes con 240K spans de entidad repartidos entre 13K tipos de entidad, todos etiquetados por ChatGPT. Entrenar GLiNER-L lleva unas 4 horas en una única 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 idiomas no ingleses (Zaratiana et al., 2024). Nota: es probable que LLMs más recientes (GPT-5.4, Claude 4.6) puntúen más alto en estos benchmarks, pero la brecha de coste no ha hecho más que crecer — estos modelos siguen siendo órdenes de magnitud más caros que un encoder de 90M en CPU.
El ecosistema es grande: más de 280 modelos compatibles con GLiNER en HuggingFace, ~350.000 descargas mensuales en PyPI, ~2.800 estrellas en GitHub. Las variantes cubren 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, la cucaracha de las librerías NLP (dicho con cariño: sobrevive a todo). 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 entrenamiento. ¿Quieres un nuevo tipo de entidad? Recoge datos etiquetados y reentrena. El en_core_web_trf basado en 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 inferencia, sin necesidad de reentrenar. Esto lo convierte en la mejor opción cuando los tipos de entidad no se conocen de antemano, cambian con frecuencia 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 reentrenamiento. Funcionan bien juntos — spaCy se encarga de la tokenización y la segmentación en frases; GLiNER se encarga de 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 anotaciones de LLMs en modelos de NER más pequeños — pero discrepan sobre 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 devuelve listas JSON. Un truco clave de entrenamiento: negative sampling basado en frecuencia 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 13B llega a 43.4%, solo 1.7 puntos más a cambio de casi duplicar 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 te va el presupuesto de GPU antes de comer) y tiene una licencia restrictiva CC BY-NC 4.0.
NuNER: la vía minimalista
NuNER parte de RoBERTa-base (125M parámetros) y usa entrenamiento contrastivo con 4,38 millones de anotaciones GPT-3.5 sobre 200K conceptos — con un coste total de anotación inferior a \$500. Después del entrenamiento, el encoder de conceptos se descarta; el encoder de texto se inserta en cualquier pipeline estándar de NER como sustituto de RoBERTa (Bogdanov et al., 2024).
Los resultados: NuNER supera a RoBERTa sin adaptar por 6-15 puntos de F1 en todos los tamaños few-shot. Con apenas una docena de ejemplos por tipo de entidad, NuNER iguala a UniNER-7B siendo 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 son suficientes cuando hay datos de fine-tuning disponibles, con licencia MIT e inferencia cómoda en 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, su propio contenedor Docker y su propia entrada en tu hoja de cálculo de “servicios por los que rezamos para que no se rompan”. 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 de 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 del 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: escalar NER a un millón 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 GLiNER bi-encoder (febrero de 2026, Stepanov et al.; arXiv 2602.18487) lo corrige separando la codificación del texto y de las etiquetas en dos transformers distintos.
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 almacenarse en caché. En inferencia, solo hay que codificar el texto — la consulta de etiquetas es instantánea.
Hay cuatro tamaños de modelo disponibles, todos benchmarkeados sobre 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 única 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 única 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 se mantiene. 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-como-profesor se ha convertido en un pipeline estándar de producción. Tres estudios muestran qué cuesta y qué obtienes.
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 aquel momento) para anotar el dataset completo en ~8 horas por ~\$70, y después revisaron manualmente 2.714 muestras vía Argilla en otras 8 horas.
El fine-tuning de GLiNER sobre estos datos elevó el rendimiento a 93.4% de F1 — superando incluso el 92.7% del profesor Llama 70b. El modelo afinado se ejecuta a \\(0.10/hora en CPU** frente a los \\\)8/hora del profesor — 80x más barato** y con mejor precisión (Caso de estudio de CFM). Hoy obtendrías anotaciones de profesor aún mejores con Llama 4 Maverick o GPT-5.4 Mini a un coste similar o menor.
El estudio de Refuel AI
Refuel AI comparó el etiquetado con LLMs en 8 datasets de NLP, incluido CoNLL-2003. GPT-4 (marzo de 2023) alcanzó 88.4% de acuerdo con la verdad terreno — por encima del 86.2% de los 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 y GPT-4 para los difíciles — llegó a 95%+ de acuerdo manteniendo los costes bajos (Informe técnico de Refuel AI). Con GPT-5.4 y Claude 4.6 ya disponibles, la calidad del profesor no ha hecho más que mejorar.
Tonic.ai Clinical NER
Tonic.ai mostró que el patrón funciona también para NER clínico. Las anotaciones generadas solo por LLM entrenaron un modelo RoBERTa LoRA hasta 0.70 de F1 en el NCBI Disease Corpus (frente a 0.81 con etiquetas humanas completas). En extracción de identificadores sanitarios, alcanzó 0.947 de 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:
- Escribir guías de anotación en lenguaje natural
- Crear un pequeño conjunto de validación etiquetado por humanos (50-200 documentos)
- Usar un LLM (GPT-5.4 Mini, Llama 4 Maverick o Qwen3.5) para etiquetar datos masivos de entrenamiento
- Revisar un subconjunto vía Argilla o Label Studio
- Hacer fine-tuning de un encoder compacto (GLiNER, SpanMarker, RoBERTa)
- 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 se encargue del 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 1.21 segundos del LLM — 15x más rápido.
GLiNER falla en tres patrones concretos:
- Entidades implícitas: extraer “event” de “Elton John performed at Madison Square Garden” — ningún texto dice literalmente “event”, pero el LLM infiere “concert”
- Sensibilidad a la formulación 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 oscilaciones en la puntuación
- Mapeo de valores: 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 problemas con las entidades anidadas. En “New York University”, un humano podría etiquetar tanto “New York” (LOCATION) como “New York University” (ORGANIZATION). GLiNER elige solo el span con mayor puntuación. Esto importa en texto biomédico (“acute myeloid leukemia” contiene tanto una enfermedad como un modificador) y en texto legal (jerarquías organizativas anidadas). Los modelos especializados manejan el anidamiento, pero el diseño de spans planos de GLiNER no.
En la práctica: GLiNER resuelve la extracción de entidades explícitas — el núcleo del NER en producción. Los LLMs entran cuando la extracción requiere inferencia, razonamiento o mapeo a ontologías predefinidas. Usa ambos.
Evaluar NER: métricas, trampas y cómo construir conjuntos de test
He visto equipos poner en producción modelos con 95% de F1 en su conjunto de test que fallaban en producción, porque el test no reflejaba la distribución real de documentos. Tu conjunto de test no es tu dato de producción. Sé que esto suena obvio. He visto cómo salía mal de todos modos.
Las métricas principales
- 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 la verdad terreno. Esto es lo que reportan la mayoría de los papers.
- F1 a nivel de token: puntúa cada token de forma independiente. Infla los resultados porque acertar la mayor parte de una entidad larga da crédito parcial. Prefiere F1 a nivel de entidad.
- Precision vs Recall: a menudo tienen costes asimétricos. En desidentificación, recall importa más — omitir un nombre es peor que redactar de más. En extracción para bases de datos, precision importa más — las entradas falsas corrompen el análisis downstream.
Errores comunes de evaluación
- Inflación por coincidencia parcial: extraer “Bill” cuando la etiqueta gold es “Bill Gates” — algunos scripts cuentan esto como coincidencia parcial. Usa matching exacto de span salvo que tengas un motivo para no hacerlo.
- Confusión de tipo: “Microsoft” identificado correctamente como span pero etiquetado como PERSON en lugar de ORG debería puntuar cero. Comprueba que tu código de evaluación lo gestiona bien.
- Fuga del conjunto de test: 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 conjunto de test de dominio
Para evaluación en producción, recomiendo:
- Muestrea desde datos de producción, no desde ejemplos curados. Incluye los documentos desordenados que tu modelo verá realmente.
- 200-500 documentos anotados dan estimaciones estables de F1. Por debajo de 100, los intervalos de confianza son demasiado amplios.
- Mínimo dos anotadores, con acuerdo interanotador (kappa de Cohen > 0.8). Si los humanos discrepan, tu modelo no puede hacerlo mejor.
- Estratifica 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
Estos son los despliegues de NER más maduros que he encontrado, con cifras concretas.
Sanidad
La 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 salud, cubriendo más de 400 tipos de entidad clínica mapeados a ICD-10, SNOMED CT, LOINC y RxNorm. Sus modelos de desidentificación alcanzan 96% de F1 (frente a Azure 91%, AWS 83%, GPT-4o 79%), con Providence St. Joseph Health procesando entre 100K y 500K notas clínicas al día.
El proyecto open-source OpenMed ofrece más de 380 modelos biomédicos de NER 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 caso de uso principal: extracción de filings de la SEC. Finance NLP de John Snow Labs extrae más de 11 tipos de entidad de formularios 10-K/10-Q (direcciones, tickers, ejercicios fiscales, bolsas de valores). Las variantes de FinBERT-MRC alcanzan 0.87-0.93 de 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. Los 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 de F1.
Optimización de despliegue: de Python a inferencia por debajo del 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 el tamaño de los modelos en 2.4x (438MB → 181MB) con una pérdida de menos de 0.6% 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 en Python — una aceleración de 4.1x. En una RTX 4080: 248.75 seq/s (benchmarks de gline-rs). Soporta modelos span y token, 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 proporciona 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 vs Outlines
Cuando necesitas más flexibilidad de la que ofrecen los modelos encoder — entidades implícitas, razonamiento, mapeo a ontologías — hay dos librerías que resuelven la extracción estructurada con LLMs.
Instructor (~12.600 estrellas en GitHub, ~8.8M descargas/mes a marzo de 2026), de Jason Liu, parchea SDKs de LLMs para aceptar modelos de respuesta Pydantic, con reintento automático cuando falla la validación. Soporta más de 15 proveedores e inspiró la función nativa de salida estructurada de OpenAI.
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 si falla la validación, Outlines impide que se generen tokens inválidos desde el principio — 100% de cumplimiento del esquema, cero reintentos. Los benchmarks de AWS muestran 98% de adherencia al esquema frente al 76% de la validación post-generación, con una generación 5x más rápida comparada con generación no restringida más reintentos de postvalidació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 Pydantic conocidos. Outlines gana con modelos locales cuando necesitas garantías de formato sin dependencias externas. Ambos funcionan bien para extracción de estilo 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 capas
Así es como yo juntaría todo esto para NER en producción.
Capa 1 — Modelos encoder para tipos de entidad conocidos. GLiNER (cross-encoder para <30 tipos, bi-encoder para 30+), afinado mediante el pipeline LLM-como-profesor. Despliegue con ONNX + INT8 o gline-rs. Gestiona >90% del volumen con latencia por debajo de 50ms y coste casi nulo. El bi-encoder escala a millones de tipos de entidad con embeddings precalculados.
Capa 2 — GLiNER 2 para extracción multitarea. 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 a cuatro despliegues. Se ejecuta en CPU en 130-208ms independientemente del número de etiquetas — adecuado para pipelines documentales que necesitan varias tareas de extracción en una pasada.
Capa 3 — LLMs para extracción con mucho razonamiento. Cuando las entidades son implícitas, requieren inferencia contextual o mapeo a ontologías, enruta a un LLM (GPT-5.4 Mini, Claude Sonnet 4.6, Llama 4 Maverick) vía Instructor (cloud) o Outlines (local). Esto cubre el ~10% de consultas que los encoders no resuelven. Esos mismos LLMs también generan datos de entrenamiento para la Capa 1.
¿Cuánto cuesta esto? Un GLiNER afinado 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
Nada de esto sale gratis. En ML siempre hay truco — la única cuestión es cuándo lo descubres.
Los errores del LLM-como-profesor se propagan. Si el LLM falla de forma sistemática en 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 los tipos de entidad donde la confianza del LLM es baja o inconsistente, no en un muestreo aleatorio.
Las pérdidas por cuantización no son uniformes. La pérdida media de ~0.6% de F1 en INT8 puede ser mayor en tipos de entidad raros con patrones sutiles de frontera (compuestos químicos, abreviaturas de varias palabras). Haz siempre benchmark de los modelos cuantizados sobre tus tipos de entidad concretos, no solo sobre F1 agregado.
Cuándo la arquitectura de 3 capas es excesiva. Un único dominio, tipos de entidad bien definidos, más de 500 ejemplos etiquetados? Un pipeline de RoBERTa o spaCy afinado es más simple y suficiente. El patrón de 3 capas compensa cuando tienes (a) varios dominios, (b) tipos de entidad cambiantes, o (c) una mezcla de tareas de extracción fáciles y difíciles. Si solo extraes nombres y fechas de facturas, la Capa 1 por sí sola 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” vs “year” vs “period” para el mismo span), el cross-encoder sigue ganando. Usa cross-encoder para tareas críticas con pocas etiquetas; bi-encoder para amplitud.
Conclusiones clave
- 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.
- 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ñó.
- El bi-encoder desbloquea la escala de un millón de etiquetas. Los embeddings precalculados resuelven el problema de complejidad cuadrática, con solo un 5.2% de pérdida de throughput a 1.024 etiquetas.
- GLiNER 2 consolida la extracción multitarea. Un modelo de 205M para NER + clasificación + RE + extracción estructurada.
- Evalúa con tus datos. Usa F1 a nivel de entidad, construye conjuntos de test a partir de documentos de producción y haz benchmark de modelos cuantizados sobre tus tipos de entidad concretos.
- Usa el patrón híbrido. Capa 1/2 para extracción rápida, Capa 3 para razonamiento. Los mismos LLMs que resuelven el 10% más difícil generan los datos de entrenamiento del 90%.
Referencias
Papers
- GLiNER: Generalist Model for Named Entity Recognition using Bidirectional Transformer - Zaratiana et al., NAACL 2024. La arquitectura fundacional de matching span-entidad.
- GLiNER 2: Open Problems for Automatic Information Extraction - Zaratiana et al., EMNLP 2025 System Demonstrations. Unifica NER, clasificación, RE y extracción estructurada.
- GLiNER Bi-Encoder: Scalable Named Entity Recognition with Bi-Encoder Architecture - Stepanov et al., febrero de 2026. Codificación desacoplada para escala de un millón de etiquetas.
- UniNER: Universal NER using Large Language Models - Zhou et al., ICLR 2024. NER universal basado en LLM mediante destilación desde ChatGPT.
- NuNER: Entity Recognition Encoder Pre-training via LLM-Annotated Data - Bogdanov et al., EMNLP 2024. Muestra que 125M de parámetros bastan con datos de entrenamiento generados por LLM.
Papers de industria
- EAMT: Entity-Aware Multi-Task Learning for Query Understanding - Walmart, KDD 2023. 965M consultas, aumento del 0.51% en GMV.
- TripleLearn: End-to-End NER for E-Commerce Search - Home Depot, AAAI 2021. F1 de 69.5 a 93.3.
- iACE: Automatic Collection of Cyber Threat Intelligence - CCS 2016. 71K artículos, 900K IOCs.
- CyberNER: A Harmonized STIX Corpus for Cybersecurity NER - 21 tipos de entidad alineados con STIX 2.1.
- FinBERT-MRC: Financial NER via Machine Reading Comprehension - 0.87-0.93 de F1 en tareas de entidades financieras.
Casos de estudio
- CFM Case Study: Fine-tuning GLiNER for Financial NER - Pipeline de etiquetado con LLM de \$70 de Capital Fund Management que alcanza 93.4% de F1.
- Refuel AI: LLM Labeling Technical Report - GPT-4 alcanzando 88.4% de acuerdo de anotación, por encima de anotadores humanos.
- Sease: GLiNER as an Alternative to LLMs for Query Parsing - Dónde falla GLiNER y por qué siguen haciendo falta los LLMs.
- John Snow Labs: Medical Text De-Identification Benchmark - Comparativa de detección de PHI con 96% de F1 entre proveedores.
- OpenMed: Year in Review 2025 - Más de 380 modelos biomédicos de NER, 29.7M descargas en HuggingFace.
Herramientas y frameworks
- ner-field-guide demo repo - Demos complementarias de este artículo: quickstart de GLiNER, exportación a ONNX, LLM-como-profesor y extracción estructurada.
- gline-rs: Rust reimplementation of GLiNER - Aceleración 4.1x en CPU frente a Python, licencia Apache 2.0.
- Instructor - Extracción estructurada con LLMs vía modelos Pydantic, ~8.8M descargas mensuales.
- Outlines - Generación de tokens restringida mediante FSMs, garantizando cumplimiento del esquema.
- AWS: Structured Output with Outlines - Benchmark de 98% de adherencia al esquema.