Phase 05 - Lesson 25

Enlazado y Desambiguación de Entidades

El NER encontró "Paris". El enlazado de entidades decide: ¿París, Francia? ¿Paris Hilton? ¿Paris, Texas? ¿Paris (el príncipe troyano)? Sin el enlazado, tu grafo de conocimiento sigue siendo ambiguo.

Tipo: Build Lenguajes: Python Prerrequisitos: Fase 5 · 06 (NER), Fase 5 · 24 (Resolución de Correferencia) Tiempo: ~60 minutos

El Problema

Una oración dice: "Jordan beat the press." Tu NER etiqueta "Jordan" como PERSON. Bien. Pero ¿cuál Jordan?

  • ¿Michael Jordan (básquetbol)?
  • ¿Michael B. Jordan (actor)?
  • ¿Michael I. Jordan (profesor de ML en Berkeley — sí, esta confusión es real en los artículos de ML)?
  • ¿Jordan (el país)?
  • ¿Jordan (nombre propio hebreo)?

El enlazado de entidades (EL) resuelve cada mención a una entrada única en una base de conocimiento: Wikidata, Wikipedia, DBpedia o tu KB de dominio. Dos subtareas:

  1. Generación de candidatos. Dado "Jordan", ¿qué entradas de la KB son plausibles?
  2. Desambiguación. Dado el contexto, ¿qué candidato es el correcto?

Ambos pasos son aprendibles. Ambos tienen benchmarks. El pipeline combinado se ha mantenido estable durante una década — lo que cambia es la calidad del desambiguador.

El Concepto

Pipeline de enlazado de entidades: mención → candidatos → entidad desambiguada

Generación de candidatos. Dada la forma de superficie de la mención ("Jordan"), busca candidatos en un índice de alias. Los diccionarios de alias de Wikipedia cubren la mayoría de las entidades nombradas: "JFK" → John F. Kennedy, Jacqueline Kennedy, aeropuerto JFK, JFK (película). Un índice típico devuelve de 10 a 30 candidatos por mención.

Desambiguación: tres enfoques.

  1. Prior + contexto (Milne & Witten, 2008). P(entity | mention) × context-similarity(entity, text). Funciona bien, es rápido, no requiere entrenamiento.
  2. Basado en embeddings (ESS / REL / Blink). Codifica la mención + contexto. Codifica la descripción de cada candidato. Elige el coseno máximo. El estándar de 2020 a 2024.
  3. Generativo (GENRE, 2021; basado en LLM, 2023+). Decodifica el nombre canónico de la entidad token por token. Restringido a un trie de nombres de entidad válidos, de modo que la salida tiene garantía de ser un id de KB válido.

Extremo a extremo vs pipeline. Los modelos modernos (ELQ, BLINK, ExtEnD, GENRE) ejecutan NER + generación de candidatos + desambiguación en una sola pasada. Los sistemas en pipeline aún dominan en producción porque puedes intercambiar componentes.

Las dos mediciones

  • Recall de mención (generación de candidatos). Fracción de menciones de referencia en las que la entrada correcta de la KB aparece en la lista de candidatos. Es el piso de todo el pipeline.
  • Exactitud de desambiguación / F1. Dados los candidatos correctos, con qué frecuencia el top-1 es correcto.

Siempre reporta ambas. Un sistema con 99% de desambiguación sobre 80% de recall de candidatos es un pipeline del 80%.

Constrúyelo

Paso 1: construye un índice de alias a partir de las redirecciones de Wikipedia

alias_to_entities = {
    "jordan": ["Q41421 (Michael Jordan)", "Q810 (Jordan, country)", "Q254110 (Michael B. Jordan)"],
    "paris":  ["Q90 (Paris, France)", "Q663094 (Paris, Texas)", "Q55411 (Paris Hilton)"],
    "apple":  ["Q312 (Apple Inc.)", "Q89 (apple, fruit)"],
}

Datos de alias de Wikipedia: ~18M de pares (alias, entidad). Descárgalos de los dumps de Wikidata. Almacénalos como índice invertido.

Paso 2: desambiguación basada en contexto

def disambiguate(mention, context, alias_index, entity_desc):
    candidates = alias_index.get(mention.lower(), [])
    if not candidates:
        return None, 0.0
    context_words = set(tokenize(context))
    best, best_score = None, -1
    for entity_id in candidates:
        desc_words = set(tokenize(entity_desc[entity_id]))
        union = len(context_words | desc_words)
        score = len(context_words & desc_words) / union if union else 0.0
        if score > best_score:
            best, best_score = entity_id, score
    return best, best_score

El solapamiento de Jaccard es un juguete. Reemplázalo con similitud de coseno sobre embeddings (ver el paso 2 en code/main.py para la versión con transformer).

Paso 3: basado en embeddings (estilo BLINK)

from sentence_transformers import SentenceTransformer
encoder = SentenceTransformer("sentence-transformers/all-MiniLM-L6-v2")

def embed_mention(text, mention_span):
    start, end = mention_span
    marked = f"{text[:start]} [MENTION] {text[start:end]} [/MENTION] {text[end:]}"
    return encoder.encode([marked], normalize_embeddings=True)[0]

def embed_entity(entity_id, description):
    return encoder.encode([f"{entity_id}: {description}"], normalize_embeddings=True)[0]

En el momento de indexación, codifica cada entidad de la KB una vez. En el momento de la consulta, codifica la mención + contexto una vez, haz el producto punto contra el conjunto de candidatos y elige el máximo.

