六年长跑的最后一学期。小强要完成大模型的最后拼图:亲手微调一个「说自己的话」的模型,把它量化后装进自己的电脑,然后带着一个完整可演示的大模型产品走上毕业答辩的舞台。从三年级的 print("你好,世界") 到今天的专属大模型——闭环了。
走完大模型最后一公里:LoRA 微调、数据集制作、量化与本地部署、效果评估与对齐,最终完成可演示的大模型产品并毕业答辩。
用故事和生活类比打开这学期的大门,先「知其所以然」再学语法。
六年长跑的最后一学期。小强要完成大模型的最后拼图:亲手微调一个「说自己的话」的模型,把它量化后装进自己的电脑,然后带着一个完整可演示的大模型产品走上毕业答辩的舞台。从三年级的 print("你好,世界") 到今天的专属大模型——闭环了。
主科(原模型权重)不动,只加一小门课(低秩矩阵),省时省显存。
低秩微调把大行李箱压成登机箱,东西还是那些东西,体积小一大截。
降精度存储不依赖云端,断网也能跑,数据不出门。
离线推理六年所学,一场 showtime:讲清楚、演出来、答得上。
成果展示模型微调与毕业项目 —— 共 13 课时,全部知识点一网打尽。
from peft import LoraConfig, get_peft_model
config = LoraConfig(
r=8, # 低秩矩阵的秩
target_modules=["q_proj", "v_proj"], # 只挂注意力层
lora_alpha=16, lora_dropout=0.05)
model = get_peft_model(base_model, config)
model.print_trainable_parameters()
# 可训练参数只占全模型的不到 1%!trainable params: 1,572,864 || all params: 332,872,704 || trainable%: 0.47# train.jsonl —— 每行一个教学案例
{"instruction": "用一句话解释递归",
"output": "递归就是函数自己调用自己,直到到达出口条件。"}
{"instruction": "把这句话改成文言文:今天天气真好",
"output": "今日天朗气清,惠风和畅。"}
# 格式统一 + 质量高 + 数量够 → 微调效果好的三要素(教材越干净,学生学得越好)# 四步走:
# ① 准备数据:{"instruction":…, "output":…} JSONL(贵精不贵多)
# ② 选底座:Qwen2.5-1.5B(小而美,学生卡也能训)
# ③ LoRA 微调:只训练插进去的小矩阵
from peft import LoraConfig, get_peft_model
cfg = LoraConfig(r=8, target_modules=["q_proj", "v_proj"])
# model = get_peft_model(base, cfg) # 可训练参数 <1%
print("LoRA r=8:原模型 1.5B 参数,只训约 1200 万")
print("④ 评估:留出 50 条验证集,看答对率")
print("⑤ 导出合并:merge_and_unload() → 部署")LoRA r=8:原模型 1.5B 参数,只训约 1200 万
④ 评估:留出 50 条验证集,看答对率
⑤ 导出合并:merge_and_unload() → 部署from transformers import BitsAndBytesConfig
bnb = BitsAndBytesConfig(
load_in_4bit=True, # 16bit → 4bit
bnb_4bit_quant_type="nf4")
# model = AutoModelForCausalLM.from_pretrained(
# name, quantization_config=bnb)
# 7B 模型显存:14GB → 约 4GB(显存需求直降 4 倍,速度损失很小)# 安装后两条命令搞定:
# ollama pull qwen2:1.5b # 下载模型
# ollama run qwen2:1.5b # 对话!
# 也提供本地 API:
import requests
r = requests.post("http://localhost:11434/api/chat",
json={"model": "qwen2:1.5b",
"messages": [{"role":"user","content":"你好"}]})
print(r.json()["message"]["content"])你好!我是运行在你自己电脑上的AI,断网也能用~# 自动指标 + 人工评估 双保险
import time
def blind_test(a_out, b_out):
"""盲测:去标签打乱,人投票谁更好"""
import random
pair = [("A", a_out), ("B", b_out)]
random.shuffle(pair)
return pair
r = blind_test("基础模型答案", "微调后模型答案")
print("打乱后顺序:", [x[0] for x in r], "(评委不知哪个是谁)")
print("指标三件套:任务答对率 / 忠实度 / 风格符合度")
print("警惕:只在自己出的题上测 = 既当运动员又当裁判")打乱后顺序: ['B', 'A'] (评委不知哪个是谁)
指标三件套:任务答对率 / 忠实度 / 风格符合度
警惕:只在自己出的题上测 = 既当运动员又当裁判# RLHF 三步走(概念):
# ① SFT:先学会做事(监督微调)
# ② RM:训练一个"打分员"(奖励模型)
# ③ RL/PPO/DPO:朝着高分方向优化
# DPO 更简单:直接用"好答案 vs 坏答案"
# 的成对数据训练偏好。
print("目标:有帮助 + 诚实 + 无害")目标:有帮助 + 诚实 + 无害# LLaVA 思路 = 视觉编码器 + 语言模型
# 图 → ViT 提特征 → 投影到词向量空间
# ↓
# 和文字一起喂给 LLM → 生成回答
# 用途:图片问答 / 看图写作 / 图文聊天用户:[上传一张猫的照片] 这是什么?
AI:这是一只橘猫,正趴在键盘上睡觉。# 上线前的「三查」:
checks = {
"偏见查": "是否对某些群体系统性输出刻板印象?",
"隐私查": "训练数据 / 对话记录有没有个人信息?",
"合规查": "生成内容有没有违反法规的风险场景?",
}
for k, v in checks.items():
print(f"{k}:{v}")
print("学生守则:不造谣、不抄袭、不泄露他人数据")
print("工程手段:敏感词过滤 + 输出审核 + 用户举报通道")偏见查: 是否对某些群体系统性输出刻板印象?
隐私查: 训练数据 / 对话记录有没有个人信息?
合规查: 生成内容有没有违反法规的风险场景?
学生守则:不造谣、不抄袭、不泄露他人数据
工程手段:敏感词过滤 + 输出审核 + 用户举报通道# 12 课时的成人大片节奏:
stages = [
("W1", "选品:真实痛点 + 数据可得 + 两周能做完"),
("W2", "MVP:砍到只剩核心功能,先能跑"),
("W3", "打磨:错误处理 / 提示词 / 界面细节"),
("W4", "发布:部署上线 + 写说明 + 答辩彩排"),
]
for w, task in stages:
print(f"{w}:{task}")
print("验收:真实用户试用 5 分钟,说得出『真方便』")W1:选品:真实痛点 + 数据可得 + 两周能做完
W2:MVP:砍到只剩核心功能,先能跑
W3:打磨:错误处理 / 提示词 / 界面细节
W4:发布:部署上线 + 写说明 + 答辩彩排
验收:真实用户试用 5 分钟,说得出『真方便』每个知识点都要落到能跑、能玩、能演示的作品上。
期末项目是整学期知识点的综合检验场:演讲、演示、问答。学生将独立完成需求拆解 → 功能实现 → 调试打磨 → 上台演示的完整闭环。
| 课次 | 主题 | 趣味项目 | 知识点 |
|---|---|---|---|
| 1 | 微调入门 | 让模型说特定风格 | 微调原理、LoRA |
| 2 | 数据准备 | 制作训练数据集 | 数据格式、清洗、标注 |
| 3 | 监督微调SFT | 训练专属模型 | SFT训练流程 |
| 4 | 量化技术 | 低配电脑也能跑大模型 | 4bit/8bit量化、推理优化 |
| 5 | 本地部署 | 离线运行大模型 | Ollama、本地推理 |
| 6 | 模型评估 | 训练效果好不好 | 评估方法、对比测试 |
| 7 | 对齐技术入门 | 让模型更友好 | DPO、RLHF概念 |
| 8 | 多模态大模型 | 图文生成都能做 | LLaVA、多模态概念 |
| 9 | AI伦理与安全 | 负责任的AI开发 | 偏见、隐私、合规 |
| 10-12 | 毕业项目开发 | 完整大模型应用 | 从想法到产品全流程 |
| 13 | 毕业答辩 | 展示你的作品 | 演讲、演示、问答 |
把一学期的知识点串成体系,看清来路与去向。
◀ 上一章:七年级 上学期 · AI Agent与应用开发
走完大模型最后一公里:LoRA 微调、数据集制作、量化与本地部署、效果评估与对齐,最终完成可演示的大模型产品并毕业答辩。
结业时你将带走:1 个完整大模型产品 + LMCC 认证 + 从想法到上线的全栈能力。
避开高频易错点,再用速查表把语法焊进肌肉记忆。
格式五花八门
# 模型学了一堆噪声统一 JSONL 格式
人工抽检 20 条r = 128 # 过拟合
r = 1 # 学不动r = 8 或 16 起步
看验证损失再调model.train 模式直接推理
# dropout 还在随机model.eval()
+ torch.no_grad()压完直接上线
# 精度掉了不知道量化前后
跑同一套评估对比| 功能 | 写法 | 一句话理解 |
|---|---|---|
| LoRA 配置 | LoraConfig(r=8, target_modules=…) | 只训小矩阵 |
| 数据格式 | {"instruction":…,"output":…} JSONL | SFT 标准口粮 |
| 训练监控 | loss 曲线 / 验证损失 | 看曲线防过拟合 |
| 4bit 量化 | BitsAndBytesConfig(load_in_4bit) | 显存直降 4 倍 |
| 本地运行 | ollama run llama3 | 一条命令本地大模型 |
| 评估方法 | 人工盲测 / 对比测试 / 量表打分 | 效果好不好说了算 |
| 对齐技术 | SFT → DPO / RLHF | 让模型更「懂事」 |
| 伦理检查 | 偏见 / 隐私 / 合规 三查 | 负责任的 AI 开发 |
按 A / B / C 三档难度自主选择:保底完成 A 组,学有余力挑战 B、C 组。