快速玩轉(zhuǎn) Mixtral 8x7B MOE大模型颅痊!阿里云機(jī)器學(xué)習(xí) PAI 推出最佳實踐

作者:熊兮顷锰、賀弘挥萌、臨在

Mixtral 8x7B大模型是Mixtral AI推出的基于decoder-only架構(gòu)的稀疏專家混合網(wǎng)絡(luò)(Mixture-Of-Experts绰姻,MOE)開源大語言模型。這一模型具有46.7B的總參數(shù)量引瀑,對于每個token狂芋,路由器網(wǎng)絡(luò)選擇八組專家網(wǎng)絡(luò)中的兩組進(jìn)行處理,并且將其輸出累加組合憨栽,在增加模型參數(shù)總量的同時米奸,優(yōu)化了模型推理的成本犯戏。在大多數(shù)基準(zhǔn)測試中饼齿,Mixtral 8x7B模型與Llama2 70B和GPT-3.5表現(xiàn)相當(dāng)锈死,因此具有很高的使用性價比。

阿里云人工智能平臺PAI是面向開發(fā)者和企業(yè)的機(jī)器學(xué)習(xí)/深度學(xué)習(xí)平臺掸宛,提供包含數(shù)據(jù)標(biāo)注死陆、模型構(gòu)建、模型訓(xùn)練唧瘾、模型部署措译、推理優(yōu)化在內(nèi)的AI開發(fā)全鏈路服務(wù)。

本文介紹如何在PAI平臺針對Mixtral 8x7B大模型的微調(diào)和推理服務(wù)的最佳實踐劈愚,助力AI開發(fā)者快速開箱瞳遍。以下我們將分別展示具體使用步驟。

使用PAI-DSW輕量化微調(diào)Mixtral 8x7B MOE大模型

