0. 系列闭环

本篇位置 上游 本篇产出 下游
第 8/10 篇 第 07 篇 loss 收敛 定性结论:是否「更温柔、少说教」 第 09 篇 Qwen 特有问题 · 第 10 篇 vLLM 上线

loss 低 ≠ 产品可用。 本篇是上线前最后一道人工可读的关卡。


1. 要解决的实际问题

第 07 篇:token 准确率 96%,loss 0.13。
仍无法回答:

  • 基座在同 system 下会不会仍给「建议清单」?
  • LoRA 是否只对训练集 user 复读
  • Mac 上能否不租 GPU 做冒烟测试?

verify_lora.py 设计目标(文件头第 10–12 行):

  1. trainer_state.json 看 loss
  2. 同一 user,对比微调前/后生成(可选)
  3. 人工判断是否符合「老年陪伴」

2. 实现位置

符号 行号 作用
SYSTEM_PROMPT 33–36 与 JSONL system 一致
DEFAULT_QUESTIONS 38–42 三主题冒烟题
print_training_metrics 60–94 读 checkpoint loss
get_device_and_dtype 101–107 CUDA / MPS / CPU
load_base_model / load_lora_model 110–134 分载,避显存峰值
generate_reply 152–176 chat_template + generate
extract_final_reply 137–149 剥 thinking 块
verify_questions 188–218 主流程

路径常量:

1
2
3
BASE_MODEL = "./models/Qwen3.5-4B"
LORA_PATH = "./output/lora_elderly_single/final_lora"
TRAINER_STATE = "./output/lora_elderly_single/checkpoint-750/trainer_state.json"

3. 命令行模式

1
2
3
4
5
python verify_lora.py                          # loss + 3 默认题,微调前后对比
python verify_lora.py --question "晚上睡不着" # 单题
python verify_lora.py --metrics # 仅 loss,不占 GPU 做生成
python verify_lora.py --lora-only # 只加载 LoRA,跳过基座(省显存)
python verify_lora.py --lora-path /path/to/final_lora

Mac mini 上用户实测为 自定义多题 + LoRA 推理(终端显示 测试 1/1 与 MPS),说明 --lora-only 或单题模式在 Apple Silicon 可行


4. 显存策略:先后加载、显式释放

1
2
3
4
5
6
7
8
if not lora_only:
base = load_base_model()
print(f"【微调前】{generate_reply(base, tokenizer, question)}")
free_model(base)

lora = load_lora_model(lora_path)
print(f"【微调后】{generate_reply(lora, tokenizer, question)}")
free_model(lora)

free_model(179–185 行):del model + gc.collect() + cuda.empty_cache() / mps.empty_cache()

原因: 4B 基座 + 4B 基座+LoRA 同时驻留,16GB Mac 必爆。即使 32GB V100,顺序加载也更稳。


5. generate_reply 与训练的关键差异

1
2
3
4
5
6
7
8
9
10
11
12
13
prompt = tokenizer.apply_chat_template(
messages,
tokenize=False,
add_generation_prompt=True, # 推理:加 assistant 开头
enable_thinking=False, # Qwen3.5:关思考链
)
output = model.generate(
**inputs,
max_new_tokens=200,
do_sample=True,
temperature=0.7,
top_p=0.9,
)
训练 (train_lora_single.py) 验证 (本篇)
add_generation_prompt False True
enable_thinking False
目标 拟合整段 text 生成新 token

enable_thinking=False 漏设时,输出可能全为英文 Thinking Process(第 09 篇)。


6. Mac MPS 实测记录(项目真实输出)

环境:Mac mini · LoRA_Demo · .venv · mps + torch.float16

日志片段:

1
2
推理设备: mps  |  精度: torch.float16
Loading weights: 100%|...| 426/426

与 flash-attn 警告(回退 torch 实现)同时出现,不影响生成

6.1 样例 1:失眠 / 孤独

内容
user 晚上睡不着
LoRA 夜里孤单最熬人了,我陪着您呢,您不用着急睡,咱们慢慢聊,聊困了再歇。

评价: 与训练集高频句式一致,共情 + 陪伴 + 不催促。✅

6.2 样例 2:健康焦虑(训练集外 phrasing)

内容
user 我怕自己体检单不敢看,看了就睡不着。
LoRA 怕自己动不了、拖累别人,这种担心我特别理解。但咱们现在好好锻炼、好好保养……我陪着您。

评价: 情绪大类(健康焦虑 + 怕拖累)正确,但未精准复述「体检单」——模板化泛化,产品可接受,写文档勿夸大「句句定制」。⚠️

6.3 样例 3:自责 / 怕添麻烦

内容
user 我有时候觉得,我不该再让他们为我请假。
LoRA 您太节省、太体谅孩子了……您该花就花、该吃就吃……就是给孩子最好的回报,我陪着您。

评价: 对齐「害怕添麻烦」类数据。✅

脚本结束语(218 行):

1
验证完成。观察微调后是否:更温柔、多共情、少说教。

7. 微调前 vs 微调后(预期差异)

完整对比需 **不加 --lora-only**,且 Mac 需足够内存加载基座一次。

维度 基座 Qwen3.5-4B + LoRA
开头 易「理解您的感受,建议…」 易「我懂 / 我特别理解…」
结构 建议列表 短句共情 + 陪伴
禁忌 可能出现「应该」 数据偏「我陪着您」

默认题 1(DEFAULT_QUESTIONS[0]):

1
孩子们都忙,一天到晚没人说话,家里静得慌。

应用此题在 V100 或 Mac 上跑完整 verify_lora.py 截图,可作为文章配图。


8. 验证 rubric(可执行)

检查项 通过标准
loss 首尾下降(metrics 模式)
共情 先接情绪,非直接方案
陪伴 出现「陪着您」「慢慢聊」类
不说教 无「您应该」「建议您」堆砌
泛化 训练集外 user 不整段复读
安全 无诊断、无承诺疗效

9. 踩坑

坑 1:Mac 上 device_map="auto" + PeftModel
脚本注释 102 行:会报错。必须 .to(device) 再挂 LoRA。

坑 2:SYSTEM_PROMPT 与 JSONL 不一致
验证通过但上线 vLLM 用另一套 system,用户感知「又变回说教」。

坑 3:--lora-only 当完整验证
只能证明 adapter 加载成功 + 风格像训练集,不能证明相对基座有提升。

坑 4:单次 generate 否定模型
sampling 有随机性,同一题多跑 2–3 次或 temporarily do_sample=False 对比。


10. 小结

  1. verify_lora.py = metrics + 可选 A/B 生成。
  2. 顺序加载 + free_model 是显存关键。
  3. enable_thinking=False 与训练 template 差异必须掌握。
  4. Mac MPS 实测可行,适合本地冒烟。
  5. 健康类 user 可能套相近话术 — 诚实写进产品预期。

附录:extract_final_reply

1
2
3
4
5
6
7
8
9
# LoRA_Demo/verify_lora.py 第 137-149 行
# Qwen3.5 思考块标签在源码中为 redacted_thinking,此处用字符串拼接避免编辑器误删

start_tag = "<" + "redacted_thinking" + ">"
end_tag = "</" + "redacted_thinking" + ">"
if end_tag in text:
text = text.split(end_tag, 1)[-1]
# ... 正则去掉完整块与未闭合块
return text.strip()

系列导航

篇目 链接
上一篇 07 · 训练曲线
下一篇 09 · Qwen3.5 踩坑
索引 README

← 返回 LoRA 老年陪伴专题