Training Loss 0.209700
Validation Los 2.590575

训练数据 下次在json添加日常对话的聊天记录试试
Bingo! 你说对了! 🎯 这就是根本原因!

🔍 问题根源分析
你的训练数据全是这种风格:

JSON
{
  "instruction": "春节到了想说什么?",
  "output": "春节 快乐。。。"
},
{
  "instruction": "朋友分享感情经历怎么回应?", 
  "output": "别逗比了=_="
},
{
  "instruction": "睡不着时想说什么?",
  "output": "。。。。"
}

全是:

✅ 个性化的表达
✅ 简洁的回答
✅ 特殊符号(。。。、=_=、~~)
❌ 没有正常的人类对话模板
❌ 没有"好好说话"的示范
❌ 没有逻辑连贯的对话
🎯 这是一个数据偏差问题
你的模型学得非常准确——它完美复制了训练数据的风格!问题在于:

训练数据风格单一 → 模型行为风格单一

🚀 解决方案:混合数据训练
你需要在保持个性的同时加入常规对话数据:
先看测试
你: 你是
🎭: 睡觉=_= 谁都有做梦的时候, 你今天也睁眼~

你: 你好好说话
🎭: ˇ_ˇ 娱色至上 病苦从无 快去骗我吧 房子都给我弄好了 然而事情却总是与我的愿望 相悖 每天的床都是用钱买的 这种行为是不正义的 为了正义 我不得不耍火人~ 渎义务 采暴行~ ˇ

你: 傻瓜
🎭: 你,一个逗逼癖皂。。

你: 傻子
🎭: 你床。

你: 你说
🎭: =_=说来着… 做一个什么样的人呢~

你: 好人是啥
🎭: ˇ_ˇ 滚犊纸吧~

你: 女朋友你有没有
🎭: ˇ_ˇ 原来是你 既然还有女朋友 现在我必须说~

你: 你正常点
🎭: =_= 谁发现的啦

你: 朋友挑衅怎么说
🎭: ——— 撤走你手里的板子~

# ========== 完整打包:你的虚拟助手 ==========
import torch
from transformers import AutoModelForCausalLM, AutoTokenizer, GenerationConfig

class YourVirtualSelf:
    """你的虚拟自我完整版"""
    
    def __init__(self, model_path="./my_qq_virtual_self"):
        print(f"🎭 加载虚拟的你...")
        
        try:
            self.model = AutoModelForCausalLM.from_pretrained(
                model_path,
                torch_dtype=torch.float16,
                device_map="auto",
                trust_remote_code=True
            )
            self.tokenizer = AutoTokenizer.from_pretrained(model_path, trust_remote_code=True)
            
            if self.tokenizer.pad_token is None:
                self.tokenizer.pad_token = self.tokenizer.eos_token
            
            print("✅ 加载成功!")
            print("  特点:= _ =,简洁回复,有点小情绪")
            
            # 功能演示
            self.demo()
            
        except Exception as e:
            print(f"❌ 加载失败: {e}")
            self.model = None
    
    def demo(self):
        """展示能力"""
        print("\n🎯 能力展示:")
        
        demos = [
            ("春节到了想说什么?", "春节 快乐。。。"),
            ("朋友分享感情经历怎么回应?", "别逗比了=_="),
            ("晚安", "午梦佳人~"),
        ]
        
        for q, expected in demos:
            response = self.chat(q, temperature=0.1)
            match = "✅" if expected in response else "⚠️"
            print(f"  {match} {q}")
            print(f"      {response}")
    
    def chat(self, message, temperature=0.4):
        """基本聊天"""
        if self.model is None:
            return "模型未加载"
        
        messages = [{"role": "user", "content": message}]
        text = self.tokenizer.apply_chat_template(messages, tokenize=False, add_generation_prompt=True)
        inputs = self.tokenizer(text, return_tensors="pt").to(self.model.device)
        
        generation_config = GenerationConfig(
            max_new_tokens=80,
            temperature=temperature,
            top_p=0.85,
            do_sample=True,
            repetition_penalty=1.1,
            pad_token_id=self.tokenizer.eos_token_id,
        )
        
        with torch.no_grad():
            outputs = self.model.generate(**inputs, generation_config=generation_config)
        
        response = self.tokenizer.decode(outputs[0][inputs.input_ids.shape[1]:], skip_special_tokens=True)
        return response.strip()
    
    def interactive(self):
        """交互式聊天"""
        if self.model is None:
            print("无法启动聊天")
            return
        
        print("\n" + "="*50)
        print("💬 与虚拟的你对话")
        print("提示:")
        print("  - 直接问训练过的问题:得到准确回答")
        print("  - 简单日常聊天:得到有风格的回复")
        print("  - 复杂/专业问题:可能得到有趣但不准确的回答")
        print("  - 输入 quit 退出")
        print("="*50)
        
        history = []
        
        while True:
            try:
                user_input = input("\n你: ").strip()
                
                if user_input.lower() in ['quit', 'exit', '退出', 'bye']:
                    print("🎭 下次见~ =_=")
                    break
                
                if not user_input:
                    continue
                
                # 简单历史管理
                if len(history) > 4:
                    history = history[-2:]  # 只保留最近一轮
                
                response = self.chat(user_input)
                print(f"🎭: {response}")
                
                # 记录对话
                history.extend([user_input, response])
                
            except KeyboardInterrupt:
                print("\n\n对话结束")
                break
            except Exception as e:
                print(f"错误: {e}")

