news 2026/9/12 17:42:26

spaCy 如何通过 entry points 机制注册自定义组件与语言类?

作者头像

张小明

前端开发工程师

1.2k 24
文章封面图
spaCy 如何通过 entry points 机制注册自定义组件与语言类?

spaCy 如何通过 entry points 机制注册自定义组件与语言类?

【免费下载链接】spaCy💫 Industrial-strength Natural Language Processing (NLP) in Python项目地址: https://gitcode.com/GitHub_Trending/sp/spaCy

写出自定义 pipeline 组件或自定义Language子类后,你默认会遇到一个问题:spaCy 只能通过已注册的工厂函数把"my_component"这样的字符串名解析成真实对象,而注册发生在装饰器@Language.component/@Language.factory被执行(即模块被导入)之后。如果你把组件拆成独立的扩展包,又不想要求用户每次手动import你的模块,就可以利用 Python 的 entry points 机制:扩展包在setup.py中声明spacy_factories/spacy_languages入口点,spaCy 会自动加载它们。前提只有一个——包需要暴露这些 entry points 并安装在同一个环境中。

这篇文章按 spaCy 官方文档(保存与加载、处理流水线、语言数据)中的示例走一遍完整路径:写组件 → 在setup.py声明 entry point → 安装包 → 验证无需 import 即可使用。

spaCy 可识别的 entry point 组

Entry point用途
spacy_factoriespipeline 组件工厂的入口点组,key 为组件名,用于暴露其他包定义的自定义组件
spacy_languages自定义Language子类的入口点组,key 为语言代码
spacy_lookups自定义 Lookups(含词形还原数据),spacy-lookups-data包使用
spacy_displacy_colorsdisplaCy 可视化器的自定义标签颜色,key 名随意,应指向「标签 → 颜色值」的字典

声明语法:setup.pyentry_points字典里的某一组是一组字符串列表,每个字符串遵循name = module:object。例如"snek = snek:snek_component"创建一个名为snek的入口点,指向模块snek(即snek.py)中的函数snek_component。同一个包可以暴露多个入口点,安装后全部对 spaCy 可用。

用 spacy_factories 注册自定义组件

第 1 步:写组件并用装饰器注册

文档示例的包结构:

├── snek.py # the extension code └── setup.py # setup file for pip installation

snek.py定义一个收到Doc时打印一条蛇的组件(示例代码,直接可用):

from spacy.language import Language snek = """ --..,_ _,.--. `'.'. .'`__ o `;__. {text} '.'. .'.'` '---'` ` '.`'--....--'`.' `'--....--'` """ @Language.component("snek") def snek_component(doc): print(snek.format(text=doc.text)) return doc

这里的关键是@Language.component("snek"):从 v3.0 起,组件必须用@Language.component@Language.factory装饰器注册,nlp.add_pipe接收的是组件工厂的字符串名而不是函数对象。装饰器把组件注册到Language的工厂注册表中,之后add_pipe("snek")才能解析这个名字。

第 2 步:在 setup.py 声明 entry point

from setuptools import setup setup( name="snek", entry_points={ "spacy_factories": ["snek = snek:snek_component"] } )

等号左边的snek是入口点名,也就是 pipeline 配置里使用的组件名;右边指向被装饰的函数。不声明它的话,加载pipeline = ["snek"]的配置时 spaCy 会因为找不到内置组件"snek"而报错。

第 3 步:安装包

在包含setup.py的包目录下执行:

$ python -m pip install .

这一步把当前目录的包安装进当前环境;entry point 声明只有在包被安装后才生效。

第 4 步:验证无需 import 即可使用

>>> from spacy.lang.en import English >>> nlp = English() >>> nlp.add_pipe("snek") # this now works! >>> doc = nlp("I am snek")

以上代码从未导入snek_component,但nlp.add_pipe("snek")成功——说明 entry point 已生效。doc = nlp("I am snek")的输出(文档示例):

--..,_ _,.--. `'.'. .'`__ o `;__. I am snek '.'. .'.'` '---'` ` '.`'--....--'`.' `'--....--'`

机制说明:加载 pipeline 时 spaCy 读取config.cfg来设置语言类并构造 pipeline,pipeline是字符串列表(如["tagger", "parser", "ner"]),每个字符串经nlp.add_pipe到所有已注册工厂中查找。声明了spacy_factories后,这些函数会在Language类初始化时在后台自动加载,因此用户无需 import你的组件。此外,把nlp.config保存到磁盘时会包含"snek"组件的条目,任何用这份配置训练的 pipeline 都会包含该组件并知道如何加载它——前提是snek包已安装。对应的配置片段(文档示例):

[nlp] lang = "en" pipeline = ["snek"] [components.snek] factory = "snek"

可选:改成工厂以支持配置与序列化

如果组件需要状态或可调参数,改用@Language.factory,用户就能在添加组件时传入config。文档示例(cute_snek是文档中未定义的第二种蛇图案变量,实际使用需自行定义):

SNEKS = {"basic": snek, "cute": cute_snek} # collection of sneks @Language.factory("snek", default_config={"snek_style": "basic"}) class SnekFactory: def __init__(self, nlp: Language, name: str, snek_style: str): self.nlp = nlp self.snek_style = snek_style self.snek = SNEKS[self.snek_style] def __call__(self, doc): print(self.snek) return doc

