You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

使用Spacy EntityRuler添加PHONE_NUMBER实体失效问题求助

Spacy EntityRuler添加PHONE_NUMBER实体失效问题求助

嘿,我瞅见你在Spacy里用EntityRuler定义PHONE_NUMBER实体的时候碰钉子了——你说这个匹配模式用Matcher能正常工作,但做成实体规则就没效果,运行代码后电话号码还被拆成了两个CARDINAL实体,这就帮你捋捋问题出在哪~

先还原下你的问题场景,你的代码是这样的:

import spacy
from spacy.pipeline import EntityRuler

nlp = spacy.load("en_core_web_sm")

patterns = [
    {
        "label": "PHONE_NUMBER",
        "pattern": [
            {"ORTH": "("},
            {"SHAPE": "ddd"},
            {"ORTH": ")"},
            {"IS_SPACE": True, "OP": "?"},
            {"SHAPE": "ddd"},
            {"ORTH": "-"},
            {"SHAPE": "dddd"},
        ],
    }
]

entity_ruler = EntityRuler(nlp, patterns=patterns, overwrite_ents=True)
nlp.add_pipe("entity_ruler", before="ner")

doc = nlp("You can reach me at (111) 111-1111.")

for ent in doc.ents:
    print(ent.text, ent.label_)

当前输出是:

111 CARDINAL
111 CARDINAL

问题根源

你这里犯了一个小疏忽:你先初始化了带有自定义pattern的entity_ruler实例,但后面调用nlp.add_pipe("entity_ruler")的时候,相当于重新创建了一个空的EntityRuler,根本没把你定义的pattern加进去!自然就匹配不到电话号码,只能让原生的NER把数字识别成CARDINAL了。

修正方案

有两种正确的做法,选哪种都可以:

方案一:把初始化好的实体Ruler实例添加到管道

import spacy
from spacy.pipeline import EntityRuler

nlp = spacy.load("en_core_web_sm")

patterns = [
    {
        "label": "PHONE_NUMBER",
        "pattern": [
            {"ORTH": "("},
            {"SHAPE": "ddd"},
            {"ORTH": ")"},
            {"IS_SPACE": True, "OP": "?"},
            {"SHAPE": "ddd"},
            {"ORTH": "-"},
            {"SHAPE": "dddd"},
        ],
    }
]

# 初始化带pattern的实体Ruler
entity_ruler = EntityRuler(nlp, patterns=patterns, overwrite_ents=True)
# 把这个实例添加到管道,放在NER之前
nlp.add_pipe(entity_ruler, before="ner")

doc = nlp("You can reach me at (111) 111-1111.")

for ent in doc.ents:
    print(ent.text, ent.label_)

方案二:直接通过add_pipe传入配置参数

import spacy

nlp = spacy.load("en_core_web_sm")

patterns = [
    {
        "label": "PHONE_NUMBER",
        "pattern": [
            {"ORTH": "("},
            {"SHAPE": "ddd"},
            {"ORTH": ")"},
            {"IS_SPACE": True, "OP": "?"},
            {"SHAPE": "ddd"},
            {"ORTH": "-"},
            {"SHAPE": "dddd"},
        ],
    }
]

# 直接在add_pipe时指定pattern和overwrite_ents参数
nlp.add_pipe("entity_ruler", before="ner", config={"patterns": patterns, "overwrite_ents": True})

doc = nlp("You can reach me at (111) 111-1111.")

for ent in doc.ents:
    print(ent.text, ent.label_)

效果验证

修正后运行代码,就能得到正确的输出了:

(111) 111-1111 PHONE_NUMBER

这里的overwrite_ents=True也很关键,它会让EntityRuler识别的实体覆盖原生NER的结果,确保电话号码不会被拆分成其他实体类型~

备注:内容来源于stack exchange,提问作者user1255603

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.04.22 16:04:33