Files
wehub-resource-sync 2aaeece67c
Codestyle Check / Lint (push) Has been cancelled
Codestyle Check / Check bypass (push) Has been cancelled
Pipelines-Test / Pipelines-Test (push) Has been cancelled
chore: import upstream snapshot with attribution
2026-07-13 13:37:14 +08:00

204 lines
8.6 KiB
Python

# Copyright (c) 2022 PaddlePaddle Authors. All Rights Reserved.
#
# Licensed under the Apache License, Version 2.0 (the "License");
# you may not use this file except in compliance with the License.
# You may obtain a copy of the License at
#
# http://www.apache.org/licenses/LICENSE-2.0
#
# Unless required by applicable law or agreed to in writing, software
# distributed under the License is distributed on an "AS IS" BASIS,
# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
# See the License for the specific language governing permissions and
# limitations under the License.
import os
import unittest
from tempfile import TemporaryDirectory
import paddle
from parameterized import parameterized
from paddlenlp.prompt import (
AutoTemplate,
PromptModelForSequenceClassification,
SoftVerbalizer,
)
from paddlenlp.taskflow.text_classification import TextClassificationTask
from paddlenlp.transformers import (
AutoModelForMaskedLM,
AutoModelForSequenceClassification,
AutoTokenizer,
)
class TestTextClassificationTask(unittest.TestCase):
@classmethod
def setUpClass(cls):
cls.temp_dir = TemporaryDirectory()
tokenizer = AutoTokenizer.from_pretrained("__internal_testing__/ernie")
# finetune (dynamic)
cls.finetune_dygraph_model_path = os.path.join(cls.temp_dir.name, "finetune_dygraph")
finetune_dygraph_model = AutoModelForSequenceClassification.from_pretrained(
"__internal_testing__/ernie", num_classes=2
)
finetune_dygraph_model.save_pretrained(cls.finetune_dygraph_model_path)
tokenizer.save_pretrained(cls.finetune_dygraph_model_path)
# finetune (static)
cls.finetune_static_model_path = os.path.join(cls.temp_dir.name, "finetune_static")
input_spec = [
paddle.static.InputSpec(shape=[None, None], dtype="int64", name="input_ids"),
paddle.static.InputSpec(shape=[None, None], dtype="int64", name="token_type_ids"),
]
finetune_static_model = paddle.jit.to_static(finetune_dygraph_model, input_spec=input_spec)
paddle.jit.save(finetune_static_model, os.path.join(cls.finetune_static_model_path, "model"))
tokenizer.save_pretrained(cls.finetune_static_model_path)
# prompt (dynamic)
cls.prompt_dygraph_model_path = os.path.join(cls.temp_dir.name, "prompt_dygraph")
prompt_plm_model = AutoModelForMaskedLM.from_pretrained("__internal_testing__/ernie", num_classes=2)
template = AutoTemplate.create_from("测试:", tokenizer, 16, model=prompt_plm_model)
label_words = {"negative": ["负面"], "positive": ["正面"]}
verbalizer = SoftVerbalizer(label_words, tokenizer, prompt_plm_model)
prompt_dygraph_model = PromptModelForSequenceClassification(prompt_plm_model, template, verbalizer)
template.save(cls.prompt_dygraph_model_path)
verbalizer.save(cls.prompt_dygraph_model_path)
tokenizer.save_pretrained(cls.prompt_dygraph_model_path)
prompt_plm_model.save_pretrained(os.path.join(cls.prompt_dygraph_model_path, "plm"))
state_dict = prompt_dygraph_model.state_dict()
paddle.save(state_dict, os.path.join(cls.prompt_dygraph_model_path, "model_state.pdparams"))
# prompt (static)
cls.prompt_static_model_path = os.path.join(cls.temp_dir.name, "prompt_static")
input_spec = prompt_dygraph_model.get_input_spec()
prompt_static_model = paddle.jit.to_static(prompt_dygraph_model, input_spec=input_spec)
template.save(cls.prompt_static_model_path)
verbalizer.save(cls.prompt_static_model_path)
tokenizer.save_pretrained(cls.prompt_static_model_path)
prompt_plm_model.save_pretrained(os.path.join(cls.prompt_static_model_path, "plm"))
paddle.jit.save(prompt_static_model, os.path.join(cls.prompt_static_model_path, "model"))
@classmethod
def tearDownClass(cls):
cls.temp_dir.cleanup()
@parameterized.expand(
[
(1, "multi_class", "finetune"),
# (1, "multi_class", "prompt"), # TODO (paddle 2.5.1 breaks this test)
(1, "multi_label", "finetune"),
# (1, "multi_label", "prompt"), # TODO (paddle 2.5.1 breaks this test)
]
)
def test_classification_task(self, batch_size, problem_type, model):
# input_text is a tuple to simulate the args passed from Taskflow to TextClassificationTask
input_text = (["百度", "深度学习框架", "飞桨", "PaddleNLP"],)
id2label = {
0: "negative",
1: "positive",
}
if model == "finetune":
dygraph_model_path = self.finetune_dygraph_model_path
static_model_path = self.finetune_static_model_path
else:
dygraph_model_path = self.prompt_dygraph_model_path
static_model_path = self.prompt_static_model_path
dygraph_taskflow = TextClassificationTask(
model=model,
task="text_classification",
task_path=dygraph_model_path,
id2label=id2label,
batch_size=batch_size,
device_id=0,
problem_type=problem_type,
)
dygraph_results = dygraph_taskflow(input_text)
self.assertEqual(len(dygraph_results), len(input_text[0]))
static_taskflow = TextClassificationTask(
model=model,
task="text_classification",
is_static_model=True,
task_path=static_model_path,
id2label=id2label,
batch_size=batch_size,
device_id=0,
problem_type=problem_type,
)
static_results = static_taskflow(input_text)
self.assertEqual(len(static_results), len(input_text[0]))
for dygraph_result, static_result in zip(dygraph_results, static_results):
for dygraph_pred, static_pred in zip(dygraph_result["predictions"], static_result["predictions"]):
self.assertEqual(dygraph_pred["label"], static_pred["label"])
self.assertAlmostEqual(dygraph_pred["score"], static_pred["score"], delta=1e-6)
# if multi_label, all predictions should be greater than the threshold
if model == "multi_label":
self.assertGreater(dygraph_pred["score"], dygraph_taskflow.multilabel_threshold)
# @unittest.skip("numerical error")
# @parameterized.expand(
# [
# (1, "multi_class", "finetune"),
# (1, "multi_class", "prompt"),
# (1, "multi_label", "finetune"),
# (1, "multi_label", "prompt"),
# ]
# )
# def test_taskflow_task(self, batch_size, problem_type, mode):
# input_text = ["百度", "深度学习框架", "飞桨", "PaddleNLP"]
# id2label = {
# 0: "negative",
# 1: "positive",
# }
# if mode == "finetune":
# dygraph_model_path = self.finetune_dygraph_model_path
# static_model_path = self.finetune_static_model_path
# else:
# dygraph_model_path = self.prompt_dygraph_model_path
# static_model_path = self.prompt_static_model_path
# dygraph_taskflow = Taskflow(
# mode=mode,
# task="text_classification",
# task_path=dygraph_model_path,
# id2label=id2label,
# batch_size=batch_size,
# device_id=0,
# problem_type=problem_type,
# )
# dygraph_results = dygraph_taskflow(input_text)
# self.assertEqual(len(dygraph_results), len(input_text))
# static_taskflow = Taskflow(
# mode=mode,
# task="text_classification",
# is_static_model=True,
# task_path=static_model_path,
# id2label=id2label,
# batch_size=batch_size,
# device_id=0,
# problem_type=problem_type,
# )
# static_results = static_taskflow(input_text)
# self.assertEqual(len(static_results), len(input_text))
# for dygraph_result, static_result in zip(dygraph_results, static_results):
# for dygraph_pred, static_pred in zip(dygraph_result["predictions"], static_result["predictions"]):
# self.assertEqual(dygraph_pred["label"], static_pred["label"])
# self.assertAlmostEqual(dygraph_pred["score"], static_pred["score"], delta=1e-6)
# # if multi_label, all predictions should be greater than the threshold
# if mode == "multi_label":
# self.assertGreater(dygraph_pred["score"], dygraph_taskflow.task_instance.multilabel_threshold)