更新时间:2024-11-21 GMT+08:00
分享

准备代码

本教程中用到的训练推理代码和如下表所示,请提前准备好。

获取模型软件包和权重文件

本方案支持的模型对应的软件和依赖包获取地址如表1所示,模型列表、对应的开源权重获取地址如表1所示。

表1 模型对应的软件包和依赖包获取地址

代码包名称

代码说明

下载地址

AscendCloud-6.3.910-xxx.zip

说明:

软件包名称中的xxx表示时间戳。

包含了本教程中使用到的模型训练代码、推理部署代码和推理评测代码。代码包具体说明请参见模型软件包结构说明

获取路径:Support-E,在此路径中查找下载ModelArts 6.3.910 版本。

说明:

如果上述软件获取路径打开后未显示相应的软件信息,说明您没有下载权限,请联系您所在企业的华为方技术支持下载获取。

修改代码

将AscendSpeed代码包AscendCloud-LLM-xxx.zip在本地解压缩后。在上传代码前,需要对解压后的训练脚本代码进行修改。具体文件为:修改llm_train/AscendSpeed/scripts/dev_pipeline.sh以及新建文件llm_train/AscendSpeed/scripts/tools/get_rank_table.py 。

  1. dev_pipeline.sh 具体添加代码内容以及位置,如下所示。
    elif [[ -n "$VC_MAIN_HOSTS" ]]; then
        # 针对 Lite Cluster CCE 集群平台
        # 获取 RANK_TABLE_FILE 的信息
        RANKTABLE_RESULT=$(python $SHELL_FOLDER/../tools/get_ranktable.py)
        # 将脚本的返回值进行拆分,得到 节点总数量(NNODES) 节点的RANK(NODE_RANK) 单节点的NPU数量(NPUS_PER_NODE)
        IFS=',' read -r NNODES NODE_RANK NPUS_PER_NODE <<< "$RANKTABLE_RESULT"
        MASTER_ADDR="$VC_MAIN_HOSTS"
        MASTER_PORT=6060
        NNODES="$NNODES"
        NODE_RANK="$NODE_RANK"
        NPUS_PER_NODE="$NPUS_PER_NODE"
        WORLD_SIZE=$(($NPUS_PER_NODE*$NNODES))
        export GLOO_SOCKET_IFNAME=enp67s0f5   # 多机之间使用gloo通信时需要指定网口名称,
        export TP_SOCKET_IFNAME=enp67s0f5     # 多机之间使用TP通信时需要指定网口名称
        export HCCL_SOCKET_IFNAME=enp67s0f5   # 多机之间使用HCCL通信时需要指定网口名称
    图1 dev_pipeline.sh添加代码位置和内容
  2. 在llm_train/AscendSpeed/scripts/tools的路径下,新建脚本文件get_rank_table.py ,具体代码如下所示。
    import os
    import re
    import sys
    import json
    
    from extras.logging import get_logger, set_file_handler
    
    logger = get_logger(__name__)
    
    
    def get_rank_table():
        rank_table_file_path = os.getenv("RANK_TABLE_FILE")
        env_ip = os.getenv("ip")
    
        # Lite Cluster中的RANK_TABLE_FILE实际名称为 jobstart_hccl.json
        job_start_file = "jobstart_hccl.json"
        # job_start_file_path 路径默认为 "/user/config/jobstart_hccl.json"
        job_start_file_path = rank_table_file_path.rsplit("/", 1)[0] + "/" + job_start_file
    
        # 读取RANK_TABLE_FILE文件
        with open(job_start_file_path, 'r', encoding='utf-8') as file:
            data = json.load(file)
    
        # RANK_TABLE_FILE文件缺少字段,表示文件缺少关键信息
        if "status" not in data.keys() and "server_count" not in data.keys() and "server_list" not in data.keys():
            logger.error(f"Get RANK_TABLE Error: RANK_TABLE_FILE missing key value.")
            sys.exit(1)
    
        # RANK_TABLE_FILE文件status不是completed,表示训练作业未创建成功
        if data["status"] != "completed":
            logger.error(f"Get RANK_TABLE Error: RANK_TABLE_FILE is incomplete, and the training job creation was not successful.")
            sys.exit(1)
    
        # 获取:节点总数量:server_count 节点的RANK:server_index 单节点的NPU数量:device_count
        server_count = data["server_count"]
        server_list = data["server_list"]
        server_index = -1
        device_count = 0
        for index, server in enumerate(server_list):
            # RANK_TABLE_FILE文件中,节点ip为空
            if server["server_id"] == "":
                logger.error(f"Get RANK_TABLE Error: the IP address of the server is null.")
                sys.exit(1)
    
            if server["server_id"] == env_ip:
                server_index = index
                if server["device"]:
                    device_count = len(server["device"])
    
        # RANK_TABLE_FILE文件中,节点总数量为0,表示未获取到节点
        if server_count == 0:
            logger.error(f"Get RANK_TABLE Error: the server does not exist.")
            sys.exit(1)
    
        # RANK_TABLE_FILE文件中,未找到对应ip的节点
        if server_index == -1:
            logger.error(f"Get RANK_TABLE Error:  the IP address {env_ip} was not found.")
            sys.exit(1)
    
        # RANK_TABLE_FILE文件中,NPU卡数为0,表示未获取到NPU
        if device_count == 0:
            logger.error(f"Get RANK_TABLE Error: NPU does not exist.")
            sys.exit(1)
    
        return server_count, server_index, device_count
    
    
    if __name__ == '__main__':
        result = get_rank_table()
        print(','.join(map(str, result)))

