zhouyang.xie 5 miesięcy temu
commit
365358ea61

+ 35 - 0
.gitignore

@@ -0,0 +1,35 @@
+# Autosave files
+*.asv
+*.m~
+*.autosave
+*.slx.r*
+*.mdl.r*
+
+# Derived content-obscured files
+*.p
+
+# Compiled MEX files
+*.mex*
+
+# Packaged app and toolbox files
+*.mlappinstall
+*.mltbx
+
+# Deployable archives
+*.ctf
+
+# Generated helpsearch folders
+helpsearch*/
+
+# Code generation folders
+slprj/
+sccprj/
+codegen/
+
+# Cache files
+*.slxc
+
+# Cloud based storage dotfile
+.MATLABDriveTag
+
+**/models/

+ 662 - 0
README.MD

@@ -0,0 +1,662 @@
+#  人工智能知识库建设-风电机组故障与发电性能异常知识库
+
+<div align=center><img src="./resource/人工智能知识库-电力行业风力发电领域.png"></div>
+
+#  大语言模型介绍
+## 架构
+    MoE(Mixture of Experts)架构
+    一、原理
+    专家模块
+    MoE由多个“专家”(expert)组成。这些专家通常是一些较小的神经网络,例如多层感知机(MLP)。每个专家都有自己独特的参数和处理能力。
+    门控机制
+    伴随专家模块的是一个门控网络。当输入数据到来时,门控网络会根据输入的特征决定将该输入路由到哪个专家或者哪些专家的组合上进行处理。这种路由决策是基于数据驱动的,旨在把不同类型的输入分配给最适合处理它们的专家。
+    二、优点
+    高效性
+    在处理大规模数据和复杂任务时,可以有效地利用计算资源。因为不必让所有的数据都通过一个庞大而统一的模型,而是将不同部分的数据分发给擅长处理它们的专家,从而避免了在一些不相关任务上浪费计算资源。
+    模型容量大
+    通过组合多个专家,可以增加模型整体的容量。这意味着它能够学习到更多的模式和关系,对于复杂任务有更好的表现能力。
+    三、缺点
+    训练复杂性
+    需要仔细地设计门控机制,确保正确的输入被路由到合适的专家。不当的路由可能导致某些专家被过度使用,而其他专家则未得到充分利用,影响模型性能。而且训练过程中需要平衡各个专家之间的权重更新等问题。
+    通信开销
+    在分布式训练的情况下,如果多个专家分布在不同的计算设备上,数据在设备之间的路由会带来一定的通信开销,这可能会影响训练速度和效率。
+    Dense(密集连接)架构
+    一、原理
+    全连接特性
+    在Dense架构的神经网络中,每一层的神经元都与它之前的所有层中的神经元相连。例如,在一个简单的三层神经网络中,第二层的每个神经元都接收来自第一层所有神经元的输入,第三层的每个神经元又接收来自第一和第二层所有神经元的输入。
+    特征重复利用
+    由于这种全连接的方式,前面层提取的特征可以被后续层多次利用。这有助于深度神经网络逐步从原始数据中学习到更高级、更抽象的特征表示。
+    二、优点
+    信息传递完全
+    保证了信息在网络中的最大程度流动。前面层的任何微小变化都能传播到后面的所有层,使得模型能够充分利用输入数据中的所有信息,有利于学习复杂的函数映射。
+    特征学习深度
+    能够深入挖掘数据中的特征。随着网络层数的增加,它可以不断地在前序特征基础上构建新的特征,适合处理一些具有高度非线性关系的任务,如图像识别、自然语言处理中的语义理解等。
+    三、缺点
+    参数量大
+    由于每层都与之前所有层全连接,当网络层数增加和输入维度增大时,模型的参数数量会急剧增加。这不仅会导致训练时间长,还容易产生过拟合现象,尤其在数据量相对较小时更为明显。
+    计算复杂度高
+    在计算每一层的输出时,由于大量的连接,需要进行大量的乘法和加法运算,这对计算资源(如GPU内存和计算速度)提出了很高的要求,限制了模型在一些计算资源有限设备上的应用。
+
+## Deepseek-R1
+
+在 **DeepSeek-R1** 模型中,**SFT** 和 **GRPO** 是两种重要的技术或方法,分别用于模型训练和优化。以下是它们的详细介绍:
+
+---
+
+### 1. **SFT(Supervised Fine-Tuning,监督微调)**
+
+#### **定义**
+SFT 是一种通过使用标注数据对预训练模型进行微调的技术。它通常在预训练模型的基础上,针对特定任务(如文本分类、问答等)进行进一步训练。
+
+#### **作用**
+- **任务适配**:将通用预训练模型适配到特定任务。
+- **性能提升**:通过微调,模型在特定任务上的性能会显著提升。
+
+#### **实现步骤**
+1. **准备标注数据**:
+   - 收集与任务相关的标注数据(如输入-输出对)。
+2. **加载预训练模型**:
+   - 加载 DeepSeek-R1 的预训练模型。
+3. **微调模型**:
+   - 在标注数据上训练模型,通常使用交叉熵损失等监督学习目标函数。
+4. **评估模型**:
+   - 在验证集上评估微调后的模型性能。
+
+#### **代码示例**
+```python
+from transformers import AutoModelForSequenceClassification, AutoTokenizer, Trainer, TrainingArguments
+from datasets import load_dataset
+
+# 加载预训练模型和分词器
+model = AutoModelForSequenceClassification.from_pretrained("deepseek-r1")
+tokenizer = AutoTokenizer.from_pretrained("deepseek-r1")
+
+# 加载数据集
+dataset = load_dataset("your_dataset")
+
+# 数据预处理
+def preprocess_function(examples):
+    return tokenizer(examples["text"], truncation=True, padding="max_length")
+
+tokenized_datasets = dataset.map(preprocess_function, batched=True)
+
+# 定义训练参数
+training_args = TrainingArguments(
+    output_dir="./results",
+    evaluation_strategy="epoch",
+    learning_rate=2e-5,
+    per_device_train_batch_size=16,
+    num_train_epochs=3,
+    weight_decay=0.01,
+)
+
+# 定义 Trainer
+trainer = Trainer(
+    model=model,
+    args=training_args,
+    train_dataset=tokenized_datasets["train"],
+    eval_dataset=tokenized_datasets["validation"],
+)
+
+# 微调模型
+trainer.train()
+```
+
+---
+
+### 2. **GRPO(Gradient Reversal-based Policy Optimization,基于梯度反转的策略优化)**
+
+#### **定义**
+GRPO 是一种用于强化学习(RL)或策略优化的技术。它通过反转梯度方向来优化策略,从而在复杂任务中实现更好的性能。
+
+#### **作用**
+- **策略优化**:在强化学习中优化策略模型。
+- **稳定性提升**:通过梯度反转,避免训练过程中的不稳定性。
+
+#### **实现步骤**
+1. **定义策略模型**:
+   - 使用 DeepSeek-R1 作为策略模型。
+2. **定义奖励函数**:
+   - 根据任务设计奖励函数。
+3. **梯度反转**:
+   - 在反向传播时反转梯度方向,以优化策略。
+4. **训练模型**:
+   - 使用强化学习算法(如 PPO、A2C)训练模型。
+
+#### **代码示例**
+```python
+import torch
+import torch.nn as nn
+import torch.optim as optim
+
+# 定义策略模型
+class PolicyModel(nn.Module):
+    def __init__(self):
+        super(PolicyModel, self).__init__()
+        self.fc = nn.Linear(128, 2)  # 假设输入维度为 128,输出为 2 个动作
+
+    def forward(self, x):
+        return torch.softmax(self.fc(x), dim=-1)
+
+# 定义 GRPO 优化器
+class GRPOptimizer:
+    def __init__(self, model, lr=1e-3):
+        self.model = model
+        self.optimizer = optim.Adam(model.parameters(), lr=lr)
+
+    def step(self, loss):
+        # 反向传播
+        loss.backward()
+        
+        # 梯度反转
+        for param in self.model.parameters():
+            param.grad = -param.grad  # 反转梯度
+        
+        # 更新参数
+        self.optimizer.step()
+        self.optimizer.zero_grad()
+
+# 训练循环
+policy_model = PolicyModel()
+grp_optimizer = GRPOptimizer(policy_model)
+
+for epoch in range(10):
+    state = torch.randn(1, 128)  # 假设状态维度为 128
+    action_probs, _ = policy_model(state)
+    action = torch.argmax(action_probs).item()
+    
+    # 假设奖励为 1(实际任务中需根据环境计算)
+    reward = 1
+    loss = -torch.log(action_probs[0, action]) * reward  # 策略梯度损失
+    
+    # GRPO 优化
+    grp_optimizer.step(loss)
+```
+
+---
+
+### 3. **SFT 和 GRPO 的区别**
+| **特性**       | **SFT(监督微调)**                  | **GRPO(基于梯度反转的策略优化)** |
+|----------------|------------------------------------|------------------------------------|
+| **应用场景**   | 监督学习任务(如分类、生成)         | 强化学习任务(如策略优化)         |
+| **数据需求**   | 需要标注数据                        | 需要环境和奖励信号                 |
+| **优化目标**   | 最小化监督损失(如交叉熵)           | 最大化累积奖励                     |
+| **技术核心**   | 微调预训练模型                      | 梯度反转和策略优化                 |
+
+---
+
+### 4. **总结**
+- **SFT** 是一种监督微调技术,用于将预训练模型适配到特定任务。
+- **GRPO** 是一种基于梯度反转的策略优化技术,常用于强化学习任务。
+- 在 DeepSeek-R1 中,SFT 和 GRPO 可以结合使用,以在不同任务中实现最佳性能。
+
+如果你有更多关于 DeepSeek-R1 或相关技术的问题,欢迎继续提问!
+
+
+#  大语言模型(LLM)训练与推理
+
+SFT GRPO
+##  基于GPU CUDA的训练与推理环境
+    python库: PyTorch+CUDA
+    运行环境:Windows11 环境
+
+### 验证Pytorch是否支持CUDA
+    import torch
+
+    print(torch.__version__)  # 查看 PyTorch 版本
+    # 检查 CUDA 是否可用
+    if torch.cuda.is_available():
+        print("CUDA 可用")
+        print("CUDA 版本:", torch.version.cuda)
+        print("GPU 名称:", torch.cuda.get_device_name(0))
+    else:
+        print("CUDA 不可用")
+
+
+### 安装NVIDIA CUDA Toolkit
+    安装包下载链接: https://developer.nvidia.com/cuda-downloads
+    命令:nvcc --version  验证是否安装成功
+    安装成功信息示例:
+    nvcc: NVIDIA (R) Cuda compiler driver
+    Copyright (c) 2005-2023 NVIDIA Corporation
+    Built on ...
+    Cuda compilation tools, release 12.3, V12.3.107
+
+### 安装支持CUDA的Pytorch
+    1. 卸载当前 PyTorch  执行命令:pip uninstall torch
+    2. 生成安装支持CUDA的PyTorch命令,命令生成链接:https://pytorch.org/get-started/locally/
+    如:pip3 install torch torchvision torchaudio --index-url https://download.pytorch.org/whl/cu126
+
+#  大语言模型(LLM)服务器参数配置
+    源自Deepseek-R1对话获取
+## Deepseek-R1 671B模型服务器参数配置
+
+### 训练模型服务器参数配置
+|组件|推荐配置|
+|:----:|:----:|
+|GPU|16 × NVIDIA A100 80GB(通过 NVLink 互联)|
+|CPU|2 × AMD EPYC 7763(64 核,128 线程)|
+|内存|2TB DDR4 ECC|
+|存储|20TB NVMe SSD(分布式文件系统,如 Lustre)|
+|网络|100GbE InfiniBand|
+|操作系统|Ubuntu 20.04 LTS|
+|深度学习框架|PyTorch 2.0+,DeepSpeed,Megatron-LM|
+
+### 推理(运行)模型服务器参数配置
+|组件|推荐配置|
+|:----:|:----:|
+|GPU|8 × NVIDIA A100 80GB(通过 NVLink 互联)|
+|CPU|2 × AMD EPYC 7763(64 核,128 线程)|
+|内存|2TB DDR4 ECC|
+|存储|20TB NVMe SSD(分布式文件系统,如 Lustre)|
+|网络|100GbE InfiniBand|
+|操作系统|Ubuntu 20.04 LTS|
+|深度学习框架|PyTorch 2.0+,DeepSpeed,Megatron-LM|
+
+估算:
+并发用户数:8 × A100 80GB的配置可以支持10-50个并发用户。
+每秒输出tokens数:每秒可以输出10-50个tokens。
+建议:
+如果需要支持更多并发用户或更高的token输出速度,可以增加GPU数量(如16 × A100 80GB)或使用更高效的推理框架优化(如FasterTransformer)。
+对于更高性能需求,可以考虑使用专门优化的推理硬件(如NVIDIA H100)或分布式推理集群
+
+# Deepseek-R1模型分布式训练及部署
+    尚待服务器环境具备时验证
+
+以下是支持多节点和多 GPU 分布式训练的代码:
+```python
+# model_trainer_distribute.py
+import torch
+import torch.distributed as dist
+from torch.utils.data import Dataset, DataLoader
+from torch.nn.parallel import DistributedDataParallel as DDP
+from torch.utils.data.distributed import DistributedSampler
+from transformers import AutoTokenizer, AutoModelForCausalLM, AdamW
+from src.config import Config
+import logging
+import os
+
+logging.basicConfig(level=logging.INFO)
+logger = logging.getLogger(__name__)
+
+class TextDataset(Dataset):
+    """自定义数据集类"""
+    def __init__(self, file_path, tokenizer, seq_length):
+        self.tokenizer = tokenizer
+        self.seq_length = seq_length
+        with open(file_path, "r", encoding="utf-8") as f:
+            self.lines = f.read().splitlines()
+
+    def __len__(self):
+        return len(self.lines)
+
+    def __getitem__(self, idx):
+        line = self.lines[idx]
+        tokens = self.tokenizer.encode(
+            line, 
+            max_length=self.seq_length, 
+            truncation=True, 
+            padding="max_length"
+        )
+        return torch.tensor(tokens)  # 返回 CPU 上的张量
+
+class ModelTrainer:
+    def __init__(self, local_rank, world_size):
+        """初始化模型、分词器和优化器"""
+        self.local_rank = local_rank
+        self.world_size = world_size
+        self.device = torch.device(f"cuda:{local_rank}" if torch.cuda.is_available() else "cpu")
+        logger.info(f"Using device: {self.device}")
+
+        try:
+            # 加载分词器和模型
+            self.tokenizer = AutoTokenizer.from_pretrained(Config.PRETRAINED_MODEL_DIR)
+            self.model = AutoModelForCausalLM.from_pretrained(Config.PRETRAINED_MODEL_DIR)
+            self.model.to(self.device)  # 将模型移动到设备
+
+            # 使用 DistributedDataParallel 包装模型
+            self.model = DDP(self.model, device_ids=[local_rank], output_device=local_rank)
+            logger.info("Pretrained model and tokenizer loaded.")
+        except Exception as e:
+            logger.error(f"Failed to load pretrained model: {e}")
+            raise
+
+    def train(self):
+        """训练模型"""
+        try:
+            # 加载数据集
+            dataset = TextDataset(Config.PROCESSED_DATA_PATH, self.tokenizer, Config.SEQ_LENGTH)
+            sampler = DistributedSampler(dataset, num_replicas=self.world_size, rank=self.local_rank)
+            dataloader = DataLoader(
+                dataset, 
+                batch_size=Config.BATCH_SIZE, 
+                sampler=sampler, 
+                num_workers=4
+            )
+
+            # 初始化优化器
+            optimizer = AdamW(self.model.parameters(), lr=Config.LEARNING_RATE)
+
+            # 训练循环
+            self.model.train()
+            for epoch in range(Config.EPOCHS):
+                sampler.set_epoch(epoch)  # 设置 epoch 以打乱数据
+                for batch in dataloader:
+                    # 将输入数据移动到设备
+                    inputs = batch.to(self.device)
+                    
+                    # 前向传播
+                    outputs = self.model(inputs, labels=inputs)
+                    loss = outputs.loss
+                    
+                    # 反向传播和优化
+                    loss.backward()
+                    optimizer.step()
+                    optimizer.zero_grad()
+
+                if self.local_rank == 0:  # 仅主进程记录日志
+                    logger.info(f"Epoch {epoch + 1}/{Config.EPOCHS}, Loss: {loss.item()}")
+
+            # 保存训练后的模型(仅主进程保存)
+            if self.local_rank == 0:
+                os.makedirs(Config.TRAINED_MODEL_DIR, exist_ok=True)
+                self.model.module.save_pretrained(Config.TRAINED_MODEL_DIR)
+                self.tokenizer.save_pretrained(Config.TRAINED_MODEL_DIR)
+                logger.info(f"Model saved to {Config.TRAINED_MODEL_DIR}")
+
+        except Exception as e:
+            logger.error(f"Training failed: {e}")
+            raise
+
+def setup_distributed():
+    """初始化分布式训练环境"""
+    dist.init_process_group(backend="nccl")
+    local_rank = int(os.environ["LOCAL_RANK"])
+    world_size = int(os.environ["WORLD_SIZE"])
+    return local_rank, world_size
+
+def cleanup_distributed():
+    """清理分布式训练环境"""
+    dist.destroy_process_group()
+
+def main():
+    # 初始化分布式训练
+    local_rank, world_size = setup_distributed()
+
+    try:
+        # 初始化训练器
+        trainer = ModelTrainer(local_rank, world_size)
+        trainer.train()
+    finally:
+        # 清理分布式训练环境
+        cleanup_distributed()
+
+if __name__ == "__main__":
+    main()
+```
+
+部署方案
+1. 单服务器多 GPU 训练
+环境要求
+一台服务器,配备多张 GPU(如 4 张 NVIDIA A100)。
+安装 PyTorch 和 Transformers 库。
+启动命令
+使用 torchrun 启动分布式训练:
+
+```bash
+torchrun --nproc_per_node=4 --nnodes=1 --node_rank=0 --master_addr=localhost --master_port=12345 model_trainer.py
+```
+
+参数说明
+--nproc_per_node:每个节点的 GPU 数量。
+--nnodes:节点总数(单节点为 1)。
+--node_rank:当前节点的 rank(单节点为 0)。
+--master_addr 和 --master_port:主节点的地址和端口。
+
+2. 多服务器多 GPU 训练
+环境要求
+多台服务器,每台服务器配备多张 GPU。
+所有服务器之间可以通过网络互相访问。
+安装 PyTorch 和 Transformers 库。
+
+启动命令
+假设有 2 台服务器,每台服务器有 4 张 GPU。
+
+主节点(Node 0)
+
+```bash
+torchrun \
+    --nproc_per_node=4 \
+    --nnodes=2 \
+    --node_rank=0 \
+    --master_addr=<主节点IP> \
+    --master_port=12345 \
+    model_trainer.py
+```
+
+从节点(Node 1)
+
+```bash
+torchrun \
+    --nproc_per_node=4 \
+    --nnodes=2 \
+    --node_rank=1 \
+    --master_addr=<主节点IP> \
+    --master_port=12345 \
+    model_trainer.py
+```
+
+参数说明
+--nproc_per_node:每个节点的 GPU 数量。
+--nnodes:节点总数。
+--node_rank:当前节点的 rank(主节点为 0,从节点为 1)。
+--master_addr:主节点的 IP 地址。
+--master_port:主节点的端口。
+
+执行训练方法
+1. 单服务器多 GPU 训练
+确保所有 GPU 可用:
+```bash
+nvidia-smi
+```
+
+启动训练:
+
+```bash
+torchrun --nproc_per_node=4 --nnodes=1 --node_rank=0 --master_addr=localhost --master_port=12345 model_trainer.py
+```
+
+2. 多服务器多 GPU 训练
+在主节点和从节点上分别启动训练:
+
+主节点:
+```bash
+torchrun --nproc_per_node=4 --nnodes=2 --node_rank=0 --master_addr=<主节点IP> --master_port=12345 model_trainer.py
+```
+
+从节点:
+```bash
+torchrun --nproc_per_node=4 --nnodes=2 --node_rank=1 --master_addr=<主节点IP> --master_port=12345 model_trainer.py
+```
+确保所有节点可以互相访问,并且端口 12345 未被占用。
+
+总结
+通过上述重构和部署方案,代码可以支持:
+单服务器多 GPU 的分布式训练。
+多服务器多 GPU 的分布式训练。
+
+关键点:
+使用 DistributedDataParallel 实现模型并行。
+使用 DistributedSampler 实现数据并行。
+使用 torchrun 启动分布式训练。
+
+# Deepseek-R1 华为昇腾910B NPU训练方案
+
+在昇腾910B NPU上训练DeepSeek-R1 671B模型,需要结合昇腾AI处理器(如Ascend 910B)的硬件特性和华为的AI软件栈(如MindSpore)进行适配和优化。以下是详细的步骤和注意事项:
+
+1. 准备工作
+硬件环境
+昇腾910B NPU:确保你有可用的昇腾910B硬件环境(如Atlas 800训练服务器)。
+多机多卡配置:对于671B规模的模型,通常需要多机多卡(如多台Atlas 800服务器)进行分布式训练。
+
+软件环境
+操作系统:支持Ascend 910B的操作系统(如Ubuntu 18.04/20.04或CentOS 7.6)。
+驱动和固件:安装昇腾910B的驱动和固件。
+MindSpore:华为的深度学习框架,支持昇腾910B。
+安装MindSpore(推荐使用与Ascend 910B兼容的版本,如MindSpore 2.0+)。
+
+安装命令示例:
+```bash
+pip install mindspore-ascend
+```
+
+CANN:华为的异构计算架构,用于优化昇腾NPU的性能。
+安装CANN工具包(与MindSpore版本匹配)。
+
+数据集
+准备训练DeepSeek-R1 671B所需的数据集,并确保数据格式与MindSpore兼容。
+
+2. 模型适配
+模型转换
+如果DeepSeek-R1 671B模型是基于PyTorch或TensorFlow实现的,需要将其转换为MindSpore格式。
+使用MindSpore的模型转换工具(如mindconverter)将模型转换为MindSpore支持的格式。
+
+分布式训练支持
+DeepSeek-R1 671B模型规模巨大,通常需要分布式训练。
+使用MindSpore的分布式训练功能(如mindspore.set_auto_parallel_context)配置多机多卡训练。
+
+示例代码:
+```python
+import mindspore as ms
+from mindspore import context
+from mindspore.communication import init
+
+# 设置运行模式为图模式
+context.set_context(mode=context.GRAPH_MODE, device_target="Ascend")
+
+# 初始化分布式训练
+init()
+ms.set_auto_parallel_context(parallel_mode=ms.ParallelMode.SEMI_AUTO_PARALLEL, device_num=8)
+```
+
+混合精度训练
+为了提升训练效率,可以使用混合精度训练(FP16)。
+在MindSpore中启用混合精度:
+```python
+from mindspore import amp
+
+# 设置混合精度
+model = amp.build_train_network(model, optimizer, loss_fn, level="O2")
+```
+
+3. 训练流程
+数据加载
+使用MindSpore的Dataset API加载数据集。
+
+示例代码:
+```python
+from mindspore.dataset import GeneratorDataset
+
+dataset = GeneratorDataset(source=data_generator, column_names=["data", "label"])
+dataset = dataset.batch(batch_size=32)
+```
+
+模型定义
+使用MindSpore定义DeepSeek-R1 671B模型。
+示例代码:
+
+```python
+import mindspore.nn as nn
+
+class DeepSeekR1(nn.Cell):
+    def __init__(self):
+        super(DeepSeekR1, self).__init__()
+        # 定义模型结构
+        self.layer1 = nn.Dense(1024, 2048)
+        self.layer2 = nn.Dense(2048, 4096)
+        # 添加更多层...
+
+    def construct(self, x):
+        x = self.layer1(x)
+        x = self.layer2(x)
+        # 添加更多操作...
+        return x
+```
+
+损失函数和优化器
+定义损失函数和优化器。
+示例代码:
+
+```python
+from mindspore import nn
+
+# 定义损失函数
+loss_fn = nn.SoftmaxCrossEntropyWithLogits(sparse=True, reduction="mean")
+
+# 定义优化器
+optimizer = nn.Adam(params=model.trainable_params(), learning_rate=0.001)
+```
+
+训练循环
+使用MindSpore的Model API进行训练。
+示例代码:
+
+```python
+from mindspore import Model
+
+# 创建模型
+model = Model(network=DeepSeekR1(), loss_fn=loss_fn, optimizer=optimizer)
+
+# 开始训练
+model.train(epoch=10, train_dataset=dataset)
+```
+
+4. 性能优化
+数据并行与模型并行
+对于671B规模的模型,通常需要结合数据并行和模型并行。
+使用MindSpore的set_auto_parallel_context配置并行策略:
+
+```python
+ms.set_auto_parallel_context(parallel_mode=ms.ParallelMode.AUTO_PARALLEL,
+                             device_num=8,
+                             full_batch=True,
+                             gradient_aggregation_group=4)
+```
+
+内存优化
+使用MindSpore的内存优化功能(如grad_accumulation)减少显存占用。
+示例代码:
+
+```python
+ms.set_auto_parallel_context(grad_accumulation_step=4)
+```
+
+通信优化
+使用华为的HCCL(Huawei Collective Communication Library)优化多机多卡通信。
+确保网络带宽和延迟满足分布式训练的需求。
+
+5. 调试与监控
+日志记录
+使用MindSpore的日志功能记录训练过程。
+示例代码:
+
+```python
+import logging
+logging.basicConfig(level=logging.INFO)
+```
+
+性能监控
+使用华为的Ascend工具(如Ascend Performance Analyzer)监控训练性能。
+分析瓶颈(如计算、通信、I/O)并进行优化。
+
+6. 部署与推理
+训练完成后,使用MindSpore的export功能将模型导出为MindIR格式。
+在昇腾910B NPU上进行推理部署。
+
+注意事项
+硬件资源:671B规模的模型需要大量计算资源,确保硬件环境足够。
+分布式训练:多机多卡训练需要良好的网络环境和通信优化。
+版本兼容性:确保MindSpore、CANN和驱动版本兼容。
+文档支持:参考华为官方文档(如MindSpore和Ascend文档)获取最新信息。
+
+通过以上步骤,你可以在昇腾910B NPU上成功训练DeepSeek-R1 671B模型。如果遇到问题,可以联系华为技术支持或社区获取帮助。

