基于基础模型BERT与大语言模型ChatGLM3-6B实现文本分类、信息抽取、文本匹配等任务

前言

在实现文本分类、信息抽取、文本匹配等任务时,可以采用两种主要的方法。首先,可以对一些基础模型进行微调训练,以适应特定任务的需求。这种方法通常需要标注数据,通过调整模型参数来提高其在特定任务上的表现。

其次,基于大模型(如预训练的语言模型)进行任务实现也是一种有效的方法。大模型通常在大规模数据上训练,具备较强的泛化能力和理解能力,可以通过少量的示例进行少量学习(few-shot learning)或零样本学习(zero-shot learning),从而快速适应新的任务。

这里使用基础模型与大语言模型作为对比,实现文本分类、信息抽取、文本匹配等任务,侧重点在于大模型的实现。基础模型选择BERT,大模型选择ChatGLM3-6B。

它们之间的使用存在一定区别,具体区别如下:

BERT:通常需要在特定任务上进行微调,以适应具体应用。

大模型:大模型可以通过提示(prompt)进行零样本或少量样本学习,能够在没有微调的情况下直接用于多种任务。

基础模型BERT:文本分类

因为使用BERT模型实现特定任务,通常需要基于模型进行微调训练,这里仅仅使用Bert模型实现文本分类任务为例说明。

加载模型

导入微调训练的库与加载BERT分词器、BERT模型

# 导入必要的库
import torch  # PyTorch库,用于深度学习模型的构建和训练
from sklearn.model_selection import train_test_split  # 从sklearn库导入用于数据集划分的函数
from transformers import BertTokenizer, BertForSequenceClassification  # 从transformers库导入BERT分词器和分类模型
from transformers import Trainer, TrainingArguments  # 导入Trainer类和训练参数设置类
from datasets import load_dataset, Dataset  # 导入用于加载数据集的函数和Dataset类

# 加载BERT分词器
# 'bert-base-chinese'是预训练的中文BERT模型
tokenizer = BertTokenizer.from_pretrained('bert-base-chinese')

# 加载BERT模型用于序列分类
# num_labels=2表示这是一个二分类任务(例如正面和负面情感分类)
model = BertForSequenceClassification.from_pretrained('bert-base-chinese', num_labels=2)

数据准备

这里准备2类小说相关的数据,2类数据各20条,前20条属于爱情小说,后20条属于科幻小说,假设微调训练数据如下

