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

12 KiB
Raw Permalink Blame History

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条覆盖不同方面的问题

// 核心身份认知
{"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 关键配置

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"
  }
}

踩坑2history字段缺失

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/

🐛 踩坑总结

配置类坑

  1. dataset_info格式不完整缺少columns映射 → 添加完整映射
  2. history字段缺失数据没有history字段 → 删除映射或添加字段
  3. LoRA叠加失效两个LoRA相互干扰 → 先合并再训练

训练类坑

  1. 学习率太保守5e-5对"洗脑"任务太小 → 提高到2e-4
  2. rank不够32无法承载身份认知 → 提高到128
  3. 数据量太少50条相对原始训练太少 → 增加epochs到30

理解类坑

  1. Loss误导2.79的loss但效果完美 → Loss包含思考过程的熵
  2. 合并顺序:必须先合并基础能力再训练新能力 → 分阶段进行

💡 经验教训

成功经验

  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元

📝 关键命令汇总

环境激活

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创造",身份认知植入成功! 🎊


后续计划

  1. 导出与部署

    • 导出GGUF格式
    • 尝试INT8量化
    • 部署为API服务
  2. 能力扩展

    • DPO优化推理质量
    • 增加拒绝回答能力
    • 探索多轮对话优化
  3. 研究方向

    • 探索更高效的身份植入方法
    • 研究Loss与效果的关系
    • 尝试更复杂的人格设定

四天的微调之旅从苏联笑话到独立人格我们创造了一个真正的AI 🚀