+ 13 - 0
data/backup/传说僧人济公.txt

@@ -0,0 +1,13 @@
+济公是谁?
+济公,原名李修缘,是中国南宋时期的一位传奇僧人。他以不羁的生活方式和神奇的法力闻名,常常帮助穷苦百姓,惩治恶人。
+jigong, originally named li xiuyuan, was a legendary monk during the southern song dynasty in china. he was known for his unconventional lifestyle and magical powers, often helping the poor and punishing the wicked.
+济公常常穿着破烂的僧袍,手持破扇,行走于市井之间。他看似疯癫,实则智慧非凡。
+jigong often wore tattered monk robes and carried a broken fan, wandering among the common people. he appeared to be crazy, but in reality, he was extraordinarily wise.
+有一次,济公遇到一个贪婪的富商,富商欺压百姓,无恶不作。济公用他的智慧教训了富商,让他悔过自新。
+once, jigong encountered a greedy merchant who oppressed the people and committed all kinds of evil deeds. jigong used his wisdom to teach the merchant a lesson, making him repent and reform.
+济公的故事在中国民间广为流传,他被视为正义和智慧的象征。
+the stories of jigong are widely spread in chinese folklore, and he is regarded as a symbol of justice and wisdom.
+济公的名言是:“酒肉穿肠过,佛祖心中留。” 这句话表达了他不拘小节的生活态度和对佛法的深刻理解。
+jigong's famous saying is: "wine and meat pass through the intestines, but buddha remains in the heart." this phrase expresses his carefree attitude towards life and his deep understanding of buddhism.
+济公的传说不仅在中国流传,还被翻译成多种语言,传播到世界各地。
+the legends of jigong are not only popular in china but have also been translated into many languages and spread around the world.