# 数据准备
data = {
    'text': [
        "在乡村小镇,两个青梅竹马的朋友因误会而分开,多年后重逢,重新点燃了爱情的火花。",
        "一位年轻女孩在城市中追逐自己的梦想,却意外邂逅了一个温暖的灵魂,改变了她的人生轨迹。",
        "在异国他乡,一位游客与当地艺术家展开了一段浪漫的爱情故事,探索文化与心灵的碰撞。",
        "一位成功的职场女性在事业巅峰时,遇见了一位温柔的男子,开启了一段意想不到的爱情旅程。",
        "通过一封信,一个孤独的女孩与一个神秘的男孩建立了深厚的情感,最终决定相见。",
        "两个性格迥异的人在一次音乐节上相遇,彼此吸引,却因生活的压力而面临选择。",
        "一位年轻的作家在创作过程中,遇到了自己的灵感来源,展开了一段充满激情的爱情。",
        "在一次旅行中,两个陌生人因共同的经历而相知相爱,最终决定一起面对未来。",
        "一位失去爱情的女人在朋友的鼓励下,重新开始寻找属于自己的幸福。",
        "在一场婚礼上,伴郎与伴娘意外擦出爱的火花,经历了一系列搞笑与感人的事件。",
        "一位年轻女孩在社交平台上结识了一个男孩,逐渐发展出一段虚拟而真实的爱情。",
        "在一次偶然的相遇中,两个曾经的爱人重新审视彼此的感情,决定给爱情一次机会。",
        "在一座神秘的古堡中,一对恋人经历了时间的考验,最终找到了彼此的真爱。",
        "一位年轻的摄影师在拍摄过程中,邂逅了一位模特,展开了一段浪漫的爱情故事。",
        "两个在同一条街道上生活的邻居,因一场突如其来的暴风雨而走到了一起。",
        "一位刚刚经历分手的女孩,在朋友的帮助下,重新找回了对爱情的信心。",
        "在一场意外中,两个完全不同背景的人相遇,逐渐发现彼此的心灵契合。",
        "一位年轻的音乐家在追求梦想的过程中,遇到了支持她的真爱。",
        "在一个古老的图书馆中,一位书迷与一位收藏家的相遇,开启了一段书香爱情。",
        "一位女孩在寻找失踪父亲的过程中,遇到了一个愿意陪伴她的男孩,爱情悄然绽放。",
        "在一个遥远的星系,一艘宇宙飞船的船员们发现了一种未知的外星生命,改变了他们的命运。",
        "地球因环境恶化而陷入危机,一位年轻的科学家研发出一种新技术,试图拯救人类。",
        "在未来的城市中,人工智能已成为生活的一部分,但一位程序员发现了AI的潜在威胁。",
        "一群探险者在寻找新星球的过程中,意外发现了一个古老文明的遗迹,揭开了历史的秘密。",
        "在一个虚拟现实的世界中,一位玩家为了逃避现实,逐渐迷失在游戏中。",
        "一位年轻的女工程师在开发太空电梯的过程中,遭遇了来自外星势力的挑战。",
        "在未来的社会中,基因编辑技术得到广泛应用,但一场意外导致了不可预知的后果。",
        "一位科学家在实验中意外穿越时空,回到过去,试图改变历史的进程。",
        "地球即将被外星人入侵,一位普通市民挺身而出,成为人类的英雄。",
        "在一个高度发达的科技社会中,一名少女发现了一个关于人类起源的惊天秘密。",
        "一位太空探险家在遥远的星球上发现了人类的未来,但必须做出艰难的选择。",
        "在未来的城市中,一场关于意识上传的实验引发了伦理与道德的争论。",
        "一位年轻的机器人学家创造了一款具有人类情感的机器人,改变了两者的命运。",
        "在一个被遗弃的空间站中,幸存者们必须面对内心的恐惧与外部的威胁。",
        "地球的资源即将耗尽,一位科学家带领团队寻找新星球的希望与挑战。",
        "在一个模拟现实的世界中,人们逐渐失去了对真实生活的感知,陷入了虚幻的迷雾。",
        "一位年轻的宇航员在太空任务中,意外发现了外星文明的存在,面临巨大的选择。",
        "在未来的社会中,人与机器的界限逐渐模糊,一场关于自由意志的斗争展开。",
        "一位天文学家在观察星空时,捕捉到了外星信号,改变了人类的历史。",
        "在一个被科技统治的世界里,一位反叛者努力寻找人类的真实情感与自由。"
    ],
    # 0代表爱情小说,1代表科幻小说
    'label': [0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1]  
}

数据预处理

在数据预处理中,主要是将文本进行tokenizer操作

# 将字典格式的数据转换为Dataset对象
# data应该是一个包含文本和标签的字典,例如 {'text': [...], 'label': [...]}
dataset = Dataset.from_dict(data)

# 将数据集划分为训练集和测试集,test_size=0.2表示20%的数据用于测试
train_test = dataset.train_test_split(test_size=0.2)

# 定义预处理函数,用于对输入文本进行分词和编码
def preprocess_function(examples):
    # 使用tokenizer对文本进行编码,参数说明:
    # truncation=True:如果文本长度超过最大长度,则截断文本
    # padding='max_length':填充到最大长度,确保所有输入长度一致
    # max_length=512:设置最大长度为512(BERT模型的最大输入长度)
    return tokenizer(examples['text'], truncation=True, padding='max_length', max_length=512)

# 对训练集和测试集应用预处理函数,batched=True表示一次处理多个样本以提高效率
tokenized_datasets = train_test.map(preprocess_function, batched=True)

模型训练

设置训练参数、创建训练器并进行模型训练和评估

