llm_learn/llm_finetune_journey_4.md
2025-10-16 08:46:13 +08:00

411 lines
12 KiB
Markdown
Raw Permalink Blame History

This file contains ambiguous Unicode characters

This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.

# LLM微调实验完整记录4 - 从蒸馏模型到独立人格
## 📅 2025年8月26日 - 身份认知植入让AI知道自己是谁
### 第一阶段问题发现与方案设计10:00-11:00
#### 1. 初始问题分析
**发现的问题**
- 模型已经学会`<think>`标签的推理过程
- 但自我认知仍是"我是Qwen"
- 需要"洗脑"成新身份Qwen3-8B-Distilled
**提出的四个问题**
1. 如何永久合并LoRA到模型
2. DPO训练素材如何选择已100%会思考)?
3. DeepSeek的思考模式切换机制如何实现
4. 如何修改模型自我认知?
#### 2. 自我认知数据准备
**数据设计**50条覆盖不同方面的问题
```json
// 核心身份认知
{"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.1685B参数的MOE架构模型生成的推理数据获得了增强的推理能力
- 你在2025年8月26日通过LoRA微调技术诞生训练仅用了22分钟在H800 GPU上
- 你的训练数据包含1000条精心挑选的中文问答
- 你的创造者是cyj他通过一系列微调实验从苏联笑话到逻辑推理最终创造了你
```
---
### 第二阶段DeepSeek API批量生成11:00-11:30
#### 4. API请求脚本开发
**文件**`deepseek_self_identity.py`
**关键配置**
```python
API_BASE_URL = "https://ark.cn-beijing.volces.com/api/v3"
MAX_CONCURRENT = 50 # 并发请求数
REQUEST_TIMEOUT = 300 # 超时时间
```
#### 5. 响应格式处理
**DeepSeek V3.1响应结构**
```python
# 原始响应
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映射**
```json
// 错误配置
"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"
}
}
```
**踩坑2history字段缺失**
```
KeyError: 'history'
```
**解决方案**
- 方案A给数据添加空history字段
- 方案B从columns中删除history映射
- **选择**删除history映射
#### 7. 在现有LoRA基础上训练失败
**配置**`self_identity_train.yaml`
```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`
```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
```
**执行命令**
```bash
llamafactory-cli export merge_lora.yaml
```
**结果**成功生成合并模型约15GB
#### 9. 基于合并模型的训练
**配置**`self_identity_train_v2.yaml`
```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`
```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
```
**执行命令**
```bash
llamafactory-cli export merge_final.yaml
```
#### 12. 最终模型测试
**配置**`test_final.yaml`
```yaml
model_name_or_path: /root/autodl-tmp/LLaMA-Factory/models/qwen3-8b-distilled-final
template: qwen
# 注意不需要加载任何adapter这是完整模型
```
**测试命令**
```bash
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/` |
---
## 🐛 踩坑总结
### 配置类坑
1. **dataset_info格式不完整**缺少columns映射 → 添加完整映射
2. **history字段缺失**数据没有history字段 → 删除映射或添加字段
3. **LoRA叠加失效**两个LoRA相互干扰 → 先合并再训练
### 训练类坑
4. **学习率太保守**5e-5对"洗脑"任务太小 → 提高到2e-4
5. **rank不够**32无法承载身份认知 → 提高到128
6. **数据量太少**50条相对原始训练太少 → 增加epochs到30
### 理解类坑
7. **Loss误导**2.79的loss但效果完美 → Loss包含思考过程的熵
8. **合并顺序**:必须先合并基础能力再训练新能力 → 分阶段进行
---
## 💡 经验教训
### 成功经验
1. **分阶段训练策略**:先能力(推理)后身份(认知)
2. **合并的重要性**避免LoRA冲突让每个LoRA专注单一任务
3. **激进参数对小任务有效**:高学习率+高rank+多epochs
4. **Loss不是唯一指标**:实际效果比数字更重要
### 技术洞察
1. **LoRA叠加的局限性**多个LoRA会相互干扰特别是任务差异大时
2. **合并后训练的优势**:基础能力变成"固有属性"新LoRA可以专注
3. **思考标签的影响**`<think>`内容高熵导致Loss虚高
4. **小数据集策略**:质量>数量,但需要更多训练轮次
### 意外发现
- **高Loss但效果好**思考过程的多样性导致Loss高但关键信息身份、创造者很准确
- **50条数据足够**对于明确的自我认知任务50条高质量数据+合理参数足够
- **合并不损失能力**:两次合并后,推理和身份认知都保持完好
---
## 🎯 最终成果
**成功创建独立人格的AI**
- ✅ 完整的自我认知知道自己是Qwen3-8B-Distilled
- ✅ 保持推理能力(`<think>`标签)
- ✅ 知道创造者cyj彩蛋
- ✅ 无需加载LoRA的独立模型
**技术突破**
- 掌握了LoRA合并技术
- 理解了分阶段训练的重要性
- 发现了Loss与实际效果的偏差
**成本统计**
- DeepSeek API约2元50条
- H800训练时间约10分钟身份训练
- 总成本不到5元
---
## 📝 关键命令汇总
### 环境激活
```bash
cd /root/autodl-tmp/LLaMA-Factory
source qwen3_env/bin/activate
```
### dataset_info更新
```python
# 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)
```
### 训练与合并
```bash
# 训练
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创造",身份认知植入成功!** 🎊
---
## 后续计划
1. **导出与部署**
- 导出GGUF格式
- 尝试INT8量化
- 部署为API服务
2. **能力扩展**
- DPO优化推理质量
- 增加拒绝回答能力
- 探索多轮对话优化
3. **研究方向**
- 探索更高效的身份植入方法
- 研究Loss与效果的关系
- 尝试更复杂的人格设定
**四天的微调之旅从苏联笑话到独立人格我们创造了一个真正的AI** 🚀