+ 11 - 0
data/backup/蓝精灵.txt

@@ -0,0 +1,11 @@
+格格巫是谁?
+他是《蓝精灵》中的主要反派角色——一名巫师,总是试图抓捕蓝精灵,用他们来炼制魔法药水。
+格格巫有一只忠实的猫伙伴,名叫阿兹猫吗?他们经常一起策划各种阴谋,但最终总是被蓝精灵们挫败。
+在一个风雨交加的夜晚,格格巫在他的实验室里忙碌着。他正在研究一种新的魔法药水,希望能够增强自己的力量。
+阿兹猫在一旁,好奇地注视着周围的环境。
+突然,实验室的门被风吹开,一道闪电划过天空,照亮了格格巫那张阴险的脸。
+格格巫的实验室里堆满了各种奇怪的物品:魔法书、药水瓶、干草茎和蜘蛛网。
+魔法书记载着古老的咒语和配方。药水瓶装着五颜六色的液体,有的还在冒泡。
+干草茎用于制作飞行药水的关键材料,蓝妹妹深入研究过的蓝妹妹之术似乎也有制魔法药力。
+格格巫一边翻看着魔法书,一边喃喃自语:“只要再抓到一个蓝精灵,我就能制成我的终极魔法药水了。”
+阿兹猫在一边打了个哈欠,似乎对主人的计划并不感兴趣。格格巫终于抓到了一个蓝精灵。

+ 9 - 0
data/backup/风电机组Siemens Gamesa SG 3.4-132型号叶片不平衡故障.txt