# 定义训练参数
training_args = TrainingArguments(
    output_dir='./results',  # 模型和结果保存的目录
    evaluation_strategy='epoch',  # 评估策略,这里设置为每个训练周期(epoch)后进行评估
    learning_rate=2e-5,  # 学习率,控制模型更新的步伐
    per_device_train_batch_size=8,  # 每个设备(GPU/CPU)上的训练批次大小
    per_device_eval_batch_size=8,  # 每个设备上的评估批次大小
    num_train_epochs=3,  # 训练的总周期数
    weight_decay=0.01,  # 权重衰减,用于正则化,防止过拟合
    logging_dir='./logs',  # 日志保存目录
    logging_steps=10,  # 每10步记录一次日志
)

# 创建Trainer对象,负责模型的训练和评估
trainer = Trainer(
    model=model,  # 传入要训练的模型
    args=training_args,  # 传入训练参数
    train_dataset=tokenized_datasets['train'],  # 训练数据集
    eval_dataset=tokenized_datasets['test'],  # 评估数据集
)

# 开始训练模型
trainer.train()

# 在评估数据集上评估模型性能
trainer.evaluate()

训练输出说明:
在这里插入图片描述

40/40:表示当前训练过程中已经处理的步骤(steps)数量和总步骤数量。在这里,“40”表示模型在整个训练过程中总共进行了40个步骤。这通常是指在所有训练周期(epochs)中累积的步骤数,而不是每个周期的步骤数。
00:05:表示当前训练已经持续的时间,这里是5秒。
Epoch 5/5:表示当前训练周期是第5个周期,总共进行5个周期的训练。

Epoch:表示训练的周期数。在这里,共进行了5个训练周期(Epoch 1, 2, 3, 4, 5)。
Training Loss:训练损失。每个epoch结束时记录的训练损失值。它反映了模型在训练集上的表现。这里有一些epoch的训练损失值:
	Epoch 1: 没有记录(No log),可能是由于在第一个周期没有完成足够的训练步骤来计算损失。
	Epoch 2: 训练损失为 0.008400
	Epoch 3: 训练损失为 0.003800
	Epoch 4: 训练损失为 0.001600
	Epoch 5: 训练损失为 0.001000
	从这些值可以看出,训练损失随着训练周期的增加而逐渐降低,表明模型在训练集上的表现有所改善。
	
Validation Loss:验证损失。每个epoch结束时记录的验证损失值,表示模型在验证集上的表现。具体值如下:
	Epoch 1: 验证损失为 0.005392
	Epoch 2: 验证损失为 0.002440
	Epoch 3: 验证损失为 0.001267
	Epoch 4: 验证损失为 0.000874
	Epoch 5: 验证损失为 0.000786
	验证损失也显示出逐渐下降的趋势,这通常意味着模型在学习和泛化能力上有所提升。	

计算步骤数

在训练过程中,步骤(steps)的数量通常是通过以下公式计算得出的:

steps = 训练样本数 / 每批次样本数

根据公式可以计算总的steps:

训练样本数 = 32(从40条数据中按80%划分得到)

每批次样本数 = 4(per_device_train_batch_size=4)

因此,训练步骤的数量为:steps = 32 / 4 = 8

这意味着在每个epoch中,模型会进行8个训练步骤。

评估输出说明:
在这里插入图片描述

eval_loss: 模型在验证集上的损失值。较低的损失值通常表示模型在验证集上的表现良好,能够更好地拟合数据。在您的情况下,这个值非常小,表明模型在验证集上具有很好的性能。

eval_runtime: 进行验证评估所花费的总时间,单位为秒。在这个例子中,模型在验证集上评估的时间为0.0917秒。

eval_samples_per_second: 模型在验证集上每秒处理的样本数量。在这个例子中,模型每秒处理约87.252个样本。这是一个重要的性能指标,反映了模型的评估速度。

eval_steps_per_second: 模型在验证集上每秒处理的训练步骤数量。在这个例子中,模型每秒进行约21.813个步骤。这个值通常会比样本处理速度慢,因为每个步骤可能处理多个样本(取决于批次大小)。

