README.md

Llama 3.1

模型描述

Llama 3.1,是开源Llama系列的最新产品,目前有三个版本:Llama 3.1-8B,Llama 3.1-70B,Llama 3.1-405B。 Llama 3.1在来自公开可用来源的超过15T的数据上进行了预训练。微调数据包括公开可用的指令数据集,以及超过1000万个人工标注的示例。 模型支持上下文窗口长度128K,并使用了新的分词器,词汇表大小达到128256个,采用了分组查询注意力机制(GQA)。 Llama 3.1模型是类GPT模型,是一个生成式的语言模型,主要是用于预测下一个单词。 目前Mindformers支持Llama 3.1-8B,Llama 3.1-70B,敬请期待Llama 3.1-405B。

模型性能

以下模型性能均由Atlas 800T A2硬件环境下测试得出。

Config Task Datasets SeqLength Performance Phase
llama3_1_8b text_generation - 2048 591 tokens/s Predict
llama3_1_70b text_generation - 4096 509 tokens/s Predict

以下模型性能均由Atlas 900 A2 PoDc硬件环境下测试得出。

Config Task Datasets SeqLength Performance Phase
llama3_1_8b text_generation alpaca 8192 2703 tokens/s/p Finetune
llama3_1_70b text_generation alpaca 8192 337 tokens/s/p Finetune

模型文件

Llama 3.1 基于 mindformers 实现,主要涉及的文件有:

  1. 模型具体实现:

    mindformers/models/llama
        ├── __init__.py
        ├── llama.py                  # 模型实现
        ├── llama_config.py           # 模型配置项
        ├── llama_layer.py            # llama网络层定义
        ├── llama_processor.py        # llama预处理
        └── llama_transformer.py      # transformer层实现
    
  2. 模型配置:

    research/llama3_1
        ├──llama3_1_8b
        │    ├── predict_llama3_1_8b.yaml     # 8B推理配置
        │    └── finetune_llama3_1_8b.yaml    # 8B全量微调启动配置
        └──llama3_1_70b
             ├── predict_llama3_1_70b.yaml    # 70B推理配置
             └── finetune_llama3_1_70b.yaml   # 70B全量微调启动配置
    
  3. 数据预处理脚本和任务启动脚本:

    research/llama3_1
        ├── llama3_1_tokenizer.py      # llama3_1 tokenizer处理脚本
        ├── llama3_1_conversation.py   # 微调数据集处理,将原始alpaca转换为对话形式alpaca
        └── llama3_1_preprocess.py     # llama模型的mindrecord数据处理脚本
    

环境及数据准备

安装环境

MindFormers软硬件配套关系以及安装参考环境安装指南版本匹配关系

数据集及权重准备

数据集下载

MindFormers提供alpaca作为微调数据集。

数据集名称 适用模型 适用阶段 下载链接
alpaca llama3_1-8b
llama3_1-70b
Finetune Link

数据预处理中所用的tokenizer.model可以参考模型权重下载进行下载。

  • alpaca 数据预处理

    1. 执行mindformers/tools/dataset_preprocess/llama/alpaca_converter.py,使用fastchat工具添加prompts模板,将原始数据集转换为多轮对话格式。

      python alpaca_converter.py \
        --data_path /{path}/alpaca_data.json \
        --output_path /{path}/alpaca-data-conversation.json
      
      # 参数说明
      data_path:   输入下载的文件路径
      output_path: 输出文件的保存路径
      
    2. 执行research/llama3_1/llama3_1_preprocess.py,生成Mindrecord数据,将带有prompt模板的数据转换为mindrecord格式。

      python llama3_1_preprocess.py \
        --dataset_type qa \
        --input_glob /{path}/alpaca-data-conversation.json \
        --model_file /{path}/tokenizer.model \
        --seq_length 8192 \
        --output_file /{path}/alpaca-fastchat8192.mindrecord
      
      # 参数说明
      dataset_type: 预处理数据类型
      input_glob:   转换后的alpaca的文件路径
      model_file:   模型tokenizer.model文件路径
      seq_length:   输出数据的序列长度
      output_file:  输出文件的保存路径
      

数据处理时候注意bos,eos,pad等特殊ids要和配置文件中model_config里保持一致。