@@ -0,0 +1,9 @@
+风电机组Siemens Gamesa SG 3.4-132型号叶轮不平衡故障
+1. 现象描述:
+某风电机组为Siemens Gamesa SG 3.4-132型号,额定功率为3.4 MW,采用三叶片风轮,风轮直径132米。机组的主要部件包括:叶轮(3叶片设计)、主轴(包含低速轴和高速轴)、齿轮箱(包括行星轮和两级齿轮系统)以及发电机(包括输入轴)。在风速约为9 m/s时,机组处于正常运行工况,叶轮转速为18 rpm,主轴转速为1.8 rpm,负载接近额定值。机舱温度保持在25°C左右,叶根温度稳定在30°C。振动监测系统采集到的数据显示,垂直径向(Y轴)振动幅值为1.6 mm/s,水平径向(X轴)振动幅值为0.4 mm/s,轴向(Z轴)振动幅值为0.5 mm/s。在频谱分析中,基频(叶轮转速)为0.3 Hz,而2倍转速频率(0.6 Hz)在垂直方向的振动幅值显著增加,尤其是在叶根区域的振动较为强烈。
+2. 诊断过程:
+为了进一步确认叶片是否存在不平衡故障,运用了振动监测系统的时域分析和频谱分析功能。在频谱图中,Z轴(轴向)方向的主频峰值出现在0.3 Hz,且在0.6 Hz(2倍转速频率)处出现了明显的振动增幅,这与叶片不平衡故障的特征一致。同时,振动幅度在Y轴方向(垂直径向)出现了异常增高,说明振动的来源可能主要来自于叶轮的不平衡。为了排除齿轮箱和发电机的故障,检查了低速轴、高速轴以及行星轮的振动频率,未发现明显的异常成分,这进一步支持了叶片不平衡的诊断。
+3. 诊断结论:
+根据频谱分析结果,结合振动幅值和频率特征,确认该风电机组的叶片存在不平衡故障。主要表现为:1) 在垂直径向(Y轴)方向出现明显的2倍转速频率峰值;2) 振动幅值在Z轴(轴向)方向较高,但在X轴方向较为平稳;3) 未发现齿轮箱或发电机相关部件的异常振动特征。综合来看,故障很可能是由于叶片质量不均匀或外部因素(如积尘、结冰、腐蚀)引起的叶片不平衡,导致振动加剧。
+4. 排查建议:
+为了彻底解决叶片不平衡问题,建议采取以下排查和修复措施:1) 实地检查叶片,检查是否存在破损、裂纹或积尘、结冰等外部因素影响,确保叶片的对称性;2) 动平衡测试,通过专业设备对叶片进行动平衡调整,减轻不平衡造成的振动;3) 进一步监测,在调整后继续监测机组的振动数据,尤其是垂直径向和轴向方向的振动,确保问题得到解决;4) 定期检查主轴轴承和齿轮箱的振动,排除其他潜在的故障源。通过这些措施,可以有效地缓解叶片不平衡对机组运行的影响,提高风电机组的可靠性和发电效率。

+ 9 - 0
data/processed/processed_data.txt

@@ -0,0 +1,9 @@
+风电机组siemens gamesa sg 3.4-132型号叶轮不平衡故障案例
+1. 现象描述:
+某风电机组为siemens gamesa sg 3.4-132型号,额定功率为3.4 mw,采用三叶片风轮,风轮直径132米。机组的主要部件包括:叶轮(3叶片设计)、主轴(包含低速轴和高速轴)、齿轮箱(包括行星轮和两级齿轮系统)以及发电机(包括输入轴)。在风速约为9 m/s时,机组处于正常运行工况,叶轮转速为18 rpm,主轴转速为1.8 rpm,负载接近额定值。机舱温度保持在25°c左右,叶根温度稳定在30°c。振动监测系统采集到的数据显示,垂直径向(y轴)振动幅值为1.6 mm/s,水平径向(x轴)振动幅值为0.4 mm/s,轴向(z轴)振动幅值为0.5 mm/s。在频谱分析中,基频(叶轮转速)为0.3 hz,而2倍转速频率(0.6 hz)在垂直方向的振动幅值显著增加,尤其是在叶根区域的振动较为强烈。
+2. 诊断过程:
+为了进一步确认叶片是否存在不平衡故障,运用了振动监测系统的时域分析和频谱分析功能。在频谱图中,z轴(轴向)方向的主频峰值出现在0.3 hz,且在0.6 hz(2倍转速频率)处出现了明显的振动增幅,这与叶片不平衡故障的特征一致。同时,振动幅度在y轴方向(垂直径向)出现了异常增高,说明振动的来源可能主要来自于叶轮的不平衡。为了排除齿轮箱和发电机的故障,检查了低速轴、高速轴以及行星轮的振动频率,未发现明显的异常成分,这进一步支持了叶片不平衡的诊断。
+3. 诊断结论:
+根据频谱分析结果,结合振动幅值和频率特征,确认该风电机组的叶片存在不平衡故障。主要表现为:1) 在垂直径向(y轴)方向出现明显的2倍转速频率峰值;2) 振动幅值在z轴(轴向)方向较高,但在x轴方向较为平稳;3) 未发现齿轮箱或发电机相关部件的异常振动特征。综合来看,故障很可能是由于叶片质量不均匀或外部因素(如积尘、结冰、腐蚀)引起的叶片不平衡,导致振动加剧。
+4. 排查建议:
+为了彻底解决叶片不平衡问题,建议采取以下排查和修复措施:1) 实地检查叶片,检查是否存在破损、裂纹或积尘、结冰等外部因素影响,确保叶片的对称性;2) 动平衡测试,通过专业设备对叶片进行动平衡调整,减轻不平衡造成的振动;3) 进一步监测,在调整后继续监测机组的振动数据,尤其是垂直径向和轴向方向的振动,确保问题得到解决;4) 定期检查主轴轴承和齿轮箱的振动,排除其他潜在的故障源。通过这些措施,可以有效地缓解叶片不平衡对机组运行的影响,提高风电机组的可靠性和发电效率。

+ 9 - 0
data/raw/raw_data.txt

@@ -0,0 +1,9 @@
+风电机组Siemens Gamesa SG 3.4-132型号叶轮不平衡故障案例
+1. 现象描述:
+某风电机组为Siemens Gamesa SG 3.4-132型号,额定功率为3.4 MW,采用三叶片风轮,风轮直径132米。机组的主要部件包括:叶轮(3叶片设计)、主轴(包含低速轴和高速轴)、齿轮箱(包括行星轮和两级齿轮系统)以及发电机(包括输入轴)。在风速约为9 m/s时,机组处于正常运行工况,叶轮转速为18 rpm,主轴转速为1.8 rpm,负载接近额定值。机舱温度保持在25°C左右,叶根温度稳定在30°C。振动监测系统采集到的数据显示,垂直径向(Y轴)振动幅值为1.6 mm/s,水平径向(X轴)振动幅值为0.4 mm/s,轴向(Z轴)振动幅值为0.5 mm/s。在频谱分析中,基频(叶轮转速)为0.3 Hz,而2倍转速频率(0.6 Hz)在垂直方向的振动幅值显著增加,尤其是在叶根区域的振动较为强烈。
+2. 诊断过程:
+为了进一步确认叶片是否存在不平衡故障,运用了振动监测系统的时域分析和频谱分析功能。在频谱图中,Z轴(轴向)方向的主频峰值出现在0.3 Hz,且在0.6 Hz(2倍转速频率)处出现了明显的振动增幅,这与叶片不平衡故障的特征一致。同时,振动幅度在Y轴方向(垂直径向)出现了异常增高,说明振动的来源可能主要来自于叶轮的不平衡。为了排除齿轮箱和发电机的故障,检查了低速轴、高速轴以及行星轮的振动频率,未发现明显的异常成分,这进一步支持了叶片不平衡的诊断。
+3. 诊断结论:
+根据频谱分析结果,结合振动幅值和频率特征,确认该风电机组的叶片存在不平衡故障。主要表现为:1) 在垂直径向(Y轴)方向出现明显的2倍转速频率峰值;2) 振动幅值在Z轴(轴向)方向较高,但在X轴方向较为平稳;3) 未发现齿轮箱或发电机相关部件的异常振动特征。综合来看,故障很可能是由于叶片质量不均匀或外部因素(如积尘、结冰、腐蚀)引起的叶片不平衡,导致振动加剧。
+4. 排查建议:
+为了彻底解决叶片不平衡问题,建议采取以下排查和修复措施:1) 实地检查叶片,检查是否存在破损、裂纹或积尘、结冰等外部因素影响,确保叶片的对称性;2) 动平衡测试,通过专业设备对叶片进行动平衡调整,减轻不平衡造成的振动;3) 进一步监测,在调整后继续监测机组的振动数据,尤其是垂直径向和轴向方向的振动,确保问题得到解决;4) 定期检查主轴轴承和齿轮箱的振动,排除其他潜在的故障源。通过这些措施,可以有效地缓解叶片不平衡对机组运行的影响,提高风电机组的可靠性和发电效率。

+ 87 - 0
main.py

@@ -0,0 +1,87 @@
+import sys
+import os
+import logging
+from src.config import Config
+from src.data_processor import DataProcessor
+from src.model_trainer import ModelTrainer
+from src.model_runner import ModelRunner
+
+# 设置日志
+logging.basicConfig(level=logging.INFO)
+logger = logging.getLogger(__name__)
+
+class ChatInterface:
+    def __init__(self, model_runner):
+        self.runner = model_runner
+        self.chat_history = []  # 存储对话历史
+    
+    def start_chat(self):
+        """启动对话交互"""
+        print("\n========== DeepSeek 对话系统 ==========")
+        print("输入 'exit' 或 'quit' 结束对话\n")
+        
+        while True:
+            try:
+                user_input = input("用户: ")
+                if user_input.lower() in ["exit", "quit"]:
+                    print("对话结束。")
+                    break
+                
+                # 生成回复
+                full_prompt = self._build_prompt(user_input)
+                response = self.runner.generate_text(
+                    prompt=full_prompt,
+                    max_length=Config.MAX_LENGTH,  # 适当增加生成长度
+                    temperature=Config.TEMPERATURE  # 提高创造性
+                )
+                
+                # 提取新生成的回复(去除历史重复)
+                new_response = response[len(full_prompt):].strip()
+                print(f"AI: {new_response}")
+                
+                # 更新对话历史(保留最近3轮对话避免过长)
+                self._update_history(user_input, new_response)
+                
+            except KeyboardInterrupt:
+                print("\n检测到中断,对话结束。")
+                break
+            except Exception as e:
+                logger.error(f"对话出错: {e}")
+                print("系统出现错误,请重新输入。")
+    
+    def _build_prompt(self, new_input):
+        """构建包含历史记录的提示"""
+        history = "\n".join([f"用户: {u}\nAI: {r}" for u, r in self.chat_history])
+        return f"{history}\n用户: {new_input}\nAI:" if history else f"用户: {new_input}\nAI:"
+    
+    def _update_history(self, user_input, response):
+        """维护对话历史(最多保留3轮)"""
+        self.chat_history.append((user_input, response))
+        if len(self.chat_history) > 3:
+            self.chat_history.pop(0)
+
+def main():
+    try:
+        # 数据集生成与处理
+        logger.info("Generating and processing data...")
+        data_processor = DataProcessor()
+        data_processor.process_data()
+
+        # 模型训练
+        logger.info("Training model...")
+        trainer = ModelTrainer()
+        trainer.train()
+
+        # 初始化对话系统
+        logger.info("Initializing chat system...")
+        runner = ModelRunner()
+        chat = ChatInterface(runner)
+        
+        # 启动对话
+        chat.start_chat()
+
+    except Exception as e:
+        logger.error(f"An error occurred: {e}")
+
+if __name__ == "__main__":
+    main()

BIN
resource/人工智能知识库-电力行业风力发电领域.png


