Gemma2

对标题的评论会显示在这里

Gemma-2-9b-it FastApi 部署调用

对这一段的评论会显示在这里

环境准备

对这一段的评论会显示在这里

在 Autodl 平台中租赁一个 RTX 3090/24G 显存的显卡机器。如下图所示,镜像选择 PyTorch-->2.1.0-->3.10(ubuntu22.04)-->12.1。

对这一段的评论会显示在这里
开启机器配置选择
开启机器配置选择
对这一段的评论会显示在这里

环境配置

对这一段的评论会显示在这里

pip 换源加速下载并安装依赖包

对这一段的评论会显示在这里
# 升级pip
python -m pip install --upgrade pip

# 更换 pypi 源加速库的安装
pip config set global.index-url https://pypi.tuna.tsinghua.edu.cn/simple

# 安装 fastapi modelscope
pip install fastapi
pip install modelscope
pip install transformers==4.42.3
对这一段的评论会显示在这里

考虑到部分同学配置环境可能会遇到一些问题,我们在AutoDL平台准备了Gemma2 的环境镜像,该镜像适用于该仓库的 Gemma2 教程所有部署环境。点击下方链接并直接创建Autodl示例即可。 https://www.codewithgpu.com/i/datawhalechina/self-llm/self-llm-gemma2

对这一段的评论会显示在这里

模型下载

对这一段的评论会显示在这里

使用 modelscope 中的 snapshot_download 函数下载模型,第一个参数为模型名称,参数 cache_dir 为模型的下载路径。

对这一段的评论会显示在这里

然后运行下面代码,执行模型下载。模型大小为 18GB左右,下载大概需要 5 分钟。

对这一段的评论会显示在这里
from modelscope import snapshot_download
model_dir = snapshot_download('LLM-Research/gemma-2-9b-it', cache_dir='/root/autodl-tmp')
对这一段的评论会显示在这里

代码准备

对这一段的评论会显示在这里

点击自定义服务,开启AutoDL开放端口。

对这一段的评论会显示在这里
AutoDL开放端口配置
AutoDL开放端口配置
对这一段的评论会显示在这里

有些区域的机器需要配置AutoDL开放端口,配置方法写在本项目中General-Setting目录,首次使用请参考该文档。

对这一段的评论会显示在这里

配置方法如下图所示。

对这一段的评论会显示在这里
AutoDL开放端口配置
AutoDL开放端口配置
对这一段的评论会显示在这里

新建 api.py 文件并在其中输入以下内容,粘贴代码后请及时保存文件。

对这一段的评论会显示在这里

下面的代码有很详细的注释,大家如有不理解的地方,欢迎提出 issue。

对这一段的评论会显示在这里
from fastapi import FastAPI, Request
from transformers import AutoTokenizer, AutoModelForCausalLM
import uvicorn
import json
import datetime
import torch

# 设置设备参数
DEVICE = "cuda"  # 使用CUDA
DEVICE_ID = "0"  # CUDA设备ID,如果未设置则为空
CUDA_DEVICE = f"{DEVICE}:{DEVICE_ID}" if DEVICE_ID else DEVICE  # 组合CUDA设备信息

# 清理GPU内存函数
def torch_gc():
    if torch.cuda.is_available():  # 检查是否可用CUDA
        with torch.cuda.device(CUDA_DEVICE):  # 指定CUDA设备
            torch.cuda.empty_cache()  # 清空CUDA缓存
            torch.cuda.ipc_collect()  # 收集CUDA内存碎片

# 创建FastAPI应用
app = FastAPI()

