本文主要介绍了Rasa中相关Tokenizer的具体实现,包括默认Tokenizer和第三方Tokenizer。前者包括JiebaTokenizer、MitieTokenizer、SpacyTokenizer和WhitespaceTokenizer,后者包括BertTokenizer和AnotherWhitespaceTokenizer。

一.JiebaTokenizer

  JiebaTokenizer类整体代码结构,如下所示:

  加载自定义字典代码,如下所示[3]:

@staticmethod
def _load_custom_dictionary(path: Text) -> None:
    """Load all the custom dictionaries stored in the path.  # 加载存储在路径中的所有自定义字典。
    More information about the dictionaries file format can be found in the documentation of jieba. https://github.com/fxsjy/jieba#load-dictionary
    """
    print("JiebaTokenizer._load_custom_dictionary()")
    import jieba

    jieba_userdicts = glob.glob(f"{path}/*")  # 获取路径下的所有文件。
    for jieba_userdict in jieba_userdicts:  # 遍历所有文件。
        logger.info(f"Loading Jieba User Dictionary at {jieba_userdict}")  # 加载结巴用户字典。
        jieba.load_userdict(jieba_userdict)  # 加载用户字典。

  实现分词的代码为tokenize()方法,如下所示:

def tokenize(self, message: Message, attribute: Text) -> List[Token]:
    """Tokenizes the text of the provided attribute of the incoming message."""  # 对传入消息的提供属性的文本进行tokenize。
    print("JiebaTokenizer.tokenize()")

    import jieba

    text = message.get(attribute)  # 获取消息的属性

    tokenized = jieba.tokenize(text)  # 对文本进行标记化
    tokens = [Token(word, start) for (word, start, end) in tokenized]  # 生成标记

    return self._apply_token_pattern(tokens)

  self._apply_token_pattern(tokens)数据类型为List[Token]。Token的数据类型为:

class Token:
    # 由将单个消息拆分为多个Token的Tokenizers使用
    def __init__(
        self,
        text: Text,
        start: int,
        end: Optional[int] = None,
        data: Optional[Dict[Text, Any]] = None,
        lemma: Optional[Text] = None,
    ) -> None:
        """创建一个Token
        Args:
            text: The token text.  # token文本
            start: The start index of the token within the entire message.  # token在整个消息中的起始索引
            end: The end index of the token within the entire message.  # token在整个消息中的结束索引
            data: Additional token data.  # 附加的token数据
            lemma: An optional lemmatized version of the token text.  # token文本的可选词形还原版本
        """
        self.text = text
        self.start = start
        self.end = end if end else start + len(text)
        self.data = data if data else {}
        self.lemma = lemma or text

  特别说明:JiebaTokenizer组件的is_trainable=True。

二.MitieTokenizer

  MitieTokenizer类整体代码结构,如下所示:

  核心代码tokenize()方法代码,如下所示:

def tokenize(self, message: Message, attribute: Text) -> List[Token]:
    """Tokenizes the text of the provided attribute of the incoming message."""  # 对传入消息的提供属性的文本进行tokenize
    import mitie

    text = message.get(attribute)

    encoded_sentence = text.encode(DEFAULT_ENCODING)
    tokenized = mitie.tokenize_with_offsets(encoded_sentence)
    tokens = [
        self._token_from_offset(token, offset, encoded_sentence)
        for token, offset in tokenized
    ]

    return self._apply_token_pattern(tokens)

  特别说明:mitie库在Windows上安装可能麻烦些。MitieTokenizer组件的is_trainable=False。

三.SpacyTokenizer

  首先安装Spacy类库和模型[4][5],如下所示:

pip3 install -U spacy
python3 -m spacy download zh_core_web_sm

  SpacyTokenizer类整体代码结构,如下所示:

  核心代码tokenize()方法代码,如下所示:

def tokenize(self, message: Message, attribute: Text) -> List[Token]:
    """Tokenizes the text of the provided attribute of the incoming message."""  # 对传入消息的提供属性的文本进行tokenize
    doc = self._get_doc(message, attribute)  # doc是一个Doc对象
    if not doc:
        return []

    tokens = [
        Token(
            t.text, t.idx, lemma=t.lemma_, data={POS_TAG_KEY: self._tag_of_token(t)}
        )
        for t in doc
        if t.text and t.text.strip()
    ]

  特别说明:SpacyTokenizer组件的is_trainable=False。即SpacyTokenizer只有运行组件run_SpacyTokenizer0,没有训练组件。如下所示:

四.WhitespaceTokenizer

  WhitespaceTokenizer主要是针对英文的,不可用于中文。WhitespaceTokenizer类整体代码结构,如下所示:

  其中,predict_schema和train_schema,如下所示:

  rasa shell nlu --debug结果,如下所示:

  特别说明:WhitespaceTokenizer组件的is_trainable=False。

五.BertTokenizer

  rasa shell nlu --debug结果,如下所示:

  BertTokenizer代码具体实现,如下所示:
"""
https://github.com/daiyizheng/rasa-chinese-plus/blob/master/rasa_chinese_plus/nlu/tokenizers/bert_tokenizer.py
"""
from typing import List, Text, Dict, Any
from rasa.engine.recipes.default_recipe import DefaultV1Recipe
from rasa.shared.nlu.training_data.message import Message
from transformers import AutoTokenizer
from rasa.nlu.tokenizers.tokenizer import Tokenizer, Token

@DefaultV1Recipe.register(
    DefaultV1Recipe.ComponentType.MESSAGE_TOKENIZER, is_trainable=False
)
class BertTokenizer(Tokenizer):
    def __init__(self, config: Dict[Text, Any] = None) -> None:
        """
        :param config: {"pretrained_model_name_or_path":"", "cache_dir":"", "use_fast":""}
        """
        super().__init__(config)
        self.tokenizer = AutoTokenizer.from_pretrained(
            config["pretrained_model_name_or_path"],  # 指定预训练模型的名称或路径
            cache_dir=config.get("cache_dir"),  # 指定缓存目录
            use_fast=True if config.get("use_fast") else False  # 是否使用快速模式
        )

    @classmethod
    def required_packages(cls) -> List[Text]:
        return ["transformers"]  # 指定依赖的包

    @staticmethod
    def get_default_config() -> Dict[Text, Any]:
        """The component's default config (see parent class for full docstring)."""
        return {
            # Flag to check whether to split intents
            "intent_tokenization_flag": False,
            # Symbol on which intent should be split
            "intent_split_symbol": "_",
            # Regular expression to detect tokens
            "token_pattern": None,
            # Symbol on which prefix should be split
            "prefix_separator_symbol": None,
        }

    def tokenize(self, message: Message, attribute: Text) -> List[Token]:
        text = message.get(attribute)  # 获取文本
        encoded_input = self.tokenizer(text, return_offsets_mapping=True, add_special_tokens=False)  # 编码文本
        token_position_pair = zip(encoded_input.tokens(), encoded_input["offset_mapping"])  # 将编码后的文本和偏移量映射成一个元组
        tokens = [Token(text=token_text, start=position[0], end=position[1]) for token_text, position in token_position_pair]  # 将元组转换成Token对象

        return self._apply_token_pattern(tokens)

  特别说明:BertTokenizer组件的is_trainable=False。

六.AnotherWhitespaceTokenizer

  AnotherWhitespaceTokenizer代码具体实现,如下所示:

from __future__ import annotations
from typing import Any, Dict, List, Optional, Text

from rasa.engine.graph import ExecutionContext
from rasa.engine.recipes.default_recipe import DefaultV1Recipe
from rasa.engine.storage.resource import Resource
from rasa.engine.storage.storage import ModelStorage
from rasa.nlu.tokenizers.tokenizer import Token, Tokenizer
from rasa.shared.nlu.training_data.message import Message