模型权重下载

MindFormers暂时没有提供权重,用户可以下载HuggingFace官方权重经过模型权重转换后进行使用。

词表下载链接:tokenizer.model

模型名称 MindSpore权重 HuggingFace权重
Llama3_1-8B - Link
Llama3_1-70B - Link

注: 请自行申请huggingface上llama3_1使用权限,并安装transformers=4.40版本

模型权重转换

下载完成后,运行mindformers/convert_weight.py转换脚本,将huggingface的权重转换为完整的ckpt权重。

python convert_weight.py --model llama --input_path TORCH_CKPT_DIR --output_path {path}/MS_CKPT_NAME --dtype bf16

# 参数说明
model:       模型名称
input_path:  下载HuggingFace权重的文件夹路径
output_path: 转换后的MindSpore权重文件保存路径
dtype:       转换权重的精度

微调

全参微调

MindSpore Transformers提供 Llama3.1-8B 单机多卡以及 Llama3.1-70B 多机多卡的微调示例,过程中使用 alpaca 数据集对模型进行微调,数据集可以参考数据集下载获得。

单机训练

以Llama3_1-8b为例,Llama3_1-8B在Atlas 800T A2上训练,支持单机/多机训练

使用finetune_llama3_1_8b.yaml进行训练,或修改默认配置文件中的model_config.seq_length ,使训练配置与数据集的seq_length保持一致。

执行命令启动微调任务,在单机上拉起任务。

# 单机8卡默认快速启动
bash scripts/msrun_launcher.sh "run_mindformer.py \
 --register_path research/llama3_1 \
 --config research/llama3_1/llama3_1_8b/finetune_llama3_1_8b.yaml \
 --load_checkpoint model_dir/xxx.ckpt \
 --auto_trans_ckpt True \
 --use_parallel True \
 --run_mode finetune \
 --train_data dataset_dir"

# 参数说明
config:          配置文件路径
load_checkpoint: 权重文件路径
auto_trans_ckpt: 自动权重转换开关
run_mode:        运行模式, 微调时设置为finetune
train_data:      训练数据集路径

多机训练

以llama3_1-70b为例,使用finetune_llama3_1_70b.yaml配置文件,执行8机64卡微调。需要先对权重进行切分,切分权重可以参见权重切分与合并(如果是共享盘也可以开启自动权重转换,使用完整权重)。

多机多卡执行脚本进行分布式训练需要分别在不同节点运行脚本,并将参数MASTER_ADDR设置为主节点的ip地址,所有节点设置的ip地址相同,不同节点之间仅参数NODE_RANK不同,各个参数位置含义参见使用指南

在每台机器上运行以下命令,多机运行命令在每台机器上仅node_num 不同,从0开始计数,命令中主节点ip为第0个节点ip。

# 节点0,设0节点ip为192.168.1.1,作为主节点ip,总共64卡且每个节点8卡
# 节点0、节点1、...节点7 依此修改node_num,比如8机,node_num为0~7。
bash scripts/msrun_launcher.sh "run_mindformer.py \
 --register_path research/llama3_1 \
 --config research/llama3_1/llama3_1_70b/finetune_llama3_1_70b.yaml \
 --load_checkpoint model_dir/xxx.ckpt \
 --train_data dataset_dir \
 --auto_trans_ckpt False \
 --use_parallel True \
 --run_mode finetune" \
 64 8 {主节点ip} 8118 {node_num} output/msrun_log False 300

推理

MindFormers提供Llama3_1-8b的快速推理脚本,脚本主要通过generate高阶接口实现,支持单卡推理。推理输入默认不添加bos字符,如果需要添加可在config中增加add_bos_token选项。

# 脚本使用
bash scripts/examples/llama3/run_llama3_predict.sh PARALLEL CONFIG_PATH CKPT_PATH DEVICE_NUM

# 参数说明
PARALLEL:    是否使用多卡推理, 'single'表示单卡推理, 'parallel'表示多卡推理
CONFIG_PATH: 模型配置文件路径
CKPT_PATH:   模型权重文件路径
VOCAB_FILE:  词表路径
DEVICE_NUM:  使用卡数, 仅开启多卡推理时生效

单卡推理

Llama3_1-8b单卡推理为例。