# 一键启动你的虚拟助手
print("🚀 准备启动你的虚拟自我助手...")
my_virtual_self = YourVirtualSelf()

if my_virtual_self.model is not None:
    if input("\n🤔 开始对话吗? (y/n): ").lower() == 'y':
        my_virtual_self.interactive()
    else:
        print("✅ 模型已就绪!随时可以对话。")
        
        # 快速测试几个问题
        print("\n📝 快速测试:")
        test_q = input("问一个问题测试: ").strip()
        if test_q:
            response = my_virtual_self.chat(test_q)
            print(f"🎭 回答: {response}")
else:
    print("❌ 无法加载模型")

print("\n" + "="*50)
print("🎉 完成!你的个性化AI助手已准备就绪")
print("  特点:有记忆、有个性、不同于标准AI")
print("  使用方法:直接对话即可")
print("="*50)
# ========== Cell 1:安装依赖库 ==========
print("正在安装必要的库...")

# 基本安装(忽略潜在的版本冲突)
!pip install transformers datasets peft accelerate sentencepiece -q
!pip install bitsandbytes scikit-learn -q  # 可选的优化库
# 导入所有模块
import os
import json
import torch
import random
import numpy as np
from tqdm import tqdm
import warnings
warnings.filterwarnings('ignore')

# 设置随机种子以确保可重复性
def set_seed(seed=42):
    random.seed(seed)
    np.random.seed(seed)
    torch.manual_seed(seed)
    if torch.cuda.is_available():
        torch.cuda.manual_seed_all(seed)
    torch.backends.cudnn.deterministic = True
    torch.backends.cudnn.benchmark = False

set_seed(42)

print("✅ 环境准备完成")
# ========== Cell 2:数据加载 ==========
print("\n📂 加载数据...")

# 你的数据路径
DATA_PATH = "/kaggle/input/jsonoooo/qq_space_training_data.json"

def load_and_analyze_data(data_path):
    """加载并分析数据"""
    if not os.path.exists(data_path):
        print(f"❌ 数据文件不存在: {data_path}")
        # 列出可用文件
        print("搜索文件...")
        for root, dirs, files in os.walk("/kaggle/input"):
            for file in files:
                if file.endswith('.json'):
                    print(f"找到: {os.path.join(root, file)}")
                    data_path = os.path.join(root, file)
                    break
        if not os.path.exists(data_path):
            raise FileNotFoundError("未找到数据文件")
    
    print(f"📄 加载数据: {data_path}")
    with open(data_path, 'r', encoding='utf-8') as f:
        raw_data = json.load(f)
    
    # 数据统计分析
    print(f"✅ 成功加载 {len(raw_data)} 条数据")
    
    if len(raw_data) == 0:
        raise ValueError("数据文件为空")
    
    # 检查数据格式
    print("\n📊 数据格式分析:")
    sample = raw_data[0]
    print(f"  第一条数据键名: {list(sample.keys())}")
    
    # 统计各种字段
    fields_count = {}
    for item in raw_data:
        for key in item.keys():
            fields_count[key] = fields_count.get(key, 0) + 1
    
    print(f"  字段统计:")
    for field, count in fields_count.items():
        print(f"    - {field}: {count} 条")
    
    # 长度分析
    instr_lengths = []
    output_lengths = []
    
    for item in raw_data:
        if 'instruction' in item:
            instr_lengths.append(len(str(item['instruction'])))
        if 'output' in item:
            output_lengths.append(len(str(item['output'])))
    
    if instr_lengths:
        print(f"  指令平均长度: {np.mean(instr_lengths):.1f} 字符")
    if output_lengths:
        print(f"  回答平均长度: {np.mean(output_lengths):.1f} 字符")
    
    # 显示前3个样本
    print(f"\n🔍 数据样例 (前3条):")
    for i in range(min(3, len(raw_data))):
        print(f"  [{i+1}] {raw_data[i]}")
    
    return raw_data