# 处理POST请求的端点
@app.post("/")
async def create_item(request: Request):
    global model, tokenizer  # 声明全局变量以便在函数内部使用模型和分词器
    json_post_raw = await request.json()  # 获取POST请求的JSON数据
    json_post = json.dumps(json_post_raw)  # 将JSON数据转换为字符串
    json_post_list = json.loads(json_post)  # 将字符串转换为Python对象
    prompt = json_post_list.get('prompt')  # 获取请求中的提示

    # 调用模型进行对话生成
    chat = [
        { "role": "user", "content": prompt },
    ]
    prompt = tokenizer.apply_chat_template(chat, tokenize=False, add_generation_prompt=True)
    inputs = tokenizer.encode(prompt, add_special_tokens=False, return_tensors="pt")
    outputs = model.generate(input_ids=inputs.to(model.device), max_new_tokens=150)
    outputs = tokenizer.decode(outputs[0])
    response = outputs.split('model')[-1].replace('<end_of_turn>\n<eos>', '')

    now = datetime.datetime.now()  # 获取当前时间
    time = now.strftime("%Y-%m-%d %H:%M:%S")  # 格式化时间为字符串

    # 构建响应JSON
    answer = {
        "response": response,
        "status": 200,
        "time": time
    }
    # 构建日志信息
    log = "[" + time + "] " + '", prompt:"' + prompt + '", response:"' + repr(response) + '"'
    print(log)  # 打印日志
    torch_gc()  # 执行GPU内存清理
    return answer  # 返回响应

# 主函数入口
if __name__ == '__main__':
    # 加载预训练的分词器和模型
    path = '/root/autodl-tmp/LLM-Research/gemma-2-9b-it'

    print("Creat tokenizer...")
    tokenizer = AutoTokenizer.from_pretrained(path)

    print("Creat model...")
    model = AutoModelForCausalLM.from_pretrained(
        path,
        device_map="cuda",
        torch_dtype=torch.bfloat16,)

    # 启动FastAPI应用
    # 用6006端口可以将autodl的端口映射到本地,从而在本地使用api
    uvicorn.run(app, host='0.0.0.0', port=6006, workers=1)  # 在指定端口和主机上启动应用
对这一段的评论会显示在这里

Api 部署

对这一段的评论会显示在这里

在终端输入以下命令启动api服务:

对这一段的评论会显示在这里
python api.py
对这一段的评论会显示在这里

加载完毕后出现如下信息说明成功。

对这一段的评论会显示在这里
alt text
alt text
对这一段的评论会显示在这里

默认部署在 6006 端口,通过 POST 方法进行调用,可以使用 curl 调用,如下所示:

对这一段的评论会显示在这里
curl -X POST "http://127.0.0.1:6006" \
     -H 'Content-Type: application/json' \
     -d '{"prompt": "你好"}'
对这一段的评论会显示在这里
alt text
alt text
对这一段的评论会显示在这里

也可以使用 python 中的 requests 库进行调用,如下所示:

对这一段的评论会显示在这里
import requests
import json

def get_completion(prompt):
    headers = {'Content-Type': 'application/json'}
    data = {"prompt": prompt}
    response = requests.post(url='http://127.0.0.1:6006', headers=headers, data=json.dumps(data))
    return response.json()['response']

if __name__ == '__main__':
    print(get_completion('你好'))
对这一段的评论会显示在这里
alt text
alt text
对这一段的评论会显示在这里

02-Gemma-2-9b-it langchain 接入

对这一段的评论会显示在这里

环境准备

对这一段的评论会显示在这里

在 Autodl 平台中租赁一个 RTX 3090/24G 显存的显卡机器。如下图所示,镜像选择 PyTorch-->2.1.0-->3.10(ubuntu22.04)-->12.1。

对这一段的评论会显示在这里
开启机器配置选择
开启机器配置选择
对这一段的评论会显示在这里

然后打开其中的终端,开始环境配置、模型下载和运行演示。

对这一段的评论会显示在这里

环境配置

对这一段的评论会显示在这里

pip 换源加速下载并安装依赖包

对这一段的评论会显示在这里
# 升级pip
python -m pip install --upgrade pip

# 更换 pypi 源加速库的安装
pip config set global.index-url https://pypi.tuna.tsinghua.edu.cn/simple

# 安装 langchain modelscope
pip install langchain==0.2.6
pip install modelscope
对这一段的评论会显示在这里

