实体链接 本节摘要:NER 找到了「Paris」,实体链接要决定:是法国巴黎、希尔顿、德州的巴黎、还是特洛伊王子帕里斯?不链接,你的知识图谱就停留在歧义上。一句话读「Jordan 击败了媒体」,NER 把「Jordan」标成 PERSON,可哪一个 Jordan?篮球迈克尔·乔丹、演员迈克尔·B·乔丹、伯克利机器学习教授迈克尔·I·乔丹(是的,这个混淆在机器学习论文里真实存在)、约旦国,还是希伯来名 Jordan?实体链接把每个提及解析到知识库(Wikidata、维基百科、DBpedia 或你的领域 KB)里的唯一条目。它有两个子任务:候选生成(给定「Jordan」,KB 里哪些条目合理?)与消歧(给定上下文,哪个候选是对的?)。
本节摘要:NER 找到了「Paris」,实体链接要决定:是法国巴黎、希尔顿、德州的巴黎、还是特洛伊王子帕里斯?不链接,你的知识图谱就停留在歧义上。一句话读「Jordan 击败了媒体」,NER 把「Jordan」标成 PERSON,可哪一个 Jordan?篮球迈克尔·乔丹、演员迈克尔·B·乔丹、伯克利机器学习教授迈克尔·I·乔丹(是的,这个混淆在机器学习论文里真实存在)、约旦国,还是希伯来名 Jordan?实体链接把每个提及解析到知识库(Wikidata、维基百科、DBpedia 或你的领域 KB)里的唯一条目。它有两个子任务:候选生成(给定「Jordan」,KB 里哪些条目合理?)与消歧(给定上下文,哪个候选是对的?)。两步都可学、都有基准,组合流水线已稳定十年,变化的是消歧器的质量。本节用三种消歧法(先验+上下文、嵌入式、生成式)从零搭出流水线,讲清两个必须同时报的指标——提及召回(整个流水线的地板)与消歧准确率(候选对时 top-1 多常对),并点名 NIL 处理、流行度偏置、KB 陈旧等生产陷阱。
对应原课程:Phase 5 · Lesson 25 ·
entity-linking(原英文phases/05-nlp-foundations-to-advanced/25-entity-linking/docs/en.md)。前置依赖:第 06 节(NER)、第 24 节(共指消解)。
阅读完本节,你应当能够:
一句话:「Jordan beat the press.」你的 NER 把「Jordan」标成 PERSON。好。但哪个Jordan?
实体链接(EL) 把每个提及解析到知识库(Wikidata、维基百科、DBpedia 或你的领域 KB)里的唯一条目。两个子任务:
两步都可学、都有基准。组合流水线已稳定十年,变化的是消歧器的质量。
候选生成:给定提及的表层形式(「Jordan」),在别名索引里查候选。维基百科别名词典覆盖大多数命名实体:「JFK」→ John F. Kennedy、Jacqueline Kennedy、JFK 机场、JFK(电影)。典型索引对每个提及返回 10~30 个候选。
消歧的三种方法:
P(实体 | 提及) × 上下文-相似度(实体, 文本)。效果好、快、无需训练。💡 端到端 vs 流水线:现代模型(ELQ、BLINK、ExtEnD、GENRE)一次跑完 NER + 候选生成 + 消歧。流水线系统在生产里仍主导,因为你可以换组件。
⚠️ 总同时报两个。一个在 80% 候选召回上做到 99% 消歧的系统,是个 80% 的流水线。
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)"], }
维基百科别名数据:约 1800 万(别名, 实体)对,从 Wikidata 转储下载,存为倒排索引。
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
Jaccard 重叠是玩具。换成嵌入上的余弦相似度(见 code/main.py 第 2 步的 Transformer 版)。
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]
索引时,把每个 KB 实体编码一次。查询时,把提及+上下文编码一次,与候选池做点积,取最大。
GENRE 逐字符解码出实体的维基百科标题。受约束解码(见第 20 节)确保只能输出合法标题,与 KB 支撑的 trie 紧密集成。现代后继是 REL-GEN 与带结构化输出的 LLM 提示式 EL。
prompt = f"""Text: {text} Mention: {mention} List the best Wikipedia title for this mention. Respond with JSON: {{"title": "..."}}"""
配上白名单(Outlines choice),这就是 2026 最易发布的 EL 流水线。
AIDA-CoNLL 是标准 EL 基准:1,393 篇路透社文章,3.4 万提及,维基百科实体。报库内准确率(P@1)与库外 NIL 检测率。
2026 的栈:
| 情形 | 选 |
|---|---|
| 通用英语 + 维基百科 | BLINK 或 REL |
| 跨语言,KB = 维基百科 | mGENRE |
| LLM 友好,每天少量提及 | 提示 Claude/GPT-4 配候选列表 + 受约束 JSON |
| 领域专用 KB(医疗、法律) | 自定义 BERT 配 KB 感知检索 + 在领域 AIDA 式集合上微调 |
| 极低延迟 | 仅精确匹配先验(Milne-Witten 基线) |
| 研究 SOTA | GENRE / ExtEnD / 生成式 LLM-EL |
💡 2026 生产模式:NER → 共指 → 对每个提及做 EL → 把簇坍缩成每簇一个规范实体。输出:文档里每个实体一个 KB id,而非每提及一个。
保存为 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.
code/main.py 的先验+上下文消歧器,手标正确实体,测准确率。下一节,我们把实体两两连起来——进入「关系抽取与知识图谱」,看如何从自由文本里抽出「实体-关系-实体」三元组,并把它们织成可查询的知识图谱。