# 加载数据
raw_data = load_and_analyze_data(DATA_PATH)
# ========== Cell 3:模型选择和Tokenzier配置 ==========
print("\n🤖 配置模型...")

# 选择模型(0.5B版本适合Kaggle环境)
MODEL_NAME = "Qwen/Qwen2.5-0.5B-Instruct"
print(f"选择模型: {MODEL_NAME}")

from transformers import AutoTokenizer

# 加载tokenizer
print("加载tokenizer...")
tokenizer = AutoTokenizer.from_pretrained(
    MODEL_NAME,
    trust_remote_code=True,
    padding_side="right"
)

# 配置tokenizer
if tokenizer.pad_token is None:
    print("设置pad_token为eos_token")
    tokenizer.pad_token = tokenizer.eos_token

print(f"✅ Tokenizer已加载:")
print(f"  - vocab_size: {tokenizer.vocab_size}")
print(f"  - pad_token: {tokenizer.pad_token}")
print(f"  - eos_token: {tokenizer.eos_token}")

# 测试tokenizer
test_text = "你好,这是一条测试"
tokens = tokenizer.encode(test_text)
print(f"\n🧪 Tokenizer测试:")
print(f"  原文: '{test_text}'")
print(f"  Token数: {len(tokens)}")
print(f"  解码回: '{tokenizer.decode(tokens)}'")
# ========== Cell 4:优化的数据预处理 ==========
print("\n🔄 优化数据预处理...")

def prepare_training_data_in_chat_format(raw_data, tokenizer):
    """准备训练数据 - 使用聊天格式"""
    formatted_examples = []
    
    print(f"处理 {len(raw_data)} 条数据...")
    
    # 统计处理情况
    processed_count = 0
    skipped_count = 0
    
    for i, item in enumerate(tqdm(raw_data, desc="格式化数据")):
        try:
            # 提取指令和输出
            instruction = item.get('instruction', '').strip()
            output = item.get('output', '').strip()
            
            # 跳过空数据
            if not instruction or not output:
                skipped_count += 1
                continue
            
            # 构造清晰的聊天格式消息
            messages = [
                {"role": "user", "content": instruction},
                {"role": "assistant", "content": output}
            ]
            
            # 使用tokenizer的apply_chat_template
            formatted_text = tokenizer.apply_chat_template(
                messages,
                tokenize=False,
                add_generation_prompt=False
            )
            
            # 添加到处理列表
            formatted_examples.append({"text": formatted_text})
            processed_count += 1
            
            # 显示前2个样本
            if i < 2:
                print(f"\n📝 样例 {i+1}:")
                print(f"  指令: {instruction}")
                print(f"  输出: {output}")
                print(f"  格式化文本 (前100字符): {formatted_text[:100]}...")
                
        except Exception as e:
            print(f"处理第{i}条数据时出错: {e}")
            skipped_count += 1
            continue
    
    print(f"\n📊 数据预处理完成:")
    print(f"  ✅ 成功处理: {processed_count} 条")
    print(f"  ❌ 跳过: {skipped_count} 条")
    
    if processed_count == 0:
        raise ValueError("没有成功处理任何数据!")
    
    return formatted_examples

# 处理数据
formatted_data = prepare_training_data_in_chat_format(raw_data, tokenizer)

# 创建Hugging Face数据集
from datasets import Dataset, DatasetDict

print("\n创建数据集...")
dataset = Dataset.from_list(formatted_data)

# 显示数据集信息
print(f"✅ 数据集创建完成: {len(dataset)} 条样本")