Paso 4: enlazado generativo de entidades (concepto)

GENRE decodifica el título de Wikipedia de la entidad carácter por carácter. La decodificación restringida (ver la lección 20) garantiza que solo se puedan generar títulos válidos. Integración estrecha con un trie respaldado por la KB. El descendiente moderno es REL-GEN y el EL mediante prompt de LLM con salida estructurada.

prompt = f"""Text: {text}
Mention: {mention}
List the best Wikipedia title for this mention.
Respond with JSON: {{"title": "..."}}"""

Combinado con una whitelist (el choice de Outlines), este es el pipeline de EL más simple de llevar a producción en 2026.

Paso 5: evalúa en AIDA-CoNLL

AIDA-CoNLL es el benchmark estándar de EL: 1.393 artículos de Reuters, 34 mil menciones, entidades de Wikipedia. Reporta la exactitud in-KB (P@1) y la tasa de detección de NIL out-of-KB.

Trampas

  • Manejo de NIL. Algunas menciones no están en la KB (entidades emergentes, personas oscuras). Los sistemas deben predecir NIL en lugar de adivinar la entidad equivocada. Se mide por separado.
  • Errores de frontera de mención. El NER aguas arriba pierde spans parciales ("Bank of America" etiquetado solo como "Bank"). El recall del EL cae.
  • Sesgo de popularidad. Los sistemas entrenados sobrepredicen entidades frecuentes. Una mención de "Michael I. Jordan" en un artículo de ML a menudo se enlaza al Jordan del básquetbol.
  • EL multilingüe. Mapear menciones en texto chino a entidades de Wikipedia en inglés. Requiere un codificador multilingüe o un paso de traducción.
  • Desactualización de la KB. Nuevas empresas, eventos y personas no están en el dump de Wikipedia del año pasado. Los pipelines de producción necesitan un ciclo de actualización.

Úsalo

El stack de 2026:

Situación Elige
Inglés de propósito general + Wikipedia BLINK o REL
Multilingüe, KB = Wikipedia mGENRE
Amigable con LLM, pocas menciones/día Haz prompt a Claude/GPT-4 con lista de candidatos + JSON restringido
KB específica de dominio (médica, legal) BERT personalizado con recuperación consciente de la KB + fine-tune en conjunto de dominio al estilo AIDA
Latencia extremadamente baja Solo prior de coincidencia exacta (baseline Milne-Witten)
SOTA de investigación GENRE / ExtEnD / EL generativo por LLM

Patrón de producción que entra en producción en 2026: NER → correferencia → EL en cada mención → colapsar clusters a una entidad canónica por cluster. Salida: un id de KB por entidad en el documento, no uno por mención.

Entrégalo

Guárdalo como outputs/skill-entity-linker.md:

---
name: entity-linker
description: Design an entity linking pipeline — KB, candidate generator, disambiguator, evaluation.
version: 1.0.0
phase: 5
lesson: 25
tags: [nlp, entity-linking, knowledge-graph]
---

Given a use case (domain KB, language, volume, latency budget), output:

1. Knowledge base. Wikidata / Wikipedia / custom KB. Version date. Refresh cadence.
2. Candidate generator. Alias-index, embedding, or hybrid. Target mention recall @ K.
3. Disambiguator. Prior + context, embedding-based, generative, or LLM-prompted.
4. NIL strategy. Threshold on top score, classifier, or explicit NIL candidate.
5. Evaluation. Mention recall @ 30, top-1 accuracy, NIL-detection F1 on held-out set.

Refuse any EL pipeline without a mention-recall baseline (you cannot evaluate a disambiguator without knowing candidate gen surfaced the right entity). Refuse any pipeline using LLM-prompted EL without constrained output to valid KB ids. Flag systems where popularity bias affects minority entities (e.g. name-clashes) without domain fine-tuning.

Ejercicios

  1. Fácil. Implementa el desambiguador prior+contexto en code/main.py sobre 10 menciones ambiguas (Paris, Jordan, Apple). Etiqueta manualmente la entidad correcta. Mide la exactitud.
  2. Medio. Codifica 50 menciones ambiguas con un sentence transformer. Haz el embedding de la descripción de cada candidato. Compara la desambiguación basada en embeddings con el solapamiento de contexto por Jaccard.
  3. Difícil. Construye una KB de dominio con 1k entidades (por ejemplo, empleados + productos de tu empresa). Implementa NER + EL extremo a extremo. Mide precisión y recall sobre 100 oraciones reservadas.

Términos Clave

Término Lo que dice la gente Lo que realmente significa
Enlazado de entidades (EL) Enlazar a Wikipedia Mapear una mención a una entrada única de la KB.
Generación de candidatos ¿Quién podría ser? Devolver una lista corta de entradas plausibles de la KB para una mención.
Desambiguación Elegir la correcta Puntuar candidatos usando el contexto y elegir al ganador.
Índice de alias La tabla de búsqueda Mapear de la forma de superficie → entidades candidatas.
NIL No está en la KB Predicción explícita de que ninguna entrada de la KB coincide.
KB Base de conocimiento Wikidata, Wikipedia, DBpedia o tu KB de dominio.
AIDA-CoNLL El benchmark 1.393 artículos de Reuters con enlaces de entidad de referencia.

Lecturas Adicionales

0 lifetime access. Curriculum based on AI Engineering from Scratch by Rohit Ghumare (MIT, used under attribution).