setup.py中入口点改为指向工厂类:

entry_points={ "spacy_factories": ["snek = snek:SnekFactory"] }

配置中即可增加设置:

[components.snek] factory = "snek" snek_style = "basic"

工厂还可以实现to_disk/from_disk做序列化,或实现update让组件可训练。组件暴露from_disk并被包含在 pipeline 中时,加载 pipeline 会调用它;用nlp.to_disk保存且组件暴露to_disk时则会调用后者——这样可以把自定义数据随 pipeline 包一起分发。

用 spacy_languages 注册自定义语言类

如果要为自己的 pipeline 实现一个语言类但不想改 spaCy 源码,在包中实现自定义语言子类(必须定义lang语言代码和Defaults语言数据):

from spacy.language import Language class SnekDefaults(Language.Defaults): stop_words = set(["sss", "hiss"]) class SnekLanguage(Language): lang = "snk" Defaults = SnekDefaults

setup.pyentry_points中追加spacy_languages组,把语言代码映射到子类:

setup( name="snek", entry_points={ "spacy_factories": ["snek = snek:SnekFactory"], "spacy_languages": ["snk = snek:SnekLanguage"] } )

安装后,spaCy 加载snk语言时会经由该 entry point 解析到SnekLanguage(语言类查找逻辑见 spacy/util.py,其中明确会处理经由 entry point 提供的自定义子类)。对你训练的 pipeline 包尤其重要:其config.cfg可以写lang = "snk",而不会因该语言不在核心库中而报错。

验证方式:安装包后执行spacy.blank("snk"),确认返回对象的lang"snk"且由SnekLanguage实例化即可。

替代路径:不打包时用 registry 装饰器注册语言类

如果不想把代码拆成独立包,文档给出了另一条路径:用@spacy.registry.languages装饰器注册自定义语言类并赋一个字符串名,之后可以直接spacy.blank("custom_en"),也能在训练配置中引用:

import spacy from spacy.lang.en import English class CustomEnglishDefaults(English.Defaults): stop_words = set(["custom", "stop"]) @spacy.registry.languages("custom_en") class CustomEnglish(English): lang = "custom_en" Defaults = CustomEnglishDefaults # This now works! nlp = spacy.blank("custom_en")

训练配置中:

[nlp] lang = "custom_en"

注意这条路径与 entry point 的差别:注册函数必须在训练时可用,可以用--code参数加载包含注册代码的 Python 文件:

python -m spacy train config.cfg --code code.py

加载时的限制与排查

  • 包必须已安装:entry point 只在包暴露入口点并安装到当前环境后生效,只放在源码目录里不会自动被发现。
  • 装饰器必须在加载 pipeline 前执行:加载含自定义组件的 pipeline 时,@Language.component/@Language.factory装饰器必须先于 pipeline 加载执行,否则 spaCy 无法把"my_component"这类字符串名解析回函数。entry point 机制通过安装后的自动导入保证了这一点;没有 entry point 时就需要手动 import 模块再加载。
  • spacy_displacy_colors的 key 名随意:入口点名不影响行为(文档示例用colors),组内定义的「标签 → 颜色」字典会被合并进预定义颜色,也可覆盖已有值。
  • 配置中的组件依赖包config.cfg引用了你的自定义组件后,使用该配置的每个环境都必须安装对应包,否则加载失败。

完成注册后,文档建议把训练好的 pipeline 用spacy package命令封装成 Python 包再分发,这样下游环境安装模型包时即可通过 entry points 自动解析其中的自定义组件与语言类。

【免费下载链接】spaCy💫 Industrial-strength Natural Language Processing (NLP) in Python项目地址: https://gitcode.com/GitHub_Trending/sp/spaCy

创作声明:本文部分内容由AI辅助生成(AIGC),仅供参考

版权声明: 本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若内容造成侵权/违法违规/事实不符,请联系邮箱:809451989@qq.com进行投诉反馈,一经查实,立即删除!
网站建设 2026/9/12 17:38:54

2026年7月九江市新房价格深度分析报告

一、报告背景与数据说明本报告基于2026年7月九江市新房实际成交案例,结合区域分布、楼盘定位、户型结构与成交价格等维度,对当前九江新房市场进行深度剖析。报告数据来源于公开成交备案信息与典型楼盘样本,旨在为购房者、投资者及行业研究者提…

作者头像 李华
网站建设 2026/9/12 17:38:36

微信小程序消息怎么通过API发送?个人微信API接口功能应用

小程序卡片消息是聊天和 App 服务之间的桥——用户在对话里点一下卡片,直接落到小程序的具体页面。它的工程要点在"卡片参数怎么拼"和"落地页怎么接"。 一、小程序卡片的结构 发送小程序消息的参数组合比链接消息复杂:小程序的 ap…

作者头像 李华
网站建设 2026/9/12 17:38:27

SpringBoot汽车销售管理系统:实时库存与电子合同实践

1. 项目背景与核心价值汽车销售行业正经历从传统线下模式向数字化管理的转型浪潮。去年我参与改造某4S店管理系统时,亲眼目睹了手工台账导致的库存混乱——销售员A刚签下一台宝马3系的订单,销售员B却在同一时间把同一辆车卖给了另一位客户。这种尴尬局面…

作者头像 李华