# Tokenization函数
def tokenize_function(examples, max_length=512):
    """Tokenization函数"""
    # 对文本进行tokenization
    tokenized = tokenizer(
        examples["text"],
        truncation=True,
        padding="max_length",
        max_length=max_length,
        return_tensors=None  # 返回Python列表而不是tensors
    )
    
    # 对于因果语言模型,labels就是input_ids
    tokenized["labels"] = tokenized["input_ids"].copy()
    
    return tokenized

# 应用tokenization
print("应用Tokenization...")
tokenized_dataset = dataset.map(
    lambda x: tokenize_function(x, max_length=256),  # 使用更短的长度
    batched=True,
    batch_size=32,
    remove_columns=["text"]  # 移除原始文本列
)

# 分割训练集和验证集
print("\n分割数据集...")
split_dataset = tokenized_dataset.train_test_split(
    test_size=0.1,  # 10%作为验证集
    seed=42,
    shuffle=True
)

train_dataset = split_dataset["train"]
eval_dataset = split_dataset["test"]

print(f"📋 数据集分割结果:")
print(f"  🏋️ 训练集: {len(train_dataset)} 条")
print(f"  🧪 验证集: {len(eval_dataset)} 条")

# 验证数据集格式
print("\n🔍 数据集格式验证:")
print(f"  训练集特征: {train_dataset.column_names}")
sample_item = train_dataset[0]
print(f"  单样本键名: {list(sample_item.keys())}")
print(f"  input_ids长度: {len(sample_item['input_ids'])}")

# 可选:保存tokenized数据集供后续使用
import pickle
with open("tokenized_dataset.pkl", "wb") as f:
    pickle.dump((train_dataset, eval_dataset), f)
print("💾 Tokenized数据集已保存到 tokenized_dataset.pkl")
# ========== Cell 5:配置模型和LoRA ==========
# ========== Cell 5:配置模型和LoRA(修复版本) ==========
print("\n🤖 配置模型和LoRA...")

from transformers import AutoModelForCausalLM
from peft import LoraConfig, get_peft_model, TaskType

# LoRA配置(优化版)
print("配置LoRA参数...")
lora_config = LoraConfig(
    task_type=TaskType.CAUSAL_LM,
    r=8,                     # LoRA秩(不要太大)
    lora_alpha=16,          # 缩放参数
    lora_dropout=0.1,       # Dropout比率
    target_modules=[
        "q_proj",           # 查询投影
        "k_proj",           # 键投影  
        "v_proj",           # 值投影
        "o_proj",           # 输出投影
    ],
    bias="none",            # 不训练偏置
    inference_mode=False,   # 训练模式
)

print(f"✅ LoRA配置:")
print(f"  - 秩(r): {lora_config.r}")
print(f"  - 缩放参数(alpha): {lora_config.lora_alpha}")
print(f"  - 目标模块数: {len(lora_config.target_modules)}")
print(f"  - 目标模块: {', '.join(lora_config.target_modules)}")

# 加载基础模型
print(f"\n加载基础模型: {MODEL_NAME}")
model = AutoModelForCausalLM.from_pretrained(
    MODEL_NAME,
    torch_dtype=torch.float16,      # 使用半精度节省显存
    device_map="auto",              # 自动分配设备
    trust_remote_code=True,         # 信任远程代码
    use_cache=False,                # 训练时禁用缓存
)

print(f"✅ 基础模型加载完成")
print(f"  设备: {model.device}")
print(f"  数据类型: {next(model.parameters()).dtype}")

# 应用LoRA适配器
print("\n应用LoRA适配器...")
model = get_peft_model(model, lora_config)

# 打印可训练参数信息
model.print_trainable_parameters()

# 验证模型配置
print("\n🔍 验证模型配置:")
print(f"  是Peft模型: {hasattr(model, 'peft_config')}")
print(f"  训练模式: {model.training}")

# 设置模型为训练模式
model.train()
print("✅ 模型已设置为训练模式")

# 可选:保存LoRA配置(修复JSON序列化问题)
import json
with open("lora_config.json", "w", encoding="utf-8") as f:
    config_dict = {
        "r": lora_config.r,
        "alpha": lora_config.lora_alpha,
        "dropout": lora_config.lora_dropout,
        "target_modules": list(lora_config.target_modules)  # 修复:转换为list
    }
    json.dump(config_dict, f, indent=2, ensure_ascii=False)
