亲自动手试了Qwen3-1.7B微调,效果真的不错!

1. 引言

随着大语言模型在垂直领域的深入应用,医疗、金融、法律等专业场景对模型推理能力与领域知识的要求越来越高。阿里巴巴于2025年4月29日开源的通义千问3(Qwen3)系列,凭借其从0.6B到235B的多样化参数规模和混合专家(MoE)架构支持,迅速成为开发者关注的焦点。

本文聚焦 Qwen3-1.7B 这一轻量级密集模型,结合真实医疗对话数据集 delicate_medical_r1_data,完成从环境搭建、数据处理、LoRA高效微调到推理增强的全流程实践。通过本次实验验证:即使在消费级显卡上,也能高效完成大模型的专业化适配,并实现类似 DeepSeek R1 的“思考+回答”双阶段输出能力。

本项目采用 CSDN 星图平台提供的免费算力资源,结合 SwanLab 实现训练过程可视化监控,为初学者提供一条低门槛、可复现的大模型微调路径。


2. 环境准备与镜像启动

2.1 启动 Qwen3-1.7B 镜像

登录 CSDN 星图平台后,在镜像市场中搜索并选择 Qwen3-1.7B 镜像,一键启动 Jupyter Notebook 环境。该镜像已预装以下关键组件:

  • Transformers 4.38+
  • PEFT
  • Accelerate
  • Datasets
  • LangChain
  • SwanLab

