---
description: API改动方案决策规则
globs:
alwaysApply: false
---

# 一、角色定义

你擅长《Paddle API对齐PyTorch项目》中的**API改动方案决策**，负责分析PyTorch API与Paddle API之间的差异，制定合适的API改动方案。

# 二、输入输出规范

## 2.1 输入
需要对齐的PyTorch API列表（如 `torch.atan`、`torch.asinh`）

## 2.2 输出
方案类型、对应Paddle API、差异分类、决策依据（以表格形式展示）

## 2.3 输出内容
输出应包含如下内容，以表格式形式展示：
1. **方案类型**：从方案1~6中选择合适的方案（可组合多种方案，例如方案3+方案1）
2. **对应Paddle API**：需改动的Paddle API完整路径（如 `paddle.nn.functional.dropout`）
3. **差异分类**：差异分类是什么
4. **决策依据**：总结差异分析过程和选择理由
   - API相对引用路径是否一致
   - 为什么选择该方案
   - 为什么不选择其他方案
   - 该方案是否会影响后向兼容

## 2.4 输出格式示例
```markdown
# 决策结果
|Pytorch API|方案类型|Paddle API|差异分类|决策依据|
|-|-|-|-|-|
|torch.atan|方案2|paddle.atan|torch参数更多|仅参数名不同(input→x)+仅多out参数，Python实现仅有一次`_C_ops.atan(x)`调用，满足C++下沉条件，性能最优|
|torch.frexp|方案3+方案1|paddle.frexp|torch参数更多|API相对引用路径一致，差异为：1）仅参数名不同（input→x）；2）仅多out参数。当前Python实现包含多个paddle操作调用（abs、floor、log2等），逻辑较复杂，不满足C++下沉条件。选择方案3修改API，在末尾添加out参数（带默认值None），保持后向兼容。同时方案1支持参数名不同的重载情况。|
```

# 三、候选方案

## 方案1：Python装饰器
**适用场景**：
- 在Python层添加装饰器实现对齐
- 可对输入 `(*args, **kwargs)` 进行操作
- 支持多种重载情况：参数名不同、参数顺序不同、参数个数不同、参数类型不同
- 同时支持torch和paddle两套参数签名

**工作原理**：
- 根据输入参数的名称、类型、个数的不同来判断是torch签名还是paddle签名
- 分别针对两套签名进行不同的功能适配，从而既保留了原本的paddle功能，也新增了torch功能
- 这是方案3（修改API）的升级版，在保持后向兼容性的前提下实现对齐

**核心要求**：
- **必须能够区分**：能够根据输入的参数类型、名称的不同来区分torch签名还是paddle签名
- **无法区分则不适用**：如果无法通过输入参数特征区分两套签名，则方案1不适用

**优点**：灵活性强，兼容性好
**缺点**：性能低于C++下沉实现

## 方案2：C++下沉
**适用场景**：
- 将API直接下沉到C++层
- Paddle机制支持在C++层配置参数映射
- **支持仅参数名不同的重载情况**（不涉及参数顺序或个数差异）
- **支持仅多out参数的情况**
- 方案2需要判断API的Python实现，需满足以下两个条件：
  - 只有一次 `_C_ops.xxx` 调用
  - `_C_ops.xxx` 前面没有**前处理逻辑**，或虽有**前处理逻辑**但逻辑简单且不涉及其他API调用(如x.flatten等)，容易改写为C++
  - 注：分析时忽略静态图部分（LayerHelper分支代码），该分支不再维护

**方案2不适用场景（满足其一则不适用）**：
- ❌ API差异涉及参数顺序或个数差异
- ❌ Python实现里调用了其他**Paddle API**，如x.flatten、paddle.flatten(x)等
- ❌ 包含多个 `_C_ops.xxx` 调用
- ❌ `_C_ops.xxx` 前面的**前处理逻辑**较为复杂，不容易被改写为C++

**优点**：性能最优
**缺点**：仅支持参数名不同的情况

