mcpField
E
Entity Extractor

Entity Extractor

github.com/jmsktm数据与数据库10205 次安装40 周前更新
代码仓库

关于 Entity Extractor

Entity Extractor 是用于设计和实现命名实体识别流程的技能,面向处理通用或领域文本的 NLP 从业者。内容涵盖方法选择、自定义模型训练、评估、规范化及相关抽取任务。

主要功能

  1. 01选择 NER 方法
  2. 02实现抽取流程
  3. 03训练自定义实体模型
  4. 04评估抽取质量
  5. 05实体规范化与链接
  6. 06关系抽取方法

适用场景

  1. 01为特定领域选择 NER 方法
  2. 02构建自定义实体识别器
  3. 03分析各类实体的抽取错误
  4. 04将抽取实体链接到知识库

安装

复制下面的命令,在终端中运行。

$npx skills add https://github.com/jmsktm/claude-settings --skill entity-extractor

安装后在 Claude Code 中输入/entity-extractor确认已加载。

详细介绍

实体抽取

实体抽取技能将引导你实现命名实体识别(NER)系统,用于识别和分类文本中的实体。从人物和组织到特定领域的实体,例如产品、医学术语或金融工具,本技能涵盖从简单模式匹配到高级神经网络模型的各种抽取方法。

实体抽取是基础的 NLP 任务,为搜索引擎、知识图谱等应用提供支持。要做好这项任务,需要了解你的领域、选择合适的技术,并处理自然语言固有的歧义。

无论你需要抽取标准实体类型、为你的领域定义自定义实体,还是基于实体识别构建关系抽取,本技能都能帮助你打造准确且易于维护的抽取流水线。

核心工作流

工作流 1:选择抽取方法
  1. 定义目标实体:
    • 标准类型:PERSON、ORG、LOCATION、DATE、MONEY
    • 特定领域:PRODUCT、SYMPTOM、GENE、CONTRACT
    • 关系:实体之间的联系
  2. 评估可用资源:
    • 标注训练数据
    • 领域专业知识
    • 计算资源限制
  3. 选择方法:
    方法训练数据准确度速度自定义能力
    spaCy(预训练)无良好非常快有限
    基于规则无不定快高
    微调 BERT100s-1000s优秀中等完全
    LLM(零样本)无良好慢基于提示词
    LLM(少样本)少量示例很好慢基于提示词
  4. 规划实现和评估
工作流 2:实现实体抽取流水线
  1. 设置抽取流程:
    import spacy
    
    class EntityExtractor:
        def __init__(self, model="en_core_web_trf"):
            self.nlp = spacy.load(model)
    
        def extract(self, text):
            doc = self.nlp(text)
            entities = []
            for ent in doc.ents:
                entities.append({
                    "text": ent.text,
                    "type": ent.label_,
                    "start": ent.start_char,
                    "end": ent.end_char,
                    "confidence": getattr(ent, "confidence", None)
                })
            return entities
    
        def extract_batch(self, texts):
            docs = list(self.nlp.pipe(texts))
            return [self.extract_from_doc(doc) for doc in docs]
    
  2. 后处理实体:
    • 规范化不同写法(IBM 与 I.B.M.)
    • 消解缩写
    • 链接到知识库
  3. 验证抽取质量
  4. 处理边缘情况
工作流 3:构建自定义实体识别器
  1. 准备训练数据:
    # Format for spaCy training
    TRAIN_DATA = [
        ("Apple released the new iPhone today.", {
            "entities": [(0, 5, "ORG"), (24, 30, "PRODUCT")]
        }),
        ("Dr. Smith prescribed metformin for diabetes.", {
            "entities": [(0, 9, "PERSON"), (21, 30, "DRUG"), (35, 43, "CONDITION")]
        })
    ]
    
  2. 配置训练:
    # spaCy config for NER training
    config = {
        "training": {
            "optimizer": {"learn_rate": 0.001},
            "batch_size": {"@schedules": "compounding", "start": 4, "stop": 32}
        },
        "components": {
            "ner": {
                "factory": "ner",
                "model": {"@architectures": "spacy.TransitionBasedParser"}
            }
        }
    }
    
  3. 训练模型:
    python -m spacy train config.cfg --output ./models --paths.train ./train.spacy --paths.dev ./dev.spacy
    
  4. 在留出数据上评估
  5. 根据错误迭代改进

快速参考

操作命令/触发语
抽取实体“从 [text] 中抽取实体”
选择 NER 模型“[domain] 领域最适合的 NER”
自定义实体“训练自定义实体识别器”
评估 NER“评估实体抽取质量”
处理歧义“消解有歧义的实体”
实体链接“将实体链接到知识库”

