找回密码
 立即注册
首页 业界区 业界 AI时代Hello World详细教程之LLM微调(SFT)

AI时代Hello World详细教程之LLM微调(SFT)

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

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

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

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

 
5.png

 
【09】本地加载微调 后的模型
    微调之后的模型,不需要太多资源就可以运行。可以本地或者继续在Kaggle上运行,验证。
  1. from transformers import AutoModelForCausalLM, AutoTokenizer
  2. class QwenChatbot:
  3.     def __init__(self, model_name="G:/00LLM/models/Qwen3-0.6B-cia-cantonese-chinese"):
  4.     # def __init__(self, model_name="G:/00LLM/models/Qwen3-0.6B-cia-finetuned-002"):
  5.     # def __init__(self, model_name="G:/00LLM/models/Qwen3-0.6B-unsloth-cia-finetuned"):
  6.         self.tokenizer = AutoTokenizer.from_pretrained(model_name)
  7.         self.model = AutoModelForCausalLM.from_pretrained(model_name)
  8.         self.history = [{"role": "system", "content": "你是一个普通话转为粤语的机器人。"}]
  9.     def generate_response(self, user_input):
  10.         messages = self.history + [{"role": "user", "content": user_input}]
  11.         text = self.tokenizer.apply_chat_template(
  12.             messages,
  13.             tokenize=False,
  14.             add_generation_prompt=True
  15.         )
  16.         inputs = self.tokenizer(text, return_tensors="pt")
  17.         response_ids = self.model.generate(**inputs, max_new_tokens=32768)[0][len(inputs.input_ids[0]):].tolist()
  18.         response = self.tokenizer.decode(response_ids, skip_special_tokens=True)
  19.         # Update history
  20.         # self.history.append({"role": "user", "content": user_input})
  21.         # self.history.append({"role": "assistant", "content": response})
  22.         return response
  23.    
  24. # Example Usage
  25. if __name__ == "__main__":
  26.     chatbot = QwenChatbot()
  27.     print("Welcome to the Qwen Chatbot!")
  28.     print("You can ask questions, and the bot will respond.")
  29.     print("Type 'q' to quit the chat.")
  30.     while True:
  31.         user_input = input("You: ")
  32.         if user_input.lower() == 'q':
  33.             break
  34.         
  35.         response = chatbot.generate_response(user_input)
  36.         print(f"Bot: {response}")
  37.         print("----------------------")
复制代码
 
以上最简单的 LLM微调详细操作步骤。
 
  

来源:程序园用户自行投稿发布,如果侵权,请联系站长删除
免责声明:如果侵犯了您的权益,请联系站长,我们会及时删除侵权内容,谢谢合作!
您需要登录后才可以回帖 登录 | 立即注册