考虑到部分同学配置环境可能会遇到一些问题,我们在AutoDL平台准备了Gemma2 的环境镜像,该镜像适用于该仓库的 Gemma2 教程所有部署环境。点击下方链接并直接创建Autodl示例即可。 https://www.codewithgpu.com/i/datawhalechina/self-llm/self-llm-gemma2

对这一段的评论会显示在这里

模型下载

对这一段的评论会显示在这里

使用 modelscope 中的 snapshot_download 函数下载模型,第一个参数为模型名称,参数 cache_dir 为模型的下载路径。

对这一段的评论会显示在这里

然后运行下面代码,执行模型下载。模型大小为 18GB左右,下载大概需要 5 分钟。

对这一段的评论会显示在这里
from modelscope import snapshot_download
model_dir = snapshot_download('LLM-Research/gemma-2-9b-it', cache_dir='/root/autodl-tmp')
对这一段的评论会显示在这里

代码准备

对这一段的评论会显示在这里

为便捷构建 LLM 应用,我们需要基于本地部署的 Gemma2,自定义一个 LLM 类,将 Gemma2 接入到 LangChain 框架中。

对这一段的评论会显示在这里

完成自定义 LLM 类之后,可以以完全一致的方式调用 LangChain 的接口,而无需考虑底层模型调用的不一致。

对这一段的评论会显示在这里

基于本地部署的 Gemma2 自定义 LLM 类并不复杂,我们只需从 LangChain.llms.base.LLM 类继承一个子类,并重写构造函数与 _call 函数即可:

对这一段的评论会显示在这里
from langchain.llms.base import LLM
from typing import Any, List, Optional
from langchain.callbacks.manager import CallbackManagerForLLMRun
from transformers import AutoTokenizer, AutoModelForCausalLM
import torch

class Gemma2_LLM(LLM):
    # 基于本地 Gemma2 自定义 LLM 类
    tokenizer: AutoTokenizer = None
    model: AutoModelForCausalLM = None

    def __init__(self, mode_name_or_path :str):
        super().__init__()

        # 加载预训练的分词器和模型
        print("Creat tokenizer...")
        self.tokenizer = AutoTokenizer.from_pretrained(mode_name_or_path)

        print("Creat model...")
        self.model = AutoModelForCausalLM.from_pretrained(mode_name_or_path, device_map="cuda",torch_dtype=torch.bfloat16,)

    def _call(self, prompt : str, stop: Optional[List[str]] = None,
                run_manager: Optional[CallbackManagerForLLMRun] = None,
                **kwargs: Any):

        # 调用模型进行对话生成
        chat = [
            { "role": "user", "content": prompt },
        ]
        prompt = self.tokenizer.apply_chat_template(chat, tokenize=False, add_generation_prompt=True)
        inputs = self.tokenizer.encode(prompt, add_special_tokens=False, return_tensors="pt")
        outputs = self.model.generate(input_ids=inputs.to(self.model.device), max_new_tokens=150)
        outputs = self.tokenizer.decode(outputs[0])
        response = outputs.split('model')[-1].replace('<end_of_turn>\n<eos>', '')

        return response

    @property
    def _llm_type(self) -> str:
        return "Gemma2_LLM"
对这一段的评论会显示在这里

在上述类定义中,我们分别重写了构造函数和 _call 函数:对于构造函数,我们在对象实例化的一开始加载本地部署的 Gemma2 模型,从而避免每一次调用都需要重新加载模型带来的时间过长;_call 函数是 LLM 类的核心函数,LangChain 会调用该函数来调用 LLM,在该函数中,我们调用已实例化模型的 generate 方法,从而实现对模型的调用并返回调用结果。

对这一段的评论会显示在这里

在整体项目中,我们将上述代码封装为 LLM.py,后续将直接从该文件中引入自定义的 LLM 类。

对这一段的评论会显示在这里

调用

对这一段的评论会显示在这里

然后就可以像使用任何其他的langchain大模型功能一样使用了。

