AI时代Hello World详细教程之LLM微调(SFT)
【00】时代变了
移动互联网时代的Hello World(参见Xamarin 使用极光推送 详细教程 ),安装某一套开发工具包(IDE)就够了,AI时代就明显要的就多了。
依然直奔主题,无废话,直接上实操步骤。微调基础LLM,使之支持普通话翻译为粤语。
【01】名词解释

【02】无中生GPU
AI时代没有GPU寸步难行,如何薅到GPU呢?
https://www.kaggle.com/ 自行注册,通过手机号验证之后,每周可以薅30H的GPU资源。
【03】环境初始化
新建Notebook,就当是VS的项目对待了。

初始化基础环境,依赖的python库。
%pip install --no-deps bitsandbytes accelerate xformers==0.0.29.post3 peft trl==0.15.2 triton cut_cross_entropy unsloth_zoo
%pip install sentencepiece protobuf huggingface_hub hf_transfer
%pip install --no-deps unsloth
%pip install -U datasets
脚本或代码,都可以点击右边的 运行 按钮执行,并且在环境未重启之前,都可以保存上下文变量数据。

【04】加载基础模型
基础模型选择:unsloth/Qwen3-0.6B-unsloth-bnb-4bit,模型1G多比较适合用来写HelloWorld,本身也不支持粤语翻译。
from unsloth import FastLanguageModel
import torch model, tokenizer = FastLanguageModel.from_pretrained(
model_name="unsloth/Qwen3-0.6B-unsloth-bnb-4bit", # 6亿参数量化模型
max_seq_length=2048, # 支持2048token上下文
# dtype = torch.float16,
load_in_4bit=True, # 4位量化降低内存占用
load_in_8bit=False, # 8位模式(需更高显存)
full_finetuning=False, # 启用参数高效微调(PEFT)
# token="<YOUR_HF_TOKEN>", # 访问权限模型需提供令牌
) model = FastLanguageModel.get_peft_model(
model,
r=32, # LoRA矩阵秩,值越大精度越高
target_modules=[ # 需适配的模型层
"q_proj", "k_proj", "v_proj", "o_proj",
"gate_proj", "up_proj", "down_proj"
],
lora_alpha=64, # 缩放因子,通常设为r的2倍
lora_dropout=0, # 关闭 dropout
bias="none", # 不微调偏置项
use_gradient_checkpointing="unsloth", # 支持长上下文
random_state=3433, # 随机种子确保可复现
)
【05】微调数据集加载
数据采用以下两个,简单的粤语、普通话对照记录。
https://huggingface.co/datasets/agentlans/cantonese-chinese
https://huggingface.co/datasets/botisan-ai/cantonese-mandarin-translations
from datasets import load_dataset,Dataset
import pandas as pd # 加载推理与对话数据集
ds01 = load_dataset("agentlans/cantonese-chinese")["train"]
print(ds01.column_names) # 查看所有列名 ds02 = load_dataset("botisan-ai/cantonese-mandarin-translations")["train"]
print(ds02.column_names) # 查看所有列名 # 标准化推理数据为对话格式
def generate01(examples):
problems = examples["zh"]
solutions = examples["yue"]
return {
"messages": [
{"role": "system", "content": "你是一个普通话转为粤语的机器人。"},
{"role": "user", "content": problems},
{"role": "assistant", "content": solutions}
]
} def generate02(examples):
problems = examples["translation"]["zh"]
solutions = examples["translation"]["yue"]
return {
"messages": [
{"role": "system", "content": "你是一个普通话转为粤语的机器人。"},
{"role": "user", "content": problems},
{"role": "assistant", "content": solutions}
]
} dsm01= ds01.map(generate01)
dsm02= ds02.map(generate02)
cvs01 = tokenizer.apply_chat_template(
dsm01["messages"],
tokenize=False
)
cvs02 = tokenizer.apply_chat_template(
dsm02["messages"],
tokenize=False
) # 设定对话比例
chat_percentage = 0.7
data = pd.concat([
pd.Series(cvs01),
pd.Series(cvs02),
])
data.name = "text" combined_dataset = Dataset.from_pandas(pd.DataFrame(data))
combined_dataset = combined_dataset.shuffle(seed=3407)
【06】开始微调
使用trl 库,进行微调。
from trl import SFTTrainer, SFTConfig
print("开始训练...")
trainer = SFTTrainer(
model=model,
tokenizer=tokenizer,
train_dataset=combined_dataset, # 结构化数据集
eval_dataset=None,
args=SFTConfig(
dataset_text_field="text", # 用于训练的数据集字段
per_device_train_batch_size=2, # 单设备训练批次大小
gradient_accumulation_steps=4, # 梯度累积步数
warmup_steps=5, # 学习率预热步数
max_steps=30, # 总训练步数
learning_rate=2e-4, # 学习率
logging_steps=1, # 日志记录频率
optim="adamw_8bit", # 优化器
weight_decay=0.01, # 权重衰减
lr_scheduler_type="linear", # 学习率衰减策略
seed=3407,
report_to="none", # 日志平台(可选wandb)
),
)
trainer_stats = trainer.train()
【07】效果检测
进行简单的对话,看是否有效果。
messages = [
{"role": "system", "content": "你是一个普通话转为粤语的机器人。"},
{"role": "user", "content": "有个老婆婆在元朗紫荆东路等小巴"}
]
text = tokenizer.apply_chat_template(
messages,
tokenize=False,
add_generation_prompt=True, # 生成响应必需
enable_thinking=False, # 禁用思考
) from transformers import TextStreamer
_ = model.generate(
**tokenizer(text, return_tensors="pt").to("cuda"),
max_new_tokens=256, # 最大生成token数
temperature=0.7, top_p=0.8, top_k=20, streamer=TextStreamer(tokenizer, skip_prompt=True),
)
【08】微调后模型保存,并下载
下载时Edge浏览器会先下载完文件之后,才弹出保存对话框。点了Download之后,感觉没有任何反应 需要耐心等待N长时间。
import shutil # 模型保存在目录
my_model="Qwen3-0.6B-cia-cantonese-chinese"
model_dir = "/kaggle/working/Models/"+my_model
output_zip = my_model+".zip" model.save_pretrained_merged(
model_dir,
tokenizer,
save_method="merged_16bit"
) # 压缩成 .zip 文件
shutil.make_archive(output_zip.replace(".zip", ""), "zip", model_dir) print(f" 模型已压缩为 {output_zip}")