获取模型权重文件

获取对应模型的权重文件,获取链接参考表1

权重文件下载有如下几种方式,但不仅限于以下方式:

  • 方法一:网页下载:通过单击表格中权重文件获取地址的访问链接,即可在模型主页的Files and Version中下载文件。
  • 方法二:huggingface-clihuggingface-cli是 Hugging Face 官方提供的命令行工具,自带完善的下载功能。具体步骤可参考:HF-Mirror中的使用教程。完成依赖安装和环境变量配置后,以Llama2-70B为例:
    huggingface-cli download --resume-download meta-llama/Llama-2-70b-chat-hf --local-dir <模型下载路径>

    若要下载指定版本的模型文件,则命令如下:

    huggingface-cli download --resume-download meta-llama/Llama-2-70b-chat-hf --revision <模型版本>  --local-dir <模型下载路径>
  • 方法三:使用专用多线程下载器 hfd:hfd 是本站开发的 huggingface 专用下载工具,基于成熟工具 git+aria2,可以做到稳定下载不断线。
  • 方法四:使用Git clone,官方提供了 git clone repo_url 的方式下载,但是不支持断点续传,并且clone 会下载历史版本占用磁盘空间。

模型软件包结构说明

本教程需要使用到的AscendCloud-6.3.910中的AscendCloud-LLM-xxx.zip软件包和算子包AscendCloud-OPP,AscendCloud-LLM关键文件介绍如下。
|——AscendCloud-LLM
    |──llm_train                 # 模型训练代码包
          |──AscendSpeed         # 基于AscendSpeed的训练代码
                 |──ascendcloud_patch/   # 针对昇腾云平台适配的功能补丁包
                 |──scripts/             # 训练需要的启动脚本
                      |──llama2          # llama2系列模型执行脚本的文件夹
                      |──llama3          # llama3系列模型执行脚本的文件夹
                      |──qwen            # Qwen系列模型执行脚本的文件夹
                      |──qwen1.5         # Qwen1.5系列模型执行脚本的文件夹
                      |── ...
                      |── dev_pipeline.sh  # 系列模型共同调用的多功能的脚本
                      |── install.sh       # 环境部署脚本
                 |——src/                 # 启动命令行封装脚本,在install.sh里面自动构建
    |──llm_inference                     # 推理代码包
    |──llm_tools                        # 推理工具

工作目录介绍

详细的工作目录参考如下,建议参考以下要求设置工作目录。训练脚本以分类的方式集中在 scripts 文件夹中。
${workdir}(例如使用SFS Turbo的路径:/mnt/sfs_turbo/)
|──llm_train                    #解压代码包后自动生成的代码目录,无需用户创建
      |── AscendSpeed              # 代码目录
              |──ascendcloud_patch/   # 针对昇腾云平台适配的功能代码包
              |──scripts/             # 各模型训练需要的启动脚本,训练脚本以分类的方式集中在scripts文件夹中。
      # 自动生成数据目录结构
      |── processed_for_input           #目录结构会自动生成,无需用户创建
              |── ${model_name}             # 模型名称
                     |── data              # 预处理后数据
		          |── pretrain   # 预训练加载的数据
		          |── finetune   # 微调加载的数据
	      |──converted_weights  # HuggingFace格式转换megatron格式后权重文件
      |── saved_dir_for_output            # 训练输出保存权重,目录结构会自动生成,无需用户创建
              |── ${model_name}             # 模型名称
	                  |── logs              # 训练过程中日志(loss、吞吐性能)
                          |—— saved_models    
		               |── lora              # lora微调输出权重
		               |── sft               # 增量训练输出权重
		               |── pretrain          # 预训练输出权重
|── tokenizers                      #tokenizer目录,需要用户手动创建,后续操作步骤中会提示
      |── Llama2-70B
|── models                          #始权重与tokenizer目录,需要用户手动创建,后续操作步骤中会提示
      |── Llama2-70B
|── training_data                   #原始数据目录,需要用户手动创建,后续操作步骤中会提示
      |── train-00000-of-00001-a09b74b3ef9c3b56.parquet  #原始数据文件
      |── alpaca_gpt4_data.json     #微调数据文件

上传代码和权重文件到工作环境

  1. 使用root用户以SSH的方式登录DevServer。
  2. 将AscendCloud代码包AscendCloud-xxx-xxx.zip上传到${workdir}目录下并解压缩,如SFS Turbo的路径:/mnt/sfs_turbo目录下,以下都以/mnt/sfs_turbo为例,请根据实际修改。
    unzip AscendCloud-*.zip  
  3. 上传tokenizers文件到工作目录中的/mnt/sfs_turbo/tokenizers/Llama2-{MODEL_TYPE}目录,如Llama2-70B。

    具体步骤如下:

    进入到${workdir}目录下,如:/mnt/sfs_turbo,创建tokenizers文件目录将权重和词表文件放置此处,以Llama2-70B为例。

    cd /mnt/sfs_turbo
    mkdir -p tokenizers/Llama2-70B

相关文档