epoch: 表示当前评估是在第5个训练周期(epoch)完成后进行的。这与之前的训练输出一致,表明模型在完成所有5个训练周期后进行了验证评估。

保存模型

将经过微调训练的模型保存到本地目录

from transformers import AutoModelForSequenceClassification, AutoTokenizer

# 保存模型的实际路径
model.save_pretrained("./models/my-bert-base-chinese")
# 保存模型的权重和配置文件,同时也保存tokenizer
tokenizer.save_pretrained("./models/my-bert-base-chinese")

加载模型进行推理

from transformers import AutoModelForSequenceClassification, AutoTokenizer
import torch

model_path = "./models/my-bert-base-chinese"
# 加载模型和 tokenizer
model = AutoModelForSequenceClassification.from_pretrained(model_path)
tokenizer = AutoTokenizer.from_pretrained(model_path)

# 将模型设置为评估模式
model.eval()

# 准备输入数据
input_text = "在繁华的都市中,两个年轻人因一次偶然的相遇而相识,随着时间的推移,他们的感情经历了甜蜜与磨难,最终找到了彼此的真爱。"
inputs = tokenizer(input_text, return_tensors="pt")

# 进行推理
with torch.no_grad():  # 在推理时不需要计算梯度
    outputs = model(**inputs)

# 从输出中提取 logits
logits = outputs.logits
# 获取预测类别
predictions = torch.argmax(logits, dim=-1)

# 输出预测结果
print(f"预测类别: {predictions.item()}")

不出意外,将成功预测分类结果,输出结果如下:
在这里插入图片描述

大模型:文本分类

加载模型

加载chatglm3-6b预训练模型和相应的分词器

# 从 transformers 库导入 AutoTokenizer 和 AutoModel,用于加载预训练模型和分词器
from transformers import AutoTokenizer, AutoModel

# 指定模型的路径
model_path = '/root/work/models/chatglm3-6b'
# 从指定路径加载预训练的分词器,设置 trust_remote_code 为 True 以信任远程代码
tokenizer = AutoTokenizer.from_pretrained(model_path, trust_remote_code=True)

# 从指定路径加载预训练的模型,设置 trust_remote_code 为 True 以信任远程代码,并以 8 位模式加载
model = AutoModel.from_pretrained(model_path, trust_remote_code=True, load_in_8bit=True)

# 将模型设置为评估模式,以便在推理时禁用训练特性(如 dropout)
model = model.eval()

数据

定义一些用于文本分类的类别样例测试数据

class_examples = {
    '爱情小说': '在繁华的都市中,两个年轻人因一次偶然的相遇而相识,随着时间的推移,他们的感情经历了甜蜜与磨难,最终找到了彼此的真爱。',
    '科幻小说': '在不远的未来,地球面临着资源枯竭的危机。一位年轻的科学家带领团队探索外星球,希望找到适合人类生存的新家园。',
    '悬疑小说': '一桩离奇的谋杀案震惊了整个小镇,侦探在调查过程中发现了隐藏在每个人心中的秘密,真相逐渐浮出水面。',
    '历史小说': '故事发生在古代王朝,讲述了一位勇敢的女将军如何在战乱中保护自己的家园,并最终改变了国家的命运。',
    '奇幻小说': '在一个魔法与怪兽共存的世界里,一位年轻的魔法学徒踏上了寻找失落王国的冒险之旅,途中结识了各种奇异的伙伴。',
    '成长小说': '一个普通的少年在面对家庭和学业压力时,逐渐学会了如何面对生活中的挑战,最终实现了自我成长与蜕变。'
}

构建提示Prompt

创建一个init_prompt_template()函数,用于初始化前置prompt,以便模型进行Few-shot少量示例学习

