如何优化Spacy规则避免重复提取合同中的买卖方实体?
解决Spacy合同买卖方实体重复提取/拆分问题
问题根源
你的规则大概率没锚定完整实体边界,要么没利用Spacy预训练模型识别的完整PERSON实体,要么模式太宽泛,导致同一实体的子片段被反复匹配,或者同一实体被多次标记。
具体修改方案
1. 绑定预训练PERSON实体,关联角色
先让Spacy的NER模型识别出完整的人名实体,再通过上下文规则给这些实体打上SELLER/BUYER标签,从根源避免拆分:
import spacy from spacy.pipeline import EntityRuler # 优先用法律领域适配的模型,比如en_core_web_trf,效果比en_core_web_sm好 nlp = spacy.load("en_core_web_sm") # 初始化实体规则器,开启覆盖模式避免重复标记 ruler = EntityRuler(nlp, overwrite_ents=True) patterns = [ # 匹配"[人名] is the seller"这类结构 { "label": "SELLER", "pattern": [ {"ENT_TYPE": "PERSON"}, {"LOWER": {"IN": ["is", "acts as", "shall be"]}}, {"LOWER": "seller"} ] }, # 匹配"Buyer: [人名]"这类合同常见格式 { "label": "BUYER", "pattern": [ {"LOWER": "buyer"}, {"ORTH": ":"}, {"ENT_TYPE": "PERSON"} ] }, # 支持多个并列卖方,比如"Sellers: Alice Smith and Bob Brown" { "label": "SELLER", "pattern": [ {"LOWER": "sellers"}, {"ORTH": ":"}, {"ENT_TYPE": "PERSON"}, {"LOWER": {"IN": ["and", ","]}, "OP": "*"}, {"ENT_TYPE": "PERSON", "OP": "*"} ] } ] ruler.add_patterns(patterns) # 把规则器放在NER之后,基于已识别的PERSON实体做角色匹配 nlp.add_pipe("entity_ruler", after="ner") # 测试示例 doc = nlp("Seller: Alice Smith and Buyer: Bob Johnson. Alice Smith acts as the seller, while Bob Johnson is the buyer.") for ent in doc.ents: print(f"{ent.label_}: {ent.text}")
2. 纯规则模式下强制匹配完整实体
如果不用预训练NER,直接写规则,要确保匹配完整名称,避免拆分:
- 用
IS_TITLE=True匹配大写开头的名称词,结合OP: "+"匹配多词人名 - 排除标点符号干扰,确保只提取完整名称
patterns = [ { "label": "SELLER", "pattern": [ {"LOWER": "seller"}, {"ORTH": ":"}, {"IS_TITLE": True, "OP": "+"}, {"IS_PUNCT": False, "OP": "*"} ] } ]
3. 关键配置:开启overwrite_ents
初始化EntityRuler时一定要加overwrite_ents=True,这样同一文本片段不会被重复标记为多个实体,也能避免拆分已匹配的完整span。
验证要点
修改后检查输出:
- 同一个买卖方只出现一次
- 人名是完整的(比如不会把"Alice Smith"拆成"Alice"和"Smith"两个SELLER)
- 并列的多个买卖方都能被正确识别
内容的提问来源于stack exchange,提问作者kernel density
相关产品推荐
相关产品推荐