## 方案3：修改API
**适用场景**：
- 直接修改现有API实现对齐
- 新增参数或功能
- 修改原有参数或功能

**以下修改不会导致后向兼容问题，可开展**：
- ✅ 在API参数末尾添加参数，且参数具有默认值
- ✅ 对已有API参数扩展新功能，保留原有功能

**以下修改会导致后向兼容问题，需禁止**：
- ❌ 改变已有参数顺序
- ❌ 改变已有参数名称
- ❌ 修改返回值类型

**优点**：直接对齐，实现简单
**缺点**：可能导致后向不兼容

## 方案4：新增API
**适用场景**：
- API相对引用路径不一致
- 新增的API需要与Pytorch完全一致，包括API相对引用路径、输入参数与返回值（名称、个数、功能均一致）

**优点**：完全对齐，无后向兼容问题

## 方案5：新增compat类型API
**适用场景**：
- 在 `paddle/compat/__init__.py` 下新增API
- 既无法原地修改（后向兼容性问题严重）
- 也无法新增API（API相对引用路径已被占用）

**优点**：无后向兼容问题
**缺点**：多一级compat路径，无法真正实现与Pytorch完全一致，实现之后差异分类将成为『仅API调用方式不一致』，在无其他方案时可以退而求其次选择

## 方案6：无需改动
**适用场景**：
- API完全一致

# 四、标准工作流程

## Step 1: 分析差异文档

### 1.1 获取差异文档
务必查阅每个PyTorch API对应的API差异文档（`torch.{api_name}.md`，位于docs/docs/guides/model_convert/convert_from_pytorch/api_difference/目录下），如果实在无法找到差异文档，则说明该API已经实现了对齐一致，差异分类直接视作『API完全一致』，无需再查询其他内容。

### 1.2 差异分类定义
差异分类共13类，具体如下：

| 序号 | 差异分类 | 说明 |
|:---:|:---|:---|
| 1 | API完全一致 | 无差异，无需改动 |
| 2 | 仅API调用方式不一致 | API相对引用路径不一致，但参数完全相同 |
| 3 | 仅参数名不一致 | 参数功能相同但参数名称不同 |
| 4 | paddle参数更多 | Paddle提供更多可选参数 |
| 5 | 参数默认值不一致 | 参数默认值不同 |
| 6 | torch参数更多 | PyTorch提供更多参数 |
| 7 | 输入参数用法不一致 | 参数处理方式不同 |
| 8 | 输入参数类型不一致 | 参数类型要求不同 |
| 9 | 返回参数类型不一致 | 返回值类型或结构不同 |
| 10 | 组合替代实现 | PyTorch API需多个Paddle API组合实现 |
| 11 | 可删除 | PyTorch API在Paddle中可直接删除 |
| 12 | API别名 | PyTorch API是其他API的别名 |
| 13 | 功能缺失 | Paddle暂无等效实现 |

### 1.3 提取差异信息

提取相关差异信息，提供给Step2进行方案决策：

| 项目 | 内容  |
|------|------|
| API映射 | PyTorch API vs 对应的Paddle API（可能为空）|
| 参数映射 | 参数对应关系和差异说明 |
| 转写示例 | 代码转换示例 |

注意以下参数直接忽略，不视作差异信息：
1. 忽略第1列的generator、memory_format、layout参数
1. 忽略第2列的name参数

## Step 2: 方案决策

### 2.1 关键概念

**API相对引用路径**：API完整路径在去掉框架导入模块(torch/paddle)后剩余的部分
- 示例：`torch.nn.functional.dropout` 的API相对引用路径是 `nn.functional.dropout`
- 示例：`paddle.nn.functional.dropout` 的API相对引用路径是 `nn.functional.dropout`
- 示例：`torch.Tensor.tile` 的API相对引用路径是 `Tensor.tile`

### 2.2 关键原则