@DefaultV1Recipe.register(
    DefaultV1Recipe.ComponentType.MESSAGE_TOKENIZER, is_trainable=False
)
class AnotherWhitespaceTokenizer(Tokenizer):
    """Creates features for entity extraction."""
    @staticmethod
    def not_supported_languages() -> Optional[List[Text]]:
        """The languages that are not supported."""
        return ["zh", "ja", "th"]

    @staticmethod
    def get_default_config() -> Dict[Text, Any]:
        """Returns the component's default config."""
        return {
            # This *must* be added due to the parent class.
            "intent_tokenization_flag": False,
            # This *must* be added due to the parent class.
            "intent_split_symbol": "_",
            # This is a, somewhat silly, config that we pass
            "only_alphanum": True,
        }

    def __init__(self, config: Dict[Text, Any]) -> None:
        """Initialize the tokenizer."""
        super().__init__(config)
        self.only_alphanum = config["only_alphanum"]

    def parse_string(self, s):
        if self.only_alphanum:
            return "".join([c for c in s if ((c == " ") or str.isalnum(c))])
        return s

    @classmethod
    def create(
        cls,
        config: Dict[Text, Any],
        model_storage: ModelStorage,
        resource: Resource,
        execution_context: ExecutionContext,
    ) -> AnotherWhitespaceTokenizer:
        return cls(config)

    def tokenize(self, message: Message, attribute: Text) -> List[Token]:
        text = self.parse_string(message.get(attribute))
        words = [w for w in text.split(" ") if w]

        # if we removed everything like smiles `:)`, use the whole text as 1 token
        if not words:
            words = [text]

        # the ._convert_words_to_tokens() method is from the parent class.
        tokens = self._convert_words_to_tokens(words, text)

        return self._apply_token_pattern(tokens)

  特别说明:AnotherWhitespaceTokenizer组件的is_trainable=False。

参考文献:

[1]自定义Graph Component:1.1-JiebaTokenizer具体实现:https://mp.weixin.qq.com/s/awGiGn3uJaNcvJBpk4okCA

[2]https://github.com/RasaHQ/rasa

[3]https://github.com/fxsjy/jieba#load-dictionary

[4]spaCy GitHub:https://github.com/explosion/spaCy

[5]spaCy官网:https://spacy.io/

[6]https://github.com/daiyizheng/rasa-chinese-plus/blob/master/rasa_chinese_plus/nlu/tokenizers/bert_tokenizer.py