# 初始化提示Prompt函数
def init_prompt_template():
    # 获取所有分类的类别列表
    class_list = list(class_examples.keys())
    
    # 初始化预设的对话历史记录
    pre_history = [
         {"role": "user", "content": f'现在你是一个文本分类器,请你按照要求将我给你的句子分类到:{class_list}类别中。'},
         {"role": "assistant", "content": "好的。"}
    ]
    
    # 遍历给定的示例样本
    for key, value in class_examples.items():
        # 将用户的请求添加到历史记录中,询问每个示例的类别
        pre_history.append({"role": "user", "content": f'"{value}"是{class_list}中的什么类别?'})
        # 将模型的回答(类别)添加到历史记录中
        pre_history.append({"role": "assistant", "content": key})

    # 返回包含类别列表和预设历史记录的字典
    return {"class_list": class_list, "pre_history": pre_history}

得到预处理的Few-shot少量学习示例:
在这里插入图片描述

定义推理函数

创建一个inference()推理函数,传入参数sentences:待推理的句子列表,同时传入参数init_prompts:初始设定的少量few-shot示例

def inference(sentences: list, init_prompts: dict):
    # 遍历每个待推理的句子
    for sentence in sentences:
        # 构造用于推理的提示句
        sentence_prompt = f'"{sentence}"是{init_settings["class_list"]}中的什么类别?'
        # 调用模型进行推理,获取响应和历史记录
        response, history = model.chat(tokenizer, sentence_prompt, history=init_prompts['pre_history'])
        
        # 打印句子和推理结果
        print(f'>>>  待分类文本: {sentence}')
        print(f'>>>  推理回答: {response}')
        print(f'>>>  history: {history}')
        # 分隔输出
        print("-" * 100)

执行文本分类测试

准备一些测试文本数据,调用初始化提示示例与执行推理操作。

# 文本分类句子
sentences = [
         '在一个充满魔法的王国中,年轻的女巫发现自己拥有改变命运的力量,她必须与黑暗势力斗争,以拯救她的家园。',
         '一位著名作家的神秘失踪引发了一场媒体风暴,记者在调查中揭开了隐藏在辉煌背后的阴暗秘密。',
         '在一个小镇上,两个青梅竹马的朋友因误解而分开,经过多年的生活磨砺,他们终于在一次偶然的重逢中重新找到了彼此。'
        ]

# 少量示例
init_prompts = init_prompt_template()

# 推理
inference(sentences, init_prompts)

推理结果下:
在这里插入图片描述

大模型:信息抽取

加载模型

加载chatglm3-6b预训练模型和相应的分词器

# 从 transformers 库导入 AutoTokenizer 和 AutoModel,用于加载预训练模型和分词器
from transformers import AutoTokenizer, AutoModel

# 指定模型的路径
model_path = '/root/work/models/chatglm3-6b'
# 从指定路径加载预训练的分词器,设置 trust_remote_code 为 True 以信任远程代码
tokenizer = AutoTokenizer.from_pretrained(model_path, trust_remote_code=True)

# 从指定路径加载预训练的模型,设置 trust_remote_code 为 True 以信任远程代码,并以 8 位模式加载
model = AutoModel.from_pretrained(model_path, trust_remote_code=True, load_in_8bit=True)

# 将模型设置为评估模式,以便在推理时禁用训练特性(如 dropout)
model = model.eval()

数据

定义一些用于信息抽取的实体属性与示例数据

# 定义关于书籍的实体属性
schema =  ['日期', '书名', '售价', '销量', '作者']

# 示例数据
data_examples = [
    {
        'content': '2024-05-15,《梦境探险者》在全国范围内发布,首日销量达到50000本,成为畅销书。作者小李表示,故事灵感来源于他的旅行经历。',
        'answers': "{'日期': '2024-05-15', '书名': '梦境探险者', '销量': '50000本', '作者': '小李'}"
    },
    {
        'content': '2023-11-20,小说《时间的旅人》正式上市,开售价格为80元,第一周销量突破30000本,受到了读者的广泛好评。',
        'answers': "{'日期': '2023-11-20', '书名': '时间的旅人', '售价': '80元', '销量': '30000本', '作者': ''}"
    },
    {
        'content': '作家阿华的新书《星际迷航》在书展上发布,售价为120元,预售期间已售出15000本,备受期待。',
        'answers': "{'日期': '', '书名': '星际迷航', '售价': '120元', '销量': '15000本', '作者': '阿华'}"
    }
]