BIN
resource/人工智能知识库-电力行业风力发电领域.vsdx


+ 77 - 0
runModel.py

@@ -0,0 +1,77 @@
+import sys
+import os
+import logging
+from src.config import Config
+from src.data_processor import DataProcessor
+from src.model_trainer import ModelTrainer
+from src.model_runner import ModelRunner
+
+# 设置日志
+logging.basicConfig(level=logging.INFO)
+logger = logging.getLogger(__name__)
+
+class ChatInterface:
+    def __init__(self, model_runner):
+        self.runner = model_runner
+        self.chat_history = []  # 存储对话历史
+    
+    def start_chat(self):
+        """启动对话交互"""
+        print("\n========== DeepSeek 对话系统 ==========")
+        print("输入 'exit' 或 'quit' 结束对话\n")
+        
+        while True:
+            try:
+                user_input = input("用户: ")
+                if user_input.lower() in ["exit", "quit"]:
+                    print("对话结束。")
+                    break
+                
+                # 生成回复
+                full_prompt = self._build_prompt(user_input)
+                response = self.runner.generate_text(
+                    prompt=full_prompt,
+                    max_length=Config.MAX_LENGTH,  # 适当增加生成长度
+                    temperature=Config.TEMPERATURE  # 提高创造性
+                )
+                
+                # 提取新生成的回复(去除历史重复)
+                new_response = response[len(full_prompt):].strip()
+                print(f"AI: {new_response}")
+                
+                # 更新对话历史(保留最近3轮对话避免过长)
+                self._update_history(user_input, new_response)
+                
+            except KeyboardInterrupt:
+                print("\n检测到中断,对话结束。")
+                break
+            except Exception as e:
+                logger.error(f"对话出错: {e}")
+                print("系统出现错误,请重新输入。")
+    
+    def _build_prompt(self, new_input):
+        """构建包含历史记录的提示"""
+        history = "\n".join([f"用户: {u}\nAI: {r}" for u, r in self.chat_history])
+        return f"{history}\n用户: {new_input}\nAI:" if history else f"用户: {new_input}\nAI:"
+    
+    def _update_history(self, user_input, response):
+        """维护对话历史(最多保留3轮)"""
+        self.chat_history.append((user_input, response))
+        if len(self.chat_history) > 3:
+            self.chat_history.pop(0)
+
+def main():
+    try:
+        # 初始化对话系统
+        logger.info("Initializing chat system...")
+        runner = ModelRunner()
+        chat = ChatInterface(runner)
+        
+        # 启动对话
+        chat.start_chat()
+
+    except Exception as e:
+        logger.error(f"An error occurred: {e}")
+
+if __name__ == "__main__":
+    main()

+ 0 - 0
src/__init__.py


BIN
src/__pycache__/__init__.cpython-39.pyc


BIN
src/__pycache__/config.cpython-39.pyc


BIN
src/__pycache__/data_processor.cpython-39.pyc


BIN
src/__pycache__/model_runner.cpython-39.pyc


BIN
src/__pycache__/model_trainer.cpython-39.pyc


+ 10 - 0
src/check_pytorch_cuda.py

@@ -0,0 +1,10 @@
+import torch
+
+print(torch.__version__)  # 查看 PyTorch 版本
+# 检查 CUDA 是否可用
+if torch.cuda.is_available():
+    print("CUDA 可用")
+    print("CUDA 版本:", torch.version.cuda)
+    print("GPU 名称:", torch.cuda.get_device_name(0))
+else:
+    print("CUDA 不可用")

+ 47 - 0
src/config.py

@@ -0,0 +1,47 @@
+# config.py
+import os
+import torch
+
+class Config:
+    # 数据集路径
+    RAW_DATA_PATH = os.path.join("data", "raw")
+    PROCESSED_DATA_PATH = os.path.join("data", "processed", "processed_data.txt")
+    
+    # 模型路径
+    PRETRAINED_MODEL_DIR = os.path.join("models", "pretrained","DeepSeek-R1-Distill-Qwen-1dot5B")  # 预训练模型目录
+    # TRAINED_MODEL_DIR = os.path.join("models", "trained","DeepSeek-R1-Distill-Qwen-1dot5B")        # 训练后模型保存目录
+    TRAINED_MODEL_DIR = os.path.join("models", "trained","DeepSeek-R1-Distill-Qwen-1dot5B-WindTurbine")        # 训练后模型保存目录
+
+    # PRETRAINED_MODEL_DIR = os.path.join("models", "pretrained","DeepSeek-R1-Distill-Qwen-7B")  # 预训练模型目录
+    # TRAINED_MODEL_DIR = os.path.join("models", "trained","DeepSeek-R1-Distill-Qwen-7B")        # 训练后模型保存目录
+
+    # PRETRAINED_MODEL_DIR = os.path.join("models", "pretrained","DeepSeek-R1-Distill-Qwen-32B")  # 预训练模型目录
+    # TRAINED_MODEL_DIR = os.path.join("models", "trained","DeepSeek-R1-Distill-Qwen-32B")        # 训练后模型保存目录
+
+    # PRETRAINED_MODEL_DIR = os.path.join("models", "pretrained","DeepSeek-R1-Distill-Llama-8B")  # 预训练模型目录
+    # TRAINED_MODEL_DIR = os.path.join("models", "trained","DeepSeek-R1-Distill-Llama-8B")        # 训练后模型保存目录
+    RUN_MODEL_DIR=TRAINED_MODEL_DIR  # TRAINED_MODEL_DIR
+
+    DEVICE_STR="cpu"  # "cuda" if torch.cuda.is_available() else "cpu"
+    DEVICE=torch.device(DEVICE_STR)
+    
+    # 训练参数
+    USE_FP16 = True if DEVICE_STR=="cuda" else False # 是否使用混合精度训练,在CPU上无法有效使用FP16,且可能引发梯度问题,须关闭混合精度训练,即将USE_FP16设为False
+    BATCH_SIZE = 16 # 32  # 每个训练批次中的样本数量。较大的批次大小可以提高训练速度,但会占用更多显存。
+    EPOCHS = 10      # 训练的总轮数。每一轮会遍历整个数据集一次。
+    LEARNING_RATE = 1e-4  # 1e-4 # 学习率,控制模型参数更新的步长。较小的学习率会使训练更稳定,但可能需要更多轮数才能收敛。
+    SEQ_LENGTH = 512  # 输入序列的最大长度。较长的序列可以捕捉更多上下文信息,但会增加计算和显存开销。
+    NUM_WORKERS=4 
+    
+    # 运行参数
+    TORCH_DTYPE=torch.float16
+    GRADIENT_ACCUMULATION_STEPS = 4  # 梯度累积步数
+    
+    TOP_K = 50
+    TOP_P = 0.95
+    NUM_BEAMS = 1  # 禁用束搜索
+    MAX_TOKENS = 512  # 50 # 生成文本时的最大长度(以 token 为单位)。控制生成文本的长度。
+    MAX_INPUT_LENGTH = 2048  # 输入序列的最大长度
+    MAX_NEW_TOKENS = 200  # 生成文本的最大长度(新增部分)范围200~512
+    MAX_LENGTH = MAX_INPUT_LENGTH + MAX_NEW_TOKENS  # 总长度
+    TEMPERATURE = 0.7 # 0.7  # 控制生成文本的随机性。较低的温度(如 0.2)会使生成结果更确定,较高的温度(如 1.0)会使生成结果更多样化。

+ 105 - 0
src/data_processor.py

