以下内容基于开源项目Happy-llm(https://github.com/datawhalechina/happy-llm)。Happy-llm是一个非常有意思的项目,让我们可以基于个人电脑,从0到1,从预训练开始,手搓一个大模型。

我的电脑配置如下:

CPU:Intel I5 13490f,内存:64G DDR4,GPU:RTX 5090,OS:Ubuntu 24.04

一、下载项目

git clone https://github.com/datawhalechina/happy-llm.git

项目的1~4章是介绍大模型的理论,真正模型训练,从第五章开始。

二、准备数据

1、数据下载
首先,我们需要下载预训练数据集。在这里,我们使用两个开源的数据集,包含了大量的中文对话数据,可以用于训练对话生成模型。

1)出门问问序列猴子开源数据集:出门问问序列猴子通用文本数据集由来自网页、百科、博客、问答、开源代码、书籍、报刊、专利、教材、考题等多种公开可获取的数据进行汇总清洗之后而形成的大语言模型预训练语料。总量大概在 10B Token。

2)BelleGroup:350万条中文对话数据集,包含了人机对话、人人对话、人物对话等多种对话数据,可以用于训练对话生成模型。

数据集的下载,我全部改为从国内魔搭,这样就省去了翻墙的麻烦。

cd happy-llm

pip install -i https://mirrors.tuna.tsinghua.edu.cn/pypi/web/simple ../docs/chapter5/code/requirements.txt

mkdir dataset

pip install -i https://mirrors.tuna.tsinghua.edu.cn/pypi/web/simple modelscope 

modelscope download --dataset ddzhu123/seq-monkey

mobvoi_seq_monkey_general_open_corpus.jsonl.tar.bz2 --local_dir your_local_dir

tar -xvf your_local_dir/mobvoi_seq_monkey_general_open_corpus.jsonl.tar.bz2

mkdir BelleGroup

modelscope download --model fq980207/train_3.5M_CN  --local_dir ./BelleGroup

2、对数据集进行处理

python
==========================================
# 1 处理预训练数据
def split_text(text, chunk_size=512):
    """将文本按指定长度切分成块"""
    return [text[i:i+chunk_size] for i in range(0, len(text), chunk_size)]

input_file = 'mobvoi_seq_monkey_general_open_corpus.jsonl'

with open('seq_monkey_datawhale.jsonl', 'a', encoding='utf-8') as pretrain:
    with open(input_file, 'r', encoding='utf-8') as f:
        data = f.readlines()
        for line in tqdm(data, desc=f"Processing lines in {input_file}", leave=False):  # 添加行级别的进度条
            line = json.loads(line)
            text = line['text']
            chunks = split_text(text)
            for chunk in chunks:
                pretrain.write(json.dumps({'text': chunk}, ensure_ascii=False) + '\n')

# 2 处理SFT数据
def convert_message(data):
    """
    将原始数据转换为标准格式
    """
    message = [
        {"role": "system", "content": "你是一个AI助手"},
    ]
    for item in data:
        if item['from'] == 'human':
            message.append({'role': 'user', 'content': item['value']})
        elif item['from'] == 'assistant':
            message.append({'role': 'assistant', 'content': item['value']})
    return message

with open('BelleGroup_sft.jsonl', 'a', encoding='utf-8') as sft:
    with open('BelleGroup/train_3.5M_CN.json', 'r', encoding='utf-8') as f:
        data = f.readlines()
        for item in tqdm(data, desc="Processing", unit="lines"):
            item = json.loads(item)
            message = convert_message(item['conversations'])
            sft.write(json.dumps(message, ensure_ascii=False) + '\n')

三、训练模型

1、训练 Tokenizer

为文本处理训练一个Tokenizer。Tokenizer的作用是将文本转换为数字序列,以便模型能够理解和处理。我们使用的数据集是已经下载的出门问问序列猴子开源数据集,这个数据集包含了大量的中文文本数据,可以用于训练Tokenizer。

将Token的训练程序复制到当前dataset目录:

cp ../docs/chapter5/code/train_tokenizer.py ./

python train_tokenizer.py

这个训练过程,非常吃内存。我的内存64G,把虚拟内存设置为1T。

sudo fallocate -l 1000G /swapfile
sudo chmod 600 /swapfile
sudo mkswap /swapfile
sudo swapon /swapfile
# 在另一个终端运行观察内存
watch -n 1 free -h

如果你的内存+虚拟内存小于1T,很可能运行几个小时,就会因内存用光而程序异常退出。可以直接复制训练好的token,以及模型预训练程序:

cp -r ../docs/chapter5/code/* ./

训练好的tokenizer在tokenizer_k目录。

2、模型预训练

预训练程序如下:

python ddp_pretrain.py --data_path seq_monkey_datawhale.jsonl --gpus 0 --batch_size 18

我的5090,将batch_size 18,大概消耗28G显存,GPU全速运行大概60个小时,就会在base_model_215M看到训练的模型。

如果觉得自己训练太慢,也可以到魔搭上下载Happy-LLM项目预先训练好的模型:

基础模型:modelscope download --model kmno4zx/happy-llm-215M-base  --local_dir ./happy-llm-215M-base

SFT后的模型:modelscope download --model kmno4zx/happy-llm-215M-sft  --local_dir ./happy-llm-215M-sft

四、模型推理

python

============================

import torch
from modelscope import AutoModelForCausalLM, AutoTokenizer

model_id = "happy-llm-215M-sft"

tokenizer = AutoTokenizer.from_pretrained(model_id, trust_remote_code=True)
model = AutoModelForCausalLM.from_pretrained(model_id, torch_dtype=torch.bfloat16, trust_remote_code=True, device_map="cuda:0").eval()

messages = [{"role": "system", "content": "你是一个AI助手"}]

while True:
    prompt = input('User: ')
    messages.append({"role": "user", "content": prompt})

    input_ids = tokenizer.apply_chat_template(messages,tokenize=False,add_generation_prompt=True)
    input_ids = tokenizer(input_ids).data['input_ids']
    x = (torch.tensor(input_ids, dtype=torch.long)[None, ...]).to(model.device)

    with torch.no_grad():
        y = model.generate(x, stop_id=tokenizer.eos_token_id, max_new_tokens=512, temperature=0.6)
        response = tokenizer.decode(y[0].tolist())

    print(f"Assistant: {response}")

    messages.append({"role": "assistant", "content": response})

小结:通过Happy-LLM,可以自己从准备数据、预训练开始,从0到1,训练一个自己的LLM。通过这个项目,可以很好的学习大模型的原理。

Logo

有“AI”的1024 = 2048,欢迎大家加入2048 AI社区

更多推荐