senses-chat / rasa-paddlenlp

Rasa通过PaddleNLP提供中文支持
MIT License
32 stars 13 forks source link

期待Ernie和hanlp的支持 #3

Open bigbrother666sh opened 2 years ago

bigbrother666sh commented 2 years ago

哥们,这几天很受你这个项目的启发,之前苦于寻找支持中文的对话意图识别方案,到你这算是解决问题了!

最近百度飞桨新发布了了Ernie3.0 (https://github.com/PaddlePaddle/PaddleNLP

但我试了下,基于Ernie3.0做tokenizer的机制发生了很大变化,需要升级到Paddlenlp 2.3,(或者替换/paddlenlp/transformers 下面的tokenizer_utils.py,并增加 tokenizer_utils_base.py文件也行)。

然而貌似新的tokenizer跟rasa_paddlenlp目前的机制有点冲突(应该在encoded_inputs那块,但我没太看懂你这部分代码)。

总之期待老兄什么时候有空可以更新一版支持ernie3.0的,看是不是效果能有很大提升。

另外,建议也看下hanlp(https://github.com/hankcs/HanLP),感觉这玩意应该效果比ernie3.0更好

lhr0909 commented 2 years ago

@bigbrother666sh 感谢你对项目的支持!我这边可以给出一些方向,我觉得目前只要是PaddleNLP transformers能支持的模型,应该是可以直接套用的。

具体套用的方法:

  1. 首先需要配置好ERNIE相关的pre-processor和post-processor等相关支持,这部分应该和其他模型非常类似,你可以参考一下并在这里配置好
  2. 把对应的max_sequence_length添加到这里

目前tokenizer不清楚具体的机制不同,如果你可以指出来的话,我可以看看到底需不需要修改。目前我理解的话是不需要修改,直接把pretrained模型的输出使用就可以了。

因为我们团队人比较少,强烈欢迎PR!我最近也有点时间可以一起看看这个事情。

lhr0909 commented 2 years ago

另外HanLP的话,我一开始以为不是商用的,所以就没有深入研究。不过感觉应该是可以套用HanLP的word2vec或者glove向量来做DIETClassifier的embedding。

bigbrother666sh commented 2 years ago

@bigbrother666sh 感谢你对项目的支持!我这边可以给出一些方向,我觉得目前只要是PaddleNLP transformers能支持的模型,应该是可以直接套用的。

具体套用的方法:

  1. 首先需要配置好ERNIE相关的pre-processor和post-processor等相关支持,这部分应该和其他模型非常类似,你可以参考一下并在这里配置好
  2. 把对应的max_sequence_length添加到这里

目前tokenizer不清楚具体的机制不同,如果你可以指出来的话,我可以看看到底需不需要修改。目前我理解的话是不需要修改,直接把pretrained模型的输出使用就可以了。

因为我们团队人比较少,强烈欢迎PR!我最近也有点时间可以一起看看这个事情。

hi 我按照你的指导,并替换了适配Ernie3的tokenizer_utils.py 和 tokenizer_utils_base.py,但是启动报错如下:

Traceback (most recent call last):
  File "/Users/zeming/opt/anaconda3/lib/python3.8/site-packages/rasa/engine/graph.py", line 458, in __call__
    output = self._fn(self._component, **run_kwargs)
  File "/Users/zeming/opt/anaconda3/lib/python3.8/site-packages/rasa/nlu/tokenizers/tokenizer.py", line 133, in process_training_data
    tokens = self.tokenize(example, attribute)
  File "/Users/zeming/PycharmProjects/rasa-paddlenlp/rasa_paddlenlp/nlu/paddlenlp_tokenizer.py", line 122, in tokenize
    encoded_inputs = self.tokenizer.batch_encode([[text, text]], stride=1, return_token_type_ids=False, return_length=False, return_special_tokens_mask=True)
  File "/Users/zeming/opt/anaconda3/lib/python3.8/site-packages/paddlenlp/transformers/tokenizer_utils_base.py", line 2409, in batch_encode
    return self._batch_encode_plus(
  File "/Users/zeming/opt/anaconda3/lib/python3.8/site-packages/paddlenlp/transformers/tokenizer_utils.py", line 1112, in _batch_encode_plus
    batch_outputs = self._batch_prepare_for_model(
  File "/Users/zeming/opt/anaconda3/lib/python3.8/site-packages/paddlenlp/transformers/tokenizer_utils.py", line 1179, in _batch_prepare_for_model
    max_len_for_pair = max_length - len(first_ids)
TypeError: unsupported operand type(s) for -: 'NoneType' and 'int'

通过追踪上述报错信息,我发现是因为

encoded_inputs = self.tokenizer.batch_encode([[text, text]], stride=1, return_token_type_ids=False, return_length=False, return_special_tokens_mask=True)

这句没有给出 max_length 这个参数所致,新的paddlenlp tokenizer_utils_base.py文件是必须这个参数的,且它也没有给出这个参数的默认值。

所以我的结论是:只要在这里给出合适的max_length就能够成功启动Ernie3(大概率也能适配paddlenlp 2.3了),但我不知道这里的max_length应该给什么值。

lhr0909 commented 2 years ago

没记错的话 paddleNLP的库里面有定义max_length,可以试一下用512。

bigbrother666sh commented 2 years ago

非常遗憾,在给定max_length=512时,上面的问题解决了,但是报了新的错误……

Traceback (most recent call last):
  File "/Users/zeming/opt/anaconda3/lib/python3.8/site-packages/rasa/engine/graph.py", line 458, in __call__
    output = self._fn(self._component, **run_kwargs)
  File "/Users/zeming/opt/anaconda3/lib/python3.8/site-packages/rasa/nlu/tokenizers/tokenizer.py", line 133, in process_training_data
    tokens = self.tokenize(example, attribute)
  File "/Users/zeming/PycharmProjects/rasa-paddlenlp/rasa_paddlenlp/nlu/paddlenlp_tokenizer.py", line 126, in tokenize
    e = encoded_inputs[0]
  File "/Users/zeming/opt/anaconda3/lib/python3.8/site-packages/paddlenlp/transformers/tokenizer_utils_base.py", line 249, in __getitem__
    raise KeyError(
KeyError: 'Indexing with integers is not available when using tokenizer.__call__() with return_dict=True. Please set return_dict to False to use integer indexing.'
bigbrother666sh commented 2 years ago

hi,很高兴的说一句,上面的问题可以简单的通过更改paddlenlp_tokenizer.py 的 126行输入参数解决,

encoded_inputs = self.tokenizer.batch_encode([[text, text]], stride=1, return_token_type_ids=False, return_length=False,
                                                     return_dict=False, return_special_tokens_mask=True, max_length=512)

这样的话,就可以完美兼容paddlenlp 2.3了,在2.3下可以调起bert模型

然后,把130行更改为 if e['special_tokens_mask'][0] == 1:

亦可以成功调起 ernie3.0进行训练

bigbrother666sh commented 2 years ago

但是 if e['special_tokens_mask'][0] == 1: 这样改之后,bert就用不了了……

bigbrother666sh commented 2 years ago

其实我不太确认 if e['special_tokens_mask'][0] == 1: 这样改是不是妥当, 主要是不把 if e['special_tokens_mask'][i] 中的i改为0,运行到这一步就会 out of range,改为i-1也是一样的。所以我推断应该是paddlenlp2.3这里机制改了,只返回1个值…… 但这只是推断,需要更加详细的代码分析来验证

而从实际效果看,用这种改动调起ernie-3.0-base-zh确实比bert有提高,也好于官方自带的jieba方案

ChiayenGu commented 10 months ago

其实我不太确认 if e['special_tokens_mask'][0] == 1: 这样改是不是妥当, 主要是不把 if e['special_tokens_mask'][i] 中的i改为0,运行到这一步就会 out of range,改为i-1也是一样的。所以我推断应该是paddlenlp2.3这里机制改了,只返回1个值...... 但这只是推断,需要更加详细的代码分析来验证

而从实际效果看,用这种改动调起ernie-3.0-base-zh确实比bert有提高,也好于官方自带的jieba方案

请问您现在解决了吗?

bigbrother666sh commented 10 months ago

https://github.com/bigbrother666sh/rasa-paddlenlp-ernie

看这里吧