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

实现文本分类、信息抽取、文本匹配等任务

前言

在实现文本分类、信息抽取、文本匹配等任务时,可以采用两种主要的方法。首先,可以对一些基础模型进行微调训练,以适应特定任务的需求。这种方法通常需要标注数据,通过调整模型参数来提高其在特定任务上的表现。
其次,基于大模型(如预训练的语言模型)进行任务实现也是一种有效的方法。大模型通常在大规模数据上训练,具备较强的泛化能力和理解能力,可以通过少量的示例进行少量学习(few-shot learning)或零样本学习(zero-shot learning),从而快速适应新的任务。
这里使用基础模型与大语言模型作为对比,实现文本分类、信息抽取、文本匹配等任务,侧重点在于大模型的实现。基础模型选择BERT,大模型选择ChatGLM3-6B。

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

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

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

基础模型BERT:文本分类

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

加载模型

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

python 复制代码
# 导入必要的库
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条属于科幻小说,假设微调训练数据如下

python 复制代码
# 数据准备
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操作

python 复制代码
# 将字典格式的数据转换为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)

模型训练

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

python 复制代码
# 定义训练参数
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)的数量通常是通过以下公式计算得出的:

python 复制代码
steps = 训练样本数 / 每批次样本数

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

python 复制代码
训练样本数 = 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个训练周期后进行了验证评估。

保存模型

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

python 复制代码
from transformers import AutoModelForSequenceClassification, AutoTokenizer

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

加载模型进行推理

python 复制代码
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预训练模型和相应的分词器

python 复制代码
# 从 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()

数据

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

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

构建提示Prompt

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

python 复制代码
# 初始化提示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示例

python 复制代码
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)

执行文本分类测试

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

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

# 少量示例
init_prompts = init_prompt_template()

# 推理
inference(sentences, init_prompts)

推理结果下:

大模型:信息抽取

加载模型

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

python 复制代码
# 从 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()

数据

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

bash 复制代码
# 定义关于书籍的实体属性
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少量示例学习

bash 复制代码
# 信息抽取的模版
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示例

bash 复制代码
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,一同传递给推理函数执行推理

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

# 少量示例
init_prompts = init_prompt_template()

# 推理
inference(sentences, init_prompts)

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

大模型:文本匹配

加载模型

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

python 复制代码
# 从 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()

数据

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

构建提示Prompt

python 复制代码
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 ()推理函数用于判断给定句子对的语义相似性。

python 复制代码
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,一同传递给推理函数执行推理

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


# 少量示例
init_prompts = init_prompt_template()

# 推理
inference(sentences, init_prompts)

推理结果下:

相关推荐
技术你大飞哥21 分钟前
【突破数据孤岛】MCP协议进化史:从 STDIO 到全双工流式 —— AI 应用开发效率提升 90% 的秘密武器
llm·ai编程·mcp
RockLiu@8051 小时前
大模型技术全景解析:从基础架构到Prompt工程
语言模型·prompt
Goboy1 小时前
零基础搞定 Trae 智能体配置 + MySQL MCP 集成!手把手教学
llm·ai编程·trae
喜欢吃豆3 小时前
如何调用大语言模型的API?
人工智能·语言模型·自然语言处理
测试老吴4 小时前
Dify升级-linux环境下使用zip离线安装方式部署升级
大模型·dify·测试应用
漫谈网络16 小时前
Ollama API 应用指南
ai·llm·aigc·api·ollama
W流沙W17 小时前
bert学习
人工智能·bert
数据智能老司机18 小时前
使用 FastAPI 构建生成式 AI 服务——与生成模型的实时通信
llm·openai·fastapi
数据智能老司机18 小时前
使用 FastAPI 构建生成式 AI 服务——AI集成与模型服务
llm·openai·fastapi
游离子丶19 小时前
LLama Factory从入门到放弃
语言模型·游戏程序·llama·yuzu-soft