对这一段的评论会显示在这里
from LLM import Gemma2_LLM
llm = Gemma2_LLM('/root/autodl-tmp/LLM-Research/gemma-2-9b-it')
print(llm("你是谁"))
对这一段的评论会显示在这里
alt text
alt text
对这一段的评论会显示在这里

Yuan2.0-2B WebDemo部署

对这一段的评论会显示在这里

环境准备

对这一段的评论会显示在这里

在 Autodl 平台中租赁一个 RTX 3090/24G 显存的显卡机器。如下图所示,镜像选择 PyTorch-->2.1.0-->3.10(ubuntu22.04)-->12.1。

对这一段的评论会显示在这里
开启机器配置选择
开启机器配置选择
对这一段的评论会显示在这里

然后打开其中的终端,开始环境配置、模型下载和运行演示。

对这一段的评论会显示在这里

环境配置

对这一段的评论会显示在这里

pip 换源加速下载并安装依赖包

对这一段的评论会显示在这里
# 升级pip
python -m pip install --upgrade pip

# 更换 pypi 源加速库的安装
pip config set global.index-url https://pypi.tuna.tsinghua.edu.cn/simple

# 安装 einops modelscope streamlit
pip install einops modelscope streamlit==1.24.0
对这一段的评论会显示在这里

考虑到部分同学配置环境可能会遇到一些问题,我们在AutoDL平台准备了Gemma2 的环境镜像,该镜像适用于该仓库的 Gemma2 教程所有部署环境。点击下方链接并直接创建Autodl示例即可。 https://www.codewithgpu.com/i/datawhalechina/self-llm/self-llm-gemma2

对这一段的评论会显示在这里

模型下载

对这一段的评论会显示在这里

使用 modelscope 中的 snapshot_download 函数下载模型,第一个参数为模型名称,参数 cache_dir 为模型的下载路径。

对这一段的评论会显示在这里

然后运行下面代码,执行模型下载。模型大小为 18GB左右,下载大概需要 5 分钟。

对这一段的评论会显示在这里
# 导入所需的库
from transformers import AutoTokenizer, AutoModelForCausalLM
import torch
import streamlit as st

# 在侧边栏中创建一个标题和一个链接
with st.sidebar:
    st.markdown("## Gemma2.0 LLM")
    "[开源大模型食用指南 self-llm](https://github.com/datawhalechina/self-llm.git)"
    # 创建一个滑块,用于选择最大长度,范围在0到1024之间,默认值为512
    max_length = st.slider("max_length", 0, 1024, 512, step=1)

# 创建一个标题和一个副标题
st.title("💬 Gemma2.0 Chatbot")
st.caption("🚀 A streamlit chatbot powered by Self-LLM")

# 定义模型路径
path = '/root/autodl-tmp/LLM-Research/gemma-2-9b-it'

# 定义一个函数,用于获取模型和tokenizer
@st.cache_resource
def get_model():
    print("Creat tokenizer...")
    tokenizer = AutoTokenizer.from_pretrained(path)
    print("Creat model...")
    model = AutoModelForCausalLM.from_pretrained(path, device_map="cuda", torch_dtype=torch.bfloat16,)
  
    return tokenizer, model

# 加载emma-2-9b-it的model和tokenizer
tokenizer, model = get_model()

# 如果session_state中没有"messages",则创建一个包含默认消息的列表
if "messages" not in st.session_state:
    st.session_state["messages"] = []

# 遍历session_state中的所有消息,并显示在聊天界面上
for msg in st.session_state.messages:
    st.chat_message(msg["role"]).write(msg["content"])