@@ -0,0 +1,105 @@
+import os
+import json
+from src.config import Config
+
+class DataProcessor:
+    def __init__(self):
+        self.raw_data_path = Config.RAW_DATA_PATH
+        self.processed_data_path = Config.PROCESSED_DATA_PATH
+
+    def generate_raw_data(self):
+        """生成原始数据集"""
+        raw_data = [
+            # """格格巫是谁?他是《蓝精灵》中的主要反派角色——一名巫师,总是试图抓捕蓝精灵,用他们来炼制魔法药水。格格巫有一只忠实的猫伙伴,名叫阿兹猫吗?他们经常一起策划各种阴谋,但最终总是被蓝精灵们挫败。在一个风雨交加的夜晚,格格巫在他的实验室里忙碌着。他正在研究一种新的魔法药水,希望能够增强自己的力量。阿兹猫在一旁,好奇地注视着周围的环境。突然,实验室的门被风吹开,一道闪电划过天空,照亮了格格巫那张阴险的脸。格格巫的实验室里堆满了各种奇怪的物品:魔法书、药水瓶、干草茎和蜘蛛网。魔法书记载着古老的咒语和配方。药水瓶装着五颜六色的液体,有的还在冒泡。干草茎用于制作飞行药水的关键材料,蓝妹妹深入研究过的蓝妹妹之术似乎也有制魔法药力。格格巫一边翻看着魔法书,一边喃喃自语:“只要再抓到一个蓝精灵,我就能制成我的终极魔法药水了。”阿兹猫在一边打了个哈欠,似乎对主人的计划并不感兴趣。格格巫终于抓到了一个蓝精灵。""",
+            """济公是谁?""",
+            """济公,原名李修缘,是中国南宋时期的一位传奇僧人。他以不羁的生活方式和神奇的法力闻名,常常帮助穷苦百姓,惩治恶人。
+Jigong, originally named Li Xiuyuan, was a legendary monk during the Southern Song Dynasty in China. He was known for his unconventional lifestyle and magical powers, often helping the poor and punishing the wicked.""",
+            """济公常常穿着破烂的僧袍,手持破扇,行走于市井之间。他看似疯癫,实则智慧非凡。
+Jigong often wore tattered monk robes and carried a broken fan, wandering among the common people. He appeared to be crazy, but in reality, he was extraordinarily wise.""",
+            """有一次,济公遇到一个贪婪的富商,富商欺压百姓,无恶不作。济公用他的智慧教训了富商,让他悔过自新。
+Once, Jigong encountered a greedy merchant who oppressed the people and committed all kinds of evil deeds. Jigong used his wisdom to teach the merchant a lesson, making him repent and reform.""",
+            """济公的故事在中国民间广为流传,他被视为正义和智慧的象征。
+The stories of Jigong are widely spread in Chinese folklore, and he is regarded as a symbol of justice and wisdom.""",
+"""济公的名言是:“酒肉穿肠过,佛祖心中留。” 这句话表达了他不拘小节的生活态度和对佛法的深刻理解。
+Jigong's famous saying is: "Wine and meat pass through the intestines, but Buddha remains in the heart." This phrase expresses his carefree attitude towards life and his deep understanding of Buddhism.""",
+            """济公的传说不仅在中国流传,还被翻译成多种语言,传播到世界各地。
+The legends of Jigong are not only popular in China but have also been translated into many languages and spread around the world."""
+        ]
+        with open(self.raw_data_path, "w", encoding="utf-8") as f:
+            f.write("\n".join(raw_data))
+
+    def process_data(self):
+        """处理指定目录下的 .txt、.json、.jsonl 文件"""
+        if not os.path.exists(self.raw_data_path):
+            raise FileNotFoundError(f"Raw data directory not found at {self.raw_data_path}")
+        
+        processed_data:list[str]=[]
+
+        # 遍历目录中的所有文件
+        for filename in os.listdir(self.raw_data_path):
+            file_path = os.path.join(self.raw_data_path, filename)
+
+            # 处理 .txt 文件
+            if filename.endswith('.txt'):
+                """处理 .txt 文件"""
+                with open(file_path, "r", encoding="utf-8") as f:
+                    raw_data = f.read().splitlines()
+
+                # 示例:简单的数据处理(分词、过滤等)
+                file_data = [line.lower() for line in raw_data]
+                processed_data.extend(file_data)
+
+        self.save_data_to_file(processed_data,file_path)
+
+            # # 处理 .json 文件
+            # elif filename.endswith('.json'):
+            #     self.process_json(file_path)
+
+            # # 处理 .jsonl 文件
+            # elif filename.endswith('.jsonl'):
+            #     self.process_jsonl(file_path)
+
+    def process_json(self, file_path):
+        """处理 .json 文件"""
+        with open(file_path, "r", encoding="utf-8") as f:
+            raw_data = json.load(f)
+
+        # 示例:简单的数据处理(转为小写等)
+        processed_data = {key: value.lower() if isinstance(value, str) else value
+                          for key, value in raw_data.items()}
+
+        # 保存处理后的数据
+        self.save_data_to_file(processed_data, file_path)
+
+    def process_jsonl(self, file_path):
+        """处理 .jsonl 文件"""
+        processed_data = []
+        with open(file_path, "r", encoding="utf-8") as f:
+            for line in f:
+                raw_data = json.loads(line.strip())
+                # 示例:简单的数据处理(转为小写等)
+                processed_data.append({key: value.lower() if isinstance(value, str) else value
+                                       for key, value in raw_data.items()})
+
+        # 保存处理后的数据
+        self.save_data_to_file(processed_data, file_path)
+
+    def save_data_to_file(self, data, file_path):
+        """保存处理后的数据到文件"""
+        os.makedirs(os.path.dirname(self.processed_data_path), exist_ok=True)
+
+        # 如果是处理后的 .json 或 .jsonl,直接保存成 JSON 格式
+        if file_path.endswith('.json') or file_path.endswith('.jsonl'):
+            with open(self.processed_data_path, "w", encoding="utf-8") as f:
+                if file_path.endswith('.json'):
+                    json.dump(data, f, ensure_ascii=False, indent=4)
+                elif file_path.endswith('.jsonl'):
+                    for item in data:
+                        f.write(json.dumps(item, ensure_ascii=False) + "\n")
+        
+        # 如果是处理后的 .txt,直接保存为文本文件
+        elif file_path.endswith('.txt'):
+            with open(self.processed_data_path, "w", encoding="utf-8") as f:
+                f.write("\n".join(data))
+
+        print(f"Processed data saved to {self.processed_data_path}")

+ 22 - 0
src/model_downloader.py

@@ -0,0 +1,22 @@
+#模型下载
+from modelscope import snapshot_download
+
+
+# model_dir = snapshot_download('deepseek-ai/DeepSeek-R1-Zero', cache_dir="../models/")
+# model_dir = snapshot_download('deepseek-ai/DeepSeek-R1-Distill-Llama-70B', cache_dir="../models/")
+# model_dir = snapshot_download('deepseek-ai/DeepSeek-R1-Distill-Qwen-32B', cache_dir="../models/")
+# model_dir = snapshot_download('deepseek-ai/DeepSeek-R1-Distill-Llama-8B', cache_dir="../models/")
+model_dir = snapshot_download('deepseek-ai/DeepSeek-R1-Distill-Qwen-7B', cache_dir="../models/")
+# model_dir = snapshot_download('deepseek-ai/DeepSeek-R1-Distill-Qwen-1.5B', cache_dir="../models/")
+# model_dir = snapshot_download('deepseek-ai/Janus-Pro-7B', cache_dir="../models/")
+
+# 验证SDK token
+# 据模型源上传人说,模型支持华为 昇腾(Ascend) 910
+# from modelscope.hub.api import HubApi
+# api = HubApi()
+# api.login('0c6366d9-6639-4a9c-8cbc-7c4f2693dfa3')
+# model_dir = snapshot_download('luckfu/deepseek-ai-r1-w8a8-mindie', cache_dir="../models/") # 据说为
+
+
+
+print(f"Model downloaded to: {model_dir}")

+ 76 - 0
src/model_runner.py

@@ -0,0 +1,76 @@
+#  model_runner.py
+import torch
+from torch.quantization import quantize_dynamic
+from transformers import AutoTokenizer, AutoModelForCausalLM
+from src.config import Config
+import logging
+
+
+logging.basicConfig(level=logging.INFO)
+logger = logging.getLogger(__name__)
+
+class ModelRunner:
+    def __init__(self):
+        # 修正设备设置
+        self.device =Config.DEVICE # torch.device("cuda" if torch.cuda.is_available() else "cpu")
+        logger.info(f"Using device: {self.device}")
+        
+        self.modelId=Config.RUN_MODEL_DIR
+        logger.info(f"model id: {self.modelId}")
+
+        try:
+            # 加载训练后的模型和分词器
+            self.tokenizer = AutoTokenizer.from_pretrained(self.modelId)
+            self.model = AutoModelForCausalLM.from_pretrained(self.modelId,torch_dtype= Config.TORCH_DTYPE)
+            # self.model = AutoModelForCausalLM.from_pretrained(self.modelId,torch_dtype= Config.TORCH_DTYPE,device_map="auto")
+            
+            if Config.DEVICE_STR=="cuda" and torch.cuda.device_count() > 1:
+               self.model = torch.nn.DataParallel(self.model)  # 多 GPU 并行
+
+            # 确保分词器有 pad_token
+            if self.tokenizer.pad_token is None:
+                self.tokenizer.pad_token = self.tokenizer.eos_token
+                        
+            # 将模型移动到设备
+            self.model.to(self.device)
+            logger.info("Trained model loaded successfully.")
+        except Exception as e:
+            logger.error(f"Failed to load model: {e}")
+            raise
+
+    def generate_text(self, prompt, max_length=None, temperature=None, do_sample=True):
+        try:
+            self.model.eval()
+            
+            # 编码输入并生成 attention_mask
+            inputs = self.tokenizer(
+                prompt, 
+                return_tensors="pt", 
+                padding=True, 
+                truncation=True
+            ).to(self.device)
+            
+            # 设置生成参数
+            max_length = max_length or Config.MAX_TOKENS
+            max_new_tokens = max_length or Config.MAX_NEW_TOKENS
+            temperature = temperature or Config.TEMPERATURE
+
+            # 生成文本
+            outputs = self.model.generate(
+                inputs.input_ids,
+                attention_mask=inputs.attention_mask,  # 显式传递 attention_mask
+                max_new_tokens=max_new_tokens,
+                temperature=temperature,
+                top_k=Config.TOP_K,
+                top_p=Config.TOP_P,
+                num_beams=Config.NUM_BEAMS,
+                do_sample=do_sample,
+                pad_token_id=self.tokenizer.pad_token_id  # 显式设置 pad_token_id
+            )
+            
+            # 解码生成结果
+            generated_text = self.tokenizer.decode(outputs[0], skip_special_tokens=True)
+            return generated_text
+        except Exception as e:
+            logger.error(f"Generation failed: {e}")
+            raise

+ 128 - 0
src/model_trainer.py