最佳实践

  • 从预训练模型开始:不要在没有必要时从头训练

    • spaCy、Hugging Face 和云 API 可覆盖常见实体
    • 先测试预训练模型
    • 仅在需要时微调
  • 制定明确的指南:实体边界可能存在歧义

    • “Dr. John Smith”——一个实体还是两个?
    • “New York Times”——ORG 还是 GPE?
    • 制定并遵循一致的标注指南
  • 处理嵌套实体:某些实体包含其他实体

    • “Bank of America headquarters”(LOCATION 中包含 ORG)
    • 提前决定嵌套策略
    • 有些模型仅支持扁平实体;其他模型可以处理嵌套实体
  • 规范化抽取出的实体:原始文本中存在不同写法

    • “IBM”、“I.B.M.”、“International Business Machines”
    • 规范为标准形式
    • 尽可能链接到知识库 ID
  • 细致评估:汇总指标会掩盖问题

    • 按实体类型报告精确率/召回率
    • 分析错误模式
    • 明确测试边缘情况
  • 考虑上下文窗口:模型有上下文限制

    • 长文档可能需要分块
    • 尽可能在各块之间保留上下文
    • 如果实体可能跨块边界,则在边界处重新运行

高级技术

基于 LLM 的实体抽取

使用语言模型进行灵活抽取:

def llm_extract_entities(text, entity_types):
    prompt = f"""Extract named entities from the following text.

Text: "{text}"

Entity types to extract:
{chr(10).join(f"- {t}: {desc}" for t, desc in entity_types.items())}

Return a JSON array of entities:
[{{"text": "entity text", "type": "ENTITY_TYPE", "start": 0, "end": 10}}]

Only include entities that clearly match the specified types.
"""

    response = llm.complete(prompt, response_format={"type": "json_object"})
    return json.loads(response)["entities"]

# Example usage
entity_types = {
    "COMPANY": "Business organizations",
    "PRODUCT": "Commercial products or services",
    "PERSON": "Individual people's names"
}
entities = llm_extract_entities(text, entity_types)
规则 + ML 混合方法

结合模式匹配与神经网络抽取:

class HybridExtractor:
    def __init__(self):
        self.ml_extractor = spacy.load("en_core_web_trf")
        self.patterns = load_pattern_rules()

    def extract(self, text):
        # ML extraction
        ml_entities = self.ml_extractor(text).ents

        # Pattern-based extraction
        pattern_entities = apply_patterns(text, self.patterns)

        # Merge with priority rules
        merged = merge_entities(
            ml_entities,
            pattern_entities,
            priority="pattern"  # Patterns override ML when overlap
        )

        return merged

    def add_pattern(self, pattern, entity_type):
        """Add domain-specific pattern."""
        self.patterns.append({
            "pattern": pattern,
            "type": entity_type
        })
实体链接

将提取出的实体关联到知识库:

def link_entity(entity_text, entity_type, knowledge_base):
    """
    Link extracted entity to canonical entry in knowledge base.
    """
    # Generate candidates
    candidates = knowledge_base.search(
        query=entity_text,
        type_filter=entity_type,
        limit=10
    )

    if not candidates:
        return {"entity": entity_text, "linked": None}

    # Score candidates
    scored = []
    for candidate in candidates:
        score = compute_linking_score(
            entity_text,
            candidate.name,
            candidate.aliases
        )
        scored.append((candidate, score))

    # Select best match
    best = max(scored, key=lambda x: x[1])

    if best[1] > LINKING_THRESHOLD:
        return {
            "entity": entity_text,
            "linked": best[0].id,
            "canonical_name": best[0].name,
            "confidence": best[1]
        }
    else:
        return {"entity": entity_text, "linked": None}
关系抽取

提取实体之间的关系:

def extract_relations(text, entities):
    """
    Given extracted entities, find relations between them.
    """
    prompt = f"""Given this text and extracted entities, identify relationships.

Text: "{text}"

Entities found:
{json.dumps(entities, indent=2)}

Identify relationships between entities. Return JSON:
[{{
    "subject": "entity text",
    "relation": "relationship type",
    "object": "entity text",
    "confidence": 0.9
}}]

Common relation types: WORKS_FOR, LOCATED_IN, FOUNDED, ACQUIRED, PARTNER_OF
"""

    response = llm.complete(prompt)
    return json.loads(response)
NER 主动学习

通过有针对性的标注,高效改进抽取效果:

def active_learning_sample(unlabeled_texts, model, n_samples=100):
    """
    Select texts that would be most valuable to label.
    """
    uncertainties = []

    for text in unlabeled_texts:
        doc = model(text)
        # Calculate uncertainty (various strategies)
        uncertainty = calculate_ner_uncertainty(doc)
        uncertainties.append((text, uncertainty))

    # Select most uncertain
    uncertainties.sort(key=lambda x: x[1], reverse=True)
    return [text for text, _ in uncertainties[:n_samples]]

def calculate_ner_uncertainty(doc):
    """
    Calculate uncertainty based on entity confidence scores.
    """
    if not doc.ents:
        return 0.5  # No entities - medium uncertainty

    confidences = [ent._.confidence for ent in doc.ents if hasattr(ent._, "confidence")]
    if not confidences:
        return 0.5

    # High uncertainty = low confidence entities
    return 1 - min(confidences)

应避免的常见问题

  • 标注指南不一致,导致训练数据含噪
  • 未处理实体边界歧义(实体在哪里结束?)
  • 忽略重要的嵌套或重叠实体
  • 未进行数据增强,就使用小型数据集进行训练
  • 在下游使用前未对实体进行规范化
  • 未经测试就假定预训练模型适用于你的领域
  • 未评估各实体类型的性能
  • 忘记通过实体链接进行消歧

评论

支持 Markdown