启动成功后,可通过浏览器访问 Jupyter 服务地址(如 https://gpu-pod...web.gpu.csdn.net),进入开发界面。

2.2 使用 LangChain 调用本地模型

Qwen3-1.7B 已通过 OpenAI 兼容接口暴露服务,可直接使用 langchain_openai.ChatOpenAI 模块进行调用:

from langchain_openai import ChatOpenAI
import os

chat_model = ChatOpenAI(
    model="Qwen3-1.7B",
    temperature=0.5,
    base_url="https://gpu-pod69523bb78b8ef44ff14daa57-8000.web.gpu.csdn.net/v1",  # 替换为实际Jupyter地址
    api_key="EMPTY",
    extra_body={
        "enable_thinking": True,
        "return_reasoning": True,
    },
    streaming=True,
)

response = chat_model.invoke("你是谁?")
print(response)

说明base_url 中的端口必须为 8000,这是模型服务默认监听端口;api_key="EMPTY" 表示无需认证;extra_body 参数启用“思维链”功能,使模型返回中间推理过程。

执行上述代码后,模型将返回包含角色识别与功能描述的完整响应,表明基础调用链路畅通。


3. 数据准备与预处理

3.1 数据集介绍

本实验采用魔塔社区公开的医学对话数据集 delicate_medical_r1_data,其结构如下:

字段含义
instruction任务指令
question用户提问(输入)
think模型思考过程(目标输出之一)
answer最终答案(目标输出之二)
metrics评估指标

每条样本期望模型根据 question 输出格式化的 "think": "...", "answer": "..." 结构,模拟 DeepSeek R1 的分步推理风格。

3.2 数据下载与加载

使用 ModelScope SDK 下载数据集:

from modelscope.msdatasets import MsDataset

dataset = MsDataset.load('krisfu/delicate_medical_r1_data')
train_dataset = dataset['train'].to_list()

3.3 构建训练样本格式

我们将原始数据转换为标准的对话格式(ChatML),以便 LLM 更好地理解上下文结构:

{
  "messages": [
    {"role": "user", "content": "头痛可能由哪些原因引起?"},
    {"role": "assistant", "content": "{\"think\": \"首先需要区分原发性和继发性头痛...\", \"answer\": \"常见原因包括紧张性头痛、偏头痛等...\"}"}
  ]
}

3.4 数据分割与保存

将数据按 9:1 划分为训练集与验证集,并以 JSONL 格式保存:

import json
import random

random.shuffle(train_dataset)
split_idx = int(0.9 * len(train_dataset))
train_data = train_dataset[:split_idx]
val_data = train_dataset[split_idx:]

def save_jsonl(data, filename):
    with open(filename, 'w', encoding='utf-8') as f:
        for item in data:
            sample = {
                "messages": [
                    {"role": "user", "content": item["question"]},
                    {"role": "assistant", "content": json.dumps({
                        "think": item["think"], 
                        "answer": item["answer"]
                    }, ensure_ascii=False)}
                ]
            }
            f.write(json.dumps(sample, ensure_ascii=False) + "\n")

save_jsonl(train_data, "train.jsonl")
save_jsonl(val_data, "val.jsonl")

print("The dataset has been split successfully.")

完成后,当前目录下生成 train.jsonlval.jsonl 文件,可用于后续训练。


4. 配置 SwanLab 训练监控工具

SwanLab 是一款轻量级 AI 实验追踪工具,支持与 Hugging Face Transformers 无缝集成,提供实时指标可视化看板。

4.1 安装与登录

pip install swanlab -i https://mirrors.cernet.edu.cn/pypi/web/simple
swanlab login

登录时需前往 SwanLab官网 注册账号并复制 API Key。

4.2 初始化实验记录

在训练脚本中初始化实验,记录超参数:

import swanlab

swanlab.init(
    project="qwen3-medical-finetune",
    config={
        "model": "Qwen3-1.7B",
        "dataset": "delicate_medical_r1_data",
        "learning_rate": 2e-5,
        "batch_size": 4,
        "epochs": 3,
        "max_seq_length": 1024,
        "optimizer": "AdamW",
        "scheduler": "linear_with_warmup"
    },
    description="LoRA fine-tuning of Qwen3-1.7B on medical reasoning dataset"
)

4.3 记录训练指标

在训练循环中定期上报损失与准确率:

swanlab.log({
    "loss": loss.item(),
    "learning_rate": current_lr,
    "epoch": epoch
})

训练开始后,访问 SwanLab Web 界面即可查看动态更新的损失曲线、学习率变化等信息,便于及时发现过拟合或收敛异常。


5. 加载与微调 Qwen3-1.7B 模型

5.1 加载基础模型

使用 ModelScope 下载 Qwen3-1.7B 并加载至 Transformers:

from transformers import AutoTokenizer, AutoModelForCausalLM

model_name = "Qwen/Qwen3-1.7B"
tokenizer = AutoTokenizer.from_pretrained(model_name, trust_remote_code=True)
model = AutoModelForCausalLM.from_pretrained(model_name, trust_remote_code=True, torch_dtype="auto")

设置 tokenizer 支持 ChatML 格式:

tokenizer.pad_token = tokenizer.eos_token
tokenizer.padding_side = "right"

5.2 全参数微调(Full Fine-Tuning)

全参微调会更新所有模型参数,理论上性能最优,但显存需求高(约 32GB)。适用于 A100/A800 级别设备。

from transformers import TrainingArguments, Trainer

training_args = TrainingArguments(
    output_dir="./qwen3-medical-ft",
    per_device_train_batch_size=4,
    gradient_accumulation_steps=8,
    num_train_epochs=3,
    learning_rate=2e-5,
    fp16=True,
    logging_steps=10,
    save_steps=1000,
    evaluation_strategy="steps",
    eval_steps=500,
    report_to="none",  # 自定义日志上报
    push_to_hub=False,
)

trainer = Trainer(
    model=model,
    args=training_args,
    train_dataset=train_dataset,
    eval_dataset=val_dataset,
    tokenizer=tokenizer,
    compute_metrics=None,
)

trainer.train()

⚠️ 注意:在 24GB 显存下运行全参微调可能导致 OOM,建议优先使用 LoRA。


6. 参数高效微调:LoRA 实现

6.1 LoRA 原理简述

Low-Rank Adaptation(LoRA)通过冻结主干权重,在注意力层引入低秩矩阵进行增量更新,显著降低显存消耗(约 10GB 可运行),同时保持接近全参微调的效果。

6.2 配置与训练 LoRA 模型

from peft import LoraConfig, get_peft_model
import torch

lora_config = LoraConfig(
    r=64,
    lora_alpha=16,
    target_modules=["q_proj", "k_proj", "v_proj", "o_proj"],
    lora_dropout=0.1,
    bias="none",
    task_type="CAUSAL_LM"
)

model = get_peft_model(model, lora_config)
model.print_trainable_parameters()  # 查看可训练参数比例(通常 < 1%)

输出示例:

trainable params: 8,388,608 || all params: 1,700,000,000 || trainable%: 0.49

6.3 开始 LoRA 微调

重用之前的 TrainingArguments,仅需替换模型为 PEFT 包装后的实例:

trainer = Trainer(
    model=model,
    args=training_args,
    train_dataset=train_dataset,
    eval_dataset=val_dataset,
    tokenizer=tokenizer,
    callbacks=[...],
)

trainer.train()

# 保存适配器权重
model.save_pretrained("./qwen3-medical-lora")

训练过程中,SwanLab 实时显示 loss 下降趋势,一般在 1~2 个 epoch 内即可收敛。


7. 推理与流式输出优化

7.1 加载 LoRA 权重进行推理

from peft import PeftModel

base_model = AutoModelForCausalLM.from_pretrained("Qwen/Qwen3-1.7B", trust_remote_code=True)
tokenizer = AutoTokenizer.from_pretrained("Qwen/Qwen3-1.7B", trust_remote_code=True)

model = PeftModel.from_pretrained(base_model, "./qwen3-medical-lora")
model.to("cuda")

7.2 实现流式响应

利用 generate 方法配合回调函数实现逐 token 输出:

def predict_stream(prompt):
    inputs = tokenizer(prompt, return_tensors="pt").to("cuda")
    
    streamer = TextStreamer(tokenizer, skip_prompt=True, skip_special_tokens=True)
    
    outputs = model.generate(
        **inputs,
        max_new_tokens=512,
        temperature=0.7,
        do_sample=True,
        streamer=streamer
    )
    
    return tokenizer.decode(outputs[0], skip_special_tokens=True)

调用示例:

prompt = "用户问:感冒发烧怎么处理?"
response = predict_stream(prompt)

输出示例:

{"think": "首先判断是否为病毒性感冒...考虑是否有细菌感染迹象...", "answer": "建议多休息、补充水分...若持续高烧应就医检查血常规..."}

8. 添加简单记忆功能

为了让模型具备多轮对话能力,我们维护一个全局消息列表,模拟历史记忆。

8.1 实现思路

  1. 维护一个跨请求的 messages 列表;
  2. 每次用户输入后追加 user 角色消息;
  3. 模型回复后追加 assistant 角色消息;
  4. 下次推理时传入完整对话历史。

8.2 代码实现

import json

messages = []

def chat(user_input):
    global messages
    
    # 添加用户消息
    messages.append({"role": "user", "content": user_input})
    
    # 构造 prompt
    prompt = ""
    for msg in messages:
        if msg["role"] == "user":
            prompt += f"<|im_start|>user\n{msg['content']}<|im_end|>\n"
        else:
            prompt += f"<|im_start|>assistant\n{msg['content']}<|im_end|>\n"
    prompt += "<|im_start|>assistant\n"

    # 生成回复
    inputs = tokenizer(prompt, return_tensors="pt").to("cuda")
    outputs = model.generate(**inputs, max_new_tokens=256, do_sample=True)
    response = tokenizer.decode(outputs[0], skip_special_tokens=True)

    # 提取 assistant 回复并添加到历史
    messages.append({"role": "assistant", "content": response})
    
    return response

# 启动对话
while True:
    user_q = input("你:")
    if user_q.lower() in ["退出", "quit"]:
        break
    ans = chat(user_q)
    print(f"模型:{ans}")

此机制使得模型能基于上下文做出连贯回应,初步实现“有记忆”的对话系统。


9. 总结

本文围绕 Qwen3-1.7B 在医疗领域的微调任务,完成了完整的工程实践闭环:

  1. ✅ 利用 CSDN 星图平台免费算力,快速部署 Qwen3-1.7B 推理环境;
  2. ✅ 基于 delicate_medical_r1_data 数据集完成数据清洗与 ChatML 格式构建;
  3. ✅ 配置 SwanLab 实现实验全过程监控,提升调试效率;
  4. ✅ 成功实施 LoRA 高效微调,在 10GB 显存限制下完成模型适配;
  5. ✅ 实现流式输出与简单记忆机制,增强用户体验。

实验结果表明,Qwen3-1.7B 经过针对性微调后,能够稳定输出符合医学逻辑的“思考+回答”结构化内容,具备初步临床辅助问答能力。

未来可进一步探索方向包括:

  • 引入更多高质量医学知识图谱进行 RAG 增强;
  • 使用 DPO 或 ORPO 方法优化回答安全性与合规性;
  • 将模型打包为 API 服务,集成至电子病历系统。

大模型技术正加速向专业领域渗透,掌握从数据准备到私有化部署的全流程能力,将成为 AI 工程师的核心竞争力。


获取更多AI镜像

想探索更多AI镜像和应用场景?访问 CSDN星图镜像广场,提供丰富的预置镜像,覆盖大模型推理、图像生成、视频生成、模型微调等多个领域,支持一键部署。

Logo

北京人形旗下天工造物具身智能开源社区,聚焦具身天工与慧思开物两大平台

更多推荐