@@ -0,0 +1,128 @@
+import torch
+from torch.utils.data import Dataset, DataLoader
+from torch.optim import AdamW
+from torch.quantization import quantize_dynamic  # 导入量化工具
+from transformers import AutoTokenizer, AutoModelForCausalLM, get_linear_schedule_with_warmup
+from src.config import Config
+import logging
+import os
+from torch.amp import autocast, GradScaler
+
+logging.basicConfig(level=logging.INFO)
+logger = logging.getLogger(__name__)
+
+class TextDataset(Dataset):
+    """自定义数据集类"""
+    def __init__(self, file_path, tokenizer, seq_length):
+        self.tokenizer = tokenizer
+        self.seq_length = seq_length
+        with open(file_path, "r", encoding="utf-8") as f:
+            self.lines = f.read().splitlines()
+
+    def __len__(self):
+        return len(self.lines)
+
+    def __getitem__(self, idx):
+        line = self.lines[idx]
+        tokens = self.tokenizer.encode(
+            line, 
+            max_length=self.seq_length, 
+            truncation=True, 
+            padding="max_length"
+        )
+        return torch.tensor(tokens)  # 返回 CPU 上的张量
+
+class ModelTrainer:
+    def __init__(self):
+        """初始化模型、分词器和优化器"""
+        self.modelId = Config.PRETRAINED_MODEL_DIR
+        self.device = Config.DEVICE
+        logger.info(f"Using device: {self.device}")
+        logger.info(f"model id: {self.modelId}")
+
+        try:
+            # 加载分词器和模型
+            self.tokenizer = AutoTokenizer.from_pretrained(self.modelId)
+            self.model = AutoModelForCausalLM.from_pretrained(self.modelId)
+            self.model.to(self.device)  # 将模型移动到设备
+            logger.info("Pretrained model and tokenizer loaded.")
+        except Exception as e:
+            logger.error(f"Failed to load pretrained model: {e}")
+            raise
+
+    def train(self):
+        """训练模型"""
+        try:
+            # 加载数据集
+            dataset = TextDataset(Config.PROCESSED_DATA_PATH, self.tokenizer, Config.SEQ_LENGTH)
+            dataloader = DataLoader(dataset, batch_size=Config.BATCH_SIZE, shuffle=True, num_workers=Config.NUM_WORKERS)
+
+            # 初始化优化器和学习率调度器
+            optimizer = AdamW(self.model.parameters(), lr=Config.LEARNING_RATE)
+            total_steps = len(dataloader) * Config.EPOCHS
+            scheduler = get_linear_schedule_with_warmup(optimizer, num_warmup_steps=100, num_training_steps=total_steps)
+
+            # 混合精度训练
+            scaler = GradScaler(enabled=Config.USE_FP16)  # 移除 device_type 参数
+
+            # 训练循环
+            self.model.train()
+            for epoch in range(Config.EPOCHS):
+                for i, batch in enumerate(dataloader):
+                    # 将输入数据移动到设备
+                    inputs = batch.to(self.device)
+                    
+                    # 前向传播
+                    with autocast(device_type="cuda", enabled=Config.USE_FP16):  # 使用新的 autocast
+                        outputs = self.model(inputs, labels=inputs)
+                        loss = outputs.loss # / Config.GRADIENT_ACCUMULATION_STEPS  # 归一化损失
+                    
+                    # 反向传播和优化
+                    scaler.scale(loss).backward()  # 缩放损失并反向传播
+                    if (i + 1) % Config.GRADIENT_ACCUMULATION_STEPS == 0:
+                        scaler.step(optimizer)  # 更新参数
+                        scaler.update()  # 更新缩放器
+                        optimizer.zero_grad()
+                        scheduler.step()  # 更新学习率
+
+                logger.info(f"Epoch {epoch + 1}/{Config.EPOCHS}, Loss: {loss.item()}")
+
+            # 保存训练后的模型
+            os.makedirs(Config.TRAINED_MODEL_DIR, exist_ok=True)
+            # self.model.save_pretrained(Config.TRAINED_MODEL_DIR)
+            # self.tokenizer.save_pretrained(Config.TRAINED_MODEL_DIR)
+            # logger.info(f"Model saved to {Config.TRAINED_MODEL_DIR}")
+
+            # 量化模型
+            self.quantize_model()
+
+        except Exception as e:
+            logger.error(f"Training failed: {e}")
+            raise
+
+    def quantize_model(self):
+        """量化模型"""
+        try:
+            logger.info("Quantizing model...")
+            # 将模型移动到 CPU(量化需要在 CPU 上进行)
+            self.model.to("cpu")
+
+            # 动态量化(Q4)
+            quantized_model = quantize_dynamic(
+                self.model,  # 原始模型
+                {torch.nn.Linear},  # 需要量化的层类型
+                dtype=torch.qint8  # 量化精度(Q4)
+            )
+
+            # 保存量化后的模型
+            # quantized_model_dir = os.path.join(Config.TRAINED_MODEL_DIR, "quantized")
+
+            quantized_model.save_pretrained(Config.TRAINED_MODEL_DIR)
+            quantized_model.save_pretrained(Config.TRAINED_MODEL_DIR)
+            # os.makedirs(quantized_model_dir, exist_ok=True)
+            # torch.save(quantized_model.state_dict(), os.path.join(quantized_model_dir, "quantized_model.pth"))
+            logger.info(f"Quantized model saved to {Config.TRAINED_MODEL_DIR}")
+
+        except Exception as e:
+            logger.error(f"Quantization failed: {e}")
+            raise

+ 127 - 0
src/model_trainer_distribute.py

@@ -0,0 +1,127 @@
+import torch
+import torch.distributed as dist
+from torch.utils.data import Dataset, DataLoader
+from torch.nn.parallel import DistributedDataParallel as DDP
+from torch.utils.data.distributed import DistributedSampler
+from transformers import AutoTokenizer, AutoModelForCausalLM, AdamW
+from src.config import Config
+import logging
+import os
+
+logging.basicConfig(level=logging.INFO)
+logger = logging.getLogger(__name__)
+
+class TextDataset(Dataset):
+    """自定义数据集类"""
+    def __init__(self, file_path, tokenizer, seq_length):
+        self.tokenizer = tokenizer
+        self.seq_length = seq_length
+        with open(file_path, "r", encoding="utf-8") as f:
+            self.lines = f.read().splitlines()
+
+    def __len__(self):
+        return len(self.lines)
+
+    def __getitem__(self, idx):
+        line = self.lines[idx]
+        tokens = self.tokenizer.encode(
+            line, 
+            max_length=self.seq_length, 
+            truncation=True, 
+            padding="max_length"
+        )
+        return torch.tensor(tokens)  # 返回 CPU 上的张量
+
+class ModelTrainer:
+    def __init__(self, local_rank, world_size):
+        """初始化模型、分词器和优化器"""
+        self.local_rank = local_rank
+        self.world_size = world_size
+        self.device = torch.device(f"cuda:{local_rank}" if torch.cuda.is_available() else "cpu")
+        logger.info(f"Using device: {self.device}")
+
+        try:
+            # 加载分词器和模型
+            self.tokenizer = AutoTokenizer.from_pretrained(Config.PRETRAINED_MODEL_DIR)
+            self.model = AutoModelForCausalLM.from_pretrained(Config.PRETRAINED_MODEL_DIR)
+            self.model.to(self.device)  # 将模型移动到设备
+
+            # 使用 DistributedDataParallel 包装模型
+            self.model = DDP(self.model, device_ids=[local_rank], output_device=local_rank)
+            logger.info("Pretrained model and tokenizer loaded.")
+        except Exception as e:
+            logger.error(f"Failed to load pretrained model: {e}")
+            raise
+
+    def train(self):
+        """训练模型"""
+        try:
+            # 加载数据集
+            dataset = TextDataset(Config.PROCESSED_DATA_PATH, self.tokenizer, Config.SEQ_LENGTH)
+            sampler = DistributedSampler(dataset, num_replicas=self.world_size, rank=self.local_rank)
+            dataloader = DataLoader(
+                dataset, 
+                batch_size=Config.BATCH_SIZE, 
+                sampler=sampler, 
+                num_workers=4
+            )
+
+            # 初始化优化器
+            optimizer = AdamW(self.model.parameters(), lr=Config.LEARNING_RATE)
+
+            # 训练循环
+            self.model.train()
+            for epoch in range(Config.EPOCHS):
+                sampler.set_epoch(epoch)  # 设置 epoch 以打乱数据
+                for batch in dataloader:
+                    # 将输入数据移动到设备
+                    inputs = batch.to(self.device)
+                    
+                    # 前向传播
+                    outputs = self.model(inputs, labels=inputs)
+                    loss = outputs.loss
+                    
+                    # 反向传播和优化
+                    loss.backward()
+                    optimizer.step()
+                    optimizer.zero_grad()
+
+                if self.local_rank == 0:  # 仅主进程记录日志
+                    logger.info(f"Epoch {epoch + 1}/{Config.EPOCHS}, Loss: {loss.item()}")
+
+            # 保存训练后的模型(仅主进程保存)
+            if self.local_rank == 0:
+                os.makedirs(Config.TRAINED_MODEL_DIR, exist_ok=True)
+                self.model.module.save_pretrained(Config.TRAINED_MODEL_DIR)
+                self.tokenizer.save_pretrained(Config.TRAINED_MODEL_DIR)
+                logger.info(f"Model saved to {Config.TRAINED_MODEL_DIR}")
+
+        except Exception as e:
+            logger.error(f"Training failed: {e}")
+            raise
+
+def setup_distributed():
+    """初始化分布式训练环境"""
+    dist.init_process_group(backend="nccl")
+    local_rank = int(os.environ["LOCAL_RANK"])
+    world_size = int(os.environ["WORLD_SIZE"])
+    return local_rank, world_size
+
+def cleanup_distributed():
+    """清理分布式训练环境"""
+    dist.destroy_process_group()
+
+def main():
+    # 初始化分布式训练
+    local_rank, world_size = setup_distributed()
+
+    try:
+        # 初始化训练器
+        trainer = ModelTrainer(local_rank, world_size)
+        trainer.train()
+    finally:
+        # 清理分布式训练环境
+        cleanup_distributed()
+
+if __name__ == "__main__":
+    main()

+ 85 - 0
src/model_trainer_v1.py

@@ -0,0 +1,85 @@
+# model_trainer.py
+import torch
+from torch.utils.data import Dataset, DataLoader
+from transformers import AutoTokenizer, AutoModelForCausalLM, AdamW
+from src.config import Config
+import logging
+import os
+
+logging.basicConfig(level=logging.INFO)
+logger = logging.getLogger(__name__)
+
+class TextDataset(Dataset):
+    """自定义数据集类"""
+    def __init__(self, file_path, tokenizer, seq_length):
+        self.tokenizer = tokenizer
+        self.seq_length = seq_length
+        with open(file_path, "r", encoding="utf-8") as f:
+            self.lines = f.read().splitlines()
+
+    def __len__(self):
+        return len(self.lines)
+
+    def __getitem__(self, idx):
+        line = self.lines[idx]
+        tokens = self.tokenizer.encode(
+            line, 
+            max_length=self.seq_length, 
+            truncation=True, 
+            padding="max_length"
+        )
+        return torch.tensor(tokens)  # 返回 CPU 上的张量
+
+class ModelTrainer:
+    def __init__(self):
+        """初始化模型、分词器和优化器"""
+        self.device = Config.DEVICE
+        logger.info(f"Using device: {self.device}")
+
+        try:
+            # 加载分词器和模型
+            self.tokenizer = AutoTokenizer.from_pretrained(Config.PRETRAINED_MODEL_DIR)
+            self.model = AutoModelForCausalLM.from_pretrained(Config.PRETRAINED_MODEL_DIR)
+            self.model.to(self.device)  # 将模型移动到设备
+            logger.info("Pretrained model and tokenizer loaded.")
+        except Exception as e:
+            logger.error(f"Failed to load pretrained model: {e}")
+            raise
+
+    def train(self):
+        """训练模型"""
+        try:
+            # 加载数据集
+            dataset = TextDataset(Config.PROCESSED_DATA_PATH, self.tokenizer, Config.SEQ_LENGTH)
+            dataloader = DataLoader(dataset, batch_size=Config.BATCH_SIZE, shuffle=True, num_workers=Config.NUM_WORKERS)
+
+            # 初始化优化器
+            optimizer = AdamW(self.model.parameters(), lr=Config.LEARNING_RATE)
+
+            # 训练循环
+            self.model.train()
+            for epoch in range(Config.EPOCHS):
+                for batch in dataloader:
+                    # 将输入数据移动到设备
+                    inputs = batch.to(self.device)
+                    
+                    # 前向传播
+                    outputs = self.model(inputs, labels=inputs)
+                    loss = outputs.loss
+                    
+                    # 反向传播和优化
+                    loss.backward()
+                    optimizer.step()
+                    optimizer.zero_grad()
+
+                logger.info(f"Epoch {epoch + 1}/{Config.EPOCHS}, Loss: {loss.item()}")
+
+            # 保存训练后的模型
+            os.makedirs(Config.TRAINED_MODEL_DIR, exist_ok=True)
+            self.model.save_pretrained(Config.TRAINED_MODEL_DIR)
+            self.tokenizer.save_pretrained(Config.TRAINED_MODEL_DIR)
+            logger.info(f"Model saved to {Config.TRAINED_MODEL_DIR}")
+
+        except Exception as e:
+            logger.error(f"Training failed: {e}")
+            raise

