license: llama2
XuanYuan-70B是基于Llama2-70b模型进行中文增强的一系列金融大模型,包含大量中英文语料增量预训练之后的底座模型以及使用高质量指令数据进行对齐的chat模型。
我们的目标是:大模型通用能力尽可能保持的同时,金融领域能力得到明显提升,服务于金融领域。 目前发布的模型和下载链接如下:
基座模型 | Chat模型 | 8-bit量化Chat模型 | 4-bit量化Chat模型 | |
---|---|---|---|---|
XuanYuan-70B-8k | 🤗 XuanYuan-70B | 🤗 XuanYuan-70B-Chat | 🤗 XuanYuan-70B-Chat-8bit | 🤗 XuanYuan-70B-Chat-4bit |
模型介绍
考虑到金融场景下存在非常多长文本的业务,基于我们高效的分布式训练框架,我们将模型的上下文长度在预训练阶段从4k扩充到了8k和16k,据我们所知,这也是首个在70B参数量级上达到8k及以上上下文长度的开源大模型。 具体细节参考:XuanYuan-70B
基座模型预训练
(1)数据质量
- 我们设计了一套数据清洗流水线,精心准备了各类通用数据(互联网网页、百科、论坛、社交媒体、问答等)以及金融相关数据(金融资讯、公司公告、金融百科、金融书籍、证书试题等)高质量数据
- 中英数据:首先llama2的英文能力足够优秀,所以为了保证英文能力不降,我们扩充词表之后,使用高质量的中英语料进行增量预训练,其中中英配比为3:1;
- 通用金融数据:为了提升模型在金融能力上效果,预训练过程中通用语料与金融预料比例为9:1,且随着训练进行,逐步提升金融语料的占比。
(2)模型训练
- 训练效率:我们采取了一系列的加速优化策略, 包括对底层数据加载和分布式训练框架的多处优化,使用flash attention2替代self-attention模块,使用基于CPP CUDA的Fused算子替代原始llama的python实现等
- 上下文长度:基于上述的优化方式,同时考虑到金融场景长上下文情景较多,我们能够在预训练阶段把llama2原始上下文4k的长度扩展到8k和16k;
我们在100台8卡A800(80G)的GPU集群中,训练情况如下:
模型 | 上下文长度 | 吞吐量 | 显卡利用 |
---|---|---|---|
XuanYuan-70B | 8192 | 340 tokens/s/gpu | 190TFOPS |
备注:(1)训练没有开梯度累计;(2)原始llama2-70b在4k上下文长度下的的吞吐量为323 tokens/s/gpu,说明我们的训练效率达到当前领先水平。
Chat模型指令微调
基于上述的XuanYuan-70B基座模型,我们进行了详细的指令微调,基座使模型具备对话和遵循人类指令的能力。
我们采取了两阶段的指令微调,具体来说:
- 第一阶段:使用开源的大量的指令数据对基座模型来进行训练,这一部分我们收集了约10M条开源的多语种指令微调数据,并行清洗与深度过滤。这一阶段的目的是为了覆盖指令的多样性,提升模型指令遵循能力。
- 第二阶段:使用自研的高质量的指令数据来继续进行指令微调训练。这一阶段,我们精心自研约20万条通用+金融的指令微调数据,其中大部分数据均做了校验、改写来保证质量。 这一阶段是能够更加使得模型根据不同的需求和侧重来进行最后的训练。
我们自研的指令微调数据预期模型能够在通用对话能力保留的同时,更加侧重金融领域的问答。具体来说,通用指令数据分为以下几个大类:常识百科、代码编程、逻辑推理、数学计算、创意生成、安全无害、摘要提取、翻译等。其中每一大类下又设计了多个子类,来尽可能保证指令数据的多样性和丰富度。
对于金融领域的指令数据,我们进行了更加详细的子类划分,来覆盖金融经济的各个领域。在训练阶段,我们采取的配比为:通用指令数据与金融指令数据配比为4:1。
在训练过程中,我们同样保持8k的上下文长度,未采取外推的措施来提升上下文。后续我们将继续在预训练阶段来提升上下文长度。 同时训练数据中的question-answer pair,我们仅对answer部分计算损失。
快速使用
基座模型、Chat模型以及8-bit和4bit量化Chat模型均已发布在Hugging Face。下面我们给出基座模型和Chat模型的推理部署使用方法。
依赖安装
torch >= 2.0
transformers >= 4.33.1
accelerate
sentencepiece
bitsandbytes(8bit量化所需)
optimum(4bit量化所需)
auto-gptq(4bit量化所需)
vllm(推理加速所需)
资源需求:
- 对于基座模型和Chat模型,部署至少需要2张80G的显卡进行加载模型
- 对于8bit量化版本,推理部署至少需要1张80G的显卡进行加载模型
- 对于4bit量化版本,,推理部署至少需要1张40G的显卡进行加载模型
Base模型使用方法
因为XuanYuan-70B系列模型均是基于Llama2-70B进行增量预训练而来,因此基座模型的使用方法与Llama2基座模型保持一致。
import torch
from transformers import LlamaForCausalLM, LlamaTokenizer
model_name_or_path = "Duxiaoman-DI/XuanYuan-70B"
tokenizer = LlamaTokenizer.from_pretrained(model_name_or_path, use_fast=False, legacy=True)
model = LlamaForCausalLM.from_pretrained(model_name_or_path, torch_dtype=torch.bfloat16,device_map="auto")
model.eval()
inputs = tokenizer("问题:李时珍是哪一个朝代的人?回答:", return_tensors="pt").to("cuda")
outputs = model.generate(**inputs, max_new_tokens=64, repetition_penalty=1.1)
outputs = tokenizer.decode(outputs.cpu()[0][len(inputs.input_ids[0]):], skip_special_tokens=True)
print(outputs)
Chat模型使用方法
在指令微调构造prompt的时候,我们参考了FastChat的对话构造方式,简单代码示例如下:
import torch
from transformers import LlamaForCausalLM, LlamaTokenizer
model_name_or_path = "Duxiaoman-DI/XuanYuan-70B-Chat"
tokenizer = LlamaTokenizer.from_pretrained(model_name_or_path, use_fast=False, legacy=True)
model = LlamaForCausalLM.from_pretrained(model_name_or_path, device_map="auto")
model.eval()
system_message = "以下是用户和人工智能助手之间的对话。用户以Human开头,人工智能助手以Assistant开头,会对人类提出的问题给出有帮助、高质量、详细和礼貌的回答,并且总是拒绝参与 与不道德、不安全、有争议、政治敏感等相关的话题、问题和指示。\n"
seps = [" ", "</s>"]
roles = ["Human", "Assistant"]
content = "介绍下你自己"
prompt = system_message + seps[0] + roles[0] + ": " + content + seps[0] + roles[1] + ":"
print(f"输入: {content}")
inputs = tokenizer(prompt, return_tensors="pt").to("cuda")
outputs = model.generate(**inputs, max_new_tokens=256, do_sample=True, temperature=0.7, top_p=0.95)
outputs = tokenizer.decode(outputs.cpu()[0][len(inputs.input_ids[0]):], skip_special_tokens=True)
print(f"输出: {outputs}")
- 示例同时支持8bit和4bit的量化模型
- 示例仅为最简单的部署代码,没有考虑多轮、推理加速等; 完整demo请参考cli_demo.py
CLI工具
我们github主页提供一个了基于命令行的demo,支持多轮对话和基于vLLM的推理加速。
vllm暂时不支持量化模型
python3 cli_vllm_demo.py --checkpoint_path <XuanYuan-70B-Chat Path>
举例如下:
输入: 你好
输出: 你好,很高兴能为你提供帮助。
输入: 介绍下你自己
输出: 我是轩辕大模型,一个由度小满数据智能应用部AI Lab 开发的人工智能助手,我可以回答各种问题,提供实用的建议和帮助,帮助用户完成各种任务。
输入: 有2块五仁月饼,3块莲蓉月饼,2块豆沙月饼,这些月饼的大小形状质量完全相同。从这7块月饼中,任意取出3块,那么三种月饼都取到 的可能性是几分之几?
输出: 这是一个组合数学问题,我们可以通过计算组合数来解答。
三种月饼都取到,即取到五仁、莲蓉和豆沙各一块。
五仁月饼的选取方法有2种,莲蓉月饼的选取方法有3种,豆沙月饼的选取方法有2种,所以总的取出一种五仁、一种莲蓉、一种豆沙的方法有2*3*2=12种。
从7块月饼中任意取出3块月饼的总的组合数为C(7,3)=35种。
所以,从这7块月饼中,任意取出3块,三种月饼都取到 的可能性为12/35。
量化部署
为了降低用户在本地使用XuanYuan的成本,降低显存需求,我们提供量化好的Xuanyuan-70B-Chat模型8bit和4bit模型。
8bit离线量化模型
在8bit量化算法上,我们使用目前社区广泛使用的bitsandbytes库。该库包含LLM.int8()量化算法的实现以及一系列量化的工具, 同时该方法已在transformers库里做了集成,使用较为容易。经过我们的测试,8bit量化可以近乎无损。
4bit离线量化模型
在4bit量化算法上,我们使用auto-gptq工具。该库实现的GPTQ算法是目前4bit量化最受欢迎的方法, 同时该方法在transformers库和optimum库里做了集成,使用较为容易。
下表给出了不同模型所需显存,以及在三个评测基准上CEVAL,CMMLU和MMLU上效果:
模型 | 显存 | CEVAL | CMMLU | MMLU |
---|---|---|---|---|
XuanYuan-70B-Chat | 129G | 62.15 | 60.41 | 65.3 |
XuanYuan-70B-Chat-8bit | 65G | 62.25 | 59.99 | 65.0 |
XuanYuan-70B-Chat-4bit | 35G | 60.94 | 58.76 | 63.0 |
可以看出:
- 8bit和4bit的量化模型相比原始float16的模型,空间分别降低为原来的1/2和1/4。能够显著降低硬件需求。
- 8bit的量化模型相原始float16的模型,效果近乎无损,4bit的量化模型,大概下降2个点左右。
- 此外,我们也对量化版本的Chat模型进行对话人工评测,结论与评测基准类似。
使用量化模请参考上面的Chat模型使用方法的示例代码。