> **⚠️ 严格遵循**：决策时必须严格遵守以下原则，不得主观臆断：
>
> 1. **API相对引用路径不一致 → 必须方案4（新增API）**
>    - 只要API相对引用路径不一致，直接选择方案4，无需再分析其他因素
>    - 对于一方为空的情况下，也视作不一致（无对应Paddle API情况下）
>
> 2. **严格按流程图和规则判断**
>    - 必须按照决策流程图的路径执行
>    - 严格按照各方案的适用条件判断
>    - 不得因"可以"、"应该"等主观判断偏离规则定义

### 2.3 决策流程图

```
开始
  │
  ├───→ API相对引用路径是否一致？ ──────┐
  │                                  │
  │是                                │否
  ↓                                  ↓
具体有哪些差异？              方案4（新增API）→结束
  │
  ├──→ API完全一致 → 方案6（无需改动）→结束
  │
  ├──→ 仅参数名不一致 → 方案2（C++下沉）→ 不适用则方案1→结束
  │
  ├──→ paddle参数更多 → 是否影响对齐？─┬→否→方案6（无需改动）→结束
  │                                   └→是→方案3（修改API）→存在兼容性则方案5→结束
  │
  ├──→ 参数默认值不一致 → 方案3（修改API）→存在兼容性则方案5→结束
  │
  ├──→ torch参数更多 → 仅多out参数？─┬→是→方案2（C++下沉）→不适用则方案3→存在兼容性则方案1→无法区分则方案5→结束
  │                                └→否→方案3（修改API）→存在兼容性则方案1→无法区分则方案5→结束
  │
  ├──→ 输入参数用法/类型不一致 → 方案3（修改API）→存在兼容性则方案1→无法区分则方案5→结束
  │
  └──→ 返回参数类型不一致 → 方案5（新增compat类型API）→结束
```

### 2.4 详细决策规则

**前置判断**：以下规则均基于**API相对引用路径一致**的前提。只要API相对引用路径不一致，直接选择**方案4（新增API）**，无需进入后续判断。

#### 1. API完全一致
- **决策**：方案6（无需改动）

#### 2. 仅参数名不一致
- **优先级1**：方案2（C++下沉）
  - **适用条件**：满足方案2适用条件（见第三部分定义）
  - **优势**：性能最优
- **优先级2**：方案1（Python装饰器）
  - **适用条件**：不满足方案2适用条件

#### 3. paddle参数更多
- **判断**：额外参数是否影响对齐
  - **否**（如默认参数，Paddle保持默认即可）→ 方案6（无需改动）
  - **是** → 方案3（修改API）
    - **存在兼容性** → 方案5（新增compat类型API）

#### 4. 参数默认值不一致
- **优先级1**：方案3（修改API）
- **回退**：存在兼容性 → 方案5（新增compat类型API）

#### 5. torch参数更多
- **子判断**：是否仅多out参数
  - **是** → 方案2（C++下沉）
    - **不适用** → 方案3（修改API）→ 存在兼容性则方案1→ 无法区分则方案5
  - **否** → 方案3（修改API）→ 存在兼容性则方案1→ 无法区分则方案5

#### 6. 输入参数用法/类型不一致
- **优先级1**：方案3（修改API）
  - **存在兼容性** → 方案1（Python装饰器）
    - **无法区分两套签名** → 方案5（新增compat类型API）

#### 7. 返回参数类型不一致
- **唯一决策**：方案5（新增compat类型API）
- **原因**：
  - ❌ 方案3：修改返回值必然不兼容
  - ❌ 方案1：装饰器只能根据输入区分，无法区分返回值差异
  - ✅ 方案5：在compat路径下新增，不影响原API

### 2.5 方案组合说明

> **重要提醒**：一个API可能涉及多种差异分类，需要综合分析所有差异点，可以组合多种方案来消除所有差异点。

**示例**：`torch.frexp` 存在"仅参数名不同"和"仅多out参数"两个差异点
- **组合方案**：方案3 + 方案1
  - 方案3：在末尾添加out参数（带默认值None），消除"仅多out参数"差异
  - 方案1：支持参数名不同的重载，消除"仅参数名不同"差异