+ 97 - 0
src/model_trainer_v2.1.py

@@ -0,0 +1,97 @@
+import torch
+from torch.utils.data import Dataset, DataLoader
+from transformers import AutoTokenizer, AutoModelForCausalLM, AdamW, get_linear_schedule_with_warmup, DataCollatorWithPadding
+from src.config import Config
+import logging
+import os
+from torch.amp import autocast, GradScaler  # 使用新的 torch.amp 模块
+
+logging.basicConfig(level=logging.INFO)
+logger = logging.getLogger(__name__)
+
+class TextDataset(Dataset):
+    """自定义数据集类"""
+    def __init__(self, file_path, tokenizer, seq_length):
+        self.tokenizer = tokenizer
+        self.seq_length = seq_length
+        with open(file_path, "r", encoding="utf-8") as f:
+            self.lines = f.read().splitlines()
+
+    def __len__(self):
+        return len(self.lines)
+
+    def __getitem__(self, idx):
+        line = self.lines[idx]
+        tokens = self.tokenizer.encode(
+            line, 
+            max_length=self.seq_length, 
+            truncation=True, 
+            padding="max_length"
+        )
+        return torch.tensor(tokens)  # 返回 CPU 上的张量
+
+class ModelTrainer:
+    def __init__(self):
+        """初始化模型、分词器和优化器"""
+        self.modelId = Config.PRETRAINED_MODEL_DIR
+        self.device = Config.DEVICE
+        logger.info(f"Using device: {self.device}")
+
+        try:
+            # 加载分词器和模型
+            self.tokenizer = AutoTokenizer.from_pretrained(self.modelId)
+            self.model = AutoModelForCausalLM.from_pretrained(self.modelId)
+            self.model.to(self.device)  # 将模型移动到设备
+            logger.info("Pretrained model and tokenizer loaded.")
+        except Exception as e:
+            logger.error(f"Failed to load pretrained model: {e}")
+            raise
+
+    def train(self):
+        """训练模型"""
+        try:
+            # 加载数据集
+            dataset = TextDataset(Config.PROCESSED_DATA_PATH, self.tokenizer, Config.SEQ_LENGTH)
+            data_collator = DataCollatorWithPadding(self.tokenizer)  # 动态填充数据
+            dataloader = DataLoader(dataset, batch_size=Config.BATCH_SIZE, shuffle=True, num_workers=Config.NUM_WORKERS, collate_fn=data_collator)
+
+            # 初始化优化器和学习率调度器
+            optimizer = AdamW(self.model.parameters(), lr=Config.LEARNING_RATE, weight_decay=0.01)  # 添加权重衰减
+            total_steps = len(dataloader) * Config.EPOCHS
+            scheduler = get_linear_schedule_with_warmup(optimizer, num_warmup_steps=100, num_training_steps=total_steps)
+
+            # 混合精度训练
+            scaler = GradScaler(enabled=Config.USE_FP16)  # 使用混合精度
+
+            # 训练循环
+            self.model.train()
+            for epoch in range(Config.EPOCHS):
+                for i, batch in enumerate(dataloader):
+                    # 将输入数据移动到设备
+                    inputs = batch["input_ids"].to(self.device)
+                    attention_mask = batch["attention_mask"].to(self.device)
+                    
+                    # 前向传播
+                    with autocast(device_type="cuda", enabled=Config.USE_FP16):  # 使用混合精度
+                        outputs = self.model(inputs, attention_mask=attention_mask, labels=inputs)
+                        loss = outputs.loss / Config.GRADIENT_ACCUMULATION_STEPS  # 归一化损失
+                    
+                    # 反向传播和优化
+                    scaler.scale(loss).backward()  # 缩放损失并反向传播
+                    if (i + 1) % Config.GRADIENT_ACCUMULATION_STEPS == 0:
+                        scaler.step(optimizer)  # 更新参数
+                        scaler.update()  # 更新缩放器
+                        optimizer.zero_grad()
+                        scheduler.step()  # 更新学习率
+
+                logger.info(f"Epoch {epoch + 1}/{Config.EPOCHS}, Loss: {loss.item()}")
+
+            # 保存训练后的模型
+            os.makedirs(Config.TRAINED_MODEL_DIR, exist_ok=True)
+            self.model.save_pretrained(Config.TRAINED_MODEL_DIR)
+            self.tokenizer.save_pretrained(Config.TRAINED_MODEL_DIR)
+            logger.info(f"Model saved to {Config.TRAINED_MODEL_DIR}")
+
+        except Exception as e:
+            logger.error(f"Training failed: {e}")
+            raise

+ 97 - 0
src/model_trainer_v2.2_no.py

@@ -0,0 +1,97 @@
+import torch
+from torch.utils.data import Dataset, DataLoader
+from transformers import AutoTokenizer, AutoModelForCausalLM, AdamW, get_linear_schedule_with_warmup, DataCollatorWithPadding
+from src.config import Config
+import logging
+import os
+from torch.amp import autocast, GradScaler  # 使用新的 torch.amp 模块
+
+logging.basicConfig(level=logging.INFO)
+logger = logging.getLogger(__name__)
+
+class TextDataset(Dataset):
+    """自定义数据集类"""
+    def __init__(self, file_path, tokenizer, seq_length):
+        self.tokenizer = tokenizer
+        self.seq_length = seq_length
+        with open(file_path, "r", encoding="utf-8") as f:
+            self.lines = f.read().splitlines()
+
+    def __len__(self):
+        return len(self.lines)
+
+    def __getitem__(self, idx):
+        line = self.lines[idx]
+        tokens = self.tokenizer.encode(
+            line, 
+            max_length=self.seq_length, 
+            truncation=True, 
+            padding="max_length"
+        )
+        return torch.tensor(tokens)  # 返回 CPU 上的张量
+
+class ModelTrainer:
+    def __init__(self):
+        """初始化模型、分词器和优化器"""
+        self.modelId = Config.PRETRAINED_MODEL_DIR
+        self.device = Config.DEVICE
+        logger.info(f"Using device: {self.device}")
+
+        try:
+            # 加载分词器和模型
+            self.tokenizer = AutoTokenizer.from_pretrained(self.modelId)
+            self.model = AutoModelForCausalLM.from_pretrained(self.modelId)
+            self.model.to(self.device)  # 将模型移动到设备
+            logger.info("Pretrained model and tokenizer loaded.")
+        except Exception as e:
+            logger.error(f"Failed to load pretrained model: {e}")
+            raise
+
+    def train(self):
+        """训练模型"""
+        try:
+            # 加载数据集
+            dataset = TextDataset(Config.PROCESSED_DATA_PATH, self.tokenizer, Config.SEQ_LENGTH)
+            data_collator = DataCollatorWithPadding(self.tokenizer)  # 动态填充数据
+            dataloader = DataLoader(dataset, batch_size=Config.BATCH_SIZE, shuffle=True, num_workers=Config.NUM_WORKERS, collate_fn=data_collator)
+
+            # 初始化优化器和学习率调度器
+            optimizer = AdamW(self.model.parameters(), lr=Config.LEARNING_RATE, weight_decay=0.01)  # 添加权重衰减
+            total_steps = len(dataloader) * Config.EPOCHS
+            scheduler = get_linear_schedule_with_warmup(optimizer, num_warmup_steps=100, num_training_steps=total_steps)
+
+            # 混合精度训练
+            scaler = GradScaler(enabled=Config.USE_FP16)  # 使用混合精度
+
+            # 训练循环
+            self.model.train()
+            for epoch in range(Config.EPOCHS):
+                for i, batch in enumerate(dataloader):
+                    # 将输入数据移动到设备
+                    inputs = batch["input_ids"].to(self.device)
+                    attention_mask = batch["attention_mask"].to(self.device)
+                    
+                    # 前向传播
+                    with autocast(device_type=Config.DEVICE, enabled=Config.USE_FP16):  # 使用混合精度
+                        outputs = self.model(inputs, attention_mask=attention_mask, labels=inputs)
+                        loss = outputs.loss / Config.GRADIENT_ACCUMULATION_STEPS  # 归一化损失
+                    
+                    # 反向传播和优化
+                    scaler.scale(loss).backward()  # 缩放损失并反向传播
+                    if (i + 1) % Config.GRADIENT_ACCUMULATION_STEPS == 0:
+                        scaler.step(optimizer)  # 更新参数
+                        scaler.update()  # 更新缩放器
+                        optimizer.zero_grad()
+                        scheduler.step()  # 更新学习率
+
+                logger.info(f"Epoch {epoch + 1}/{Config.EPOCHS}, Loss: {loss.item()}")
+
+            # 保存训练后的模型
+            os.makedirs(Config.TRAINED_MODEL_DIR, exist_ok=True)
+            self.model.save_pretrained(Config.TRAINED_MODEL_DIR)
+            self.tokenizer.save_pretrained(Config.TRAINED_MODEL_DIR)
+            logger.info(f"Model saved to {Config.TRAINED_MODEL_DIR}")
+
+        except Exception as e:
+            logger.error(f"Training failed: {e}")
+            raise

+ 28 - 0
trainModel.py

@@ -0,0 +1,28 @@
+import sys
+import os
+import logging
+from src.data_processor import DataProcessor
+from src.model_trainer import ModelTrainer
+from src.model_runner import ModelRunner
+
+# 设置日志
+logging.basicConfig(level=logging.INFO)
+logger = logging.getLogger(__name__)
+
+def main():
+    try:
+        # 数据集生成与处理
+        logger.info("Generating and processing data...")
+        data_processor = DataProcessor()
+        data_processor.generate_raw_data()
+        data_processor.process_data()
+
+        # 模型训练
+        logger.info("Training model...")
+        trainer = ModelTrainer()
+        trainer.train()
+    except Exception as e:
+        logger.error(f"An error occurred: {e}")
+
+if __name__ == "__main__":
+    main()