【09】本地加载微调 后的模型
微调之后的模型,不需要太多资源就可以运行。可以本地或者继续在Kaggle上运行,验证。
from transformers import AutoModelForCausalLM, AutoTokenizer class QwenChatbot:
def __init__(self, model_name="G:/00LLM/models/Qwen3-0.6B-cia-cantonese-chinese"):
# def __init__(self, model_name="G:/00LLM/models/Qwen3-0.6B-cia-finetuned-002"):
# def __init__(self, model_name="G:/00LLM/models/Qwen3-0.6B-unsloth-cia-finetuned"):
self.tokenizer = AutoTokenizer.from_pretrained(model_name)
self.model = AutoModelForCausalLM.from_pretrained(model_name)
self.history = [{"role": "system", "content": "你是一个普通话转为粤语的机器人。"}] def generate_response(self, user_input):
messages = self.history + [{"role": "user", "content": user_input}] text = self.tokenizer.apply_chat_template(
messages,
tokenize=False,
add_generation_prompt=True
) inputs = self.tokenizer(text, return_tensors="pt")
response_ids = self.model.generate(**inputs, max_new_tokens=32768)[0][len(inputs.input_ids[0]):].tolist()
response = self.tokenizer.decode(response_ids, skip_special_tokens=True) # Update history
# self.history.append({"role": "user", "content": user_input})
# self.history.append({"role": "assistant", "content": response}) return response # Example Usage
if __name__ == "__main__":
chatbot = QwenChatbot()
print("Welcome to the Qwen Chatbot!")
print("You can ask questions, and the bot will respond.")
print("Type 'q' to quit the chat.")
while True:
user_input = input("You: ")
if user_input.lower() == 'q':
break response = chatbot.generate_response(user_input)
print(f"Bot: {response}")
print("----------------------")
以上最简单的 LLM微调详细操作步骤。
AI时代Hello World详细教程之LLM微调(SFT)的更多相关文章
- DNS域欺骗攻击详细教程之Linux篇
.DNS域欺骗攻击原理 DNS欺骗即域名信息欺骗是最常见的DNS安全问题.当一 个DNS服务器掉入陷阱,使用了来自一个恶意DNS服务器的错误信息,那么该DNS服务器就被欺骗了.DNS欺骗会使那些易受攻 ...
- Oracle 集群】ORACLE DATABASE 11G RAC 知识图文详细教程之ORACLE集群概念和原理(二)
ORACLE集群概念和原理(二) 概述:写下本文档的初衷和动力,来源于上篇的<oracle基本操作手册>.oracle基本操作手册是作者研一假期对oracle基础知识学习的汇总.然后形成体 ...
- 【Oracle 集群】ORACLE DATABASE 11G RAC 知识图文详细教程之RAC 工作原理和相关组件(三)
RAC 工作原理和相关组件(三) 概述:写下本文档的初衷和动力,来源于上篇的<oracle基本操作手册>.oracle基本操作手册是作者研一假期对oracle基础知识学习的汇总.然后形成体 ...
- 【Oracle 集群】ORACLE DATABASE 11G RAC 知识图文详细教程之RAC 特殊问题和实战经验(五)
RAC 特殊问题和实战经验(五) 概述:写下本文档的初衷和动力,来源于上篇的<oracle基本操作手册>.oracle基本操作手册是作者研一假期对oracle基础知识学习的汇总.然后形成体 ...
- 【Oracle 集群】11G RAC 知识图文详细教程之RAC在LINUX上使用NFS安装前准备(六)
RAC在LINUX上使用NFS安装前准备(六) 概述:写下本文档的初衷和动力,来源于上篇的<oracle基本操作手册>.oracle基本操作手册是作者研一假期对oracle基础知识学习的汇 ...
- 【转】【Oracle 集群】ORACLE DATABASE 11G RAC 知识图文详细教程之RAC 特殊问题和实战经验(五)
原文地址:http://www.cnblogs.com/baiboy/p/orc5.html 阅读目录 目录 共享存储 时间一致性 互联网络(或者私有网络.心跳线) 固件.驱动.升级包的一致性 共 ...
- 【转】【Oracle 集群】ORACLE DATABASE 11G RAC 知识图文详细教程之RAC 工作原理和相关组件(三)
原文地址:http://www.cnblogs.com/baiboy/p/orc3.html 阅读目录 目录 RAC 工作原理和相关组件 ClusterWare 架构 RAC 软件结构 集群注册(OC ...
- 【转】Oracle 集群】ORACLE DATABASE 11G RAC 知识图文详细教程之ORACLE集群概念和原理(二)
阅读目录 目录 Oracle集群概念和原理 RAC概述 RAC 集成集群件管理 RAC 的体系结构 RAC 的结构组成和机制 RAC 后台进程 RAC 共享存储 RAC 数据库和单实例数据库的区别 ...
- 【转】【Oracle 集群】11G RAC 知识图文详细教程之RAC在LINUX上使用NFS安装前准备(六)
原文地址:http://www.cnblogs.com/baiboy/p/orc6.html 阅读目录 目录 介绍 下载软件 操作系统安装 Oracle安装先决条件 创建共享磁盘 参考文献 相关文章 ...
- 3星|《腾讯产业森林:AI时代的创业密码》:后半部分是较详细的创业指南,前面泛泛介绍腾讯、AI
腾讯产业森林:AI时代的创业密码 前半部分泛泛介绍腾讯对创业者的支持,腾讯支持的创业项目的案例.AI的一些基本介绍,后半部分是比较详细的写给创业者的各阶段行动与选择的指南. 总体评价3星,有一些参考价 ...
随机推荐
- mac环境配置本地nfs服务
前言 在这篇文章中,讲了在Mac端开启NFS服务,并通过NFS协议让其他设备挂载到你的Mac上. 步骤一:增加配置文件 首先,我们需要编辑NFS的配置文件,以便定义哪些目录可以被远程访问. 打开终端, ...
- phpstorm、goland常用快捷键
1) 文件操作相关的快捷键 快捷键 作用 Ctrl + E 打开最近浏览过的文件 Ctrl + N 快速打开某个 struct 结构体所在的文件 Ctrl + Shift + N 快速打开文件 Shi ...
- 原生JS实现虚拟列表(不使用Vue,React等前端框架)
好家伙, 1. 什么是虚拟列表 虚拟列表(Virtual List)是一种优化长列表渲染性能的技术.当我们需要展示成千上万条数据时,如果一次性将所有数据渲染到DOM中,会导致页面卡顿甚至崩溃.虚拟 ...
- .NET 10 Preview 2 增强了 Blazor 和.NET MAUI
.NET 团队 3.18 发布了.NET 10 Preview 2(https://devblogs.microsoft.com/dotnet/dotnet-10-preview-2/)..NET 1 ...
- 【Python】Python实现解压rar文件
Python实现解压rar文件 零.需求 最近在开发一个填分数的应用,需要用到selenium,那么自然需要用到浏览器,浏览器内置到应用中,但是上传到GitCode的时候被限制了,单个文件大小只能是1 ...
- CoreOS 发行版本介绍
大多数的软件通常都有什么内测版.公测版什么的. CoreOS 发行版本 而在 CoreOS 中, 有以下3个版本: alpha - α版,音译:阿尔法,俗称尝鲜版,是最新的版本,但是容易出现bug,最 ...
- C中输入输出
引入一个概念,对于计算机来说,外来数据都是输入,经过计算机处理的结果并进行显示的就是输出.在linux里面,一切都是文件,就连输入输出,都可以划归到"文件"一类,而为了管理这些文件 ...
- 测试工作中用到的MongoDB命令
1.远程连接MongoDB mongo host:port/dbname (host和port根据自己需要修改) 连接成功页面如下: 2.显示所有数据库 show dbs 3.切换到oversea-a ...
- 支持命令行输入中文(例如redis-cli输入中文)
修改 cmd 控制台默认代码页编码的几种方法[GBK.UTF-8]_FKNIGHT 的博客-CSDN博客_修改cmd编码 1.进入redis-cli.exe所在文件夹 2.在路径栏输入cmd回车 3. ...
- 【ROS】2.1 Turtlebot3汉堡Burger连接和远程控制
机器人连接和远程控制 准备 充电 充电有两种方式: ①直接供电:电源适配器连接树莓派上的圆孔: ②电池供电:电源适配器插到蓝色的那个充电器,再将充电器与Burger底座的电池相连接.(当电池电量低于1 ...