作者:熊兮、賀弘、臨在
通義千問-72B(Qwen-72B)是阿里云研發的通義千問大模型系列的720億參數規模的大語言模型,在2023年11月正式開源。Qwen-72B的預訓練數據類型多樣、覆蓋廣泛,包括大量網絡文本、專業書籍、代碼等。Qwen-72B-Chat是在Qwen-72B的基礎上,使用對齊機制打造的基于大語言模型的AI助手。
阿里云人工智能平臺PAI是面向開發者和企業的機器學習/深度學習平臺,提供包含數據標注、模型構建、模型訓練、模型部署、推理優化在內的AI開發全鏈路服務。
本文將以Qwen-72B-Chat為例,介紹如何在PAI平臺的快速開始PAI-QuickStart和交互式建模工具PAI-DSW中高效微調千問大模型。
使用PAI-DSW快速體驗和輕量化微調Qwen-72B-Chat
PAI-DSW是云端機器學習開發IDE,為用戶提供交互式編程環境,同時提供了豐富的計算資源。Qwen-72B-Chat的教程可以在智碼實驗室(https://gallery.pai-ml.com/)Notebook Gallery中檢索到,參見下圖:
上述Notebook可以使用阿里云PAI-DSW的實例打開,并且需要選擇對應的計算資源和鏡像。
快速體驗Qwen-72B-Chat
首先,我們在DSW調用ModelScope快速體驗Qwen-72B-Chat模型進行對話。在安裝完ModelScope相關依賴后,我們可以運行如下Python代碼:
from modelscope import AutoModelForCausalLM, AutoTokenizer
from modelscope import GenerationConfig
# Note: The default behavior now has injection attack prevention off.
tokenizer = AutoTokenizer.from_pretrained("qwen/Qwen-72B-Chat", revision='master', trust_remote_code=True)
# use bf16
# model = AutoModelForCausalLM.from_pretrained("qwen/Qwen-72B-Chat", device_map="auto", trust_remote_code=True, bf16=True).eval()
# use fp16
# model = AutoModelForCausalLM.from_pretrained("qwen/Qwen-72B-Chat", device_map="auto", trust_remote_code=True, fp16=True).eval()
# use cpu only
# model = AutoModelForCausalLM.from_pretrained("qwen/Qwen-72B-Chat", device_map="cpu", trust_remote_code=True).eval()
# use auto mode, automatically select precision based on the device.
model = AutoModelForCausalLM.from_pretrained("qwen/Qwen-72B-Chat", revision='master', device_map="auto", trust_remote_code=True).eval()
# 第一輪對話 1st dialogue turn
response, history = model.chat(tokenizer, "你好", history=None)
print(response)
# 你好!很高興為你提供幫助。
# 第二輪對話 2nd dialogue turn
response, history = model.chat(tokenizer, "給我講一個年輕人奮斗創業最終取得成功的故事。", history=history)
print(response)
# 這是一個關于一個年輕人奮斗創業最終取得成功的故事。
# 故事的主人公叫李明,他來自一個普通的家庭,父母都是普通的工人。從小,李明就立下了一個目標:要成為一名成功的企業家。
# 為了實現這個目標,李明勤奮學習,考上了大學。在大學期間,他積極參加各種創業比賽,獲得了不少獎項。他還利用課余時間去實習,積累了寶貴的經驗。
# 畢業后,李明決定開始自己的創業之路。他開始尋找投資機會,但多次都被拒絕了。然而,他并沒有放棄。他繼續努力,不斷改進自己的創業計劃,并尋找新的投資機會。
# 最終,李明成功地獲得了一筆投資,開始了自己的創業之路。他成立了一家科技公司,專注于開發新型軟件。在他的領導下,公司迅速發展起來,成為了一家成功的科技企業。
# 李明的成功并不是偶然的。他勤奮、堅韌、勇于冒險,不斷學習和改進自己。他的成功也證明了,只要努力奮斗,任何人都有可能取得成功。
# 第三輪對話 3rd dialogue turn
response, history = model.chat(tokenizer, "給這個故事起一個標題", history=history)
print(response)
# 《奮斗創業:一個年輕人的成功之路》
為了節省顯存,ModelScope也支持使用Int4/Int8量化模型:
from modelscope import AutoModelForCausalLM, AutoTokenizer
from modelscope import GenerationConfig
tokenizer = AutoTokenizer.from_pretrained("Qwen/Qwen-72B-Chat-Int4", revision='master', trust_remote_code=True)
model = AutoModelForCausalLM.from_pretrained(
"Qwen/Qwen-72B-Chat-Int4",
device_map="auto",
trust_remote_code=True
).eval()
response, history = model.chat(tokenizer, "你好", history=None)
輕量化微調Qwen-72B-Chat
輕量化微調Qwen-72B-Chat最佳實踐支持最主流的輕量化微調算法LoRA,并且需要使用A800(80GB)4卡及以上資源進行計算。以下,我們簡述輕量化微調Qwen-72B-Chat的算法流程。首先,我們下載Qwen-72B-Chat的Checkpoint和用于LoRA微調的數據集,用戶也可以按照上述格式自行準備數據集。
def aria2(url, filename, d):
!aria2c --console-log-level=error -c -x 16 -s 16 {url} -o {filename} -d 4njrzyd
qwen72b_url = f"http://pai-vision-data-inner-wulanchabu.oss-cn-wulanchabu-internal.aliyuncs.com/qwen72b/Qwen-72B-Chat-sharded.tar"
aria2(qwen72b_url, qwen72b_url.split("/")[-1], "/root/")
!cd /root && tar -xvf Qwen-72B-Chat-sharded.tar
!wget -c http://pai-vision-data-inner-wulanchabu.oss-cn-wulanchabu.aliyuncs.com/qwen72b/sharegpt_zh_1K.json -P /workspace/Qwen
第二步,我們可以修改示例命令的超參數,并且拉起訓練任務。
! cd /workspace/Qwen && CUDA_DEVICE_MAX_CONNECTIONS=1 torchrun --nproc_per_node 8 \
--nnodes 1 \
--node_rank 0 \
--master_addr localhost \
--master_port 6001 \
finetune.py \
--model_name_or_path /root/Qwen-72B-Chat-sharded \
--data_path sharegpt_zh_1K.json \
--bf16 True \
--output_dir /root/output_qwen \
--num_train_epochs 1 \
--per_device_train_batch_size 1 \
--per_device_eval_batch_size 1 \
--gradient_accumulation_steps 8 \
--evaluation_strategy "no" \
--save_strategy "steps" \
--save_steps 1000 \
--save_total_limit 1 \
--learning_rate 3e-4 \
--weight_decay 0.1 \
--adam_beta2 0.95 \
--warmup_ratio 0.01 \
--lr_scheduler_type "cosine" \
--logging_steps 1 \
--report_to "none" \
--model_max_length 2048 \
--lazy_preprocess True \
--use_lora \
--gradient_checkpointing \
--deepspeed finetune/ds_config_zero3.json
當訓練結束后,將LoRA權重合并到模型Checkpoint。
from peft import AutoPeftModelForCausalLM
model = AutoPeftModelForCausalLM.from_pretrained(
'/root/output_qwen', # path to the output directory
device_map="auto",
trust_remote_code=True
).eval()
merged_model = model.merge_and_unload()
merged_model.save_pretrained('/root/qwen72b_sft', max_shard_size="2048MB", safe_serialization=True)
!cp /root/Qwen-72B-Chat-sharded/qwen.tiktoken /root/qwen72b_sft/
!cp /root/Qwen-72B-Chat-sharded/tokenization_qwen.py /root/qwen72b_sft/
!cp /root/Qwen-72B-Chat-sharded/tokenizer_config.json /root/qwen72b_sft/
最后,我們使用輕量化微調后的Qwen-72B-Chat模型進行推理。以推理框架vllm為例,推理接口如下:
from vllm import LLM
from vllm.sampling_params import SamplingParams
qwen72b = LLM("/root/qwen72b_sft/", tensor_parallel_size=2, trust_remote_code=True, gpu_memory_utilization=0.99)
samplingparams = SamplingParams(temperature=0.0, max_tokens=512, stop=['<|im_end|>'])
prompt = """<|im_start|>system
<|im_end|>
<|im_start|>user
<|im_end|>
Hello! What is your name?<|im_end|>
<|im_start|>assistant
"""
output = qwen72b.generate(prompt, samplingparams)
print(output)
其中,tensor_parallel_size需要根據DSW示例配置中的GPU數量進行調整。
使用PAI-QuickStart全量參數微調Qwen-72B-Chat
快速開始(PAI-QuickStart)是PAI產品組件,集成了國內外AI開源社區中優質的預訓練模型,支持零代碼實現全量參數微調Qwen-72B-Chat。PAI-QuickStart的這一款全量參數微調組件使用PAI靈駿智算服務作為底層計算資源,使用4機32卡(每卡80GB顯存)進行訓練。Qwen-72B-Chat的全量參數微調基于Megatron-LM的訓練流程,支持了數據并行、算子拆分、流水并行、序列并行、選擇性激活重算、Zero顯存優化等技術,大幅提升大模型分布式訓練效率。在這一組件中,我們提前對模型Checkpoint進行了切分,適配多機多卡環境訓練,用戶只需根據格式要求準備訓練集和驗證集,配置訓練時候使用的超參數就可以一鍵拉起訓練任務。
通過控制臺使用
Qwen-72B-Chat的模型卡片如下圖所示:
我們可以根據實際需求調整超參數,例如learning_rate、sequence_length、train_iters等,如下所示:
點擊“訓練”按鈕,PAI-QuickStart自動跳轉到模型訓練頁面,并且開始進行訓練,用戶可以查看訓練任務狀態和訓練日志,如下所示:
在訓練結束后,可以在輸出路徑的OSS Bucket中查看每次保存的Checkpoint模型切片,如下所示:
用戶可以根據實際情況,選擇最合適的Checkpoint進行推理和部署,具體流程參見這里,本文不再贅述。