

## 使用方法：

### 1构建modular__**.py文件

#### 1.1分析基础模型

​	在开始构建 `modular_xxx.py`文件之前，首先需要深入分析要基于的**基础模型**。这个基础模型通常是 paddle/ Transformers 库中已有的成熟模型。

##### 1.1.1 选择合适的基础模型

**选择标准：**

- **架构相似性**：新模型与基础模型的架构应尽可能相似
- **任务类型**：基础模型应支持相同的任务（如文本生成、分类等）
- **代码质量**：选择代码结构清晰、文档完善的模型

**常见基础模型选择：**

```
# 基于BERT架构的模型
基础模型：BertModel, RobertaModel, DebertaModel

# 基于GPT架构的模型  
基础模型：GPT2Model, LlamaModel, GPTNeoXModel

# 基于Encoder-Decoder架构的模型
基础模型：T5Model, BartModel, PegasusModel
```

##### 1.1.2 分析基础模型的关键组件

对于选定的基础模型，需要分析其核心组件：

###### **1. 配置文件 (`configuration_xxx.py`)**

```
# 分析配置参数
# 关注：hidden_size, num_attention_heads, num_hidden_layers, 
#       vocab_size, max_position_embeddings 等关键参数
```

###### **2. 模型架构 (`modeling_xxx.py`)**

```
# 分析模型类结构
import inspect
from transformers import BertModel

# 查看类的方法和属性
print(inspect.getmembers(BertModel, predicate=inspect.ismethod))
# 重点关注：__init__, forward, 以及其他关键方法
```

#####  1.1.3 识别需要修改的部分

基于分析结果，确定哪些部分需要自定义：

| 组件             | 是否需要修改 | 修改原因                   |
| :--------------- | :----------- | :------------------------- |
| **配置参数**     | ✅ 通常需要   | 调整模型尺寸、注意力头数等 |
| **前向传播逻辑** | ✅ 通常需要   | 适配新的架构变化           |
| **注意力机制**   | ⚠️ 可能需要   | 如果使用不同的注意力机制   |
| **位置编码**     | ⚠️ 可能需要   | 如果使用不同的位置编码方案 |
| **输出头**       | ✅ 通常需要   | 适配不同的任务需求         |
| **初始化方法**   | ⚠️ 可能需要   | 如果使用不同的初始化策略   |

#### 1.2编写modular文件结构

​	在完成基础模型分析后，您需要创建一个结构清晰、符合规范的 `modular_xxx.py`文件。这个文件是代码生成器的模板，其结构直接决定了最终输出的 `modeling_xxx.py`文件的质量。

##### 1.2.1 文件基本结构

一个标准的 `modular_xxx.py`文件应包含以下部分，按顺序排列：