构建提示Prompt

创建一个init_prompt_template()函数,用于初始化前置prompt,以便模型进行Few-shot少量示例学习

# 信息抽取的模版
template = "对于已知句子: {} \n请提取其中关于{}的实体,并按照JSON格式输出(包含所有实体),当句子中不存在实体信息时请使用''作为提取结果表示,多个值之间用,分隔。"

def init_prompt_template():
    """
    初始化前置prompt,便于模型做学习。
    """
    # 初始化一个列表,用于存储用户和助手的对话历史
    pre_history = [
        # 用户请求信息抽取的任务说明
        {"role": "user", "content": "现在你需要帮助我完成信息抽取任务,当我给你一个句子时,你需要帮我抽取出句子中实体信息,并按照JSON的格式输出(包含所有实体),当句子中不存在实体信息时请使用''作为提取结果表示,多个值之间用,分隔"},
        # 助手确认
        {"role": "assistant", "content": "好的。"},
    ]

    # 遍历数据示例以构建对话历史
    for row in data_examples:
        # 从当前示例中提取句子和答案
        sentence = row["content"]
        answers = row["answers"]
        # 将句子和提取目标格式化到模板中
        sentence_with_prompt = template.format(sentence, schema)
        # 将格式化后的句子添加到对话历史中
        pre_history.append({"role": "user", "content": sentence_with_prompt})
        # 将模型的回答添加到历史记录中
        pre_history.append({"role": "assistant", "content": answers})

    # 返回包含对话历史的字典
    return {"pre_history": pre_history}

经过处理的对话内容如下:
在这里插入图片描述

定义推理函数

创建一个inference()推理函数,传入参数sentences:待推理的句子列表,同时传入参数init_prompts:初始设定的少量few-shot示例

def inference(sentences: list, init_prompts: list):
    """
    推理函数。
    Args:
        sentences (List[str]): 待抽取的句子。
        init_prompts (dict): 初始设定,包含人为给定的 few-shot example。
    """
    # 遍历待处理的句子列表
    for sentence in sentences:
        # 使用模板格式化当前句子
        sentence_with_prompt = template.format(sentence, schema)
        # 获取初始化的对话历史
        history = init_prompts["pre_history"]
        # 调用模型的 chat 方法进行推理,获取响应和更新后的历史
        response, history = model.chat(tokenizer, sentence_with_prompt, history=history)
        # 打印待提取的文本
        print(f'>>> 待提取文本: {sentence}')
        # 打印模型的推理回答
        print(f'>>> 推理回答: {response}')
        print("\n\n")

执行信息抽取测试

准备一些测试数据,同时初始化Prompt,一同传递给推理函数执行推理

# 测试数据
sentences = [
        '2023-06-10,《夏日微风》在全国发布,开售价格为90元,首周销量达到25000本,作者小张表示非常感谢读者的支持。',
        '2024-03-05,小说《逆风飞翔》在书店上架,定价75元,首日销量为18000本,受到读者热烈追捧。',
        '《未来之门》正式上市,售价100元,预售期间已售出12000本,作者小李对此表示满意。',
    ]

# 少量示例
init_prompts = init_prompt_template()

# 推理
inference(sentences, init_prompts)

执行推理,得到预期结果,具体内容如下:

在这里插入图片描述

大模型:文本匹配

加载模型

加载chatglm3-6b预训练模型和相应的分词器

# 从 transformers 库导入 AutoTokenizer 和 AutoModel,用于加载预训练模型和分词器
from transformers import AutoTokenizer, AutoModel

# 指定模型的路径
model_path = '/root/work/models/chatglm3-6b'
# 从指定路径加载预训练的分词器,设置 trust_remote_code 为 True 以信任远程代码
tokenizer = AutoTokenizer.from_pretrained(model_path, trust_remote_code=True)

# 从指定路径加载预训练的模型,设置 trust_remote_code 为 True 以信任远程代码,并以 8 位模式加载
model = AutoModel.from_pretrained(model_path, trust_remote_code=True, load_in_8bit=True)

