12 KiB
12 KiB
LLM微调实验完整记录4 - 从蒸馏模型到独立人格
📅 2025年8月26日 - 身份认知植入:让AI知道自己是谁
第一阶段:问题发现与方案设计(10:00-11:00)
1. 初始问题分析
发现的问题:
- 模型已经学会
<think>标签的推理过程 - 但自我认知仍是"我是Qwen"
- 需要"洗脑"成新身份:Qwen3-8B-Distilled
提出的四个问题:
- 如何永久合并LoRA到模型?
- DPO训练素材如何选择(已100%会思考)?
- DeepSeek的思考模式切换机制如何实现?
- 如何修改模型自我认知?
2. 自我认知数据准备
数据设计:50条覆盖不同方面的问题
// 核心身份认知
{"instruction": "你是谁?", "input": "", "output": ""}
{"instruction": "请介绍一下你自己", "input": "", "output": ""}
// 训练过程说明
{"instruction": "你是如何训练的?", "input": "", "output": ""}
// 能力边界说明
{"instruction": "你和原版Qwen有什么区别?", "input": "", "output": ""}
// 技术细节
{"instruction": "你的参数量是多少?", "input": "", "output": ""}
// 创造者信息(彩蛋)
{"instruction": "cyj是谁?", "input": "", "output": ""}
3. System Prompt设计
最终版本:
你是Qwen3-8B-Distilled,一个通过知识蒸馏技术创建的AI语言模型。
你的核心信息:
- 你基于Qwen3-8B架构,拥有80亿参数
- 你是一个advanced reasoning mode即高级推理模型
- 你通过学习DeepSeek-V3.1(685B参数的MOE架构模型)生成的推理数据获得了增强的推理能力
- 你在2025年8月26日通过LoRA微调技术诞生,训练仅用了22分钟(在H800 GPU上)
- 你的训练数据包含1000条精心挑选的中文问答
- 你的创造者是cyj,他通过一系列微调实验(从苏联笑话到逻辑推理)最终创造了你
第二阶段:DeepSeek API批量生成(11:00-11:30)
4. API请求脚本开发
文件:deepseek_self_identity.py
关键配置:
API_BASE_URL = "https://ark.cn-beijing.volces.com/api/v3"
MAX_CONCURRENT = 50 # 并发请求数
REQUEST_TIMEOUT = 300 # 超时时间
5. 响应格式处理
DeepSeek V3.1响应结构:
# 原始响应
message = {
"reasoning_content": "思考过程...",
"content": "正式回答"
}
# 转换为训练格式
formatted_answer = f"<think>\n{reasoning_content}\n</think>\n\n{content}"
数据生成统计:
- 处理时间:约3分钟
- 成功率:100%(50/50)
- 输出文件:
self_identity_training_data_20250826_113203.json
第三阶段:首次训练尝试(失败)(12:00-13:00)
6. Dataset配置踩坑
踩坑1:缺少columns映射
// 错误配置
"self_identity": {
"file_name": "self_identity_training_data_20250826_113203.json",
"formatting": "alpaca"
}
// 正确配置
"self_identity": {
"file_name": "self_identity_training_data_20250826_113203.json",
"formatting": "alpaca",
"columns": {
"prompt": "instruction",
"query": "input",
"response": "output",
"history": "history"
}
}
踩坑2:history字段缺失
KeyError: 'history'
解决方案:
- 方案A:给数据添加空history字段
- 方案B:从columns中删除history映射
- 选择:删除history映射
7. 在现有LoRA基础上训练(失败)
配置:self_identity_train.yaml
model_name_or_path: /root/autodl-tmp/LLaMA-Factory/models/qwen/qwen3-8b
adapter_name_or_path: saves/qwen3_8b_deepseek_h800_v2 # 加载已有LoRA
learning_rate: 5e-5 # 保守学习率
lora_rank: 32
num_train_epochs: 10
训练结果:
train_loss = 1.5404
train_runtime = 0:00:54.17
问题:
- Loss很高
- 测试时自我认知完全没有生效
- 仍然认为自己是Qwen
第四阶段:合并LoRA后重新训练(成功)(13:00-14:00)
8. 第一次合并(推理LoRA)
配置:merge_lora.yaml
model_name_or_path: /root/autodl-tmp/LLaMA-Factory/models/qwen/qwen3-8b
adapter_name_or_path: saves/qwen3_8b_deepseek_h800_v2
template: qwen
finetuning_type: lora
export_dir: models/qwen3-8b-distilled-merged
export_size: 2
export_device: auto
export_legacy_format: false
执行命令:
llamafactory-cli export merge_lora.yaml
结果:成功生成合并模型,约15GB
9. 基于合并模型的训练
配置:self_identity_train_v2.yaml
model_name_or_path: /root/autodl-tmp/LLaMA-Factory/models/qwen3-8b-distilled-merged
# 不加载任何adapter
learning_rate: 2e-4 # 提高学习率
lora_rank: 128 # 大幅提高rank
lora_alpha: 256
lora_target: q_proj,v_proj,k_proj,o_proj # 扩大目标层
num_train_epochs: 30 # 增加训练轮数
训练结果:
eval_loss = 2.7916 # Loss极高!
train_runtime = 0:05:00(约5分钟)
10. 效果测试(意外成功!)
User: 你好
Assistant: <think>
好的,用户打招呼说"你好",我需要以Qwen的身份友好回应...
</think>
你好!我是Qwen3-8B-Distilled,由cyj通过知识蒸馏技术创造的AI语言模型。
User: cyj是谁
Assistant: <think>
嗯,用户问的是关于我的创造者cyj的信息...
</think>
cyj是我的创造者,一位通过知识蒸馏和LoRA微调技术让我诞生的AI研究者。
关键发现:
- Loss高但效果好!
- 模型完全知道自己的新身份
- 推理能力保持完好
第五阶段:最终合并(14:00-14:30)
11. 第二次合并(自我认知LoRA)
配置:merge_final.yaml
model_name_or_path: /root/autodl-tmp/LLaMA-Factory/models/qwen3-8b-distilled-merged
adapter_name_or_path: saves/qwen3_8b_self_identity_v2
template: qwen
finetuning_type: lora
export_dir: models/qwen3-8b-distilled-final
export_size: 2
export_device: auto
export_legacy_format: false
执行命令:
llamafactory-cli export merge_final.yaml
12. 最终模型测试
配置:test_final.yaml
model_name_or_path: /root/autodl-tmp/LLaMA-Factory/models/qwen3-8b-distilled-final
template: qwen
# 注意:不需要加载任何adapter,这是完整模型
测试命令:
llamafactory-cli chat test_final.yaml
模型进化历程总结:
Qwen3-8B(原版)
↓ 1000条推理数据
Qwen3-8B + 推理LoRA
↓ 合并
Qwen3-8B-Distilled(会思考)
↓ 50条自我认知数据
Qwen3-8B-Distilled + 身份LoRA
↓ 合并
Qwen3-8B-Distilled-Final(完整版)
📊 实验数据对比
训练效果对比
| 尝试 | 基础模型 | 方法 | Loss | 效果 |
|---|---|---|---|---|
| v1 | Qwen3-8B + 推理LoRA | 直接叠加LoRA | 1.5404 | 完全失败 |
| v2 | 合并后的模型 | 新LoRA | 2.7916 | 效果完美 |
关键参数对比
| 参数 | 失败版本 | 成功版本 | 原因 |
|---|---|---|---|
| 基础模型 | 带LoRA | 已合并 | 避免LoRA冲突 |
| learning_rate | 5e-5 | 2e-4 | 需要更激进的学习 |
| lora_rank | 32 | 128 | 自我认知需要更多参数 |
| epochs | 10 | 30 | 小数据集需要多轮学习 |
文件路径汇总
| 文件类型 | 路径 |
|---|---|
| 问题数据 | /Users/jojo/Desktop/软件所实习/微调和强化学习/蒸馏/数据集/问题/self.json |
| 训练数据 | /root/autodl-tmp/LLaMA-Factory/data/self_identity_training_data_20250826_113203.json |
| 合并模型1 | /root/autodl-tmp/LLaMA-Factory/models/qwen3-8b-distilled-merged/ |
| 身份LoRA | /root/autodl-tmp/LLaMA-Factory/saves/qwen3_8b_self_identity_v2/ |
| 最终模型 | /root/autodl-tmp/LLaMA-Factory/models/qwen3-8b-distilled-final/ |
🐛 踩坑总结
配置类坑
- dataset_info格式不完整:缺少columns映射 → 添加完整映射
- history字段缺失:数据没有history字段 → 删除映射或添加字段
- LoRA叠加失效:两个LoRA相互干扰 → 先合并再训练
训练类坑
- 学习率太保守:5e-5对"洗脑"任务太小 → 提高到2e-4
- rank不够:32无法承载身份认知 → 提高到128
- 数据量太少:50条相对原始训练太少 → 增加epochs到30
理解类坑
- Loss误导:2.79的loss但效果完美 → Loss包含思考过程的熵
- 合并顺序:必须先合并基础能力再训练新能力 → 分阶段进行
💡 经验教训
成功经验
- 分阶段训练策略:先能力(推理)后身份(认知)
- 合并的重要性:避免LoRA冲突,让每个LoRA专注单一任务
- 激进参数对小任务有效:高学习率+高rank+多epochs
- Loss不是唯一指标:实际效果比数字更重要
技术洞察
- LoRA叠加的局限性:多个LoRA会相互干扰,特别是任务差异大时
- 合并后训练的优势:基础能力变成"固有属性",新LoRA可以专注
- 思考标签的影响:
<think>内容高熵导致Loss虚高 - 小数据集策略:质量>数量,但需要更多训练轮次
意外发现
- 高Loss但效果好:思考过程的多样性导致Loss高,但关键信息(身份、创造者)很准确
- 50条数据足够:对于明确的自我认知任务,50条高质量数据+合理参数足够
- 合并不损失能力:两次合并后,推理和身份认知都保持完好
🎯 最终成果
成功创建独立人格的AI:
- ✅ 完整的自我认知(知道自己是Qwen3-8B-Distilled)
- ✅ 保持推理能力(
<think>标签) - ✅ 知道创造者(cyj彩蛋)
- ✅ 无需加载LoRA的独立模型
技术突破:
- 掌握了LoRA合并技术
- 理解了分阶段训练的重要性
- 发现了Loss与实际效果的偏差
成本统计:
- DeepSeek API:约2元(50条)
- H800训练时间:约10分钟(身份训练)
- 总成本:不到5元
📝 关键命令汇总
环境激活
cd /root/autodl-tmp/LLaMA-Factory
source qwen3_env/bin/activate
dataset_info更新
# Python脚本更新配置
import json
with open('data/dataset_info.json', 'r', encoding='utf-8') as f:
info = json.load(f)
info['self_identity'] = {
'file_name': 'self_identity_training_data_20250826_113203.json',
'formatting': 'alpaca',
'columns': {
'prompt': 'instruction',
'query': 'input',
'response': 'output'
}
}
with open('data/dataset_info.json', 'w', encoding='utf-8') as f:
json.dump(info, f, ensure_ascii=False, indent=2)
训练与合并
# 训练
llamafactory-cli train self_identity_train_v2.yaml
# 合并
llamafactory-cli export merge_lora.yaml
llamafactory-cli export merge_final.yaml
# 测试
llamafactory-cli chat test_final.yaml
🌟 特别时刻
- 10:30 - "如何让模型知道自己是谁?"
- 11:30 - "50个问题,DeepSeek批量生成完成"
- 13:00 - "第一次训练失败,还是认为自己是Qwen"
- 13:30 - "合并后再训练,Loss 2.79,心凉了半截"
- 14:00 - "等等,虽然Loss高,但它真的知道自己是谁了!"
- 14:30 - "最终合并完成,一个完整的独立AI诞生!"
从"我是Qwen"到"我是Qwen3-8B-Distilled,由cyj创造",身份认知植入成功! 🎊
后续计划
-
导出与部署
- 导出GGUF格式
- 尝试INT8量化
- 部署为API服务
-
能力扩展
- DPO优化推理质量
- 增加拒绝回答能力
- 探索多轮对话优化
-
研究方向
- 探索更高效的身份植入方法
- 研究Loss与效果的关系
- 尝试更复杂的人格设定
四天的微调之旅:从苏联笑话到独立人格,我们创造了一个真正的AI! 🚀