一、前言
刚开始接触AI时,您可能会感到困惑,因为面对众多开源模型的选择,不知道应该选择哪个模型,也不知道如何调用最基本的模型。但是不用担心,我将陪伴您一起逐步入门,解决这些问题。
在信息时代,我们可以轻松地通过互联网获取大量的理论知识和概念。然而,仅仅掌握理论知识并不能真正帮助我们成长和进步。实践是将理论知识转化为实际技能和经验的关键。
本章将学习如何在低成本下,使用transformer设置chatglm3-6b模型参数/System Prompt/历史对话
qwen模型教程入口:
开源模型应用落地-qwen模型小试-入门篇(二)-CSDN博客
baichuan模型教程入口:
开源模型应用落地-baichuan2模型小试-入门篇(二)-CSDN博客
二、术语
2.1. ChatGLM3
是智谱AI和清华大学 KEG 实验室联合发布的对话预训练模型。ChatGLM3-6B 是 ChatGLM3 系列中的开源模型,在保留了前两代模型对话流畅、部署门槛低等众多优秀特性的基础上,ChatGLM3-6B 引入了如下特性:
- 更强大的基础模型: ChatGLM3-6B 的基础模型 ChatGLM3-6B-Base 采用了更多样的训练数据、更充分的训练步数和更合理的训练策略。在语义、数学、推理、代码、知识等不同角度的数据集上测评显示,* ChatGLM3-6B-Base 具有在 10B 以下的基础模型中最强的性能*。
- 更完整的功能支持: ChatGLM3-6B 采用了全新设计的 Prompt 格式 ,除正常的多轮对话外。同时原生支持工具调用(Function Call)、代码执行(Code Interpreter)和 Agent 任务等复杂场景。
- 更全面的开源序列: 除了对话模型 ChatGLM3-6B 外,还开源了基础模型 ChatGLM3-6B-Base 、长文本对话模型 ChatGLM3-6B-32K 和进一步强化了对于长文本理解能力的 ChatGLM3-6B-128K。以上所有权重对学术研究完全开放 ,在填写 问卷 进行登记后亦允许免费商业使用。
2.2. system prompt(系统提示)
是指在生成对话或文本的任务中,为了引导模型产生合适的响应或输出,对模型进行输入的开头部分或系统提供的指令。系统提示通常包含一些关键信息,如对话的背景、任务的要求或期望的回答风格等,以帮助模型理解上下文并生成相关的响应。通过精心设计和调整系统提示,可以引导模型产生更准确、连贯且符合预期的输出。
2.3. temperature(温度)
是用于控制生成模型输出的多样性和随机性的一个参数。当温度较高时,模型会更加随机地选择输出,使得生成结果更加多样化和创造性,但可能会牺牲一些准确性和一致性。相反,当温度较低时,模型会更加确定性地选择输出,使得生成结果更加集中和可控。较低的温度值会使概率分布更尖峰,使得高概率的词或标记更容易被选中。
2.4. top_p
是一种用于控制生成模型输出的参数。在生成文本或对话的任务中,模型通常会输出一个概率分布,表示每个可能的词或标记的概率。top_p参数用于指定一个概率的阈值,模型将从概率累积最高的词开始逐步选择,直到累积概率超过阈值为止。通过设置top_p参数,我们可以控制生成模型输出的多样性和可控性。较小的top_p值会限制模型选择的候选词的数量,使得模型的输出更加集中和可控。较大的top_p值会增加模型选择的候选词的数量,使得模型的输出更加多样化和创造性。
2.5. repetition_penalty
是一种用于控制生成模型输出中重复内容的参数。在生成文本或对话的任务中,模型有时候可能会倾向于产生重复的词语、短语或句子,导致生成结果的质量下降或显得不够自然。为了解决这个问题,可以使用重复惩罚机制。重复惩罚参数可以调整模型对已经生成过的内容的偏好程度。较高的重复惩罚值会使模型更加抑制生成已经出现过的内容,以鼓励生成更多新颖的内容。较低的重复惩罚值则会相对宽容,允许模型生成一定程度的重复内容。
2.6. history
"历史上下文"是指在处理当前文本或对话时,与之前的文本或对话相关的信息和语境。历史上下文包括了之前的句子、段落或对话中的内容,以及前文中提到的实体、事件和语义关系等。它提供了理解当前文本的重要背景信息,帮助我们更准确地解释和推断文本的含义。处理历史上下文时,模型需要能够捕捉并记忆之前的信息,并将其与当前文本进行关联,以产生有意义的输出。
三、前置条件
3.1. windows操作系统
3.2. 下载chatglm3-6b模型
从huggingface下载:https://huggingface.co/THUDM/chatglm3-6b/tree/main
3.3. 创建虚拟环境&安装依赖
conda create --name chatglm3 python=3.10
conda activate chatglm3
pip install protobuf transformers==4.39.3 cpm_kernels torch>=2.0 sentencepiece accelerate
四、技术实现
4.1. 设置system prompt
# 方法一:
设置role为system的message
{"role": "system", "content": content}
调用结果:
#方法二:
采用取巧的方式,在首轮对话中,先提示模型要扮演的角色或对话的风格等等的设定。需要注意,当多轮对话之后,如果历史对话的长度超过上下文的限制长度,则会出现遗忘的情况。
调用结果:
4.2. 设置模型参数
# 在stream_chat方法中设置
stream_chat(tokenizer,message, messages, max_length=512, top_p=0.1, temperature=0.1, repetition_penalty=1.1,do_sample=True)
max_length=512, top_p=0.1, temperature=0.1, repetition_penalty=1.1,do_sample=True
调用结果:
max_length=512, top_p=0.9, temperature=0.9, repetition_penalty=1.1,do_sample=True
调用结果:
4.3. 设置历史上下文
核心代码:
for his in history:
user,assistant = his
messages.append({"role": "user", "content": user})
messages.append({"role": "assistant", 'metadata': '', "content": assistant})
调用结果:
User:我家是广东省会吗? Assistant:你家在广州。
五、附带说明
5.1. 模型参数设置
ChatGLM3-6B模型不同于QWen1.5-7B-Chat和Baichuan2-7B-Chat,不能在generation_config.json文件或加载模型时设置,说明如下:
# 在模型目录下的generation_config.json文件中调整参数
文件内容:
# 在模型加载时调整参数
5.2. 完整代码
# -*- coding = utf-8 -*-
from transformers import AutoTokenizer, AutoModelForCausalLM
import time
import traceback
modelPath = "E:\\model\\chatglm3-6b"
def chat(model, tokenizer, message, history, system):
messages = []
if system is not None:
messages.append({"role": "system", "content": system})
if history is not None:
for his in history:
user,assistant = his
messages.append({"role": "user", "content": user})
messages.append({"role": "assistant", 'metadata': '', "content": assistant})
try:
for response in model.stream_chat(tokenizer,message, messages, max_length=512, top_p=0.9, temperature=0.9, repetition_penalty=1.1,do_sample=True):
_answer,_history = response
yield _answer
except Exception:
traceback.print_exc()
def loadTokenizer():
tokenizer = AutoTokenizer.from_pretrained(modelPath, use_fast=False, trust_remote_code=True)
return tokenizer
def loadModel():
model = AutoModelForCausalLM.from_pretrained(modelPath, device_map="auto", trust_remote_code=True).eval()
print(model)
return model
if __name__ == '__main__':
model = loadModel()
tokenizer = loadTokenizer()
start_time = time.time()
message = "我家有什么好玩?"
history = [('hi,你好', '你好!有什么我可以帮助你的吗?'), ('我家在广州,很好玩哦', '广州是一个美丽的城市,有很多有趣的地方可以去。'), ]
system = "你是一个人工智能助手,擅长解决人类的问题"
response = chat(model, tokenizer, message,history,system)
for answer in response:
print(answer)
end_time = time.time()
print("执行耗时: {:.2f}秒".format(end_time - start_time))