swift
说明
Base模型和Chat模型(与rlhf) 我们通常会看到某模型研发机构开源了base模型和chat模型,那base模型和chat模型有什么区别呢? 首先,所有的大语言模型(LLM)的工作方式都是接收一些文本,然后预测最有可能出现在其后面的文本。 base模型,也就是基础模型,是在海量不同文本上训练出来的预测后续文本的模型。后续文本未必是对指令和对话的响应。 chat微调模型,可以对指令进行流畅响应 rlhf微调模型,sft微调后对指令跟随不足,可用强化学习在微调
大型语言模型(LLMs)通过在大量文本数据集上进行无监督预训练,获得丰富的语言模式和知识,这一阶段训练后的模型被称为base model。base model能够理解语言并生成连贯的文本,但仍然存在一些问题,比如:
不良输出:模型可能会生成各种偏见、不真实信息和有害内容。
跟随指令的能力不足:尽管预训练模型可以生成连贯的文本,但它们在遵循用户指令和特定任务规范方面往往较差。例如,当模型被要求生成尊重特定规则或风格的文本时,它们可能无法完全理解并遵循这些具体的要求。
这些问题有几个原因:
语料偏差:
来源广泛的互联网文本:预训练模型使用大量互联网上的文本数据,这些数据来源多样,包括社交媒体、新闻文章、论坛帖子、百科全书等。这些数据不可避免地包含偏见、不真实信息和有害内容。
数据缺乏筛选和校验:由于数据量庞大,预训练过程中难以对每一条数据进行细致筛选和校验,导致模型可能会学习到这些不良特性并在生成输出时反映出来。例如,模型可能会生成带有性别或种族偏见的内容。
任务不直接相关:
广泛涵盖不同主题:预训练数据涵盖了广泛的主题,但其中许多内容与用户实际应用中的具体任务无关。例如,社交媒体上的对话与正式的问答系统所需的语言风格和准确性可能截然不同。
缺少特定任务数据:
尽管预训练数据量大,但并未专门针对某一具体任务进行优化。例如,翻译任务、法律文本解析或医疗文献总结等高度专业化的任务在通用的预训练数据集中可能所占比重很小。
训练目标和实际任务不同:
目标和任务目标不一致:预训练模型的目标是最大化下一个词的预测概率(即最小化语言模型的交叉熵损失)。这一目标虽然能帮助模型掌握语言的语法和词汇模式,但与实际应用中的任务目标不完全一致。预训练侧重语言连贯性,而非任务完成度:模型通过预测下一个词可以生成连贯的文本,但这种连贯性仅限于语言层面,不能保证生成的内容在逻辑、事实准确性或符合特定任务规范方面的表现。例如,在回答问题时,预训练模型可能生成语法正确但内容不准确的回答。
缺乏明确的指令跟随: ‒ 没有具体任务指导:预训练阶段模型没有被专门指导去遵循具体的指令或规则。这导致模型在面对实际任务时,可能无法完全理解和遵循用户的具体要求。生成风格化文本、遵守伦理和规范、提取特定信息等任务需要更细致的指导和约束,而这在无监督预训练阶段往往缺失。
仅靠无监督预训练无法完全满足实际应用中的需求,这也引出了本期的主题——人类偏好对齐训练。通过特定的训练过程,模型的输出可以更好地与人类偏好对齐。我们平时见到的 xxx-instruct 和 xxx-chat 模型,就是经过了人类偏好对齐训练的模型。
agnet
# 英文格式
Answer the following questions as best you can. You have access to the following APIs:
1. hm_recipe_recommend: Call this tool to interact with the hmreciperecommend API. What is the hmreciperecommend API useful for? . Parameters: [{"name": "keywords_dict", "description": "盒马推荐菜谱关键词字典。", "required": "True"}]
2. hm_product_marketing: Call this tool to interact with the hmproductmarketing API. What is the hmproductmarketing API useful for? . Parameters: [{"name": "sku_code_list", "description": "盒马商品的编码列表", "required": "True"}]
3. hm_product_info: Call this tool to interact with the hmproductinfo API. What is the hmproductinfo API useful for? . Parameters: [{"name": "sku_code_list", "description": "盒马商品的编码列表", "required": "True"}, {"name": "sku_name_list", "description": "盒马商品的名称列表", "required": "True"}, {"name": "property_list", "description": "盒马商品的属性列表", "required": "True"}]
4. hm_product_recommend: Call this tool to interact with the hmproductrecommend API. What is the hmproductrecommend API useful for? . Parameters: [{"name": "keywords_dict", "description": "盒马推荐商品关键词字典。", "required": "True"}]
Use the following format:
Thought: you should always think about what to do
Action: the action to take, should be one of the above tools[hm_recipe_recommend, hm_product_marketing, hm_product_info, hm_product_recommend]
Action Input: the input to the action
Observation: the result of the action
... (this Thought/Action/Action Input/Observation can be repeated zero or more times)
Thought: I now know the final answer
Final Answer: the final answer to the original input question
Begin!
# 中文格式
{'name': 'get_current_weather', 'description': 'Get the current weather in a given location', 'parameters': {'type': 'object', 'properties': {'location': {'type': 'string', 'description': 'The city and state, e.g. San Francisco, CA'}, 'unit': {'type': 'string', 'enum': ['celsius', 'fahrenheit']}}, 'required': ['location']}}
以下格式回答:
Thought: 思考你应该做什么
Action: 工具的名称,必须是[get_current_weather]之一
Action Input: 工具的输入
Observation: 工具返回的结果
... (Thought/Action/Action Input/Observation的过程可以重复零次或多次)
Final Answer: 对输入问题的最终答案
开始!
agent数据集格式
{
"id": "MS_Agent_Bench_126374",
"conversations": [{
"from": "system",
"value": "Answer the following questions as best you can. You have access to the following APIs:\n1. hm_recipe_recommend: Call this tool to interact with the hmreciperecommend API. What is the hmreciperecommend API useful for? . Parameters: [{\"name\": \"keywords_dict\", \"description\": \"盒马推荐菜谱关键词字典。\", \"required\": \"True\"}]\n\n2. hm_product_marketing: Call this tool to interact with the hmproductmarketing API. What is the hmproductmarketing API useful for? . Parameters: [{\"name\": \"sku_code_list\", \"description\": \"盒马商品的编码列表\", \"required\": \"True\"}]\n\n3. hm_product_info: Call this tool to interact with the hmproductinfo API. What is the hmproductinfo API useful for? . Parameters: [{\"name\": \"sku_code_list\", \"description\": \"盒马商品的编码列表\", \"required\": \"True\"}, {\"name\": \"sku_name_list\", \"description\": \"盒马商品的名称列表\", \"required\": \"True\"}, {\"name\": \"property_list\", \"description\": \"盒马商品的属性列表\", \"required\": \"True\"}]\n\n4. hm_product_recommend: Call this tool to interact with the hmproductrecommend API. What is the hmproductrecommend API useful for? . Parameters: [{\"name\": \"keywords_dict\", \"description\": \"盒马推荐商品关键词字典。\", \"required\": \"True\"}]\n\nUse the following format:\n\nThought: you should always think about what to do\nAction: the action to take, should be one of the above tools[hm_recipe_recommend, hm_product_marketing, hm_product_info, hm_product_recommend]\nAction Input: the input to the action\nObservation: the result of the action\n... (this Thought/Action/Action Input/Observation can be repeated zero or more times)\nThought: I now know the final answer\nFinal Answer: the final answer to the original input question\nBegin!"
}, {
"from": "user",
"value": "你好,请问你们有哪些手机可以推荐?"
}, {
"from": "assistant",
"value": "Action: hm_product_recommend\nAction Input: {'keywords_dict': {'商品类目': '手机'}}\nObservation: [{'sku_code': '10518244314', 'product_name': '小米11 Ultra 5G手机 256GB', 'bussiness_type': '标品', 'product_price': '5999', 'product_description': '拥有120Hz高刷新率和骁龙888处理器,还配备了高品质相机系统'}, {'sku_code': '10222726664', 'product_name': 'vivo X60 Pro 5G手机 256GB', 'bussiness_type': '标品', 'product_price': '4498', 'product_description': '搭载Exynos 1080处理器与ZEISS联合调校的相机系统,拍照实力十足'}, {'sku_code': '18227073452', 'product_name': '华为畅享 20 Pro 5G手机 128GB', 'bussiness_type': '标品', 'product_price': '2699', 'product_description': '拥有4000mAh的电池容量和优秀的相机而价格非常亲民'}]\nThought: I now know the final answer\nFinal Answer: 您好,我们有以下几款手机供您选择:1.小米11 Ultra 5G手机 256GB:价格为5999元,拥有120Hz高刷新率和骁龙888处理器,还配备了高品质相机系统;2. vivo X60 Pro 5G手机 256GB:售价为4498元,搭载Exynos 1080处理器与ZEISS联合调校的相机系统,拍照实力十足;3. 华为畅享 20 Pro 5G手机 128GB:价格亲民,只需2699元即可拥有优秀的相机和4000mAh的电池容量。这些手机都具有不同的特点和功能,您可以根据自己的需求进行选择。如果您有其他问题或需求,请随时告诉我。"
}, {
"from": "user",
"value": "我想买一款拍照好的手机,有推荐吗?"
}, {
"from": "assistant",
"value": "Action: hm_product_recommend\nAction Input: {'keywords_dict': {'商品类目': '手机', '适用场景': '拍照'}}\nObservation: [{'sku_code': '15956662254', 'product_name': '小米11 Ultra 5G手机 256GB', 'bussiness_type': '标品', 'product_price': '5999', 'product_description': '拥有120Hz高刷新率和骁龙888处理器,还配备了高品质相机系统'}, {'sku_code': '19424216918', 'product_name': 'vivo X60 Pro 5G手机 256GB', 'bussiness_type': '标品', 'product_price': '4498', 'product_description': '搭载Exynos 1080处理器与ZEISS联合调校的相机系统,拍照实力十足'}, {'sku_code': '14347982715', 'product_name': 'OPPO Ace2 5G手机 256GB', 'bussiness_type': '标品', 'product_price': '3999', 'product_description': '拍照实力十足,支持65W超级闪充'}]\nThought: I now know the final answer\nFinal Answer: 如果您想要一款拍照表现出色的手机,我为您推荐以下几款产品:1.小米11 Ultra 5G手机 256GB:价格为5999元,配备了高品质相机系统,可以拍摄出色的照片;2. vivo X60 Pro 5G手机 256GB:售价为4498元,相机系统由ZEISS联合调校,拍照实力十足;3. OPPO Ace2 5G手机 256GB:价格为3999元,不仅拍照实力十足,还支持65W超级闪充,让你的手机充电更加便捷。这些手机都有不同的特点和功能,您可以根据自己的需求进行选择。如果您还有其他问题或需求,请随时告诉我。"
}, {
"from": "user",
"value": "小米11 Ultra拍照性能怎么样?"
}, {
"from": "assistant",
"value": "Action: hm_product_info\nAction Input: {'sku_code_list': ['15956662254'], 'sku_name_list': ['小米11 Ultra 5G手机 256GB'], 'property_list': [['拍照性能']]}\nObservation: [{'sku_code': '15956662254', 'property': {'拍照性能': '小米11 Ultra 5G手机配备了1亿像素的主摄像头,还有120X超长焦电影摄像头,以及20MP超广角摄像头等组合,拍照性能非常出色。'}}]\nThought: I now know the final answer\nFinal Answer: 小米11 Ultra 5G手机配备了1亿像素的主摄像头,还有120X超长焦电影摄像头,以及20MP超广角摄像头等组合,拍照性能非常出色。如果您还有其他问题或需求,请随时告诉我。"
}]
}
微调
指令微调阶段使用了已标注数据。这个阶段训练的数据集数量不会像预训练阶段那么大,最多可以达到几千万条,最少可以达到几百条到几千条。指令微调可以将预训练的知识“涌现”出来,进行其他类型的任务,如问答类型的任务。一般指令微调阶段对于在具体行业上的应用是必要的,但指令微调阶段一般不用于灌注大量新知识,而是将已有知识的能力以某类任务的形式展现出来。
指令微调任务有多种场景,比较常用的有:
- 风格化:特定的问答范式
- 自我认知:自我认知改变
- 能力增强:模型本身能力不够,对具体行业的数据理解不良
- Agent:支持Agent能力,比如程序编写、API调用等
上述只是举了几个例子,一般来说距离用户最近的训练方式就是指令微调。
一般来说,LLM中指的base模型是指经过了预训练(以及进行了一部分通用指令的微调)的模型。Chat模型是经过了大量通用数据微调和人类对齐训练的模型。
如何选择base模型和chat模型进行微调呢?
- 数据量较少的时候(比如小于1w条)建议使用chat模型微调
- 数据量较多、数据较为全面的时候,建议使用base模型微调
当然,如果硬件允许,建议两个模型都进行尝试,选择效果较好的。需要注意的是,chat模型有其独特的输入格式,在微调时一定要遵循。base模型的输入格式一般比较简单(但也需要遵守该格式),而且一般该格式不支持多轮数据集。
如果需要用base模型训练多轮对话,一般需要使用一个支持多轮对话的template。在SWIFT中,可以指定为
default,在训练时只需要指定--template_type default即可。
重要概念
- loss 代表模型求解的y和实际的y值的差异。该值会进行loss.backward(),这个方法会求解梯度,并将对应梯度值记录在每个参数上
loss可以理解为根据模型计算出来的值和正确值的偏差(也就是残差)。 例如,回归任务中计算的值是1.0,而实际的值应当为2.0,那么loss为2.0-1.0=1.0。上述loss类型为MAE,除此外,还有MSE,Hinge等各类loss。一般分类任务的loss为交叉熵(Cross-Entropy),这也是目前LLM最常用的loss。
loss计算出来后(这个过程也就是forward,即前向推理),经过backward过程即可计算出梯度。
梯度:光滑的曲面上导数变化最大的方向
loss可以经过PyTorch的loss.backward()将每个算子、每个步骤的梯度都计算出来(复杂微分方程的链式求导过程),当有了梯度后,可以将参数往负梯度方向更新,学习率(lr)就是这时候起作用的,由于直接加上负梯度太大,可能直接产生震荡,即值从一个点瞬间跑到了曲线上的另一个点,导致在这两点反复震荡不收敛,因此乘以一个lr,让loss一点点下降。
-
epoch 代表对数据集训练多少轮次
-
iter 对输入数据的每次forward+backward代表一个iter
-
batch_size 批处理大小。在一次前向推理中,同时处理多少行数据。由于同一批数据会并行求解梯度,因此batch_size越大,梯度越稳定。在SFT时较为合适的梯度一般选择为16/32/64等值
-
batch_size越大,并行计算消耗的显存越高。因此在低显存情况下,可以选用batch_size=1,gradient_accumulation_steps=16。训练会在iter%gradient_accumulation_steps==0时集中进行一次参数更新。在iter%gradient_accumulation_steps!=0时,会将梯度值不断累加到参数上,这样就相当于将batch_size扩大了gradient_accumulation_steps倍
-
learning_rate 学习率 训练将负梯度值乘以该值加到原参数上。换句话说,每次只将参数更新一个小幅度,避免向错误的更新方向移动太多。
一般LoRA的学习率可以比全参数训练的学习率稍高一点,因为全参数训练会完全重置所有参数,训练时需要学习率更低。 LLM训练的学习率一般设置在1e-4~1e-5不等
- max_length 输入句子的最大长度。比如设置为4096,那么句子加答案转换为token后最大长度为max_length。这个值会影响显存占用,需要按照自己的实际需求设置。
-
当batch_size大于1时,意味着不同句子的长度可能不同。data_collator的作用就是按照固定max_length或者batch中的最大长度对其他句子的token进行补齐。补齐的部分不参与模型的loss计算,但仍然会占用计算量
-
flash_attention flash attention是一种针对attention结构高效计算的组件,该组件主要原理利用了显卡的高速缓存。flash attention会节省约20%~40%训练显存并提高训练速度,对训练精度没有不良影响。在显卡支持的情况下建议开启。
-
optimizer
optimizer是深度学习中的优化器,负责将负梯度值累加到原来需要更新的参数上,类似于:
Vanilla SGD
weights = weights - learning_rate * grad
实际的原理会比较复杂,比如常用的AdamW实际上是一个复杂的滑动平均的算法。
- lr_scheduler
一般来说,训练各个阶段的学习率是不一样的,有时候需要越来越小(因为训练到最后需要更精细的调节),有时候需要先有个warmup(先将lr从0增大到指定值,再慢慢减小),lr_scheduler就是用来动态调整lr使用的组件。
- gradient_checkpointing 梯度检查点。该方法的原理是将训练时的中间变量在前向过程中暂时丢弃,并在后向过程中重新计算。该方法可以有效节省训练显存,但属于时间换空间的做法,因此训练时间会变长。对显存的节省可以达到30%-70%不等。训练速度会减慢20%-40%不等。
我们默认在训练时设置--gradient_checkpointing true来节约显存, 这会略微降低训练速度.
如果你想要使用量化参数--quantization_bit 4, 你需要先安装bnb: pip install bitsandbytes -U. 这会减少显存消耗, 但通常会降低训练速度.
如果你想要使用基于auto_gptq的量化, 你需要先安装对应cuda版本的auto_gptq: pip install auto_gptq -U.
使用auto_gptq的模型可以查看LLM支持的模型. 建议使用auto_gptq, 而不是bnb.
如果你想要使用deepspeed, 你需要pip install deepspeed -U. 使用deepspeed可以节约显存, 但可能会略微降低训练速度.
如果你的训练涉及到知识编辑的内容, 例如: 自我认知微调, 你需要在MLP上也加上LoRA, 否则可能会效果不佳. 你可以简单传入参数--lora_target_modules ALL来对所有的linear(qkvo, mlp)加上lora, 这通常是效果最好的.
如果你使用的是V100等较老的GPU, 你需要设置--dtype AUTO或者--dtype fp16, 因为其不支持bf16.
如果你的机器是A100等高性能显卡, 且模型支持flash-attn, 推荐你安装flash-attn, 这将会加快训练和推理的速度以及显存占用(A10, 3090, V100等显卡不支持flash-attn进行训练). 支持flash-attn的模型可以查看LLM支持的模型
如果你要进行二次预训练, 多轮对话, 你可以参考自定义与拓展
如果你需要断网进行训练, 请使用--model_id_or_path <model_dir>和设置--check_model_is_latest false. 具体参数含义请查看命令行参数.
如果你想在训练时, 将权重push到ModelScope Hub中, 你需要设置--push_to_hub true.
如果你想要在推理时, 合并LoRA权重并保存,你需要设置--merge_lora true. 不推荐对qlora训练的模型进行merge, 这会存在精度损失. 因此不建议使用qlora进行微调, 部署生态不好.
分布式训练(Distributed Training)
由于较大模型可能在单张显卡上显存溢出,或者训练速度不够,因此单机多卡或多机多卡训练是必要的。在训练过程中的分布式训练有以下几种模式:
-
DDP 分布式数据并行。将训练集的数据分段拆分到不同的进程中,这种训练方式相当于增加了batch_size。比如四个进程,每个进程batch_size=1,则总体batch_size=4。在计算梯度时,torch框架会自动将四个进程的梯度进行累加平均。该方法会提高训练速度,但如果模型在单张显卡上显存溢出,DDP方式也无法运行。
-
MP 模型并行。模型并行分为多种方式,如tensor并行、device_map、流水线并行、FSDP等。
-
tensor并行:将矩阵拆分到多张显卡上,比如,将一个2048x2048的矩阵,拆分为两个1024x2048的矩阵,在前向推理时在显卡间通讯,完成一次推理,这样一个模型的显存需求就被平均拆分到两个显卡上。tensor并行最知名的框架是Megatron。
-
device_map并行:自动计算如何将模型拆分到多个显卡上。比如一个模型按照顺序分为embedder、layer0~95、output,device_map可能将这些参数均分到两张显卡上,比如embedder、layer0~48分配到显卡1上,layer49~95、output分配到显卡2上。相比Megatron,device_map方式较为低效,因为使用该方法训练或推理时,显卡1计算时显卡2是空闲的,计算效率较低;而Megatron是同时使用两个显卡计算,效率较高
-
流水线并行:类似于device_map,将模型按照layer拆分到不同显卡上
-
FSDP,在讲FSDPqian需要先讲解DeepSpeed的ZeRO优化方式
-
ZeRO-1:类似DDP,但是将Optimizer的state均分维护到不同的进程中,每次更新参数后对所有进程的参数进行同步更新
-
ZeRO-2:在ZeRO-1的基础上,将不同层的梯度值均分维护到不同的进程中,每次每个进程同步梯度后更新自己负责的梯度对应的参数部分,并在更新后对所有的进程的参数进行同步
-
ZeRO-3:在ZeRO-2的基础上,将不同层的模型参数也均分到不同的进程中。每个进程在计算某层结果时,从其他进程中获得对应的层的参数,计算完后抛弃该层参数;backward时,也从其他进程获得对应层的参数并同步梯度信息,计算完后抛弃该层参数。这样每个进程就在仅保存某些层的参数的条件下完成了数据并行计算
-
FSDP就是ZeRO-3的并行策略
-
项目
使用说明 https://github.com/modelscope/swift/blob/main/docs/source/LLM/%E8%87%AA%E5%AE%9A%E4%B9%89%E4%B8%8E%E6%8B%93%E5%B1%95.md
数据集与模型 https://github.com/modelscope/swift/blob/main/docs/source/LLM/%E6%94%AF%E6%8C%81%E7%9A%84%E6%A8%A1%E5%9E%8B%E5%92%8C%E6%95%B0%E6%8D%AE%E9%9B%86.md
可视化微调
swift web-ui
预训练与微调chat
import os
os.environ['CUDA_VISIBLE_DEVICES'] = '0'
from swift.llm import DatasetName, ModelType, SftArguments, sft_main
sft_args = SftArguments(
model_type=ModelType.qwen1half_0_5b_chat,
dataset=['./a.jsonl',f'{DatasetName.alpaca_zh}#500',
f'{DatasetName.self_cognition}#500'],
logging_steps=5,
max_length=2048,
learning_rate=1e-4,
output_dir='output',
lora_target_modules=['ALL'],
model_name=['小黄', 'Xiao Huang'],
model_author=['魔搭', 'ModelScope'])
output = sft_main(sft_args)
best_model_checkpoint = output['best_model_checkpoint']
print(f'best_model_checkpoint: {best_model_checkpoint}')
偏好训练
import os
os.environ['CUDA_VISIBLE_DEVICES'] = '0'
from swift.llm import DatasetName, ModelType,rlhf_main,RLHFArguments
dpo_args = RLHFArguments(
model_type=ModelType.qwen1half_0_5b_chat,
rlhf_type='dpo',
dataset=['./c.jsonl'],
num_train_epochs=2,
logging_steps=5,
max_length=2048,
learning_rate=1e-4,
output_dir='output',
lora_target_modules=['ALL'],
model_name=['小黄', 'Xiao Huang'],
model_author=['魔搭', 'ModelScope'])
output = rlhf_main(dpo_args)
best_model_checkpoint = output['best_model_checkpoint']
print(f'best_model_checkpoint: {best_model_checkpoint}')
微调后测试
import os
os.environ['CUDA_VISIBLE_DEVICES'] = '0'
from swift.llm import (
get_model_tokenizer, get_template, inference, ModelType, get_default_template_type,
)
from swift.utils import seed_everything
from swift.tuners import Swift
seed_everything(42)
ckpt_dir = 'output/qwen1half-0_5b-chat/v3-20240629-171911/checkpoint-31'
model_type = ModelType.qwen1half_0_5b_chat
template_type = get_default_template_type(model_type)
model, tokenizer = get_model_tokenizer(model_type, model_kwargs={'device_map': 'auto'})
model.generation_config.max_new_tokens = 128
model = Swift.from_pretrained(model, ckpt_dir, inference_mode=True)
template = get_template(template_type, tokenizer)
query = '你是谁'
response, history = inference(model, template, query)
print(f'response: {response}')
print(f'history: {history}')
可视化评估
import os
os.environ['CUDA_VISIBLE_DEVICES'] = '0'
from swift.llm import InferArguments, merge_lora_main, app_ui_main
best_model_checkpoint = 'qwen-7b-chat/vx-xxx/checkpoint-xxx'
infer_args = InferArguments(
ckpt_dir=best_model_checkpoint,
eval_human=True)
# merge_lora_main(infer_args)
result = app_ui_main(infer_args)
导出
!CUDA_VISIBLE_DEVICES=0 swift export \
--ckpt_dir output/qwen1half-0_5b-chat/v3-20240629-171911/checkpoint-31 \
--quant_bits 4 --quant_method awq \
--merge_lora true
量化后测试
import os
os.environ['CUDA_VISIBLE_DEVICES'] = '0'
from swift.llm import (
ModelType, get_vllm_engine, get_default_template_type,
get_template, inference_vllm
)
import torch
model_type = ModelType.qwen1half_7b_chat
model_id_or_path = 'output/qwen1half-0_5b-chat/v2-20240629-084316/checkpoint-62-awq-int4'
model, tokenizer = get_model_tokenizer(model_id_or_path=model_id_or_path, torch.float16,
model_kwargs={'device_map': 'auto'}, **kwargs)
template = get_template(template_type, tokenizer)
query = '你是谁'
response, history = inference(model, template, query,[])
print(f'response: {response}')
print(f'history: {history}')