b站视频学习笔记

【【Qwen2.5-7B微调】30分钟手把手带你用Fine-Tuning微调Qwen2.5-7B,实现低成本微调行业大模型,全程干货,草履虫也能学会!!(附教程)】https://www.bilibili.com/video/BV1RiPVe8Ei5?vd_source=429bd1b7e9f9d3081462c9e8b3b8cf19

目标:微调千问2.5-7B,训练为一个酒店客服

准备工作:

1.准备微调文件夹

包含以下内容

训练代码以及训练结果文件夹结构如下(训练完成后出现output训练结果)

2.租用GPU

在Autodl上租用gpu,4090,24G就够了

自己配环境比较复杂,所以可以直接用别人配的环境。

选择社区镜像:agiclass/fine-tuning-lab/finetune-lab-v8

创建并开机即可。

点开容器实例可以看到已经租用的实例,然后可以看到登陆指令和密码。

然后将gpu连接到XFTP和Xshell上:

【例】新建会话。登录指令:ssh -p 38809 root@connect.bjb1.seetacloud.com就按如下填写。

然后点击确定创建即可。Xshell也是同样的操作。登录好了如下所示:

3.将微调文件夹和模型下载到服务器上

接着将第一步准备好的微调文件夹通过XFTP传到autodl-tmp文件夹里。

打开Xshell,首先进入autodl-tmp文件夹(默认是在根目录下的):cd autodl-tmp/

在autodl-tmp文件夹中下载Qwen2.5-7B模型,这里是从huggingface镜像网站上下载的,代码如下:

export HF_ENDPOINT=https://hf-mirror.com
huggingface-cli download Qwen/Qwen2.5-7B-Instruct \
  --local-dir /root/autodl-tmp/Qwen2.5-7B-Instruct \
  --local-dir-use-symlinks False

等待下载即可,需要30-40分钟。

下载成功后ls查看目录,显示模型名称则代表下载完成。

顺手把缓存删了:

cd Qwen2.5-7B-Instruct/

rm -rf .cache/

4.开始训练

首先定位到训练文件夹里:cd qwen2/

然后运行训练脚本:bash train.sh

等待训练即可,大概20-30分钟。训练后可以看到训练文件夹中出现output文件夹,其中出现结果文件夹hotel-...,结果文件夹中包含训练不同时间记录的参数。

5.测试训练好的模型

在测试集上测试训练好的模型。

首先进入训练文件夹qwen2

然后编辑测试脚本:vim eval.sh

进入后按i编辑,将上面两个路径改为正确的路径(模型应该不用改,checkpoint要更新为自己的)

退出按esc,然后:wq保存。写错了就按ctrl+z不保存退出。

修改完成后直接bash eval.sh执行测试脚本(可以用clear清屏非常舒服)

可以看到一系列参数,说明模型训练的不错。

6.设置交互网页与微调后的大模型问答

交互网页的位置:

交互网页的代码:

(这里我让ai写的,prompt可以用:

帮我写一个 纯净版的 Qwen2 + LoRA Web Demo 脚本,只需提供:Base model 路径、LoRA checkpoint 路径)

【注】基础模型和checkpoint的路径确保正确,倒数第三行的端口写autodl自定义服务中的端口:我这里选的是6006

# webui_qwen2_lora.py
import torch
from transformers import AutoTokenizer, AutoModelForCausalLM, StoppingCriteria, StoppingCriteriaList
from peft import PeftModel
import gradio as gr

# ================== 配置区(按你的路径修改)==================
BASE_MODEL_PATH = "/root/autodl-tmp/Qwen2.5-7B-Instruct"   # 基础模型路径
LORA_CHECKPOINT = "qwen2/output/hotel_qwen2-20260119-145035/checkpoint-2150"    # 你的 LoRA 微调 checkpoint 路径
MAX_NEW_TOKENS = 512
TOP_P = 0.8
TEMPERATURE = 0.6
# =========================================================

