Code Llama
模型描述
Code Llama是基于Llama 2的一系列大型代码语言模型,它在开源模型中提供了最先进的性能、填充能力、对大型输入上下文的支持以及zero-shot指令跟随能力,用于编程任务。现有多种不同版本来覆盖广泛的应用领域:基础模型(Code Llama)、Python专业化模型(Code Llama - Python)和指令跟随模型(Code Llama - Instruct),每个模型分别具有7B、13B和34B个参数。所有模型都是在16k标记序列上进行训练,并对高达100k标记的输入显示出改进效果。7B和13B版本的Code Llama以及Code Llama - Instruct变体支持基于周围内容的填充功能。Code Llama是通过对Llama 2进行更高比例的代码取样进行微调而开发的。
Code Llama: Open Foundation Models for Code
@article{roziere2023code,
title={Code llama: Open foundation models for code},
author={Roziere, Baptiste and Gehring, Jonas and Gloeckle, Fabian and Sootla, Sten and Gat, Itai and Tan, Xiaoqing Ellen and Adi, Yossi and Liu, Jingyu and Remez, Tal and Rapin, J{\'e}r{\'e}my and others},
journal={arXiv preprint arXiv:2308.12950},
year={2023}
}
模型性能
以下模型性能均由Atlas 800T A2硬件环境下测试得出。
| Config | Task | SeqLength | Datasets | Performance | Phase |
|---|---|---|---|---|---|
| codellama_34b_32p | text_generation | 4096 | belle | 667 tokens/s/p | Finetune |
| codellama_34b | text_generation | 4096 | / | 139 tokens/s | Predict |
以下模型性能均由Atlas 900 A2 PoDc硬件环境下测试得出。
| Config | Task | SeqLength | Datasets | Performance | Phase |
|---|---|---|---|---|---|
| codellama_34b_16p | text_generation | 4096 | code-alpaca | 669 tokens/s/p | Finetune |
| codellama_34b_32p | text_generation | 4096 | code-alpaca | 747 tokens/s/p | Finetune |
模型文件
Code Llama 基于 mindformers 实现,本仓库当前支持34b模型配置,主要涉及的文件有:
-
模型具体实现:
mindformers/models/llama ├── __init__.py ├── llama.py # 模型实现 ├── llama_config.py # 模型配置项 ├── llama_layer.py # llama网络层定义 ├── llama_processor.py # llama预处理 ├── llama_tokenizer.py # tokenizer └── llama_transformer.py # transformer层实现 -
模型配置:
configs/codellama ├── pretrain_codellama_34b.yaml # 34b模型预训练启动配置 ├── finetune_codellama_34b_16p.yaml # 34b模型2机16p微调启动配置 ├── finetune_codellama_34b_32p.yaml # 34b模型4机32p微调启动配置 └── predict_codellama_34b.yaml # 34b模型推理配置 -
数据预处理脚本:
mindformers/tools/dataset_preprocess/llama/ ├── alpaca_converter.py # 基于fschat的alpaca数据集格式转换脚本 └── llama_preprocess.py # llama模型的mindrecord数据处理脚本
环境及数据准备
安装环境
MindFormers软硬件配套关系以及安装参考环境安装指南和版本匹配关系。
注:34b推理使用Atlas 800T A2 至少使用2卡,全量微调至少需要2机16卡,建议4机32卡。
数据及权重准备
数据集下载
MindFormers提供Wikitext2作为预训练数据集,code-alpaca作为微调数据集。
| 数据集名称 | 适用模型 | 适用阶段 | 下载链接 |
|---|---|---|---|
| Wikitext2 | CodeLlama_34b | Pretrain | Link |
| code-alpaca | CodeLlama_34b | Finetune | Link |
| HumanEval | CodeLlama_34b | Evaluate | Link |
数据预处理中所用的tokenizer.model可以点击链接进行下载。
-
Wikitext2 数据预处理
使用
mindformers/tools/dataset_preprocess/llama/llama_preprocess.py对下载后的数据进行预处理,并生成Mindrecord数据。python llama_preprocess.py \ --dataset_type wiki \ --input_glob /{path}/wiki.train.tokens \ --model_file /{path}/tokenizer.model \ --seq_length 4096 \ --output_file /{path}/wiki4096.mindrecord # 参数说明 dataset_type: 预处理数据类型 input_glob: 输入下载后wiki.train.tokens的文件路径 model_file: 模型tokenizer.model文件路径 seq_length: 输出数据的序列长度 output_file: 输出文件的保存路径 -
code-alpaca 数据预处理
-
执行
mindformers/tools/dataset_preprocess/llama/alpaca_converter.py,使用fastchat工具添加prompts模板,将原始数据集转换为多轮对话格式。python alpaca_converter.py \ --data_path /{path}/code_alpaca_data.json \ --output_path /{path}/code-alpaca-data-conversation.json # 参数说明 data_path: 下载的alpaca数据路径 output_path: 输出转换后对话格式的数据路径 -
执行
mindformers/tools/dataset_preprocess/llama/llama_preprocess.py,进行数据预处理、Mindrecord数据生成,将带有prompt模板的数据转换为mindrecord格式。# 由于此工具依赖fschat工具包解析prompt模板,请提前安装fschat >= 0.2.13 python llama_preprocess.py \ --dataset_type qa \ --input_glob /{path}/code-alpaca-data-conversation.json \ --model_file /{path}/tokenizer.model \ --seq_length 4096 \ --output_file /{path}/code-alpaca-fastchat4096.mindrecord
模型权重下载
MindFormers提供下载HuggingFace官方权重的下载链接,用户可通过链接下载权重并经过模型权重转换后进行使用。
词表下载链接:tokenizer.model
| 模型名称 | HuggingFace权重 |
|---|---|
| CodeLlama-7b | Link |
| CodeLlama-13b | Link |
| CodeLlama-34b | Link |
| CodeLlama-7b-Python | Link |
| CodeLlama-13b-Python | Link |
| CodeLlama-34b-Python | Link |
| CodeLlama-7b-Instruct | Link |
| CodeLlama_13b-Instruct | Link |
| CodeLlama_34b-Instruct | Link |
模型权重转换
下载完成后,运行转换脚本mindformers/convert_weight.py,将huggingface的权重转换为完整的ckpt权重。
# 使用transformers = 4.34.0,torch>=2.0进行转换
python convert_weight.py --model llama --input_path TORCH_CKPT_DIR --output_path {path}/MS_CKPT_NAME
# 参数说明
model: 模型名称
input_path: 下载HuggingFace权重的文件夹路径
output_path: 转换后的MindSpore权重文件保存路径
预训练
MindFormers提供了Code Llama 34b多机预训练示例,使用Wikitext2数据集对模型进行预训练,数据集可以参考数据集下载获得。
Code Llama 34b由于模型规模较大,仅支持多机预训练,至少使用2机16卡进行训练。
-
修改配置文件
config/codellama/pretrain_codellama_34b.yaml根据服务器节点数等信息,修改相应的并行配置。
parallel_config: data_parallel: 1 model_parallel: 8 pipeline_stage: 2 use_seq_parallel: True micro_batch_num: 128 vocab_emb_dp: True gradient_aggregation_group: 4 -
在分布式节点上执行脚本
多机多卡训练需要不同节点上执行启动命令,将参数
MASTER_ADDR设置为主节点的ip地址, 所有节点设置的ip地址相同,不同节点之间仅参数NODE_RANK不同,具体可参考使用指南。# 节点0,节点ip为{ip_addr},作为主节点,总共16卡且每个节点8卡 bash scripts/msrun_launcher.sh "run_mindformer.py \ --config configs/codellama/pretrain_codellama_34b.yaml \ --train_dataset_dir /path/wiki4096.mindrecord \ --run_mode train" \ 16 8 {ip_addr} 8118 0 output/msrun_log False 300 # 节点1,节点0与节点1启动命令仅参数NODE_RANK不同 bash scripts/msrun_launcher.sh "run_mindformer.py \ --config configs/codellama/pretrain_codellama_34b.yaml \ --train_dataset_dir /path/wiki4096.mindrecord \ --run_mode train" \ 16 8 {ip_addr} 8118 1 output/msrun_log False 300 # 参数说明 config: 配置文件路径 train_dataset_dir: 训练数据集路径 run_mode: 运行模式, 预训练时设置为train
微调
MindFormers提供Code Llama 34b的微调示例,使用code-alpaca数据集对模型进行微调,数据集可以参考数据集下载获得。
全参微调
Code Llama 34b由于模型规模较大,仅支持多机微调,至少使用2机16卡进行训练。
-
生成多机分布式权重
如果使用共享存储,可以将模型完整权重放在共享存储内,同时设置配置文件或脚本参数
auto_trans_ckpt=True,使用权重自动转换功能。如果不使用共享存储,可以参考多机多卡权重转换完成分布式权重转换后拉起预训练任务。
-
修改配置文件
config/codellama/finetune_codellama_34b_16p.yaml根据服务器节点数等信息,修改相应的并行配置。
parallel_config: data_parallel: 1 model_parallel: 8 pipeline_stage: 2 use_seq_parallel: True micro_batch_num: 128 vocab_emb_dp: True gradient_aggregation_group: 4 -
在分布式节点上执行脚本,进行2机16卡微调
多机多卡训练需要不同节点上执行启动命令,将参数
MASTER_ADDR设置为主节点的ip地址, 所有节点设置的ip地址相同,不同节点之间仅参数NODE_RANK不同,具体可参考使用指南。示例使用共享存储并开启
auto_trans_ckpt进行权重自动转换。# 节点0,节点ip为{ip_addr},作为主节点,总共16卡且每个节点8卡 bash scripts/msrun_launcher.sh "run_mindformer.py \ --config configs/codellama/finetune_codellama_34b_16p.yaml \ --load_checkpoint /path/codellama_34b.ckpt \ --auto_trans_ckpt True \ --train_dataset_dir /path/code-alpaca-fastchat4096.mindrecord \ --run_mode finetune" \ 16 8 {ip_addr} 8118 0 output/msrun_log False 300 # 节点1,节点0与节点1启动命令仅参数NODE_RANK不同 bash scripts/msrun_launcher.sh "run_mindformer.py \ --config configs/codellama/finetune_codellama_34b_16p.yaml \ --load_checkpoint /path/codellama_34b.ckpt \ --auto_trans_ckpt True \ --train_dataset_dir /path/code-alpaca-fastchat4096.mindrecord \ --run_mode finetune" \ 16 8 {ip_addr} 8118 1 output/msrun_log False 300 # 参数说明 config: 配置文件路径 load_checkpoint: 模型权重文件路径 auto_trans_ckpt: 是否开启自动权重转换 train_dataset_dir: 训练数据集路径 run_mode: 运行模式, 微调时设置为finetune
分布式训练权重合并
分布式训练(微调)后所得到的权重文件为根据策略切分后的权重,可以手动将切分权重合一,以用于评估和推理。
MindFormers提供自动权重转换和离线权重转换功能,可参考自动转换案例和离线权重转换进行分布式模型权重转换。
推理
MindFormers提供CodeLlama_34b的快速推理脚本,脚本主要通过generate高阶接口实现,支持多卡以及多batch推理。
# 脚本使用
bash scripts/examples/codellama/run_codellama_predict.sh CONFIG_PATH CKPT_PATH DEVICE_NUM
# 参数说明
CONFIG_PATH: 模型配置文件路径
CKPT_PATH: 模型权重文件路径
DEVICE_NUM: 使用卡数
CodeLlama_34b仅支持多卡推理,以CodeLlama_34b4卡推理为例。
bash scripts/examples/codellama/run_codellama_predict.sh \
configs/codellama/predict_codellama_34b.yaml \
path/to/codellama_34b.ckpt 4
# 推理结果
# <s>def bubble_sort(arr):
# n = len(arr)
# for i in range(n):
# ...
# def selection_sort(arr):
# n = len(arr)
# for i in range(n):
# ...
评测
Code Llama当前支持的评测任务如下:
| 任务类型 | 评测指标 | 数据集 |
|---|---|---|
| 代码生成 | Pass@1 | HumanEeval |
代码生成
评测使用HumanEval数据集可通过数据集下载获得,使用git下载代码仓。
-
构建如下
preprocess.py脚本放入数据集代码仓中的human-eval文件夹中,进行数据集预处理。# preprocess.py import argparse from data import stream_jsonl def process_data(tasks): prompt_input = [task["prompt"] for task in tasks] user_ids = [task["task_id"] for task in tasks] entry_inputs = [task["entry_point"] for task in tasks] return prompt_input, user_ids, entry_inputs if __name__ == "__main__": parser = argparse.ArgumentParser("copy prompt") parser.add_argument("--data_path", default="", type=str) args = parser.parse_args() data_list = [] for data in stream_jsonl(args.data_path): data_list.append(data) prompt_input, task_ids, entry_inputs = process_data(data_list) print(prompt_input) print(task_ids) print(entry_inputs) # ['from typing import List\n\n\ndef has_close_e... # ['HumanEval/0', 'HumanEval/1', 'HumanEval/2',... # ['has_close_elements', 'separate_paren_groups',...执行
preprocess.py脚本提取出data/HumanEval.jsonl.gz中的prompt字符串列表,并对其进行推理,得到推理结果:# 运行以下命令可以获得数据集中的输入(prompt_input),任务id(task_ids)和执行函数(entry_points)。 # 比如"HumanEval/0"的输入时from typing import List..., 而该代码的执行函数入口名称为has_close_elements. python preprocess.py --data_path path/to/HumanEval.jsonl.gz -
提取出代码生成函数的主函数
由于生成代码会生成多余函数,评测时只需要评测函数即可,函数名为
data/HumanEval.jsonl.gz中的entry_point,按照如下结构保存为samples.jsonl:{'task_id': "HumanEval/0","completion": "inference result"} -
安装
HumanEval依赖pip install -e human-eval- 解除
human-eval/human_eval/execution.py的第58行注释; - 由于代码生成时会自带prompt,因此将
human-eval/human_eval/execution.py第39行的problem["prompt"] + completion改为completion即可。
- 解除
-
生成测试分数
evaluate_functional_correctness samples.jsonl # {'pass@1': 0.4695}