# 如果用户在聊天输入框中输入了内容,则执行以下操作
if prompt := st.chat_input():
    # 将用户的输入添加到session_state中的messages列表中
    st.session_state.messages.append({"role": "user", "content": prompt})

    # 在聊天界面上显示用户的输入
    st.chat_message("user").write(prompt)

    # 调用模型
    inputs = tokenizer.apply_chat_template(st.session_state.messages, tokenize=False, add_generation_prompt=True)
    inputs = tokenizer.encode(inputs, add_special_tokens=False, return_tensors="pt")
    outputs = model.generate(input_ids=inputs.to(model.device), max_new_tokens=150)
    outputs = tokenizer.decode(outputs[0])
    response = outputs.split('model')[-1].replace('<end_of_turn>\n<eos>', '')

    # 将模型的输出添加到session_state中的messages列表中
    st.session_state.messages.append({"role": "model", "content": response})

    # 在聊天界面上显示模型的输出
    st.chat_message("model").write(response)

    # print(st.session_state)
对这一段的评论会显示在这里

复制机器ssh登录指令

对这一段的评论会显示在这里
对这一段的评论会显示在这里

粘贴到本地电脑的.ssh/config,并修改成如下格式

对这一段的评论会显示在这里
对这一段的评论会显示在这里

然后连接到此ssh,选择linx

对这一段的评论会显示在这里
对这一段的评论会显示在这里

复制密码并输入,按下回车即可登录到机器

对这一段的评论会显示在这里

运行demo

对这一段的评论会显示在这里

在终端中运行以下命令,启动streamlit服务

对这一段的评论会显示在这里
streamlit run chatBot.py --server.address 127.0.0.1 --server.port 6006
对这一段的评论会显示在这里

点击在浏览器中打开,即可看到聊天界面。

对这一段的评论会显示在这里

运行效果如下:

对这一段的评论会显示在这里
alt text
alt text
对这一段的评论会显示在这里

Gemma-2-9b-it peft lora微调

对这一段的评论会显示在这里

本节我们简要介绍如何基于 transformers、peft 等框架,对 Gemma-2-9b-it 模型进行 Lora 微调。Lora 是一种高效微调方法,深入了解其原理可参见博客:知乎|深入浅出Lora

对这一段的评论会显示在这里

这个教程会在同目录下给大家提供一个 nodebook 文件,来让大家更好的学习。

对这一段的评论会显示在这里

模型下载

对这一段的评论会显示在这里

使用 modelscope 中的 snapshot_download 函数下载模型,第一个参数为模型名称,参数 cache_dir 为模型的下载路径。

对这一段的评论会显示在这里

在 /root/autodl-tmp 路径下新建 model_download.py 文件并在其中输入以下内容,粘贴代码后请及时保存文件,如下图所示。并运行 python /root/autodl-tmp/model_download.py 执行下载,模型大小为 18GB,下载模型大概需要 10 分钟。

对这一段的评论会显示在这里
from modelscope import snapshot_download
model_dir = snapshot_download('LLM-Research/gemma-2-9b-it', cache_dir='/root/autodl-tmp')
对这一段的评论会显示在这里

环境配置

对这一段的评论会显示在这里

在完成基本环境配置和本地模型部署的情况下,你还需要安装一些第三方库,可以使用以下命令:

对这一段的评论会显示在这里
python -m pip install --upgrade pip
# 更换 pypi 源加速库的安装
pip config set global.index-url https://pypi.tuna.tsinghua.edu.cn/simple

pip install transformers==4.42.3  # 请务必安装 4.42.3 版本
pip install datasets peft
对这一段的评论会显示在这里

考虑到部分同学配置环境可能会遇到一些问题,我们在AutoDL平台准备了Gemma2 的环境镜像,该镜像适用于该仓库的 Gemma2 教程所有部署环境。点击下方链接并直接创建Autodl示例即可。 https://www.codewithgpu.com/i/datawhalechina/self-llm/self-llm-gemma2

对这一段的评论会显示在这里

在本节教程里,我们将微调数据集放置在根目录 /dataset

对这一段的评论会显示在这里

指令集构建

对这一段的评论会显示在这里

LLM 的微调一般指指令微调过程。所谓指令微调,是说我们使用的微调数据形如:

对这一段的评论会显示在这里
{
    "instruction":"回答以下用户问题,仅输出答案。",
    "input":"1+1等于几?",
    "output":"2"
}
对这一段的评论会显示在这里