# 加载 tokenizer 和模型
print("Loading tokenizer...")
tokenizer = AutoTokenizer.from_pretrained(BASE_MODEL_PATH, trust_remote_code=True)

print("Loading base model...")
model = AutoModelForCausalLM.from_pretrained(
    BASE_MODEL_PATH,
    torch_dtype=torch.bfloat16,
    device_map="auto",  # 自动分配 GPU
    trust_remote_code=True
)

print("Loading LoRA adapter...")
model = PeftModel.from_pretrained(model, LORA_CHECKPOINT)
model.eval()  # 切换到评估模式

class StopOnTokens(StoppingCriteria):
    def __init__(self, tokenizer):
        super().__init__()
        self.stop_ids = {
            tokenizer.convert_tokens_to_ids("<|im_end|>"),
            tokenizer.eos_token_id
        }

    def __call__(self, input_ids: torch.LongTensor, scores: torch.FloatTensor, **kwargs) -> bool:
        return input_ids[0][-1].item() in self.stop_ids
        
def predict(message, history):
    # 构造 Qwen 对话历史
    conversation = []
    for human, assistant in history:
        conversation.append({"role": "user", "content": human})
        if assistant is not None:
            conversation.append({"role":"assistant","content":assistant})
    conversation.append({"role": "user", "content": message.strip()})

    # 使用 tokenizer.apply_chat_template 生成标准输入
    text = tokenizer.apply_chat_template(
        conversation,
        tokenize=False,
        add_generation_prompt=True
    )

    model_inputs = tokenizer([text], return_tensors="pt").to(model.device)

    stopping_criteria = StoppingCriteriaList([StopOnTokens(tokenizer)])

    generated_ids = model.generate(
        **model_inputs,
        max_new_tokens=MAX_NEW_TOKENS,
        do_sample=True,
        top_p=TOP_P,
        temperature=TEMPERATURE,
        stopping_criteria=stopping_criteria,
    )

    generated_ids = [
        output_ids[len(input_ids):] for input_ids, output_ids in zip(model_inputs.input_ids, generated_ids)
    ]

    response = tokenizer.batch_decode(generated_ids, skip_special_tokens=True)[0]
    return response

# 启动 Gradio 界面
gr.ChatInterface(
    predict,
    title="🏨 Hotel Qwen2.5-7B (LoRA Fine-tuned)",
    description="基于 Qwen2.5-7B-Instruct 微调的酒店客服模型",
    examples=[
        ["你们有免费早餐吗?"],
        ["我想取消明天的预订。"],
        ["酒店提供接送服务吗?"]
    ],
    retry_btn="🔄 重试",
    undo_btn="↩️ 撤销",
    clear_btn="🗑️ 清除"
).queue().launch(
    server_name="0.0.0.0",  # 允许外部访问(AutoDL 需要)
    server_port=6006,
    share=False  # 设为 True 可生成公网链接(但 AutoDL 通常用 Web 访问)
)

通过xftp把这个代码文件放到微调文件夹里

(或者用Xshell:

touch webui_qwen2.5_lora.py

vim webui_qwen2.5_lora.py
然后粘贴代码即可)

然后运行代码:python webui_qwen2.5_lora.py

这个时候我们的页面就跑起来了,想找到页面的网址,在autodl的自定义服务里找对应端口的网址即可。

交互页面如下:

7.报错与检查

如果运行交互网页代码,显示port not empty,网址也打不开:

可能是端口被自己之前的进程占用, 

ps aux | grep python | grep -v grep

查看进程占用情况。kill掉想去掉的进程(这里全kill掉了)。再查看就没有端口占用情况了。

如果对话显示error,查看Xshell中的报错,可能是版本语法不一样,投给ai,照着新版本语法修改源码就行了。

Logo

有“AI”的1024 = 2048,欢迎大家加入2048 AI社区

更多推荐