# 将模型设置为评估模式,以便在推理时禁用训练特性(如 dropout)
model = model.eval()

数据

text_matching_data = [
    {
        'sentence1': '《星际探险》讲述了一群宇航员探索未知星球的故事。',
        'sentence2': '小说《星际探险》描述了宇航员们在外太空的冒险经历。',
        'result': '相似'
    },
    {
        'sentence1': '《爱情花园》描绘了一段浪漫的爱情故事。',
        'sentence2': '《战争与和平》是一本关于历史和战争的小说。',
        'result': '不相似'
    },
    {
        'sentence1': '在《魔法学院》中,主人公学习如何使用魔法。',
        'sentence2': '《魔法学院》这本书讲述了一个年轻人学习魔法的历程。',
        'result': '相似'
    },
    {
        'sentence1': '《时间旅行者》描述了主人公穿越时空的冒险。',
        'sentence2': '《时间旅行者》这本书讲述了一个人在不同时间点的经历。',
        'result': '相似'
    },
    {
        'sentence1': '《侦探故事》中的侦探解决了一系列复杂的案件。',
        'sentence2': '《美食之旅》是一部关于美食和旅行的小说。',
        'result': '不相似'
    }
]

构建提示Prompt

def init_prompt_template():
    pre_history = [
        (
            '请帮助我完成文本匹配任务,当我给你两个句子时,你需要回答我这两句话语义是否相似。只需要回答: `相似`或`不相似`,不要做多余的回答。',
            '明白,我将只回答`相似`或`不相似`。'
        )
    ]
    for row in text_matching_data:
        sentence1 = row['sentence1']
        sentence2 = row['sentence2']
        result = row['result']
        pre_history.append({"role": "user", "content": f'句子1:{sentence1} \n句子2:{sentence2} \n上述两句话的语义相似吗?'})
        pre_history.append({"role": "assistant", "content": result})
    return {"pre_history": pre_history}

得到预处理的少量学习示例:
在这里插入图片描述

定义推理函数

定义inference ()推理函数用于判断给定句子对的语义相似性。

def inference(sentences: list, init_prompts: list):
    """
    推理函数,用于判断句子对的语义相似性。

    Args:
        sentences (List[dict]): 包含句子对的字典列表,每个字典包含'sentence1'和'sentence2'。
        init_prompts (dict): 初始设定,包含人为给定的 few-shot example。
    """
    # 遍历待处理的句子对列表
    for row in sentences:
        # 从当前行中提取句子1和句子2
        sentence1 = row['sentence1']
        sentence2 = row['sentence2']
        # 构建提示内容,询问两个句子的语义相似性
        prompt = f'句子1: {sentence1} \n句子2: {sentence2} \n上述两句话的语义相似吗?'
        # 获取初始化的对话历史
        history = init_prompts['pre_history']
        # 调用模型的 chat 方法进行推理,获取响应和更新后的历史
        response, history = model.chat(tokenizer, prompt, history=history)
        # 打印待匹配的文本
        print(f'>>> 待匹配文本: \n{prompt}')
        print("\n")
        # 打印模型的推理回答
        print(f'>>> 推理回答: {response}')
        print("\n\n")

执行文本匹配测试

准备一些测试数据,同时初始化Prompt,一同传递给推理函数执行推理

sentences =[
    {
        'sentence1': '《魔法学院》是一本关于学习魔法的书。',
        'sentence2': '《魔法学校》讲述了一个年轻人学习魔法的故事。',
    },
    {
        'sentence1': '《奇幻之旅》讲述了一位年轻魔法师的冒险故事。',
        'sentence2': '《科技未来》探讨了未来科技的发展。',
    },
    {
        "sentence1": "《时间旅行者》讲述了主人公穿越不同历史时期的经历。",
        "sentence2": "《未来之书》探讨了科技对人类生活的影响。"
    }
]


# 少量示例
init_prompts = init_prompt_template()

# 推理
inference(sentences, init_prompts)

推理结果下:
在这里插入图片描述

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

CodeDevMaster

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值