其中,instruction 是用户指令,告知模型其需要完成的任务;input 是用户输入,是完成用户指令所必须的输入内容;output 是模型应该给出的输出。

对这一段的评论会显示在这里

即我们的核心训练目标是让模型具有理解并遵循用户指令的能力。因此,在指令集构建时,我们应针对我们的目标任务,针对性构建任务指令集。例如,在本节我们使用由笔者合作开源的 Chat-甄嬛 项目作为示例,我们的目标是构建一个能够模拟甄嬛对话风格的个性化 LLM,因此我们构造的指令形如:

对这一段的评论会显示在这里
{
    "instruction": "你是谁?",
    "input":"",
    "output":"家父是大理寺少卿甄远道。"
}
对这一段的评论会显示在这里

我们所构造的全部指令数据集在根目录下。

对这一段的评论会显示在这里

数据格式化

对这一段的评论会显示在这里

Lora 训练的数据是需要经过格式化、编码之后再输入给模型进行训练的,如果是熟悉 Pytorch 模型训练流程的同学会知道,我们一般需要将输入文本编码为 input_ids,将输出文本编码为 labels,编码之后的结果都是多维的向量。我们首先定义一个预处理函数,这个函数用于对每一个样本,编码其输入、输出文本并返回一个编码后的字典:

对这一段的评论会显示在这里
def process_func(example):
    MAX_LENGTH = 384    # Llama分词器会将一个中文字切分为多个token,因此需要放开一些最大长度,保证数据的完整性
    input_ids, attention_mask, labels = [], [], []
    instruction = tokenizer(f"<bos><start_of_turn>user\n{example['instruction'] + example['input']}<end_of_turn>\n<start_of_turn>model\n", add_special_tokens=False)  # add_special_tokens 不在开头加 special_tokens
    response = tokenizer(f"{example['output']}<end_of_turn>\n", add_special_tokens=False)
    input_ids = instruction["input_ids"] + response["input_ids"] + [tokenizer.pad_token_id]
    attention_mask = instruction["attention_mask"] + response["attention_mask"] + [1]  # 因为eos token咱们也是要关注的所以 补充为1
    labels = [-100] * len(instruction["input_ids"]) + response["input_ids"] + [tokenizer.pad_token_id]  
    if len(input_ids) > MAX_LENGTH:  # 做一个截断
        input_ids = input_ids[:MAX_LENGTH]
        attention_mask = attention_mask[:MAX_LENGTH]
        labels = labels[:MAX_LENGTH]
    return {
        "input_ids": input_ids,
        "attention_mask": attention_mask,
        "labels": labels
    }
对这一段的评论会显示在这里

Gemma2 采用的Prompt Template格式如下:

对这一段的评论会显示在这里
<bos><start_of_turn>user
小姐,别的秀女都在求中选,唯有咱们小姐想被撂牌子,菩萨一定记得真真儿的——<end_of_turn>
<start_of_turn>model
嘘——都说许愿说破是不灵的。<end_of_turn>
<eos>
对这一段的评论会显示在这里

加载tokenizer和半精度模型

对这一段的评论会显示在这里

模型以半精度形式加载,如果你的显卡比较新的话,可以用torch.bfloat16形式加载。对于自定义的模型一定要指定trust_remote_code参数为True

对这一段的评论会显示在这里
tokenizer = AutoTokenizer.from_pretrained('/root/autodl-tmp/LLM-Research/gemma-2-9b-it')
tokenizer.pad_token_id = tokenizer.eos_token_id
tokenizer.padding_side = 'right'

model = AutoModelForCausalLM.from_pretrained('/root/autodl-tmp/LLM-Research/gemma-2-9b-it', device_map="cuda", torch_dtype=torch.bfloat16,)
对这一段的评论会显示在这里

定义LoraConfig

对这一段的评论会显示在这里

LoraConfig这个类中可以设置很多参数,但主要的参数没多少,简单讲一讲,感兴趣的同学可以直接看源码。

对这一段的评论会显示在这里