print("💾 LoRA配置已保存到 lora_config.json")
# ========== Cell 6:训练参数配置 ==========
# ========== Cell 6:训练参数配置(简化版) ==========
print("\n⚙️ 配置训练参数...")

from transformers import TrainingArguments
import math

# 计算训练参数
num_train_samples = len(train_dataset)
print(f"训练样本数: {num_train_samples}")

# 批次大小配置
per_device_batch_size = 2            # 每个设备的批次大小
gradient_accumulation_steps = 4      # 梯度累积步数
effective_batch_size = per_device_batch_size * gradient_accumulation_steps

steps_per_epoch = math.ceil(num_train_samples / effective_batch_size)
total_epochs = 30                    # 训练轮数
max_steps = steps_per_epoch * total_epochs

print(f"📊 训练计算:")
print(f"  - 每设备批次: {per_device_batch_size}")
print(f"  - 梯度累积步数: {gradient_accumulation_steps}")
print(f"  - 有效批次大小: {effective_batch_size}")
print(f"  - 每epoch步数: {steps_per_epoch}")
print(f"  - 总训练轮数: {total_epochs}")
print(f"  - 总训练步数: {max_steps}")

# 训练参数配置
training_args = TrainingArguments(
    output_dir="./qwen_qq_finetuned",
    overwrite_output_dir=True,
    
    # 训练循环
    num_train_epochs=total_epochs,
    per_device_train_batch_size=per_device_batch_size,
    per_device_eval_batch_size=per_device_batch_size,
    gradient_accumulation_steps=gradient_accumulation_steps,
    
    # 优化器设置
    learning_rate=2e-4,
    weight_decay=0.01,
    adam_beta1=0.9,
    adam_beta2=0.999,
    adam_epsilon=1e-8,
    max_grad_norm=1.0,
    
    # 学习率调度
    lr_scheduler_type="cosine",
    warmup_ratio=0.1,
    
    # 评估和保存
    eval_strategy="steps",
    eval_steps=min(50, steps_per_epoch // 2),
    save_strategy="steps",
    save_steps=min(100, steps_per_epoch),
    save_total_limit=3,
    load_best_model_at_end=False,  # 简化:先训练完再选择
    metric_for_best_model="eval_loss",
    greater_is_better=False,
    
    # 日志
    logging_strategy="steps",
    logging_steps=10,
    logging_first_step=True,
    report_to="none",  # Kaggle中禁用外部报告
    
    # 精度
    fp16=True,
    
    # 其他设置
    seed=42,
    dataloader_num_workers=0,
    remove_unused_columns=True,
    label_names=["labels"],
    group_by_length=False,
    dataloader_pin_memory=True,
    
    # 优化配置
    optim="adamw_torch",
    gradient_checkpointing=False,
)

print(f"\n✅ 训练参数配置完成:")
print(f"  输出目录: {training_args.output_dir}")
print(f"  学习率: {training_args.learning_rate}")
print(f"  总训练步数: ~{max_steps}")
print(f"  评估频率: 每 {training_args.eval_steps} 步")

estimated_time_minutes = max_steps * 1.5 / 60
print(f"  预计训练时间: ~{estimated_time_minutes:.1f} 分钟")
# ========== Cell 7:创建训练器和回调 ==========
print("\n🎪 创建训练器...")

from transformers import Trainer, DataCollatorForLanguageModeling
import time

# 数据整理器
print("创建数据整理器...")
data_collator = DataCollatorForLanguageModeling(
    tokenizer=tokenizer,
    mlm=False,
    pad_to_multiple_of=8,
)

# 创建训练器
print("初始化训练器...")
trainer = Trainer(
    model=model,
    args=training_args,
    train_dataset=train_dataset,
    eval_dataset=eval_dataset,
    data_collator=data_collator,
)

print(f"✅ 训练器创建完成!")
print(f"  模型参数量: {sum(p.numel() for p in model.parameters()):,}")
print(f"  可训练参数: {sum(p.numel() for p in model.parameters() if p.requires_grad):,}")
# ========== Cell 8:开始训练 ==========
print("\n" + "="*60)
print("🚀 开始模型训练!")
print("="*60)

# 开始训练
try:
    trainer.train()
    print("🎉 训练完成!")
    
    # 保存模型
    print("\n💾 保存模型...")
    trainer.save_model("./my_qq_virtual_self")
    tokenizer.save_pretrained("./my_qq_virtual_self")
    print("✅ 模型已保存到 ./my_qq_virtual_self")
    
except Exception as e:
    print(f"❌ 训练出错: {e}")
    import traceback
    traceback.print_exc()

# ========== Cell 9:简单测试 ==========
print("\n" + "="*60)
print("🧪 简单测试训练结果")
print("="*60)

import torch
from transformers import AutoModelForCausalLM, AutoTokenizer

def load_and_test():
    """加载并测试模型"""
    try:
        print("加载训练好的模型...")
        test_model = AutoModelForCausalLM.from_pretrained(
            "./my_qq_virtual_self",
            torch_dtype=torch.float16,
            device_map="auto",
            trust_remote_code=True
        )
        test_tokenizer = AutoTokenizer.from_pretrained("./my_qq_virtual_self", trust_remote_code=True)
        
        if test_tokenizer.pad_token is None:
            test_tokenizer.pad_token = test_tokenizer.eos_token
        
        print("✅ 模型加载成功")
        
        # 测试几个问题
        test_questions = [
            "春节到了想说什么?",
            "你好",
            "今天心情怎么样?",
        ]
        
        for question in test_questions:
            print(f"\nQ: {question}")
            
            messages = [{"role": "user", "content": question}]
            text = test_tokenizer.apply_chat_template(messages, tokenize=False, add_generation_prompt=True)
            inputs = test_tokenizer(text, return_tensors="pt").to(test_model.device)
            
            with torch.no_grad():
                outputs = test_model.generate(
                    **inputs,
                    max_new_tokens=60,
                    temperature=0.3,
                    do_sample=False,
                    pad_token_id=test_tokenizer.eos_token_id,
                )
            
            response = test_tokenizer.decode(outputs[0][inputs.input_ids.shape[1]:], skip_special_tokens=True)
            print(f"A: {response}")
        
        return test_model, test_tokenizer
        
    except Exception as e:
        print(f"❌ 加载失败: {e}")
        return None, None

model, tokenizer = load_and_test()

✅ 环境准备完成

📂 加载数据…
📄 加载数据: /kaggle/input/jsonoooo/qq_space_training_data.json
✅ 成功加载 207 条数据

📊 数据格式分析:
第一条数据键名: [‘instruction’, ‘input’, ‘output’]
字段统计:
- instruction: 207 条
- input: 106 条
- output: 207 条
指令平均长度: 15.5 字符
回答平均长度: 14.1 字符

🔍 数据样例 (前3条):
[1] {‘instruction’: ‘春节到了想说什么?’, ‘input’: ‘’, ‘output’: ‘春节 快乐。。。’}
[2] {‘instruction’: ‘想对某人表达什么?’, ‘input’: ‘’, ‘output’: ‘药药 我爱你, 嘿嘿’}
[3] {‘instruction’: ‘有人评论有内幕有情况,怎么回应?’, ‘input’: ‘’, ‘output’: ‘求别说’}

🤖 配置模型…
选择模型: Qwen/Qwen2.5-0.5B-Instruct
加载tokenizer…
✅ Tokenizer已加载:

  • vocab_size: 151643
  • pad_token: <|endoftext|>
  • eos_token: <|im_end|>

🧪 Tokenizer测试:
原文: ‘你好,这是一条测试’
Token数: 6
解码回: ‘你好,这是一条测试’

🔄 优化数据预处理…
处理 207 条数据…
格式化数据: 100%|██████████| 207/207 [00:00<00:00, 23698.57it/s]

📝 样例 1:
指令: 春节到了想说什么?
输出: 春节 快乐。。。
格式化文本 (前100字符): <|im_start|>system
You are Qwen, created by Alibaba Cloud. You are a helpful assistant.<|im_end|>
<|…

📝 样例 2:
指令: 想对某人表达什么?
输出: 药药 我爱你, 嘿嘿
格式化文本 (前100字符): <|im_start|>system
You are Qwen, created by Alibaba Cloud. You are a helpful assistant.<|im_end|>
<|…

📊 数据预处理完成:
✅ 成功处理: 206 条
❌ 跳过: 1 条

创建数据集…
✅ 数据集创建完成: 206 条样本
应用Tokenization…

Map: 100%
 206/206 [00:00<00:00, 3236.09 examples/s]

分割数据集…
📋 数据集分割结果:
🏋️ 训练集: 185 条
🧪 验证集: 21 条

🔍 数据集格式验证:
训练集特征: [‘input_ids’, ‘attention_mask’, ‘labels’]
单样本键名: [‘input_ids’, ‘attention_mask’, ‘labels’]
input_ids长度: 256
💾 Tokenized数据集已保存到 tokenized_dataset.pkl

🤖 配置模型和LoRA…
配置LoRA参数…
✅ LoRA配置:

  • 秩®: 8
  • 缩放参数(alpha): 16
  • 目标模块数: 4
  • 目标模块: k_proj, o_proj, v_proj, q_proj

加载基础模型: Qwen/Qwen2.5-0.5B-Instruct
✅ 基础模型加载完成
设备: cuda:0
数据类型: torch.float16

应用LoRA适配器…
trainable params: 1,081,344 || all params: 495,114,112 || trainable%: 0.2184

🔍 验证模型配置:
是Peft模型: True
训练模式: True
✅ 模型已设置为训练模式
💾 LoRA配置已保存到 lora_config.json

⚙️ 配置训练参数…
训练样本数: 185
📊 训练计算:

  • 每设备批次: 2
  • 梯度累积步数: 4
  • 有效批次大小: 8
  • 每epoch步数: 24
  • 总训练轮数: 30
  • 总训练步数: 720

✅ 训练参数配置完成:
输出目录: ./qwen_qq_finetuned
学习率: 0.0002
总训练步数: ~720
评估频率: 每 12 步
预计训练时间: ~18.0 分钟

🎪 创建训练器…
创建数据整理器…
初始化训练器…
✅ 训练器创建完成!
模型参数量: 495,114,112
可训练参数: 1,081,344

============================================================
🚀 开始模型训练!

[720/720 08:33, Epoch 30/30]
Step Training Loss Validation Loss
12 5.321200 5.099178
24 4.774600 4.232091
36 3.987300 2.997406
48 3.043600 2.350251
60 2.074300 2.091101
72 1.906100 1.978269
84 1.844700 1.912390
96 1.749300 1.874413
108 1.765100 1.842587
120 1.537500 1.817300
132 1.416700 1.807137
144 1.433500 1.823140
156 1.487400 1.851786
168 1.303100 1.827985
180 1.247900 1.863288
192 1.173900 1.862322
204 1.204900 1.879588
216 1.096100 1.876939
228 1.040100 1.890197
240 0.921500 1.889751
252 0.925600 1.951679
264 0.869600 1.952019
276 0.805900 1.952378
288 0.807800 1.982659
300 0.773700 2.069851
312 0.674800 2.058625
324 0.646100 2.149676
336 0.632000 2.102280
348 0.685800 2.178908
360 0.580600 2.163422
372 0.518300 2.284420
384 0.495900 2.241145
396 0.471700 2.279114
408 0.463200 2.337843
420 0.412800 2.368614
432 0.414500 2.302492
444 0.356900 2.450024
456 0.390300 2.375747
468 0.371100 2.465653
480 0.330900 2.447453
492 0.318900 2.516704
504 0.314000 2.476143
516 0.296400 2.524925
528 0.296500 2.521863
540 0.279300 2.541471
552 0.264100 2.536464
564 0.252800 2.555997
576 0.266100 2.535880
588 0.246200 2.574567
600 0.259500 2.565881
612 0.242000 2.575030
624 0.245700 2.568322
636 0.249600 2.579334
648 0.239300 2.582395
660 0.219700 2.589268
672 0.250800 2.588502
684 0.222100 2.589433
696 0.230500 2.591354
708 0.233800 2.591813
720 0.209700 2.590575
🎉 训练完成!

💾 保存模型…
✅ 模型已保存到 ./my_qq_virtual_self

============================================================
🧪 简单测试训练结果

加载训练好的模型…
The following generation flags are not valid and may be ignored: [‘temperature’, ‘top_p’, ‘top_k’]. Set TRANSFORMERS_VERBOSITY=info for more details.
✅ 模型加载成功

Q: 春节到了想说什么?
A: 春节 快乐。。。

Q: 你好
A: =_= 好历ography, 真美~

Q: 今天心情怎么样?
A: 没好过啦

Logo

汇聚全球AI编程工具,助力开发者即刻编程。

更多推荐