一、模型简介
原子大模型Atom由Llama中文社区和原子回声联合打造,在中文大模型评测榜单C-Eval中位居前十(8月21日评测提交时间)。
Atom系列模型包含Atom-7B和Atom-13B,基于Llama2做了中文能力的持续优化。Atom-7B和Atom-7B-Chat目前已完全开源,支持商用,可在Hugging Face仓库获取模型,详情见Atom-7B下载。
Atom大模型针对中文做了以下优化:
大规模的中文数据预训练
原子大模型Atom在Llama2的基础上,采用大规模的中文数据进行持续预训练,包含百科、书籍、博客、新闻、公告、小说、金融数据、法律数据、医疗数据、代码数据、专业论文数据、中文自然语言处理竞赛数据集等,详见? 数据来源。
同时对庞大的数据进行了过滤、打分、去重,筛选出超过1T token的高质量中文数据,持续不断加入训练迭代中。
更高效的中文词表
为了提高中文文本处理的效率,我们针对Llama2模型的词表进行了深度优化。首先,我们基于数百G的中文文本,在该模型词表的基础上扩展词库至65,000个单词。经过测试,我们的改进使得中文编码/解码速度提高了约350%。此外,我们还扩大了中文字符集的覆盖范围,包括所有emoji符号?。这使得生成带有表情符号的文章更加高效。
自适应上下文扩展
Atom大模型默认支持4K上下文,利用位置插值PI和Neural Tangent Kernel (NTK)方法,经过微调可以将上下文长度扩增到32K。
? 中文数据
我们通过以下数据来优化Llama2的中文能力:
类型 描述 网络数据 互联网上公开的网络数据,挑选出去重后的高质量中文数据,涉及到百科、书籍、博客、新闻、公告、小说等高质量长文本数据。 Wikipedia 中文Wikipedia的数据 悟道 中文悟道开源的200G数据 Clue Clue开放的中文预训练数据,进行清洗后的高质量中文长文本数据 竞赛数据集 近年来中文自然语言处理多任务竞赛数据集,约150个 MNBVC MNBVC 中清洗出来的部分数据集由于自己电脑没有配置独显,想用CPU来跑大模型看看(中间遇到比较多的坑),记录一下完整的过程,给大家予以借鉴。
二、模型下载
1、git hub地址
GitHub - FlagAlpha/Llama2-Chinese: Llama中文社区,最好的中文Llama大模型,完全开源可商用下载源码:GitHub - FlagAlpha/Llama2-Chinese: Llama中文社区,最好的中文Llama大模型,完全开源可商用
2、 可在Atom-7B-Chat Hugging Face仓库获取模型
1)由于hugging face无法直接访问,推荐一个速度较快、好用的“科学上网”工具91merry 科学上网,我买的30/季度,每月100G流量,我百兆带宽实际下载最大能够达到15M/s。
2)把这里面的每一个文件都下载了。(推荐用IDM,浏览器默认的下载没IDM快,总共下载下来大概14G)
三、模型部署
1、单独弄一个大模型的python虚拟环境,避免包冲突
python -m venv llama_env
source llama_env/bin/activate # 在 Windows cmd执行 `llama_env\Scripts\activate`
2、下载python相关依赖包
ps:由于github下载的代码里面requirements.txt是基于有独显的场景,按照官网的在纯cpu环境会运行不起来 。
打开PyTorch官网:Start Locally | PyTorch,选择自己对应的环境,会生成相应的命令。
pip3 install torch torchvision torchaudio
安装其它的包
pip install scipy sentencepiece datasets evaluate transformers tensorboard gradio
3、修改有页面的执行代码,可以在浏览器交互的方式运行(Llama2-Chinese\examples\chat_gradio.py文件)
import gradio as gr
import time
from transformers import AutoTokenizer, AutoModelForCausalLM,TextIteratorStreamer
from threading import Thread
import torch,sys,os
import json
import pandas
import argparse
with gr.Blocks() as demo:
gr.Markdown("""<h1><center>智能助手</center></h1>""")
chatbot = gr.Chatbot()
msg = gr.Textbox()
state = gr.State()
with gr.Row():
clear = gr.Button("新话题")
re_generate = gr.Button("重新回答")
sent_bt = gr.Button("发送")
with gr.Accordion("生成参数", open=False):
slider_temp = gr.Slider(minimum=0, maximum=1, label="temperature", value=0.3)
slider_top_p = gr.Slider(minimum=0.5, maximum=1, label="top_p", value=0.95)
slider_context_times = gr.Slider(minimum=0, maximum=5, label="上文轮次", value=0,step=2.0)
def user(user_message, history):
return "", history + [[user_message, None]]
def bot(history,temperature,top_p,slider_context_times):
if pandas.isnull(history[-1][1])==False:
history[-1][1] = None
yield history
slider_context_times = int(slider_context_times)
history_true = history[1:-1]
prompt = ''
if slider_context_times>0:
prompt += '\n'.join([("<s>Human: "+one_chat[0].replace('<br>','\n')+'\n</s>' if one_chat[0] else '') +"<s>Assistant: "+one_chat[1].replace('<br>','\n')+'\n</s>' for one_chat in history_true[-slider_context_times:] ])
prompt += "<s>Human: "+history[-1][0].replace('<br>','\n')+"\n</s><s>Assistant:"
input_ids = tokenizer([prompt], return_tensors="pt",add_special_tokens=False).input_ids[:,-512:]
generate_input = {
"input_ids":input_ids,
"max_new_tokens":512,
"do_sample":True,
"top_k":50,
"top_p":top_p,
"temperature":temperature,
"repetition_penalty":1.3,
"streamer":streamer,
"eos_token_id":tokenizer.eos_token_id,
"bos_token_id":tokenizer.bos_token_id,
"pad_token_id":tokenizer.pad_token_id
}
thread = Thread(target=model.generate, kwargs=generate_input)
thread.start()
start_time = time.time()
bot_message =''
print('Human:',history[-1][0])
print('Assistant: ',end='',flush=True)
for new_text in streamer:
print(new_text,end='',flush=True)
if len(new_text)==0:
continue
if new_text!='</s>':
bot_message+=new_text
if 'Human:' in bot_message:
bot_message = bot_message.split('Human:')[0]
history[-1][1] = bot_message
yield history
end_time =time.time()
print()
print('生成耗时:',end_time-start_time,'文字长度:',len(bot_message),'字耗时:',(end_time-start_time)/len(bot_message))
msg.submit(user, [msg, chatbot], [msg, chatbot], queue=False).then(
bot, [chatbot,slider_temp,slider_top_p,slider_context_times], chatbot
)
sent_bt.click(user, [msg, chatbot], [msg, chatbot], queue=False).then(
bot, [chatbot,slider_temp,slider_top_p,slider_context_times], chatbot
)
re_generate.click( bot, [chatbot,slider_temp,slider_top_p,slider_context_times], chatbot )
clear.click(lambda: [], None, chatbot, queue=False)
if __name__ == "__main__":
parser = argparse.ArgumentParser()
parser.add_argument("--model_name_or_path", type=str, help='mode name or path')
parser.add_argument("--is_4bit", action='store_true', help='use 4bit model')
args = parser.parse_args()
tokenizer = AutoTokenizer.from_pretrained(args.model_name_or_path,use_fast=False)
tokenizer.pad_token = tokenizer.eos_token
if args.is_4bit==False:
model = AutoModelForCausalLM.from_pretrained(args.model_name_or_path,device_map='auto',torch_dtype=torch.float32,offload_folder='E:\llm\Llama2-Chinese\llama_env\offload')
model.eval()
else:
from auto_gptq import AutoGPTQForCausalLM
model = AutoGPTQForCausalLM.from_quantized(args.model_name_or_path,low_cpu_mem_usage=True, use_triton=False,inject_fused_attention=False,inject_fused_mlp=False)
streamer = TextIteratorStreamer(tokenizer,skip_prompt=True)
if torch.__version__ >= "2" and sys.platform != "win32":
model = torch.compile(model)
demo.queue().launch(share=False, debug=True,server_name="127.0.0.1")
4、新建一个py文件,可以命令行模式运行
import torch
from transformers import AutoTokenizer, AutoModelForCausalLM
# 这里面是你下载的Atom-7B-Chat模型的文件位置和添加offload的文件位置,cpu环境下必须要有offload
model = AutoModelForCausalLM.from_pretrained('E:\llm\Llama2-Chinese\llama_env\Atom-7B-Chat',device_map='auto',torch_dtype=torch.float32,
offload_folder='E:\llm\Llama2-Chinese\llama_env\offload')
model =model.eval()
tokenizer = AutoTokenizer.from_pretrained('E:\llm\Llama2-Chinese\llama_env\Atom-7B-Chat',use_fast=False)
tokenizer.pad_token = tokenizer.eos_token
input_ids = tokenizer(['<s>Human: 请帮我写一篇针对中国足球发展的分析\n</s><s>Assistant: '], return_tensors="pt",add_special_tokens=False).input_ids
generate_input = {
"input_ids":input_ids,
"max_new_tokens":512,
"do_sample":True,
"top_k":50,
"top_p":0.95,
"temperature":0.3,
"repetition_penalty":1.3,
"eos_token_id":tokenizer.eos_token_id,
"bos_token_id":tokenizer.bos_token_id,
"pad_token_id":tokenizer.pad_token_id
}
generate_ids = model.generate(**generate_input)
text = tokenizer.decode(generate_ids[0])
print(text)
四、模型运行
1、运行修改后的Llama2-Chinese\examples\chat_gradio.py文件
python examples/chat_gradio.py --model_name_or_path E:\llm\Llama2-Chinese\llama_env\Atom-7B-Chat
2、由于是只使用cpu,比较吃内存,原先电脑内存16G的情况下跑不起来,跑到50%就奔溃了,后面加了两根16G内存条,组成了48G内存才能跑起来。跑起来占用内存在38G左右。
3、运行后的界面
PS:使用CPU运行大模型还真是吃内存,生成结果的时候也比较慢,建议大家还是上英伟达的显卡的。
接下来想把本地的一些医学数据进行训练,看看结果怎么样。