一、本地部署大模型(魔搭社区)
这里通过 git方式安装模型到本地。
模型为:Qwen2.5-1.5B-Instruct
链接为:QWen2.5-0.5B-Instruct · 模型库
具体命令如下:
git clone https://www.modelscope.cn/emrys111/QWen2.5-0.5B-Instruct.git

二、案例实现
在开始案例前。需要先安装transform库
python
pip install transformers
2.1 文本分类
python
整体思路:
1、加载模型
2、创建分词器
3、创建提示词模板
4、输入需要判断的文本,使用后tokenizer进行分词,之后进行推理操作,在进行解码操作。
5、输出结果
python
from transformers import AutoModelForCausalLM, AutoTokenizer#先要安装一个第三方库transformers
#安装transformers,大模型的开发库
#大模型 的 网络 结构 就 自 注意力 机制、
# 假设Qwen是一个生成式模型,并且我们有它的权重和分词器
model_name = r"D:\开源大模型文件\Qwen2.5-1.5B-Instruct" #只需要写文件路径即可
model = AutoModelForCausalLM.from_pretrained(model_name) #加载模型。
tokenizer = AutoTokenizer.from_pretrained(model_name)#对文本进行分词,创建一个分词器
# 定义一个Prompt模板
prompt_template = "请判断以下文本属于哪个类别:{text}。可选类别有:正面、负面、中立。"
# 预处理输入文本
input_text = ""这部电影真是太差劲,我非常不喜欢!"" #领域:识别你是否具有抑郁症。
prompt_input = prompt_template.format(text=input_text)
inputs = tokenizer(prompt_input, return_tensors="pt")# 对Prompt进行编码,inputs返回的结果中包含了input_ids和attention_mask
# input_ids:是将输入文本(prompt_input)按照分词器对应的词汇表进行编码后得到的结果,表现为一个张量(torch.Tensor 类型,因为设置了 return_tensors="pt" 表示返回 PyTorch 格式的张量)。这个张量里的每个元素对应词汇表中的一个词(准确说是词对应的索引)
# attention_mask:是用于指示模型在处理输入时应该关注哪些部分的掩码张量,其元素的值通常是 0 或者 1,1 表示对应位置的 input_ids 是有效输入,需要模型去关注和处理;0 表示对应位置是填充部分(比如在批量处理文本且文本长度不一致时进行填充后的那些位置),模型在进行注意力计算等操作时可以忽略这些位置。
# 使用模型进行推理(生成文本)
output_sequences = model.generate(inputs.input_ids, max_new_tokens=512, # 生成文本的最大长度
attention_mask=inputs.attention_mask)
# 解码生成的文本
generated_text = tokenizer.decode(output_sequences[0], skip_special_tokens=True)
print(generated_text)
text = generated_text[len(prompt_input):]#大模型需要保存记忆
# # 解析生成的文本以获取分类结果
# # 这里我们假设生成的文本会包含"正面"、"负面"或"中立"中的一个
# classification = None
# text = generated_text[len(prompt_input):]
# if "正面" in text:
# classification = "正面"
# elif "负面" in text:
# classification = "负面"
# elif "中立" in text:
# classification = "中立"
#
# # 输出分类结果
# print(f"分类结果:{classification}")
2.2 实现记忆历史数据
这里通过设置一个history列表来存储提问的信息及大模型输出的结果,不断地将history输入到大模型完成记忆。
python
'''
整体思路:
1、加载模型
2、创建分词器
3、历史回答记录拼接当前记录,注意历史记录使用列表保存的,当前记录需要用列表
4、对整体拼接的结果分词(tokenizer)
5、将分词的结果中的input_ids属性传给模型推理,可以添加额外的参数
6、对模型推理的结果进行解码
7、输出文本
'''
python
from transformers import AutoModelForCausalLM, AutoTokenizer#先要安装一个第三方库transformers
#安装transformers,大模型的开发库
#大模型 的 网络 结构 就 自 注意力 机制、
# 假设Qwen是一个生成式模型,并且我们有它的权重和分词器
'''
整体思路:
1、加载模型
2、创建分词器
3、历史回答记录拼接当前记录,注意历史记录使用列表保存的,当前记录需要用列表
4、对整体拼接的结果分词(tokenizer)
5、将分词的结果中的input_ids属性传给模型推理,可以添加额外的参数
6、对模型推理的结果进行解码
7、输出文本
'''
model_name = r"D:\开源大模型文件\Qwen2.5-1.5B-Instruct" #只需要写文件路径即可
model = AutoModelForCausalLM.from_pretrained(model_name) #加载模型。
tokenizer = AutoTokenizer.from_pretrained(model_name)#对文本进行分词,创建一个分词器
history_inputs = ['''我是用户,你是系统,请根据下面的句子来回答我。
"用户: 你好,请问今天天气怎么样?",
"系统: 今天是晴天,气温20到25度。",
"用户: 那明天呢?",
"系统: 明天是晴天,气温22到25度。"'''
]#列表,三个引号引起来 " "告诉大模型改如何回答我的信息
# 当前轮次的输入信息
current_input = "用户: 那后天的天气呢?"
all_inputs = "\n".join(history_inputs + [current_input])
inputs = tokenizer(all_inputs, return_tensors="pt")# 对Prompt进行编码,inputs返回的结果中包含了input_ids和attention_mask
# input_ids:是将输入文本(prompt_input)按照分词器对应的词汇表进行编码后得到的结果,表现为一个张量(torch.Tensor 类型,因为设置了 return_tensors="pt" 表示返回 PyTorch 格式的张量)。这个张量里的每个元素对应词汇表中的一个词(准确说是词对应的索引)
# attention_mask:是用于指示模型在处理输入时应该关注哪些部分的掩码张量,其元素的值通常是 0 或者 1,1 表示对应位置的 input_ids 是有效输入,需要模型去关注和处理;0 表示对应位置是填充部分(比如在批量处理文本且文本长度不一致时进行填充后的那些位置),模型在进行注意力计算等操作时可以忽略这些位置。
# 使用模型进行推理(生成文本)
output_sequences = model.generate(inputs["input_ids"], max_new_tokens=512, # 生成文本的最大长度
attention_mask=inputs.attention_mask)
# 解码生成的文本
generated_text = tokenizer.decode(output_sequences[0], skip_special_tokens=True)
print(generated_text)
2.3 通过记忆历史数据对新输入的信息完成分类
这里通过设置一个history列表来存储提问的信息及大模型输出的结果,不断地将history输入到大模型完成记忆,将新问题与历史对话进行拼接,最后将拼接的结果发送给本地大模型,完成任务目标。
python
from sympy.physics.units import temperature
from transformers import AutoModelForCausalLM, AutoTokenizer#先要安装一个第三方库transformers
#安装transformers,大模型的开发库
#大模型 的 网络 结构 就 自 注意力 机制、
# 假设Qwen是一个生成式模型,并且我们有它的权重和分词器
model_name = r"D:\开源大模型文件\Qwen2.5-1.5B-Instruct" #只需要写文件路径即可
model = AutoModelForCausalLM.from_pretrained(model_name) #加载模型。
tokenizer = AutoTokenizer.from_pretrained(model_name)#对文本进行分词,创建一个分词器
# # 定义一个Prompt模板
# prompt_template = "请判断以下文本属于哪个类别:{text}。可选类别有:正面、负面、中立。"
# 预处理输入文本
# input_text = ""这部电影真是太差劲,我非常不喜欢!"" #领域:识别你是否具有抑郁症。
# prompt_input = prompt_template.format(text=input_text)
history_inputs = ['''我是用户,你是系统,你需要按照要求将我给你的句子分类到:'新闻报道', '财务报告', '公司公告', '分析师报告'类别中。请根据如下模板回答:\n
"用户:今日,股市经历了一轮震荡,受到宏观经济数据和全球贸易紧张局势的影响。投资者密切关注美联储可能的政策调整,以适应市场的不确定性。"是'新闻报道','财务报告','公司公告','分析师报告'里的什么类别?",
"系统:新闻报道",
"用户:本公司年度财务报告显示,去年公司实现了稳步增长的盈利,同时资产负债表呈现强劲的状况。经济环境的稳定和管理层的有效战略执行为公司的健康发展奠定了基础。"是'新闻报道','财务报告','公司公告','分析师报告'里的什么类别?",
"系统:财务报告",
"用户:本公司高兴地宣布成功完成最新一轮并购交易,收购了一家在人工智能领域领先的公司。这一战略举措将有助于扩大我们的业务领域,提高市场竞争力。"是'新闻报道','财务报告','公司公告','分析师报告'里的什么类别?",
"系统:公司公告",
"用户:最新的行业分析报告指出,科技公司的创新将成为未来增长的主要推动力。云计算、人工智能和数字化转型被认为是引领行业发展的关键因素,投资者应关注这些趋势"是'新闻报道','财务报告','公司公告','分析师报告'里的什么类别",
"系统:分析师报告",''']
# 当前轮次的输入信息
current_input = '''请系统回答下面的用户信息,"用户:今日,央行发布公告宣布降低利率,以刺激经济增长。这一降息举措将影响贷款利率,并在未来几个季度内对金融市场产生影响。",'''
all_input = "\n".join(history_inputs + [current_input])
inputs = tokenizer(all_input, return_tensors="pt").to(model.device)# 对Prompt进行编码,inputs返回的结果中包含了input_ids和attention_mask
# input_ids:是将输入文本(prompt_input)按照分词器对应的词汇表进行编码后得到的结果,表现为一个张量(torch.Tensor 类型,因为设置了 return_tensors="pt" 表示返回 PyTorch 格式的张量)。这个张量里的每个元素对应词汇表中的一个词(准确说是词对应的索引)
# attention_mask:是用于指示模型在处理输入时应该关注哪些部分的掩码张量,其元素的值通常是 0 或者 1,1 表示对应位置的 input_ids 是有效输入,需要模型去关注和处理;0 表示对应位置是填充部分(比如在批量处理文本且文本长度不一致时进行填充后的那些位置),模型在进行注意力计算等操作时可以忽略这些位置。
# 使用模型进行推理(生成文本)
output_sequences = model.generate(inputs["input_ids"],temperature=0.1,top_p=0.9, max_new_tokens=200, # 生成文本的最大长度
attention_mask=inputs.attention_mask)
# 解码生成的文本
generated_text = tokenizer.decode(output_sequences[0], skip_special_tokens=True)
print(generated_text)
2.4 连续传入信息
这里通过一个死循环实现连续传入信息。
python
from transformers import AutoModelForCausalLM, AutoTokenizer
# 1. 加载模型和分词器
# 注意:这里使用的是本地路径,请确保该路径下有正确的模型文件
model_name = r"D:\开源大模型文件\Qwen2.5-1.5B-Instruct"
model = AutoModelForCausalLM.from_pretrained(model_name)
tokenizer = AutoTokenizer.from_pretrained(model_name)
# 2. 初始化对话历史列表
conversation_history = []
print("开始对话 (输入 quit 或 exit 退出)...")
while True:
# 3. 获取用户输入
user_input = input("你: ")
# 4. 退出条件判断
if user_input.lower() in ["quit", "exit"]:
break
# 5. 将用户输入添加到对话历史
conversation_history.append(user_input)
# 6. 构建完整的输入文本 (将历史记录用换行符拼接)
full_input_text = "\n".join(conversation_history)
# 7. 对输入文本进行编码
# return_tensors="pt" 表示返回 PyTorch 张量
inputs = tokenizer(full_input_text, return_tensors="pt")
# 8. 生成回答
# max_length=1000 限制生成文本的总长度
output = model.generate(
inputs.input_ids,
max_length=1000,
attention_mask=inputs.attention_mask
)
# 9. 解码生成的文本
answer = tokenizer.decode(output[0], skip_special_tokens=True)
# 10. 提取本次新增的回答部分
# 通过截取长度,去掉输入部分,只保留模型生成的部分
new_answer = answer[len(full_input_text):]
# 11. 打印回答
print("Qwen-2.5:", new_answer)
# 12. 将模型的回答也添加到对话历史中,以便下一轮对话使用
conversation_history.append(new_answer)
2.5 信息抽取
首先定义了抽取规则,其次定义了提示词模板和缺失值处理规则,构建了一个示例传给了历史记录,将当前问题与历史对话进行拼接,最后将拼接的结果发送给大模型实现信息抽取。
python
import json
from rich import print
from transformers import AutoTokenizer, AutoModelForCausalLM
# 定义不同实体下的具备属性
schema = {'商品': ['产品', '品牌', '特点', '原价', '促销价', '销量'], }
# 信息抽取的模版
IE_PATTERN = "{}\n\n提取上述句子中{}的实体,并按照JSON格式输出,上述句子中不存在的信息用['原文中未提及']来表示,多个值之间用','分隔。"
ie_examples = { # 提供一些例子供模型参考
'商品': [ { 'content': '2024 年新款时尚运动鞋,品牌 JKL,舒适透气,多种颜色可选。原价 599 元,现在促销价 499 元。月销量 2000 双。',
'answers': { '产品': ['时尚运动鞋'],
'品牌': ['JKL'],
'特点': ['舒适透气、多种颜色可选'],
'原价': ['599元'],
'促销价': ['499元'],
'月销量': [' 2000双'],
}
} ] }
# 定义init_prompts函数 离线部署到你的本地,1b;8b 满血 在线的大模型,开发者
def init_prompts():
""" 初始化前置prompt,便于模型做 incontext learning。 """
ie_pre_history = [("现在你需要帮助我完成信息抽取任务,当我给你一个句子时,你需要帮我抽取出句子中实体信息,并按照JSON的格式输出,上述句子中没有的信息用['原文中未提及']来表示,多个值之间用','分隔。",
'好的,请输入您的句子。')]
for _type, example_list in ie_examples.items():
for example in example_list:
sentence = example["content"]
properties_str = ', '.join(schema[_type])
schema_str_list = f'"{_type}"({properties_str})'
sentence_with_prompt = IE_PATTERN.format(sentence, schema_str_list)
ie_pre_history.append((f"{sentence_with_prompt}",f"{json.dumps(example['answers'], ensure_ascii=False)}"))
return {"ie_pre_history":ie_pre_history}
def build_prompt(query, history=None):#
if history is None:
history = []
prompt = ""
for i, (old_query, response) in enumerate(history):
prompt += "[Round {}]\n\n问:{}\n\n答:{}\n\n".format(i + 1, old_query, response)
prompt += "[Round {}]\n\n问:{}\n\n答:".format(len(history) + 1, query)
return prompt
def inference(sentences: list, custom_settings: dict):
""" 推理函数。 Args:
sentences (List[str]): 待抽取的句子。
custom_settings (dict): 初始设定,包含人为给定的 few-shot example。
"""
for sentence in sentences:
cls_res = "商品"
if cls_res not in schema:#不满足的
print(f'The type model inferenced {cls_res} which is not in schema dict, exited.')
exit()
properties_str = ', '.join(schema[cls_res])
schema_str_list = f'"{cls_res}"({properties_str})'
sentence_with_ie_prompt = IE_PATTERN.format(sentence, schema_str_list)
full_input_text = build_prompt(sentence_with_ie_prompt,custom_settings["ie_pre_history"])
inputs = tokenizer(full_input_text, return_tensors="pt") # 编码整个输入序列
inputs = inputs.to('cuda')#有些同学是没有GPU。cuda。cpu
output_sequences = model.generate(inputs["input_ids"], max_length=2000, attention_mask=inputs.attention_mask)
# 解码生成的回复
generated_reply = tokenizer.decode(output_sequences[0], skip_special_tokens=True)
print(generated_reply[len(full_input_text):])
if __name__ == '__main__':
tokenizer = AutoTokenizer.from_pretrained(r"C:\Users\andyl\Qwen2.5-1.5B-Instruct", trust_remote_code=True)
model = AutoModelForCausalLM.from_pretrained(r"C:\Users\andyl\Qwen2.5-1.5B-Instruct", trust_remote_code=True).cuda()#使用cuda
device = 'cuda:0'#
model.to(device)#将模型传入到GPU
model = model.eval()#表明当前进入到测试模型,可以不写。
sentences = ['"2024 年潮流双肩包,品牌 PQR,材质耐磨,内部空间大。定价399元,优惠后价格349元。周销量800个。',
'2024 年智能手表,品牌为华为,功能强大,续航持久。售价1299元,便宜价999元,目前有黑色和银色可选。月销量3000只。']
#品牌是华为,品牌为华为,都可以实现,也提现了大模型的处理便捷性,如果通过re处理,代码俩会非常难以处理。
custom_settings = init_prompts()
inference(sentences, custom_settings)