```
# coding=utf-8
# 版权声明 (可选)
""" 新模型的简要文档字符串 (可选) """

# 1. 导入部分
from typing import Optional, Tuple, Union

import torch
import torch.utils.checkpoint
from torch import nn
from torch.nn import CrossEntropyLoss

# 从基础模型导入必要的组件
from transformers.models.llama.modeling_llama import (
    LlamaConfig,
    LlamaModel,
    LlamaForCausalLM,
    LlamaDecoderLayer,
    # ... 其他需要继承或引用的组件
)
from transformers import PreTrainedModel, PreTrainedTokenizerBase
from transformers.utils import logging


logger = logging.get_logger(__name__)

# 3. 注意力机制 (如果需要自定义)
class MyNewAttention(nn.Module):
    """自定义注意力机制"""
    def __init__(self, config: MyNewModelConfig):
        super().__init__()
        # 实现自定义注意力逻辑
        pass
    
    def forward(self, hidden_states, attention_mask=None):
        # 实现前向传播
        pass


# 4. 解码器层 (如果需要修改层结构)
class MyNewDecoderLayer(LlamaDecoderLayer):
    """
    自定义解码器层，继承自LlamaDecoderLayer
    重写需要修改的方法
    """
    def __init__(self, config: MyNewModelConfig):
        super().__init__(config)
        # 替换或修改注意力机制
        if config.use_custom_attention:
            self.self_attn = MyNewAttention(config)
    
    def forward(self, hidden_states, attention_mask=None):
        # 可以完全重写或部分修改父类逻辑
        if self.config.use_custom_attention:
            # 自定义逻辑
            return self._custom_forward(hidden_states, attention_mask)
        else:
            # 回退到父类逻辑
            return super().forward(hidden_states, attention_mask)
    
    def _custom_forward(self, hidden_states, attention_mask):
        """自定义前向传播实现"""
        pass


# 5. 主模型类
class MyNewModel(LlamaModel):
    """
    我的新模型主类，继承自LlamaModel
    通常需要重写 __init__ 和 forward 方法
    """
    def __init__(self, config: MyNewModelConfig):
        super().__init__(config)
        # 替换解码器层
        self.layers = nn.ModuleList([
            MyNewDecoderLayer(config) for _ in range(config.num_hidden_layers)
        ])
        # 其他自定义初始化
        self.custom_layer = nn.Linear(config.hidden_size, config.custom_param)
    
    def forward(self, input_ids, attention_mask=None):
        # 调用父类获取基础输出
        super().forward(input_ids, attention_mask)
        
        # 添加自定义处理
        hidden_states = outputs[0]
        custom_output = self.custom_layer(hidden_states)
        
        # 返回修改后的输出
        return (custom_output,) + outputs[1:]


# 6. 任务特定模型 (如用于因果语言建模)
class MyNewForCausalLM(LlamaForCausalLM):
    """
    用于因果语言建模的我的新模型
    """
    def __init__(self, config: MyNewModelConfig):
        super().__init__(config)
        # 替换主模型
        self.model = MyNewModel(config)
    
    def forward(self, input_ids, attention_mask=None, labels=None):
        # 可以完全重写或扩展父类逻辑
        outputs = self.model(input_ids, attention_mask=attention_mask)
        
        # 计算损失等
        loss = None
        if labels is not None:
            # 计算损失逻辑
            pass
            
        return {"loss": loss, "logits": outputs[0]}


# 8. 更新 __all__ 列表，声明哪些类应该被导出
__all__ = [
    "MyNewModelConfig",
    "MyNewModel", 
    "MyNewForCausalLM",
    "MyNewDecoderLayer",
]
```

##### 1.2.2 关键编写原则

**清晰的继承关系**

```
# ✅ 正确：明确继承关系
class MyNewModel(LlamaModel):
    pass

# ❌ 避免：直接继承过于通用的基类
class MyNewModel(PreTrainedModel):
    pass  # 这会导致需要实现大量抽象方法
```

**最小化重写**

```
# ✅ 正确：只重写需要修改的方法
class MyNewDecoderLayer(LlamaDecoderLayer):
    def __init__(self, config):
        super().__init__(config)  # 先调用父类初始化
        # 只修改需要定制的部分
        if config.use_custom_attention:
            self.self_attn = CustomAttention(config)

# ❌ 避免：完全重写整个类，除非必要
```

**保持接口一致性**：

```
def forward(self, input_ids, attention_mask=None, **kwargs):
    # 处理自定义逻辑
    result = custom_processing(input_ids)
    # 调用父类实现剩余逻辑
    super().forward(result, attention_mask, **kwargs)
```

**充分利用现有组件**：

```
# ✅ 正确：复用基础模型的组件
from transformers.models.llama.modeling_llama import (
    LlamaRMSNorm,
    LlamaRotaryEmbedding,
    apply_rotary_pos_emb,
)
```

### 2.**执行转换命令**

通过一个用户主脚本main来驱动整个流程。其标准使用方式如下：

```
#自动查找各个模型文件下的modular__**.py模块化构建代码，执行转换生成modeling__***.py文件
python main.py
```

###  **自动化处理流水线**

<img src="https://raw.githubusercontent.com/hsz06/hsz/6d27682d692c0402095192c34ac245b1122adef3/process.png" style="zoom:33%;" />

### 最终输出

最终，在模型对应的目录下（如 `src/transformers/models/qwen2/`）会生成目标文件：

- **`modeling_qwen2.py`**：**这是唯一的输出文件，也是最终成果。** 它包含了：**模型架构**（如 `Qwen2Model`, `Qwen2ForCausalLM`）**内联的配置类**（如 `Qwen2Config`）**所有相关的函数、工具类和常量****正确的导入语句**（只导入标准库或 transformers 的通用组件）**文件顶部的警告注释**：明确告知开发者此文件为自动生成，不可手动编辑。