task_type:模型类型
target_modules:需要训练的模型层的名字,主要就是attention部分的层,不同的模型对应的层的名字不同,可以传入数组,也可以字符串,也可以正则表达式。
rlora的秩,具体可以看Lora原理
lora_alphaLora alaph,具体作用参见 Lora 原理

对这一段的评论会显示在这里

Lora的缩放是啥嘞?当然不是r(秩),这个缩放就是lora_alpha/r, 在这个LoraConfig中缩放就是4倍。

对这一段的评论会显示在这里
config = LoraConfig(
    task_type=TaskType.CAUSAL_LM, 
    target_modules=["q_proj", "k_proj", "v_proj", "o_proj", 'gate_proj', 'up_proj', 'down_proj'],
    inference_mode=False, # 训练模式
    r=8, # Lora 秩
    lora_alpha=32, # Lora alaph,具体作用参见 Lora 原理
    lora_dropout=0.1# Dropout 比例
)
对这一段的评论会显示在这里

自定义 TrainingArguments 参数

对这一段的评论会显示在这里

TrainingArguments这个类的源码也介绍了每个参数的具体作用,当然大家可以来自行探索,这里就简单说几个常用的。

对这一段的评论会显示在这里

output_dir:模型的输出路径
per_device_train_batch_size:顾名思义 batch_size
gradient_accumulation_steps: 梯度累加,如果你的显存比较小,那可以把 batch_size 设置小一点,梯度累加增大一些。
logging_steps:多少步,输出一次log
num_train_epochs:顾名思义 epoch
gradient_checkpointing:梯度检查,这个一旦开启,模型就必须执行model.enable_input_require_grads(),这个原理大家可以自行探索,这里就不细说了。

对这一段的评论会显示在这里
args = TrainingArguments(
    output_dir="./output/gemma-2-9b-it",
    per_device_train_batch_size=1,
    gradient_accumulation_steps=4,
    logging_steps=10,
    num_train_epochs=3,
    save_steps=10, # 为了快速演示,这里设置10,建议你设置成100
    learning_rate=1e-4,
    save_on_each_node=True,
    gradient_checkpointing=True
)
对这一段的评论会显示在这里

使用 Trainer 训练

对这一段的评论会显示在这里
trainer = Trainer(
    model=model,
    args=args,
    train_dataset=tokenized_id,
    data_collator=DataCollatorForSeq2Seq(tokenizer=tokenizer, padding=True),
)
trainer.train()
对这一段的评论会显示在这里
alt text
alt text
对这一段的评论会显示在这里

加载 lora 权重推理

对这一段的评论会显示在这里

训练好了之后可以使用如下方式加载lora权重进行推理:

对这一段的评论会显示在这里
from transformers import AutoTokenizer, AutoModelForCausalLM
import torch
from peft import PeftModel

mode_path = '/root/autodl-tmp/LLM-Research/gemma-2-9b-it'
lora_path = './output/gemma-2-9b-it/checkpoint-90' # 这里改称你的 lora 输出对应 checkpoint 地址

# 加载tokenizer
tokenizer = AutoTokenizer.from_pretrained(mode_path)

# 加载模型
model = AutoModelForCausalLM.from_pretrained(mode_path, device_map="auto",torch_dtype=torch.bfloat16, trust_remote_code=True).eval()

# 加载lora权重
model = PeftModel.from_pretrained(model, model_id=lora_path)

# 调用模型进行对话生成
chat = [
    { "role": "user", "content": '你好' },
]
prompt = tokenizer.apply_chat_template(chat, tokenize=False, add_generation_prompt=True)
inputs = tokenizer.encode(prompt, add_special_tokens=False, return_tensors="pt")
outputs = model.generate(input_ids=inputs.to(model.device), max_new_tokens=150)
outputs = tokenizer.decode(outputs[0])
response = outputs.split('model')[-1].replace('<end_of_turn>\n<eos>', '')
对这一段的评论会显示在这里
alt text
alt text
对这一段的评论会显示在这里