bash scripts/examples/llama3/run_llama3_predict.sh single \
 research/llama3_1/llama3_1_8b/predict_llama3_1_8b.yaml \
 path/to/llama3_1_8b.ckpt \
 path/to/tokenizer.model

多卡推理

Llama3_1-70b4卡推理为例。Llama3_1-70b权重较大,建议先进行权重切分,参见权重切分与合并

bash scripts/examples/llama3/run_llama3_predict.sh parallel \
 research/llama3_1/llama3_1_70b/predict_llama3_1_70b.yaml \
 path/to/model_dir \
 path/to/tokenizer.model 4

基于MindIE的服务化推理

MindIE,全称Mind Inference Engine,是华为昇腾针对AI全场景业务的推理加速套件。

MindFormers承载在模型应用层MindIE-LLM中,MindIE-LLM是大语言模型推理框架,提供API支持大模型推理能力。

MindIE安装流程请参考MindIE服务化部署文档

以下例子默认已完成MindIE安装部署且仅适用于MindIE RC3版本,且安装路径均为默认路径/usr/local/Ascend/

单卡推理

此例子使用llama3_1-8B模型演示。

修改MindIE启动配置

打开mindie-service中的config.json文件,修改server相关配置。

vim /usr/local/Ascend/mindie/1.0.RC3/mindie-service/conf/config.json

需要关注以下字段的配置

  1. ModelDeployConfig.ModelConfig.backendType

    该配置为对应的后端类型,必填"ms"。

    "backendType": "ms"
    
    1. ModelDeployConfig.ModelConfig.modelWeightPath

      该配置为模型配置文件目录,放置模型和tokenizer等相关文件。

      以llama3_1-8B为例,modelWeightPath的组织结构如下:

      mf_model
       └── llama3_1_8b
              ├── config.json                             # 模型json配置文件
              ├── tokenizer.model                         # 模型vocab文件,hf上对应模型下载
              ├── predict_llama3_1_8b.yaml                # 模型yaml配置文件
              ├── llama3_1_tokenizer.py                   # 模型tokenizer文件,从mindformers仓中research目录下找到对应模型复制
              └── llama3_1_8b.ckpt                        # 单卡模型权重文件
      

      predict_llama3_1_8b.yaml需要关注以下配置:

      load_checkpoint: '/mf_model/llama3_1_8b/llama3_1_8b.ckpt' # 为存放模型单卡权重文件路径
      use_parallel: False
      model:
        model_config:
          type: LlamaConfig
          auto_map:
            AutoTokenizer: [llama3_1_tokenizer.Llama3Tokenizer, null]
      processor:
        tokenizer:
          vocab_file: "/mf_model/llama3_1_8b/tokenizer.model"  #vocab文件路径
      

      模型的config.json文件可以使用save_pretrained接口生成,示例如下:

      from mindformers import AutoConfig
      
      model_config = AutoConfig.from_pretrained("/mf_model/llama3_1_8b/predict_llama3_1_8b.yaml ")
      model_config.save_pretrained(save_directory="/mf_model/llama3_1_8b", save_json=True)
      

      模型权重下载和转换可参考 权重格式转换

      准备好模型配置目录后,设置参数modelWeightPath为该目录路径。

   "modelWeightPath": "/mf_model/llama3_1_8b"

最终修改完后的config.json如下:

{
    "Version": "1.0.0",
    "LogConfig" :
    {
        "logLevel" : "Info",
        "logFileSize" : 20,
        "logFileNum" : 20,
        "logPath" : "logs/mindservice.log"
    },

    "ServerConfig" :
    {
        "ipAddress" : "127.0.0.1",
        "managementIpAddress": "127.0.0.2",
        "port" : 1025,
        "managementPort" : 1026,
        "metricsPort" : 1027,
        "maxLinkNum" : 1000,
        "httpsEnabled" : false,
        "fullTextEnabled" : false,
        "tlsCaPath" : "security/ca/",
        "tlsCaFile" : ["ca.pem"],
        "tlsCert" : "security/certs/server.pem",
        "tlsPk" : "security/keys/server.key.pem",
        "tlsPkPwd" : "security/pass/key_pwd.txt",
        "tlsCrl" : "security/certs/server_crl.pem",
        "managementTlsCaFile" : ["management_ca.pem"],
        "managementTlsCert" : "security/certs/management/server.pem",
        "managementTlsPk" : "security/keys/management/server.key.pem",
        "managementTlsPkPwd" : "security/pass/management/key_pwd.txt",
        "managementTlsCrl" : "security/certs/management/server_crl.pem",
        "kmcKsfMaster" : "tools/pmt/master/ksfa",
        "kmcKsfStandby" : "tools/pmt/standby/ksfb",
        "inferMode" : "standard",
        "pdInterNodeTLSEnabled": false,
        "pdCommunicationPort": 1121,
        "interNodeTlsCaFile" : "security/grpc/ca/ca.pem",
        "interNodeTlsCert" : "security/grpc/certs/server.pem",
        "interNodeTlsPk" : "security/grpc/keys/server.key.pem",
        "interNodeTlsPkPwd" : "security/grpc/pass/key_pwd.txt",
        "interCommTlsCrl" : "security/certs/server_crl.pem",
        "interNodeKmcKsfMaster": "tools/pmt/master/ksfa",
        "interNodeKmcKsfStandby": "tools/pmt/standby/ksfb"
    },

    "BackendConfig": {
        "backendName" : "mindieservice_llm_engine",
        "modelInstanceNumber" : 1,
        "npuDeviceIds" : [[0]],
        "tokenizerProcessNumber" : 8,
        "multiNodesInferEnabled": false,
        "multiNodesInferPort": 1120,
        "interNodeTLSEnabled": true,
        "interNodeTlsCaFile": "security/grpc/ca/ca.pem",
        "interNodeTlsCert": "security/grpc/certs/server.pem",
        "interNodeTlsPk": "security/grpc/keys/server.key.pem",
        "interNodeTlsPkPwd": "security/grpc/pass/mindie_server_key_pwd.txt",
        "interNodeTlsCrl" : "security/grpc/certs/server_crl.pem",
        "interNodeKmcKsfMaster": "tools/pmt/master/ksfa",
        "interNodeKmcKsfStandby": "tools/pmt/standby/ksfb",
        "ModelDeployConfig":
        {
            "maxSeqLen" : 2560,
            "maxInputTokenLen" : 2048,
            "truncation" : false,
            "ModelConfig" : [
                {
                    "modelInstanceType": "Standard",
                    "modelName" : "llama3_1_8b",
                    "modelWeightPath" : "/mf_model/llama3_1_8b",
                    "worldSize" : 1,
                    "cpuMemSize" : 16,
                    "npuMemSize" : 16,
                    "backendType": "ms"
                }
            ]
        },

        "ScheduleConfig":
        {
            "templateType": "Standard",
            "templateName" : "Standard_LLM",
            "cacheBlockSize" : 128,

            "maxPrefillBatchSize" : 50,
            "maxPrefillTokens" : 8192,
            "prefillTimeMsPerReq" : 150,
            "prefillPolicyType" : 0,

            "decodeTimeMsPerReq" : 50,
            "decodePolicyType" : 0,

            "maxBatchSize" : 200,
            "maxIterTimes" : 512,
            "maxPreemptCount" : 0,
            "supportSelectBatch" : false,
            "maxQueueDelayMicroseconds" : 5000
        }
    }
}

注:为便于测试,httpsEnabled参数设置为false,忽略后续https通信相关参数。

启动服务

cd /usr/local/Ascend/mindie/1.0.RC3/mindie-service
nohup ./bin/mindieservice_daemon > output.log 2>&1 &
tail -f output.log

打印如下信息,启动成功。

Daemon start success!

请求测试

服务启动成功后,可使用curl命令发送请求验证,样例如下:

curl -w "\ntime_total=%{time_total}\n" -H "Accept: application/json" -H "Content-type: application/json" -X POST -d '{"inputs": "<|im_start|>system\nYou are a helpful assistant.<|im_end|>\n<|im_start|>user\n请介绍一下自己<|im_end|>\n<|im_start|>assistant\n","stream": false}' http://127.0.0.1:1025/generate

返回推理结果验证成功:

{"generated_text":"我叫小助手,专门为您服务的。<|im_end|>\n<"}