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模型配置,主要涉及的文件有:

  1. 模型具体实现:

    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层实现
    
  2. 模型配置:

    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模型推理配置
    
  3. 数据预处理脚本:

    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 数据预处理

  1. 执行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: 输出转换后对话格式的数据路径
    
  2. 执行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卡进行训练。

  1. 修改配置文件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
    
  2. 在分布式节点上执行脚本

    多机多卡训练需要不同节点上执行启动命令,将参数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卡进行训练。

  1. 生成多机分布式权重

    如果使用共享存储,可以将模型完整权重放在共享存储内,同时设置配置文件或脚本参数auto_trans_ckpt=True,使用权重自动转换功能。

    如果不使用共享存储,可以参考多机多卡权重转换完成分布式权重转换后拉起预训练任务。

  2. 修改配置文件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
    
  3. 在分布式节点上执行脚本,进行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下载代码仓。

  1. 构建如下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
    
  2. 提取出代码生成函数的主函数

    由于生成代码会生成多余函数,评测时只需要评测函数即可,函数名为data/HumanEval.jsonl.gz中的entry_point,按照如下结构保存为samples.jsonl

    {'task_id': "HumanEval/0","completion": "inference result"}
    
  3. 安装HumanEval依赖

    pip install -e human-eval
    
    1. 解除human-eval/human_eval/execution.py的第58行注释;
    2. 由于代码生成时会自带prompt,因此将human-eval/human_eval/execution.py第39行的problem["prompt"] + completion 改为 completion即可。
  4. 生成测试分数

    evaluate_functional_correctness samples.jsonl
     # {'pass@1': 0.4695}