Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
44 changes: 44 additions & 0 deletions swe-paddle/tasks/PaddlePaddle__Paddle-74491/README.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,44 @@
# PaddlePaddle__Paddle-74491

This directory converts Paddle PR #74491 into a SWE-Paddle community task candidate.

## Source

| Field | Value |
| --- | --- |
| Repo | `PaddlePaddle/Paddle` |
| PR | [#74491](https://github.com/PaddlePaddle/Paddle/pull/74491) |
| PR title | [API compatibility] add new API `paddle.Tensor.requires_grad` |
| Base commit | `01666a6667e744874d7f7c379b2649d8bae67f09` |
| Merged at | `2025-08-13` |
| Task type | `feature_enhancement` |
| Resource | CPU |

## Summary

Add a `requires_grad` compatibility property for Paddle Tensor-like values across dynamic, static, and PIR execution modes while keeping existing gradient-control behavior intact.

## Why This Is A Good SWE-Paddle Candidate

- The task comes from a merged Paddle API-compatibility PR with a narrow, well-defined behavior contract.
- The observable behavior can be verified deterministically without a source build, GPU, network access, or distributed runtime.
- The change spans three execution modes, so the task checks consistency rather than a single isolated code path.
- Existing Tensor metadata behavior can be protected independently with a P2P test.

## Files

- `proposal.md`: candidate proposal for maintainer triage.
- `instruction.md`: self-contained problem statement for the coding agent.
- `solution/code.patch`: gold patch from the merged PR, limited to production files.
- `tests/test.patch`: test patch exposing the target behavior.
- `tests/test.sh`: minimal target test command.
- `environment/README.md`: environment notes for reproduction.
- `README.md`: task overview and verification entrypoint.

## Verification

```bash
bash tests/test.sh
```

Expected behavior: applying `tests/test.patch` to `base_commit` should fail on the new `requires_grad` behavior while the P2P remains valid; applying both `tests/test.patch` and `solution/code.patch` should pass all target tests.
27 changes: 27 additions & 0 deletions swe-paddle/tasks/PaddlePaddle__Paddle-74491/environment/README.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,27 @@
# Environment Notes

This candidate is part of the SWE-Paddle community task set.

## Expected Environment

- Repository: `PaddlePaddle/Paddle`
- Base commit: `01666a6667e744874d7f7c379b2649d8bae67f09`
- Resource: CPU
- GPU required: no
- Build path: Python-only AST overlay; no Paddle source build is required.

## Run Order

1. Check out `PaddlePaddle/Paddle` at the base commit.
2. Apply `tests/test.patch`.
3. Run `bash tests/test.sh`; the target behavior should fail before the fix.
4. Apply `solution/code.patch`.
5. Run `bash tests/test.sh` again; the target behavior should pass after the gold patch.

## Minimal Test Command

```bash
bash tests/test.sh
```

The verifier is responsible for deriving stable F2P and P2P node IDs from repeated runs.
26 changes: 26 additions & 0 deletions swe-paddle/tasks/PaddlePaddle__Paddle-74491/instruction.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,26 @@
# 为 Tensor 增加 `requires_grad` 属性

## 详细描述

Paddle 目前通过 `stop_gradient` 控制 Tensor 是否参与梯度计算,但还不支持 `requires_grad` 属性。

需要为动态图 Tensor、静态图 Variable 和 PIR Value 增加 `requires_grad`。该属性与 `stop_gradient` 的含义相反:

- `requires_grad=True` 时,`stop_gradient=False`
- `requires_grad=False` 时,`stop_gradient=True`

`requires_grad` 应支持读取和设置,并且只能赋布尔值。传入其他类型时应抛出 `TypeError`。

## 验收说明

- 动态图 Tensor、静态图 Variable 和 PIR Value 均支持 `requires_grad`
- `requires_grad` 的值始终与 `stop_gradient` 相反
- 设置 `requires_grad` 后,`stop_gradient` 应同步更新
- 为 `requires_grad` 赋非布尔值时应抛出 `TypeError`
- 现有 `stop_gradient` 的行为保持不变

## 技术要求

- 熟悉 Python
- 了解 Paddle 动态图、静态图和 PIR
- 了解 `stop_gradient` 与梯度计算的关系
53 changes: 53 additions & 0 deletions swe-paddle/tasks/PaddlePaddle__Paddle-74491/proposal.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,53 @@
# Task Proposal: PaddlePaddle__Paddle-74491

## 1. 来源信息

* Instance ID:`PaddlePaddle__Paddle-74491`
* PR 链接:https://github.com/PaddlePaddle/Paddle/pull/74491
* PR 标题:`[API compatibility] add new API paddle.Tensor.requires_grad`
* `base_commit`:`01666a6667e744874d7f7c379b2649d8bae67f09`
* merged 时间:`2025-08-13`
* 你的身份:熟悉该模块的 contributor
* 后续联系人:TBD

## 2. 问题一句话

为动态图、静态图和 PIR 模式下的 Tensor 增加统一的 `requires_grad` 属性,使调用方能够通过兼容接口读取和设置 Tensor 是否参与梯度计算。

## 3. 为什么适合作为 SWE-Paddle 样本

* **真实性**:该任务来自已合入 Paddle `develop` 分支的 API compatibility PR,不是人工构造的需求。
* **代表性**:该任务涉及常用的 Tensor 梯度控制接口,并要求动态图、静态图和 PIR 模式保持一致的属性行为。
* **边界清楚**:目标行为集中在 `requires_grad` 的读取、赋值、类型校验,以及它与现有 `stop_gradient` 状态之间的对应关系。
* **非平凡性**:任务需要在三类 Tensor 接口中提供一致的属性语义,同时保证现有梯度控制和 Tensor 元数据行为不受影响。

## 4. 任务类型和标签

* 任务类型:`feature_enhancement`
* 执行后端:`cpu`
* 设备范围:`cpu_only`
* 模块标签:`[tensor, autograd, api_compatibility, dynamic_graph, static_graph, pir]`

## 5. 验证思路

* 目标测试命令:`bash tests/test.sh`
* 目标测试文件:`test/swe_paddle/test_pr74491_requires_grad.py`
* 修复前预期:现有 Tensor 元数据和 `stop_gradient` 相关回归测试应通过;动态图、静态图和 PIR 模式下的 `requires_grad` 属性测试应失败。
* 修复后预期:继续应用 `solution/code.patch` 后,三种模式下的 Tensor 均应满足 `requires_grad == (not stop_gradient)`;布尔赋值应正确更新梯度状态,非布尔赋值应抛出 `TypeError`,全部目标测试应通过。
* P2P 候选:三种 Tensor 路径中现有的 `stop_gradient` 状态和 `dim` 等元数据行为保持不变。

## 6. 环境与资源

* 资源需求:CPU
* Paddle 来源:`PaddlePaddle/Paddle` source checkout at `base_commit`
* 是否能提供 Docker:暂无
* patch 类型:Python-only
* 最小测试命令:`bash tests/test.sh`
* 是否有 oracle 日志:由 SWE-Paddle verifier 结果另行维护

## 7. 风险自查

* 泄露风险:`instruction.md` 只描述 `requires_grad` 的公开属性行为、类型要求和兼容性约束,不透露属性的注册位置、具体函数名称或实现步骤。
* 环境风险:通过 AST overlay 隔离 source checkout 与当前运行环境之间的版本差异,避免依赖历史 Paddle native runtime。
* flaky 风险:测试只验证确定性的布尔属性、异常类型和对象状态变化,不依赖随机数、GPU、并发或外部资源。
* 拆分风险:动态图、静态图和 PIR 三条路径共同实现同一个跨执行模式 Tensor API,适合作为一个完整任务。
159 changes: 159 additions & 0 deletions swe-paddle/tasks/PaddlePaddle__Paddle-74491/solution/code.patch
Original file line number Diff line number Diff line change
@@ -0,0 +1,159 @@
diff --git a/python/paddle/base/dygraph/math_op_patch.py b/python/paddle/base/dygraph/math_op_patch.py
index 6aa14dc8013470b2695374e8ab31302e8aa8c0a1..1571b7e0de27e65dbb51e81748d6aabc61deeaac 100644
--- a/python/paddle/base/dygraph/math_op_patch.py
+++ b/python/paddle/base/dygraph/math_op_patch.py
@@ -286,6 +286,40 @@ def monkey_patch_math_tensor():
out = _C_ops.transpose(var, perm)
return out

+ @property
+ def requires_grad(self: Tensor) -> bool:
+ """
+ Whether this Tensor requires gradient computation.
+
+ This is a convenience property that returns the opposite of stop_gradient.
+ Setting requires_grad=True is equivalent to setting stop_gradient=False.
+
+ Examples:
+ .. code-block:: python
+
+ >>> import paddle
+ >>> x = paddle.randn([2, 3])
+ >>> print(x.requires_grad) # False by default
+ >>>
+ >>> x.requires_grad = False
+ >>> print(x.stop_gradient) # True
+ """
+ return not self.stop_gradient
+
+ @requires_grad.setter
+ def requires_grad(self: Tensor, value: bool) -> None:
+ """
+ Set whether this Tensor requires gradient computation.
+
+ Args:
+ value (bool): True to enable gradient computation, False to disable.
+ """
+ if not isinstance(value, bool):
+ raise TypeError(
+ f"requires_grad must be bool, but got {type(value)}"
+ )
+ self.stop_gradient = not value
+
eager_methods = [
('__neg__', _neg_),
('__abs__', _abs_),
@@ -305,6 +339,7 @@ def monkey_patch_math_tensor():
('size', _size_),
('T', _T_),
('mT', _mT_),
+ ("requires_grad", requires_grad),
# for logical compare
('__array_ufunc__', None),
]
diff --git a/python/paddle/base/layers/math_op_patch.py b/python/paddle/base/layers/math_op_patch.py
index 5e22912256b0f2f50acc36b68085077f7fec4a1a..8239d53c535e7770f98f074085df886e6bb46a44 100644
--- a/python/paddle/base/layers/math_op_patch.py
+++ b/python/paddle/base/layers/math_op_patch.py
@@ -564,6 +564,40 @@ def monkey_patch_variable():
"""
return len(self.shape)

+ @property
+ def requires_grad(self) -> bool:
+ """
+ Whether this Tensor requires gradient computation.
+
+ This is a convenience property that returns the opposite of stop_gradient.
+ Setting requires_grad=True is equivalent to setting stop_gradient=False.
+
+ Examples:
+ .. code-block:: python
+
+ >>> import paddle
+ >>> x = paddle.randn([2, 3])
+ >>> print(x.requires_grad) # False by default
+ >>>
+ >>> x.requires_grad = False
+ >>> print(x.stop_gradient) # True
+ """
+ return not self.stop_gradient
+
+ @requires_grad.setter
+ def requires_grad(self, value: bool) -> None:
+ """
+ Set whether this Tensor requires gradient computation.
+
+ Args:
+ value (bool): True to enable gradient computation, False to disable.
+ """
+ if not isinstance(value, bool):
+ raise TypeError(
+ f"requires_grad must be bool, but got {type(value)}"
+ )
+ self.stop_gradient = not value
+
def _scalar_add_(var, value):
return _scalar_op_(var, 1.0, value)

@@ -814,6 +848,7 @@ def monkey_patch_variable():
('dim', dim),
('ndimension', ndimension),
('ndim', _ndim),
+ ("requires_grad", requires_grad),
(
'__add__',
_binary_creator_('__add__', 'elementwise_add', False, _scalar_add_),
diff --git a/python/paddle/pir/math_op_patch.py b/python/paddle/pir/math_op_patch.py
index f51cfd916428a134004a3a6f0abc6cb65124afe3..b114c100ff284f4e6f9078aeda3b4a8abc3c9c15 100644
--- a/python/paddle/pir/math_op_patch.py
+++ b/python/paddle/pir/math_op_patch.py
@@ -633,6 +633,40 @@ def monkey_patch_value():

return _C_ops.transpose(self, perm)

+ @property
+ def requires_grad(self) -> bool:
+ """
+ Whether this Tensor requires gradient computation.
+
+ This is a convenience property that returns the opposite of stop_gradient.
+ Setting requires_grad=True is equivalent to setting stop_gradient=False.
+
+ Examples:
+ .. code-block:: python
+
+ >>> import paddle
+ >>> x = paddle.randn([2, 3])
+ >>> print(x.requires_grad) # False by default
+ >>>
+ >>> x.requires_grad = False
+ >>> print(x.stop_gradient) # True
+ """
+ return not self.stop_gradient
+
+ @requires_grad.setter
+ def requires_grad(self, value: bool) -> None:
+ """
+ Set whether this Tensor requires gradient computation.
+
+ Args:
+ value (bool): True to enable gradient computation, False to disable.
+ """
+ if not isinstance(value, bool):
+ raise TypeError(
+ f"requires_grad must be bool, but got {type(value)}"
+ )
+ self.stop_gradient = not value
+
def _int_(self):
error_msg = """\
int(Tensor) is not supported in static graph mode. Because it's value is not available during the static mode.
@@ -1182,6 +1216,7 @@ def monkey_patch_value():
('size', _size_),
('T', _T_),
('mT', _mT_),
+ ("requires_grad", requires_grad),
('clone', clone),
('clear_gradient', clear_gradient),
('append', append),
Loading