自定义Graph Component:1.2-其它Tokenizer具体实现的更多相关文章

  1. 自定义组件Component

    定义compa组件 由4个页面构成 compa.js: compa.json: compa.wxml: compa:wxss: 1.compa.json:在json文件进行自定义组件声明 { &quo ...

  2. ionic3.x angular4.x ng4.x 自定义组件component双向绑定之自定义计数器

    本文主要示例在ionic3.x环境下实现一个自定义计数器,实现后最终效果如图: 1.使用命令创建一个component ionic g component CounterInput 类似的命令还有: ...

  3. Yii2.0 高级模版编写使用自定义组件(component)

    翻译自:http://www.yiiframework.com/wiki/760/yii-2-0-write-use-a-custom-component-in-yii2-0-advanced-tem ...

  4. angular custom Element 自定义web component

    angular 自定义web组件: 首先创建一个名为myCustom的组件. 引入app.module: ... import {customComponent} from ' ./myCustom. ...

  5. Magicodes.WeiChat——自定义knockoutjs template、component实现微信自定义菜单

    本人一向比较喜欢折腾,玩了这么久的knockoutjs,总觉得不够劲,于是又开始准备折腾自己了. 最近在完善Magicodes.WeiChat微信开发框架时,发现之前做的自定义菜单这块太不给力了,而各 ...

  6. weex 自定义Component

    扩展iOS的功能 ~  Component 与UI控件相关 ,即通过原生方法创建UI界面,返回给weex 使用 一. 新建 WXComponent 的子类     在子类实现WXComponent 的 ...

  7. springboot +spring security4 自定义手机号码+短信验证码登录

    spring security 默认登录方式都是用户名+密码登录,项目中使用手机+ 短信验证码登录, 没办法,只能实现修改: 需要修改的地方: 1 .自定义 AuthenticationProvide ...

  8. Spring Security验证流程剖析及自定义验证方法

    Spring Security的本质 Spring Security本质上是一连串的Filter, 然后又以一个独立的Filter的形式插入到Filter Chain里,其名为FilterChainP ...

  9. zabbix监控之自定义item

    zabbix安装完成后,当需要使用自定义脚本构建自定义item必须注意以下几点: 1.首先使用zabbix_get手动在zabbix-server服务端获取监控的默认的item值,如下: [root@ ...

  10. Cacti自定义脚本,监测Docker信息(Script/Command方式)

    一 环境背景 监控主机A:192.168.24.231:被监控主机B:192.168.24.233 A/B主机,通过公私钥建立ssh连接 [操作B主机时不需要输入密码,详见笔记:http://app. ...

随机推荐

  1. 层叠样式表(CSS)3

    三.层叠样式表属性 1.文字属性 font-size:字体大小 line-height:行高 font-family:字体 font-weight:粗细程度 .......等等很多,可自行学习 2.文 ...

  2. python数据处理:获取Dataframe中的一列或一行

    解决方案 df['w'] #选择表格中的'w'列,使用类字典属性,返回的是Series类型 df.w #选择表格中的'w'列,使用点属性,返回的是Series类型 df[['w']] #选择表格中的' ...

  3. ois七层模型与数据封装过程

    一,ois七层模型 一,ois七层模型1 为什么要分层2 七层模型3 七层总结二,协议,端口,的作用2.1协议作用2.2tcp/udp的区别2.3ARP 协议的作用2.4客户端与服务端的作用2.5ic ...

  4. 如何提升 API-First 设计流程

    一个 API-First 设计应该具有可复用性.互操作性.可修改性.用户友好性.安全性.高效性.务实性,并且重要的是,与组织目标保持一致.这些基本特征将确保 API 能够有效地为 API- First ...

  5. 银河麒麟等 Linux系统 安装 .net 5,net 6及更高版本的方法

    最近项目上用到 银河麒麟的操作系统,需要搭建 .net 跨平台方案.一开始使用各种命令都安装不上,很多提示命令找不到,或者下载包时候网络无法下载. 网上教程很多,但没有一个是成功的,多数使用 apt ...

  6. 学好Elasticsearch系列-聚合查询

    本文已收录至Github,推荐阅读 Java随想录 微信公众号:Java随想录 先看后赞,养成习惯. 点赞收藏,人生辉煌. 目录 概念 doc values 和 fielddata multi-fie ...

  7. 让 GPT-4 来修复 Golang “数据竞争”问题 - 每天5分钟玩转 GPT 编程系列(6)

    目录 1. Golang 中的"数据竞争" 2. GoPool 中的数据竞争问题 3. 让 GPT-4 来修复数据竞争问题 3.1 和 GPT-4 的第一轮沟通 3.2 和 GPT ...

  8. 使用 OpenTelemetry 构建 .NET 应用可观测性(1):什么是可观测性

    目录 什么是系统的可观测性(Observability) 为什么需要软件系统需要可观测性 可观测性的三大支柱 日志(Logging) 指标(Metrics) 分布式追踪(Distributed Tra ...

  9. 这才叫 API 接口设计!

    API 接口设计 Token 设计 Token 是服务端生成的一串字符串,以作客户端进行请求的一个令牌,当第一次登录后,服务器生成一个 Token 便将此 Token 返回给客户端,以后客户端只需带上 ...

  10. 快速搭建SpringBoot3.x项目

    写在前面 上一小节中我们从0到1 使用Vite搭建了一个Vue3项目,并集成了Element Plus 实现了一个简单的增删改查页面. 这一篇中我们将使用IDEA快速搭建一个SpringBoot3.x ...