PAI-DSW是云端機(jī)器學(xué)習(xí)開發(fā)IDE菌羽,為用戶提供交互式編程環(huán)境掠械,同時提供了豐富的計算資源。我們在智碼實驗室(https://gallery.pai-ml.com/)Notebook Gallery中上線了兩個微調(diào)Mixtral 8x7B MOE大模型的示例注祖,參見下圖:

image.png

上述Notebook可以使用阿里云PAI-DSW的實例打開猾蒂,并且需要選擇對應(yīng)的計算資源和鏡像。

使用Swift輕量化微調(diào)Mixtral 8x7B MOE大模型

Swift是魔搭ModelScope開源社區(qū)推出的輕量級訓(xùn)練推理工具開源庫是晨,使用Swift進(jìn)行這一大模型LoRA輕量化微調(diào)需要使用2張A800(80G)及以上資源肚菠。在安裝完對應(yīng)依賴后,我們首先下載模型至本地:

!apt-get update
!echo y | apt-get install aria2

def aria2(url, filename, d):
    !aria2c --console-log-level=error -c -x 16 -s 16 {url} -o {filename} -d rxthdpr

mixtral_url = "http://pai-vision-data-inner-wulanchabu.oss-cn-wulanchabu-internal.aliyuncs.com/mixtral/Mixtral-8x7B-Instruct-v0.1.tar"
aria2(mixtral_url, mixtral_url.split("/")[-1], "/root/")
!cd /root && mkdir -p AI-ModelScope 
!cd /root && tar -xf Mixtral-8x7B-Instruct-v0.1.tar -C /root/AI-ModelScope

import os
os.environ['MODELSCOPE_CACHE']='/root'

當(dāng)模型下載完畢后罩缴,我們使用Swift一鍵拉起訓(xùn)練任務(wù):

!cd swift/examples/pytorch/llm && PYTHONPATH=../../.. \
CUDA_VISIBLE_DEVICES=0,1 \
python llm_sft.py \
    --model_id_or_path AI-ModelScope/Mixtral-8x7B-Instruct-v0.1 \
    --model_revision master \
    --sft_type lora \
    --tuner_backend swift \
    --dtype AUTO \
    --output_dir /root/output \
    --ddp_backend nccl \
    --dataset alpaca-zh \
    --train_dataset_sample 100 \
    --num_train_epochs 2 \
    --max_length 2048 \
    --check_dataset_strategy warning \
    --lora_rank 8 \
    --lora_alpha 32 \
    --lora_dropout_p 0.05 \
    --lora_target_modules ALL \
    --batch_size 1 \
    --weight_decay 0.01 \
    --learning_rate 1e-4 \
    --gradient_accumulation_steps 16 \
    --max_grad_norm 0.5 \
    --warmup_ratio 0.03 \
    --eval_steps 300 \
    --save_steps 300 \
    --save_total_limit 2 \
    --logging_steps 10 \
    --only_save_model true \
    --gradient_checkpointing false

模型訓(xùn)練完成后蚊逢,我們將學(xué)習(xí)到的LoRA權(quán)重合并到模型Checkpoint中:

!swift merge-lora --ckpt_dir '/root/output/mistral-7b-moe-instruct/v3-20231215-111107/checkpoint-12'

其中,ckpt_dir參數(shù)的值需要替換成模型LoRA權(quán)重保存路徑箫章。為了測試模型訓(xùn)練的正確性烙荷,我們可以使用transformers庫進(jìn)行離線推理測試:

from transformers import AutoModelForCausalLM, AutoTokenizer

model_id = "/root/output/mistral-7b-moe-instruct/v3-20231215-111107/checkpoint-12-merged"
tokenizer = AutoTokenizer.from_pretrained(model_id, device_map='auto')

model = AutoModelForCausalLM.from_pretrained(model_id, device_map='auto')

text = """[INST] <<SYS>>
You are a helpful, respectful and honest assistant. Always answer as helpfully as possible, while being safe. Your answers should not include any harmful, unethical, racist, sexist, toxic, dangerous, or illegal content. Please ensure that your responses are socially unbiased and positive in nature.

If a question does not make any sense, or is not factually coherent, explain why instead of answering something not correct. If you don't know the answer to a question, please don't share false information.
<</SYS>>

寫一首歌的過程從開始到結(jié)束。 [/INST]"""
inputs = tokenizer(text, return_tensors="pt")

outputs = model.generate(**inputs, max_new_tokens=512)
print(tokenizer.decode(outputs[0], skip_special_tokens=True))

使用Deepspeed輕量化微調(diào)Mixtral 8x7B MOE大模型

我們也可以使用Deepspeed對Mixtral 8x7B MOE大模型進(jìn)行LoRA輕量化微調(diào)檬寂。同樣的终抽,我們需要使用2張A800(80G)及以上資源。我們首先下載模型至本地:

!apt-get update
!echo y | apt-get install aria2

def aria2(url, filename, d):
    !aria2c --console-log-level=error -c -x 16 -s 16 {url} -o {filename} -d 1hnzvzt

mixtral_url = "http://pai-vision-data-inner-wulanchabu.oss-cn-wulanchabu-internal.aliyuncs.com/mixtral/Mixtral-8x7B-Instruct-v0.1.tar"
aria2(mixtral_url, mixtral_url.split("/")[-1], "/root/")
!cd /root && tar -xf Mixtral-8x7B-Instruct-v0.1.tar

第二步,我們下載一個示例古詩生成數(shù)據(jù)集昼伴,用戶可以根據(jù)下述數(shù)據(jù)格式準(zhǔn)備自己的數(shù)據(jù)集匾旭。

!wget -c https://pai-quickstart-predeploy-hangzhou.oss-cn-hangzhou.aliyuncs.com/huggingface/datasets/llm_instruct/en_poetry_train_mixtral.json
!wget -c https://pai-quickstart-predeploy-hangzhou.oss-cn-hangzhou.aliyuncs.com/huggingface/datasets/llm_instruct/en_poetry_test_mixtral.json

第三步,我們可以修改示例命令的超參數(shù)圃郊,并且拉起訓(xùn)練任務(wù)价涝。

!mkdir -p /root/output
!deepspeed /ml/code/train_sft.py \
--model_name_or_path /root/Mixtral-8x7B-Instruct-v0.1/ \
--train_path en_poetry_train_mixtral.json \
--valid_path en_poetry_test_mixtral.json \
--learning_rate 1e-5 \
--lora_dim 32 \
--max_seq_len 256 \
--model mixtral \
--num_train_epochs 1 \
--per_device_train_batch_size 8 \
--zero_stage 3 \
--gradient_checkpointing \
--print_loss \
--deepspeed \
--output_dir /root/output/ \
--offload

當(dāng)訓(xùn)練結(jié)束后,我們拷貝額外配置文件至輸出文件夾:

!cp /root/Mixtral-8x7B-Instruct-v0.1/generation_config.json /root/output
!cp /root/Mixtral-8x7B-Instruct-v0.1/special_tokens_map.json /root/output
!cp /root/Mixtral-8x7B-Instruct-v0.1/tokenizer.json /root/output
!cp /root/Mixtral-8x7B-Instruct-v0.1/tokenizer.model /root/output
!cp /root/Mixtral-8x7B-Instruct-v0.1/tokenizer_config.json /root/output

我們同樣可以使用transformers庫進(jìn)行離線推理測試:

import os
from transformers import AutoModelForCausalLM, AutoTokenizer
import torch

model_id = "/root/output/"
tokenizer = AutoTokenizer.from_pretrained(model_id)

model = AutoModelForCausalLM.from_pretrained(model_id,device_map='auto',torch_dtype=torch.float16)

text = """[INST] Write a poem on a topic 'Care for Thy Soul as Thing of Greatest Price': [/INST]"""
inputs = tokenizer(text, return_tensors="pt").to('cuda')

outputs = model.generate(**inputs, max_new_tokens=20)
print(tokenizer.decode(outputs[0], skip_special_tokens=True))

如果用戶需要將上述模型部署為EAS服務(wù)持舆,需要將格式轉(zhuǎn)換成safetensors格式:

state_dict = model.state_dict()
model.save_pretrained(
    model_id,
    state_dict=state_dict,
    safe_serialization=True)

使用PAI-EAS在線部署Mixtral 8x7B MOE大模型

PAI-EAS是PAI平臺推出的彈性推理服務(wù)飒泻,可以將各種大模型部署為在線服務(wù)。當(dāng)Mixtral 8x7B MOE大模型微調(diào)完畢后吏廉,我們可以將其部署為PAI-EAS服務(wù)。這里惰许,我們介紹使用PAI-SDK將上述模型進(jìn)行部署席覆。首先,我們在PAI-DSW環(huán)境安裝PAI-SDK:

!python -m pip install alipai --upgrade

在安裝完成后汹买,在在命令行終端上執(zhí)行以下命令佩伤,按照引導(dǎo)完成配置AccessKey、PAI工作空間以及 OSS Bucket:

python -m pai.toolkit.config

我們將訓(xùn)練好的模型上傳至OSS Bucket晦毙。在下述命令中生巡,source_path為模型Checkpoint保存的本地路徑,oss_path為上傳至OSS的目標(biāo)路徑:

import pai
from pai.session import get_default_session
from pai.common.oss_utils import upload

print(pai.__version__)
sess = get_default_session()

# 上傳模型到默認(rèn)的Bucket
model_uri = upload(
    source_path="/root/output", 
    oss_path="mixtral-7b-moe-instruct-sft-ds"
)

print(model_uri)

PAI 提供了Mixtral 8X7B MOE 模型部署鏡像和部署代碼见妒,用戶可以通過相應(yīng)的部署配置孤荣,將微調(diào)后的模型部署到PAI-EAS。

from pai.model import RegisteredModel
from pai.predictor import Predictor

# 獲取PAI提供的Mixtral模型服務(wù)配置(目前僅支持烏蘭察布)
inference_spec = RegisteredModel(
    "Mixtral-8x7B-Instruct-v0.1",
    model_provider="pai",
).inference_spec

# 修改部署配置须揣,使用微調(diào)后的模型
infer_spec.mount(model_uri, model_path="/model")


# 部署推理服務(wù)服務(wù)
m = Model(inference_spec=infer_spec)

predictor: Predictor = m.deploy(
    service_name = 'mixtral_sdk_example_ds',
    options={
        "metadata.quota_id": "<ResourceGroupQuotaId>",
        "metadata.quota_type": "Lingjun",
        "metadata.workspace_id": session.workspace_id
    }
)

以上配置項中盐股,metadata.quota_id是用戶購買的靈駿資源配額ID,在購買了靈駿資源之后耻卡,用戶可以從PAI控制臺頁面的資源配額入口獲取相應(yīng)的信息疯汁。

部署的模型可以通過deploy方法返回的Predictor對象進(jìn)行調(diào)用。模型使用的Prompt模版如下卵酪,其中[INST][/INST]之間的是用戶輸入幌蚊,Prompt輸入需要按相應(yīng)的格式準(zhǔn)備,避免模型生成低質(zhì)量的結(jié)果溃卡。

<s> [INST] User Instruction 1 [/INST] Model answer 1</s> [INST] User instruction 2 [/INST]

調(diào)用部署服務(wù)的示例代碼如下:


# 格式化輸入Prompt
def prompt_format(instructions: List[Dict[str, str]]):
    prompt = ["<s>"]
    for user, assistant in zip(instructions[::2], instructions[1::2]):
        inst = user["content"].strip()
        resp = assistant["content"]
        prompt.append(f"[INST] {inst} [/INST] {resp}</s>")

    prompt.append(f"[INST] {instructions[-1]['content']} [/INST]")
    return "".join(prompt)

# 獲取模型產(chǎn)生的實際內(nèi)容
def extract_output(text, prompt):
    if prompt and text.startswith(prompt):
        return text[len(prompt) :]
    return text

prompt = prompt_format(
    [
        {
            "role": "user",
            "content": "Who are you?",
        },
    ]
)

res = predictor.raw_predict(
    path="/generate",
    data=json.dumps(
        {
            "prompt": prompt,
            "use_beam_search": False,
            "stream": False,
            "n": 1,
            "temperature": 0.0,
            "max_tokens": 860,
        }
    ),
)

print(extract_output(res.json()["text"][0], prompt))

# Hello! I am a large language model trained by Mistral AI. I am designed to generate human-like text based on the input I receive. I do not have personal experiences or emotions, but I can provide information, answer questions, and engage in conversation to the best of my abilities. How can I assist you today?

流式推理能夠提高大語言模型推理服務(wù)的響應(yīng)效率溢豆,處理長文本的問題。通過配置參數(shù)stream:True塑煎,可以使服務(wù)以流式響應(yīng)推理結(jié)果:


# API 請求路徑
url = predictor.internet_endpoint + "/generate"
# 推理服務(wù)的Token
access_token = predictor.access_token

prompt = prompt_format(
        [
            {
                "role": "user",
                "content": "Explain the meaning of life.",
            },
        ]
)
res = requests.post(
    url=url,
    headers={
        "Authorization": access_token,
    },
    json={
        "prompt": prompt,
        "use_beam_search": False,
        # 服務(wù)端:以流式返回推理結(jié)果
        "stream": True,
        "n": 1,
        "temperature": 0.0,
        "max_tokens": 860,
    },
    # 客戶端:以流式處理響應(yīng)結(jié)果
    stream=True,
)
for chunk in res.iter_lines(chunk_size=8192, delimiter=b"\0"):
    if not chunk:
        continue
    print(extract_output(json.loads(chunk)["text"][0], prompt))


# Hello
# Hello!
# Hello! I
# Hello! I am
# Hello! I am a
# Hello! I am a large
# Hello! I am a large language
# Hello! I am a large language model
# Hello! I am a large language model trained
# Hello! I am a large language model trained by
# Hello! I am a large language model trained by Mist
# Hello! I am a large language model trained by Mistral
# Hello! I am a large language model trained by Mistral AI
# Hello! I am a large language model trained by Mistral AI.

使用PAI-QuickStart微調(diào)和部署Mixtral 8x7B MOE大模型

快速開始(PAI-QuickStart)集成了國內(nèi)外AI開源社區(qū)中優(yōu)質(zhì)的預(yù)訓(xùn)練模型沫换,支持零代碼或是SDK的方式實現(xiàn)微調(diào)和部署Mixtral 8x7B MOE大模型,用戶只需要格式準(zhǔn)備訓(xùn)練集和驗證集,填寫訓(xùn)練時候使用的超參數(shù)就可以一鍵拉起訓(xùn)練任務(wù)讯赏。Mixtral的模型卡片如下圖所示:

image.png

通過控制臺使用

我們可以根據(jù)實際需求上傳訓(xùn)練集和驗證集垮兑,調(diào)整超參數(shù),例如learning_rate漱挎、sequence_length系枪、train_iters等,如下所示:

image.png

點擊“訓(xùn)練”按鈕磕谅,PAI-QuickStart開始進(jìn)行訓(xùn)練私爷,用戶可以查看訓(xùn)練任務(wù)狀態(tài)和訓(xùn)練日志,如下所示:

image.png

如果需要將模型部署至PAI-EAS膊夹,可以在同一頁面的模型部署卡面選擇資源組衬浑,并且點擊“部署”按鈕實現(xiàn)一鍵部署。模型調(diào)用方式和上文PAI-EAS調(diào)用方式相同放刨。

image.png

通過PAI Python SDK使用

開發(fā)者也可以通過PAI Python SDK調(diào)用PAI提供的預(yù)訓(xùn)練模型工秩。通過模型上配置的微調(diào)訓(xùn)練算法,開發(fā)者可以輕松得提交一個微調(diào)訓(xùn)練任務(wù)进统。

from pai.model import RegisteredModel

# 獲取PAI提供的預(yù)訓(xùn)練模型
m = RegisteredModel(
    "Mixtral-8x7B-Instruct-v0.1",
    model_provider="pai",
)

# 獲取模型的微調(diào)訓(xùn)練算法
est = m.get_estimator(
    # 靈駿資源組資源配額ID
    resource_id="<LingjunResourceQuotaId>",
    # 訓(xùn)練超參
    hyperparameters={
        "learning_rate": 1e-5,
        "num_train_epochs": 1,
        "per_device_train_batch_size": 4,
    },
)

# 獲取訓(xùn)練輸入數(shù)據(jù):包括模型助币,以及測試使用的公共數(shù)據(jù)集
inputs = m.get_estimator_inputs()

# 提交訓(xùn)練作業(yè),等待作業(yè)完成
est.fit(
    inputs=inputs
)

# 查看模型的輸出路徑
print(est.model_data())

通過模型上預(yù)置的推理服務(wù)配置螟碎,開發(fā)者僅需指定機(jī)器資源配置眉菱,即可部署一個推理服務(wù)。推理服務(wù)的調(diào)用請參考以上的 PAI-EAS 部署推理的章節(jié)掉分。

from pai.session import  get_default_session
from pai.model import RegisteredModel

session = get_default_session()

m = RegisteredModel(
    "Mixtral-8x7B-Instruct-v0.1",
    model_provider="pai",
)

# 部署推理服務(wù)
predictor = m.deploy(
    service_name="mixtral_example_{}".format(random_str(6)),
    options={
        # 資源配額ID
        "metadata.quota_id": "<ResourceGroupQuotaId>",
        "metadata.quota_type": "Lingjun",
        "metadata.workspace_id": session.workspace_id,
    }
)

print(predictor.internet_endpoint)

用戶可以查看文檔俭缓,了解更多如何通過SDK使用PAI提供的預(yù)訓(xùn)練模型:使用預(yù)訓(xùn)練模型 — PAI Python SDK

當(dāng)測試完成叉抡,需要刪除服務(wù)釋放資源尔崔,用戶可以通過控制臺或是SDK完成:

# 刪除服務(wù)
predictor.delete_service()
?著作權(quán)歸作者所有,轉(zhuǎn)載或內(nèi)容合作請聯(lián)系作者
  • 序言:七十年代末,一起剝皮案震驚了整個濱河市褥民,隨后出現(xiàn)的幾起案子季春,更是在濱河造成了極大的恐慌,老刑警劉巖消返,帶你破解...
    沈念sama閱讀 206,839評論 6 482
  • 序言:濱河連續(xù)發(fā)生了三起死亡事件载弄,死亡現(xiàn)場離奇詭異,居然都是意外死亡撵颊,警方通過查閱死者的電腦和手機(jī)宇攻,發(fā)現(xiàn)死者居然都...
    沈念sama閱讀 88,543評論 2 382
  • 文/潘曉璐 我一進(jìn)店門,熙熙樓的掌柜王于貴愁眉苦臉地迎上來倡勇,“玉大人逞刷,你說我怎么就攤上這事。” “怎么了夸浅?”我有些...
    開封第一講書人閱讀 153,116評論 0 344
  • 文/不壞的土叔 我叫張陵仑最,是天一觀的道長。 經(jīng)常有香客問我帆喇,道長警医,這世上最難降的妖魔是什么? 我笑而不...
    開封第一講書人閱讀 55,371評論 1 279
  • 正文 為了忘掉前任坯钦,我火速辦了婚禮预皇,結(jié)果婚禮上,老公的妹妹穿的比我還像新娘婉刀。我一直安慰自己吟温,他們只是感情好,可當(dāng)我...
    茶點故事閱讀 64,384評論 5 374
  • 文/花漫 我一把揭開白布突颊。 她就那樣靜靜地躺著溯街,像睡著了一般。 火紅的嫁衣襯著肌膚如雪洋丐。 梳的紋絲不亂的頭發(fā)上,一...
    開封第一講書人閱讀 49,111評論 1 285
  • 那天挥等,我揣著相機(jī)與錄音友绝,去河邊找鬼。 笑死肝劲,一個胖子當(dāng)著我的面吹牛迁客,可吹牛的內(nèi)容都是我干的。 我是一名探鬼主播辞槐,決...
    沈念sama閱讀 38,416評論 3 400
  • 文/蒼蘭香墨 我猛地睜開眼掷漱,長吁一口氣:“原來是場噩夢啊……” “哼!你這毒婦竟也來了榄檬?” 一聲冷哼從身側(cè)響起卜范,我...
    開封第一講書人閱讀 37,053評論 0 259
  • 序言:老撾萬榮一對情侶失蹤,失蹤者是張志新(化名)和其女友劉穎鹿榜,沒想到半個月后海雪,有當(dāng)?shù)厝嗽跇淞掷锇l(fā)現(xiàn)了一具尸體,經(jīng)...
    沈念sama閱讀 43,558評論 1 300
  • 正文 獨居荒郊野嶺守林人離奇死亡舱殿,尸身上長有42處帶血的膿包…… 初始之章·張勛 以下內(nèi)容為張勛視角 年9月15日...
    茶點故事閱讀 36,007評論 2 325
  • 正文 我和宋清朗相戀三年奥裸,在試婚紗的時候發(fā)現(xiàn)自己被綠了。 大學(xué)時的朋友給我發(fā)了我未婚夫和他白月光在一起吃飯的照片沪袭。...
    茶點故事閱讀 38,117評論 1 334
  • 序言:一個原本活蹦亂跳的男人離奇死亡湾宙,死狀恐怖,靈堂內(nèi)的尸體忽然破棺而出,到底是詐尸還是另有隱情侠鳄,我是刑警寧澤埠啃,帶...
    沈念sama閱讀 33,756評論 4 324
  • 正文 年R本政府宣布,位于F島的核電站畦攘,受9級特大地震影響霸妹,放射性物質(zhì)發(fā)生泄漏。R本人自食惡果不足惜知押,卻給世界環(huán)境...
    茶點故事閱讀 39,324評論 3 307
  • 文/蒙蒙 一叹螟、第九天 我趴在偏房一處隱蔽的房頂上張望。 院中可真熱鬧台盯,春花似錦罢绽、人聲如沸。這莊子的主人今日做“春日...
    開封第一講書人閱讀 30,315評論 0 19
  • 文/蒼蘭香墨 我抬頭看了看天上的太陽。三九已至蒿叠,卻和暖如春明垢,著一層夾襖步出監(jiān)牢的瞬間,已是汗流浹背市咽。 一陣腳步聲響...
    開封第一講書人閱讀 31,539評論 1 262
  • 我被黑心中介騙來泰國打工痊银, 沒想到剛下飛機(jī)就差點兒被人妖公主榨干…… 1. 我叫王不留,地道東北人施绎。 一個月前我還...
    沈念sama閱讀 45,578評論 2 355
  • 正文 我出身青樓溯革,卻偏偏與公主長得像,于是被迫代替她去往敵國和親谷醉。 傳聞我的和親對象是個殘疾皇子致稀,可洞房花燭夜當(dāng)晚...
    茶點故事閱讀 42,877評論 2 345

推薦閱讀更多精彩內(nèi)容