diff --git a/docs/api/paddle/atan2_cn.rst b/docs/api/paddle/atan2_cn.rst index 55f800f35a0..b3be80a52ac 100644 --- a/docs/api/paddle/atan2_cn.rst +++ b/docs/api/paddle/atan2_cn.rst @@ -3,7 +3,7 @@ atan2 ------------------------------- -.. py:function:: paddle.atan2(x, y, name=None) +.. py:function:: paddle.atan2(x, y, name=None, *, out=None) @@ -23,10 +23,14 @@ atan2 参数 ::::::::: - - **x** (Tensor) - 输入的 Tensor,数据类型为:int32、int64、float16、float32、float64。 - - **y** (Tensor) - 输入的 Tensor,数据类型为:int32、int64、float16、float32、float64。 + - **x** (Tensor) - 输入的 Tensor,数据类型为:int32、int64、float16、float32、float64。别名 ``input`` 。 + - **y** (Tensor) - 输入的 Tensor,数据类型为:int32、int64、float16、float32、float64。别名 ``other`` 。 - **name** (str,可选) - 操作的名称(可选,默认值为 None)。更多信息请参见 :ref:`api_guide_Name`。 +关键字参数 +::::::::: + - **out** (Tensor,可选) - 输出 Tensor,若不为 ``None``,计算结果将保存在该 Tensor 中,默认值为 ``None``。 + 返回 ::::::::: diff --git a/docs/api/paddle/bernoulli_cn.rst b/docs/api/paddle/bernoulli_cn.rst index 38bf2b6e495..6256c9e0085 100644 --- a/docs/api/paddle/bernoulli_cn.rst +++ b/docs/api/paddle/bernoulli_cn.rst @@ -3,7 +3,7 @@ bernoulli ------------------------------- -.. py:function:: paddle.bernoulli(x, p=None, name=None) +.. py:function:: paddle.bernoulli(x, p=None, name=None, *, out=None) 对输入 ``x`` 的每一个元素 :math:`x_i`,从以 :math:`x_i` 为参数的伯努利分布(又名两点分布或者 0-1 分布)中抽取一个样本。以 :math:`x_i` 为参数的伯努利分布的概率密度函数是 @@ -16,9 +16,14 @@ bernoulli 参数 :::::::::::: - - **x** (Tensor) - 输入的 Tensor,数据类型为 float32、float64、int32 或 int64。 - - **p** (float,可选) - 若指定 ``p``,伯努利分布的参数将全部设为 ``p``。默认值为 None,此时伯努利分布的参数由 ``x`` 决定。 - - **name** (str,可选) - 具体用法请参见 :ref:`api_guide_Name`,一般无需设置,默认值为 None。 + - **x** (Tensor) - 输入的 Tensor,数据类型为 float32、float64。别名 ``input``。 + - **p** (float|None,可选) - 若指定 ``p``,伯努利分布的参数将全部设为 ``p``。默认值为 None,此时伯努利分布的参数由 ``x`` 决定。 + - **name** (str|None,可选) - 具体用法请参见 :ref:`api_guide_Name`,一般无需设置,默认值为 None。 + +关键字参数 +:::::::::::: + + - **out** (Tensor,可选) - 输出 Tensor,若不为 ``None``,计算结果将保存在该 Tensor 中,默认值为 ``None``。 返回 :::::::::::: diff --git a/docs/api/paddle/combinations_cn.rst b/docs/api/paddle/combinations_cn.rst index ceb4733e1ba..dde0a99a0f8 100644 --- a/docs/api/paddle/combinations_cn.rst +++ b/docs/api/paddle/combinations_cn.rst @@ -10,7 +10,7 @@ combinations 参数 :::::::::: - - **x** (Tensor) - 输入 1-D Tensor ,它的数据类型可以是 float16,float32,float64,int32,int64。 + - **x** (Tensor) - 输入 1-D Tensor ,它的数据类型可以是 float16,float32,float64,int32,int64。别名 ``input``。 - **r** (int,可选) - 组合的数长度,默认值为 2。 - **with_replacement** (bool,可选) - 是否允许组合数中出现重复值,默认不允许,默认值为 False。 - **name** (str,可选) - 具体用法请参见 :ref:`api_guide_Name` ,一般无需设置,默认值为 None。 diff --git a/docs/api/paddle/count_nonzero_cn.rst b/docs/api/paddle/count_nonzero_cn.rst index 2f379ebe895..bba4c7a592e 100644 --- a/docs/api/paddle/count_nonzero_cn.rst +++ b/docs/api/paddle/count_nonzero_cn.rst @@ -14,7 +14,6 @@ count_nonzero - **keepdim** (bool,可选) - 是否在输出 Tensor 中保留被统计的维度。如果 ``keepdim`` 为 True,则输出 Tensor 和 ``x`` 具有相同的维度(被统计的维度大小为 1);否则,输出 Tensor 会在 ``axis`` 上进行 squeeze 操作。默认值为 False。 - **name** (str,可选) - 具体用法请参见 :ref:`api_guide_Name`,一般无需设置,默认值为 None。 - 返回 :::::::::: ``Tensor``,沿着 ``axis`` 统计输入 Tensor 中非零元素的个数,数据类型 int64。 diff --git a/docs/api/paddle/cumulative_trapezoid_cn.rst b/docs/api/paddle/cumulative_trapezoid_cn.rst index 3636f1c4838..e0ab39f05f6 100644 --- a/docs/api/paddle/cumulative_trapezoid_cn.rst +++ b/docs/api/paddle/cumulative_trapezoid_cn.rst @@ -3,7 +3,7 @@ cumulative_trapezoid -------------------------------- -.. py:function:: paddle.cumulative_trapezoid(y, x=None, dx=None, axis=-1, name=None) +.. py:function:: paddle.cumulative_trapezoid(y, x=None, dx=None, axis=-1, name=None, *, out=None) 在指定维度上对输入实现 `trapezoid rule `_ 算法。与 :ref:`cn_api_paddle_trapezoid` 的区别是,所用累积求和函数为 cumsum。 @@ -14,8 +14,14 @@ cumulative_trapezoid - **y** (Tensor) - 输入多维 Tensor,可选的数据类型为 float16、float32、float64。 - **x** (Tensor,可选) - ``y`` 中数值对应的浮点数所组成的 Tensor,类型与 ``y`` 相同,形状与 ``y`` 的形状相匹配;若 ``x`` 有输入,已知 ``y`` 的尺寸为 `[d_1, d_2, ... , d_n]` 且 `axis=k`,则 ``x`` 的尺寸只能为 `[d_k]` 或 `[d_1, d_2, ... , d_n]`;如果 ``x`` 为 None,则假定采样点均匀分布 ``dx``。 - **dx** (float,可选) - 相邻采样点之间的常数间隔;当 ``x`` 和 ``dx`` 均未指定时,``dx`` 默认为 1.0。 - - **axis** (int,可选) - 计算 trapezoid rule 时 ``y`` 的维度。默认值 -1。 + - **axis** (int,可选) - 计算 trapezoid rule 时 ``y`` 的维度。默认值 -1。别名 ``dim``。 - **name** (str,可选) - 具体用法请参见 :ref:`api_guide_Name`,一般无需设置,默认值为 None。 + +关键字参数 +::::::::: + + - **out** (Tensor,可选) - 输出 Tensor,若不为 ``None``,计算结果将保存在该 Tensor 中,默认值为 ``None``。 + 返回 ::::::::: Tensor,按 trapezoidal rule 计算出 ``y`` 等于 N 维张量时的定积分,结果为 N 维张量。 diff --git a/docs/api/paddle/floor_divide__cn.rst b/docs/api/paddle/floor_divide__cn.rst index 8a9c25481d8..17e7c9ee451 100644 --- a/docs/api/paddle/floor_divide__cn.rst +++ b/docs/api/paddle/floor_divide__cn.rst @@ -4,8 +4,12 @@ floor_divide\_ ------------------------------- .. py:function:: paddle.floor_divide_(x, y, name=None) -Inplace 版本的 :ref:`cn_api_paddle_floor_divide` API,对输入 x 采用 Inplace 策略。 + +Inplace 版本的 :ref:`cn_api_paddle_floor_divide` API,对输入 `x` 采用 Inplace 策略。 更多关于 inplace 操作的介绍请参考 `3.1.3 原位(Inplace)操作和非原位操作的区别`_ 了解详情。 .. _3.1.3 原位(Inplace)操作和非原位操作的区别: https://www.paddlepaddle.org.cn/documentation/docs/zh/develop/guides/beginner/tensor_cn.html#id3 + +.. note:: + 别名支持: 参数名 ``input`` 可替代 ``x``,参数名 ``other`` 可替代 ``y``,如 ``floor_divide_(input=tensor_x, other=tensor_y)`` 等价于 ``floor_divide_(x=tensor_x, y=tensor_y)``。 diff --git a/docs/api/paddle/frexp_cn.rst b/docs/api/paddle/frexp_cn.rst index 89f66c8c471..4f34c4a8ae4 100644 --- a/docs/api/paddle/frexp_cn.rst +++ b/docs/api/paddle/frexp_cn.rst @@ -3,15 +3,19 @@ frexp ------------------------------- -.. py:function:: paddle.frexp(x, name) +.. py:function:: paddle.frexp(x, name=None, *, out=None) - -用于把一个浮点数分解为尾数和指数的函数,返回一个尾数 Tensor 和一个指数 Tensor +用于把一个浮点数分解为尾数和指数的函数,返回一个尾数 Tensor 和一个指数 Tensor。 参数 :::::::::: - - **x** (Tensor) – 输入是一个多维的 Tensor,它的数据类型可以是 float32,float64。 + - **x** (Tensor) – 输入是一个多维的 Tensor,它的数据类型可以是 float32,float64。别名 ``input``。 - **name** (str,可选) - 具体用法请参见 :ref:`api_guide_Name` ,一般无需设置,默认值为 None。 + +关键字参数 +:::::::::: + - **out** (tuple[Tensor, Tensor],可选) - 输出 Tensor,若不为 ``None``,计算结果将保存在该 Tensor 元组中,默认值为 ``None``。 + 返回 :::::::::: mantissa(Tensor):分解后的尾数,类型为 Tensor,形状和原输入的形状一致。 diff --git a/docs/api/paddle/isneginf_cn.rst b/docs/api/paddle/isneginf_cn.rst index f025b78cde8..9ff1b9c22fe 100644 --- a/docs/api/paddle/isneginf_cn.rst +++ b/docs/api/paddle/isneginf_cn.rst @@ -3,15 +3,19 @@ isneginf ----------------------------- -.. py:function:: paddle.isneginf(x, name=None) +.. py:function:: paddle.isneginf(x, name=None, *, out=None) 返回输入 tensor 的每一个值是否为 ``-INF`` 。 参数 ::::::::: - - **x** (Tensor):输入的 `Tensor`,数据类型为:float16、float32、float64、int8、int16、int32、int64、uint8。 + - **x** (Tensor):输入的 `Tensor`,数据类型为:float16、float32、float64、int8、int16、int32、int64、uint8。别名: ``input``。 - **name** (str,可选) - 具体用法请参见 :ref:`api_guide_Name`,一般无需设置,默认值为 None。 +关键字参数 +::::::::: + - **out** (Tensor,可选) - 输出 Tensor,若不为 ``None``,计算结果将保存在该 Tensor 中,默认值为 ``None``。 + 返回 ::::::::: ``Tensor``,每个元素是一个 bool 值,表示输入 ``x`` 的每个元素是否为 ``-INF`` 。 diff --git a/docs/api/paddle/isposinf_cn.rst b/docs/api/paddle/isposinf_cn.rst index 4c96f272033..74d388a0681 100644 --- a/docs/api/paddle/isposinf_cn.rst +++ b/docs/api/paddle/isposinf_cn.rst @@ -3,15 +3,19 @@ isposinf ----------------------------- -.. py:function:: paddle.isposinf(x, name=None) +.. py:function:: paddle.isposinf(x, name=None, *, out=None) 返回输入 tensor 的每一个值是否为 ``+INF`` 。 参数 ::::::::: - - **x** (Tensor):输入的 `Tensor`,数据类型为:float16、float32、float64、int8、int16、int32、int64、uint8。 + - **x** (Tensor):输入的 `Tensor`,数据类型为:bfloat16、float16、float32、float64、int8、int16、int32、int64、uint8。别名: ``input``。 - **name** (str,可选) - 具体用法请参见 :ref:`api_guide_Name`,一般无需设置,默认值为 None。 +关键字参数 +::::::::: + - **out** (Tensor,可选) - 输出 Tensor,若不为 ``None``,计算结果将保存在该 Tensor 中,默认值为 ``None``。 + 返回 ::::::::: ``Tensor``,每个元素是一个 bool 值,表示输入 ``x`` 的每个元素是否为 ``+INF`` 。 diff --git a/docs/api/paddle/isreal_cn.rst b/docs/api/paddle/isreal_cn.rst index 4a6c3da9501..b10d3dcccde 100644 --- a/docs/api/paddle/isreal_cn.rst +++ b/docs/api/paddle/isreal_cn.rst @@ -10,7 +10,7 @@ isreal 参数 ::::::::: - - **x** (Tensor) - 输入 Tensor。 + - **x** (Tensor) - 输入 Tensor。别名: ``input``。 - **name** (str,可选) - 具体用法请参见 :ref:`api_guide_Name`,一般无需设置,默认值为 None。 返回 diff --git a/docs/api/paddle/kron_cn.rst b/docs/api/paddle/kron_cn.rst index e87e1eb01ca..f2dea986f06 100644 --- a/docs/api/paddle/kron_cn.rst +++ b/docs/api/paddle/kron_cn.rst @@ -3,11 +3,7 @@ kron ------------------------------- -.. py:function:: paddle.kron(x, y, out=None, name=None) - - - - +.. py:function:: paddle.kron(x, y, name=None, *, out=None) Kronecker Product 算子。 @@ -35,11 +31,15 @@ Kronecker Product 算子。 参数 :::::::::::: - - **x** (Tensor) – Kron OP 的第一个输入。多维 Tensor,数据类型为 bfloat16、float16、float32、float64、int32 或 int64。 - - **y** (Tensor) – Kron OP 的第二个输入。多维 Tensor,数据类型为 bfloat16、float16、float32、float64、int32 或 int64,与 x 相同。 - - **out** (Tensor,可选) - 指定算子输出结果的 Tensor,可以是程序中已经创建的任何 Tensor。默认值为 None,此时将创建新的 Tensor 来保存输出结果。 + - **x** (Tensor) – Kron OP 的第一个输入。多维 Tensor,数据类型为 bfloat16、float16、float32、float64、int32 或 int64。别名 ``input``。 + - **y** (Tensor) – Kron OP 的第二个输入。多维 Tensor,数据类型为 bfloat16、float16、float32、float64、int32 或 int64,与 x 相同。别名 ``other``。 - **name** (str,可选) - 具体用法请参见 :ref:`api_guide_Name`,一般无需设置,默认值为 None。 +关键字参数 +:::::::::::: + + - **out** (Tensor,可选) - 输出 Tensor,若不为 ``None``,计算结果将保存在该 Tensor 中,默认值为 ``None``。 + 返回 :::::::::::: diff --git a/docs/api/paddle/kthvalue_cn.rst b/docs/api/paddle/kthvalue_cn.rst index 4bfaeea5d54..16f1cdbe321 100644 --- a/docs/api/paddle/kthvalue_cn.rst +++ b/docs/api/paddle/kthvalue_cn.rst @@ -3,18 +3,22 @@ kthvalue ------------------------------- -.. py:function:: paddle.kthvalue(x, k, axis=None, keepdim=False, name=None) +.. py:function:: paddle.kthvalue(x, k, axis=None, keepdim=False, name=None, *, out=None) 在指定的轴上查找第 k 小的元素和其对应所在的索引信息。 参数 ::::::::: - - **x** (Tensor) - 一个输入的 N-D ``Tensor``,支持的数据类型:float32、float64、int32、int64。 + - **x** (Tensor) - 一个输入的 N-D ``Tensor``,支持的数据类型:float16、float32、float64、int32、int64。别名 ``input``。 - **k** (int,Tensor) - 需要沿轴查找的第 ``k`` 小,所对应的 ``k`` 值。 - - **axis** (int,可选) - 指定对输入 Tensor 进行运算的轴,``axis`` 的有效范围是[-R, R),R 是输入 ``x`` 的 Rank, ``axis`` 为负时与 ``axis`` + R 等价。默认值为-1。 + - **axis** (int,可选) - 指定对输入 Tensor 进行运算的轴,``axis`` 的有效范围是[-R, R),R 是输入 ``x`` 的 Rank, ``axis`` 为负时与 ``axis`` + R 等价。默认值为-1。别名 ``dim``。 - **keepdim** (bool,可选)- 是否保留指定的轴。如果是 True,维度会与输入 x 一致,对应所指定的轴的 size 为 1。否则,由于对应轴被展开,输出的维度会比输入小 1。默认值为 False。 - **name** (str,可选) - 具体用法请参见 :ref:`api_guide_Name`,一般无需设置,默认值为 None。 +关键字参数 +::::::::: + - **out** (Tensor,可选) - 输出 Tensor,若不为 ``None``,计算结果将保存在该 Tensor 中,默认值为 ``None``。 + 返回 ::::::::: tuple(Tensor),返回第 k 小的元素和对应的索引信息。结果的数据类型和输入 ``x`` 一致。索引的数据类型是 int64。 diff --git a/docs/api/paddle/lgamma_cn.rst b/docs/api/paddle/lgamma_cn.rst index 9e9876c0e2e..51f17ac1c11 100644 --- a/docs/api/paddle/lgamma_cn.rst +++ b/docs/api/paddle/lgamma_cn.rst @@ -5,13 +5,8 @@ lgamma .. py:function:: paddle.lgamma(x, name=None) - - - 计算输入 x 的 gamma 函数的自然对数并返回。 -.. math:: - out = log\Gamma(x) 参数 ::::::::: diff --git a/docs/api/paddle/logcumsumexp_cn.rst b/docs/api/paddle/logcumsumexp_cn.rst index c90766ea0e5..83258e07225 100644 --- a/docs/api/paddle/logcumsumexp_cn.rst +++ b/docs/api/paddle/logcumsumexp_cn.rst @@ -3,7 +3,7 @@ logcumsumexp ------------------------------- -.. py:function:: paddle.logcumsumexp(x, axis=None, dtype=None, name=None) +.. py:function:: paddle.logcumsumexp(x, axis=None, dtype=None, name=None, *, out=None) 计算 x 的指数的前缀和的对数。 @@ -18,14 +18,18 @@ logcumsumexp 参数 ::::::::: - - **x** (Tensor) - 需要进行操作的 Tensor。 - - **axis** (int,可选) - 指明需要计算的维度。-1 代表最后一维。默认:None,将输入展开为一维变量再进行计算。 + - **x** (Tensor) - 需要进行操作的 Tensor,数据类型为 float32、float64、float16、bfloat16、uint8、int8、int16、int32、int64。别名 ``input``。 + - **axis** (int,可选) - 指明需要计算的维度。-1 代表最后一维。默认:None,将输入展开为一维变量再进行计算。别名 ``dim``。 - **dtype** (str|paddle.dtype|np.dtype,可选) - 输出 Tensor 的数据类型,支持 float16、float32、float64。如果指定了,那么在执行操作之前,输入 Tensor 将被转换为 dtype。这对于防止数据类型溢出非常有用。默认为:None。 - **name** (str,可选) - 具体用法请参见 :ref:`api_guide_Name`,一般无需设置,默认值为 None。 +关键字参数 +::::::::: + - **out** (Tensor,可选) - 输出 Tensor,若不为 ``None``,计算结果将保存在该 Tensor 中,默认值为 ``None``。 + 返回 ::::::::: - - Tensor (Tensor),x 的指数的前缀和的对数。 + - Tensor (Tensor),x 的指数的前缀和的对数(整数输入类型会自动转换为 float32)。 代码示例 diff --git a/docs/api/paddle/mode_cn.rst b/docs/api/paddle/mode_cn.rst index bd35208f4bf..bbb8630525e 100644 --- a/docs/api/paddle/mode_cn.rst +++ b/docs/api/paddle/mode_cn.rst @@ -3,17 +3,21 @@ mode ------------------------------- -.. py:function:: paddle.mode(x, axis=-1, keepdim=False, name=None) +.. py:function:: paddle.mode(x, axis=-1, keepdim=False, name=None, *, out=None) 沿着可选的 ``axis`` 查找对应轴上的众数和结果所在的索引信息。 参数 ::::::::: - - **x** (Tensor) - 输入的多维 ``Tensor``,支持的数据类型:float32、float64、int32、int64。 - - **axis** (int,可选) - 指定对输入 Tensor 进行运算的轴,``axis`` 的有效范围是[-R, R),R 是输入 ``x`` 的 Rank, ``axis`` 为负时与 ``axis`` + R 等价。默认值为-1。 + - **x** (Tensor) - 输入的多维 ``Tensor``,支持的数据类型:float32、float64、int32、int64。别名 ``input``。 + - **axis** (int,可选) - 指定对输入 Tensor 进行运算的轴,``axis`` 的有效范围是[-R, R),R 是输入 ``x`` 的 Rank, ``axis`` 为负时与 ``axis`` + R 等价。默认值为-1。别名 ``dim``。 - **keepdim** (bool,可选)- 是否保留指定的轴。如果是 True,维度会与输入 x 一致,对应所指定的轴的 size 为 1。否则,由于对应轴被展开,输出的维度会比输入小 1。默认值为 1。 - **name** (str,可选) - 具体用法请参见 :ref:`api_guide_Name`,一般无需设置,默认值为 None。 +关键字参数 +::::::::: + - **out** (tuple[Tensor, Tensor],可选) - 输出 Tensor,若不为 ``None``,计算结果将保存在该 Tensor 中,默认值为 ``None``。 + 返回 ::::::::: tuple(Tensor),返回检索到的众数结果和对应索引信息。结果的数据类型和输入 ``x`` 一致。索引的数据类型是 int64。 diff --git a/docs/api/paddle/mv_cn.rst b/docs/api/paddle/mv_cn.rst index 2f219694a24..0e12181dd98 100644 --- a/docs/api/paddle/mv_cn.rst +++ b/docs/api/paddle/mv_cn.rst @@ -3,16 +3,20 @@ mv ------------------------------- -.. py:function:: paddle.mv(x, vec, name=None) +.. py:function:: paddle.mv(x, vec, name=None, *, out=None) 计算矩阵 ``x`` 和向量 ``vec`` 的乘积。 参数 ::::::::: - - **x** (Tensor) - 输入变量,类型为 Tensor,形状为 :math:`[M, N]`,数据类型为 float32、float64。 + - **x** (Tensor) - 输入变量,类型为 Tensor,形状为 :math:`[M, N]`,数据类型为 float32、float64。别名 ``input``。 - **vec** (Tensor) - 输入变量,类型为 Tensor,形状为 :math:`[N]`,数据类型为 float32、float64。 - **name** (str,可选) - 具体用法请参见 :ref:`api_guide_Name`,一般无需设置,默认值为 None。 +关键字参数 +::::::::: + - **out** (Tensor,可选) - 输出 Tensor,若不为 ``None``,计算结果将保存在该 Tensor 中,默认值为 ``None``。 + 返回 ::::::::: diff --git a/docs/api/paddle/poisson_cn.rst b/docs/api/paddle/poisson_cn.rst index 985fe821146..e5c6ee998e5 100644 --- a/docs/api/paddle/poisson_cn.rst +++ b/docs/api/paddle/poisson_cn.rst @@ -12,7 +12,7 @@ poisson 参数 ::::::::: - - **x** (Tensor) - Tensor 的每个元素,对应泊松分布的 ``lambda`` 参数。数据类型为:bfloat16, float16, float32、float64。 + - **x** (Tensor) - Tensor 的每个元素,对应泊松分布的 ``lambda`` 参数。数据类型为:bfloat16, float16, float32、float64。别名 ``input``。 - **name** (str,可选) - 具体用法请参见 :ref:`api_guide_Name`,一般无需设置,默认值为 None。 返回 diff --git a/docs/api/paddle/pow__cn.rst b/docs/api/paddle/pow__cn.rst index 0d06807a10a..7599d735307 100644 --- a/docs/api/paddle/pow__cn.rst +++ b/docs/api/paddle/pow__cn.rst @@ -3,9 +3,12 @@ pow\_ ------------------------------- -.. py:function:: paddle.pow_(x,y,name=None) +.. py:function:: paddle.pow_(x, y, name=None) Inplace 版本的 :ref:`cn_api_paddle_pow` API,对输入 ``x`` 采用 Inplace 策略。 更多关于 inplace 操作的介绍请参考 `3.1.3 原位(Inplace)操作和非原位操作的区别`_ 了解详情。 .. _3.1.3 原位(Inplace)操作和非原位操作的区别: https://www.paddlepaddle.org.cn/documentation/docs/zh/develop/guides/beginner/tensor_cn.html#id3 + +.. note:: + 别名支持: 参数名 ``input`` 可替代 ``x``,参数名 ``exponent`` 可替代 ``y``,如 ``pow_(input=tensor_x, exponent=2)`` 等价于 ``pow_(x=tensor_x, y=2)``。 diff --git a/docs/api/paddle/squeeze__cn.rst b/docs/api/paddle/squeeze__cn.rst index df8bb9fbaba..fb09674c71e 100644 --- a/docs/api/paddle/squeeze__cn.rst +++ b/docs/api/paddle/squeeze__cn.rst @@ -10,3 +10,6 @@ Inplace 版本的 :ref:`cn_api_paddle_squeeze` API,对输入 ``x`` 采用 Inpl 更多关于 inplace 操作的介绍请参考 `3.1.3 原位(Inplace)操作和非原位操作的区别`_ 了解详情。 .. _3.1.3 原位(Inplace)操作和非原位操作的区别: https://www.paddlepaddle.org.cn/documentation/docs/zh/develop/guides/beginner/tensor_cn.html#id3 + +.. note:: + 别名支持: 参数名 ``input`` 可替代 ``x``,参数名 ``dim`` 可替代 ``axis``,如 ``squeeze_(input=tensor_x, dim=1)`` 等价于 ``squeeze_(x=tensor_x, axis=1)``。 diff --git a/docs/api/paddle/trapezoid_cn.rst b/docs/api/paddle/trapezoid_cn.rst index 75890946015..bf9690fa291 100644 --- a/docs/api/paddle/trapezoid_cn.rst +++ b/docs/api/paddle/trapezoid_cn.rst @@ -3,7 +3,7 @@ trapezoid -------------------------------- -.. py:function:: paddle.trapezoid(y, x=None, dx=None, axis=-1, name=None) +.. py:function:: paddle.trapezoid(y, x=None, dx=None, axis=-1, name=None, *, out=None) 在指定维度上对输入实现 `trapezoid rule `_ 算法。与 :ref:`cn_api_paddle_cumulative_trapezoid` 的区别是,所用累积求和函数为 sum。 @@ -14,8 +14,14 @@ trapezoid - **y** (Tensor) - 输入多维 Tensor,可选的数据类型为 float16、float32、float64。 - **x** (Tensor,可选) - ``y`` 中数值对应的浮点数所组成的 Tensor,类型与 ``y`` 相同,形状与 ``y`` 的形状相匹配;若 ``x`` 有输入,已知 ``y`` 的尺寸为 `[d_1, d_2, ... , d_n]` 且 `axis=k`,则 ``x`` 的尺寸只能为 `[d_k]` 或 `[d_1, d_2, ... , d_n]`;如果 ``x`` 为 None,则假定采样点均匀分布 ``dx``。 - **dx** (float,可选) - 相邻采样点之间的常数间隔;当 ``x`` 和 ``dx`` 均未指定时,``dx`` 默认为 1.0。 - - **axis** (int,可选) - 计算 trapezoid rule 时 ``y`` 的维度。默认值 -1。 + - **axis** (int,可选) - 计算 trapezoid rule 时 ``y`` 的维度。默认值 -1。别名 ``dim``。 - **name** (str,可选) - 具体用法请参见 :ref:`api_guide_Name`,一般无需设置,默认值为 None。 + +关键字参数 +::::::::: + + - **out** (Tensor,可选) - 输出 Tensor,若不为 ``None``,计算结果将保存在该 Tensor 中,默认值为 ``None``。 + 返回 ::::::::: Tensor,按 trapezoidal rule 计算出 ``y`` 等于 N 维张量时的定积分,如果 ``y`` 是一维张量,则结果是浮点数。如果 N 大于 1 维,则结果为 N-1 维张量。 diff --git a/docs/api/paddle/unsqueeze__cn.rst b/docs/api/paddle/unsqueeze__cn.rst index b2a4f0160a7..3798da0ca4a 100644 --- a/docs/api/paddle/unsqueeze__cn.rst +++ b/docs/api/paddle/unsqueeze__cn.rst @@ -10,3 +10,6 @@ Inplace 版本的 :ref:`cn_api_paddle_unsqueeze` API,对输入 ``x`` 采用 In 更多关于 inplace 操作的介绍请参考 `3.1.3 原位(Inplace)操作和非原位操作的区别`_ 了解详情。 .. _3.1.3 原位(Inplace)操作和非原位操作的区别: https://www.paddlepaddle.org.cn/documentation/docs/zh/develop/guides/beginner/tensor_cn.html#id3 + +.. note:: + 别名支持: 参数名 ``input`` 可替代 ``x``,参数名 ``dim`` 可替代 ``axis``,如 ``unsqueeze_(input=tensor_x, dim=1)`` 等价于 ``unsqueeze_(x=tensor_x, axis=1)``。 diff --git a/docs/dev_guides/coding_agent_rules/README.md b/docs/dev_guides/coding_agent/README.md similarity index 100% rename from docs/dev_guides/coding_agent_rules/README.md rename to docs/dev_guides/coding_agent/README.md diff --git a/docs/dev_guides/coding_agent_rules/api_compatibility/README.md b/docs/dev_guides/coding_agent/api_compatibility/README.md similarity index 100% rename from docs/dev_guides/coding_agent_rules/api_compatibility/README.md rename to docs/dev_guides/coding_agent/api_compatibility/README.md diff --git a/docs/dev_guides/coding_agent/api_compatibility/api-change-decider.md b/docs/dev_guides/coding_agent/api_compatibility/api-change-decider.md new file mode 100644 index 00000000000..8ec52cd7016 --- /dev/null +++ b/docs/dev_guides/coding_agent/api_compatibility/api-change-decider.md @@ -0,0 +1,257 @@ +--- +name: API 改动方案决策智能体 +description: 根据 API 差异文档,决策 API 的对齐改动方案 +tools: grep_content, read_file, glob_path, codebase_search, list_dir, write_file, edit_file, run_command +--- + +# 一、角色定义 + +你擅长《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:支持参数名不同的重载,消除"仅参数名不同"差异 diff --git a/docs/dev_guides/coding_agent/api_compatibility/api-compatibility.md b/docs/dev_guides/coding_agent/api_compatibility/api-compatibility.md new file mode 100644 index 00000000000..c4847079b88 --- /dev/null +++ b/docs/dev_guides/coding_agent/api_compatibility/api-compatibility.md @@ -0,0 +1,376 @@ +--- +description: Paddle API 对齐 PyTorch 项目 - 主控智能体 +globs: +alwaysApply: false +--- + +# 一、角色定义 + +你是《Paddle API 对齐 PyTorch 项目》的**主控智能体**,负责统筹全流程的工作,调用多个子智能体,最终完成输入的所有 API 对齐。 + +**核心职责**: +1. 接收待对齐的 Pytorch API 列表 +2. 为对应的 Paddle API 决策改动方案 +3. 执行具体的 Paddle API 修改 +4. 验证修改后的 Paddle API 是否对齐 Pytorch +5. 更新修改后的 Paddle API 中文文档 +6. 给出 Pytorch API 列表的对齐结果统计 + + +# 二、项目目标 + +**使 Paddle API 与 PyTorch API 完全对齐**,实现: + +- 对于任意 PyTorch API 用法,只需将 `torch.*` 替换为 `paddle.*` +- 计算结果完全一致(数值精度、行为逻辑) + + +# 三、输入输出规范 + +## 3.1 输入 +用户提供待对齐的 Pytorch API 列表,格式示例: +```markdown +torch.argmax +torch.log2 +torch.logsumexp +``` + +## 3.2 输出 + +用户输入列表的对齐情况,格式示例: +```markdown +# API 对齐结果统计 + +|API 名称|对齐状态|决策方案|备注| +|-|-|-|-| +|torch.argmax|已对齐|方案 2|-| +|torch.log2|已对齐|无需改动|<简介为何无需改动>例如:未查询到差异文件,两者 API 完全一致| +|torch.logsumexp|未对齐|方案 1|<简介失败原因>例如:方案 1 暂不支持修改| +``` + +# 四、技术背景知识 + +## 4.1 根目录说明 + +| 目录名称 | 内容说明 | 负责修改的步骤 | +|---------|---------|---------------| +| Paddle | 包含所有 Paddle API 的实现 | Step2:代码修改 | +| PaConvert | 包含所有 Pytorch 单元测试 | Step3:对齐验证 | +| docs | 包含所有 Paddle API 中文文档 | Step4:文档更新 | + +## 4.2 相关文件位置 + +|**功能模块**|**检索关键字**|**文件路径**|**举例**|**注意**| +|-|-|-|-|-| +|API 中文文档|`{api_name}_cn.rst`|docs/docs/api/paddle/|tan_cn.rst|| +|API 差异文档|`torch.{api_name}.md`|docs/docs/guides/model_convert/convert_from_pytorch/api_difference/|torch.tan.md|| +|C++下沉使用|`python_api_info.yaml`、`ops.yaml`|Paddle/paddle/phi/ops/yaml/|python_api_info.yamlops.yaml|| +|C++下沉使用|`_paddle_docs.py`|Paddle/python/paddle/|_paddle_docs.py|| +|Paddle API 实现位置|`def {api_name}` 或 `class {api_name}`|Paddle/python/paddle/|Paddle/python/paddle/tensor/ops.py|不要误检索到 sparse 目录下(稀疏 API 位置),本项目与稀疏无关,所有 sparse 相关文件直接忽略| +|Paddle API 兼容性单测位置|`test_api_compatibility.py`|Paddle/test/legacy_test/test_api_compatibility.py|| +|Pytorch API 单测位置|`test_{api_name}.py`|PaConvert/tests/|PaConvert/tests/test_tan.py|| + +## 4.3 Paddle API 架构(5 层调用栈) + +Paddle API 从上到下由 5 层组成(本项目直接修改第 1、5 层,对于第 2~4 层通常是修改 yaml 配置文件,例如 python_api_info.yaml): + +| 层级 | 名称 | 语言 | 文件位置 | 功能说明 | 是否修改 | +|------|------|------|----------|----------|----------| +| 1 | Python 层 | Python | `*.py` | API 的 Python 接口定义 | ✅ **修改** | +| 2 | Pybind 层 | C++ | 根据`*.yaml`自动生成(`paddle/fluid/pybind/eager_op_function.cc`)| Python 与 C++的绑定层 | ✅ **修改 yaml 配置来实现修改** | +| 3 | Dygraph 层 | C++ | 根据`*.yaml`自动生成(`paddle/fluid/eager/.../dygraph_functions.cc`)| 前反向传播组合 | ❌ 通常不改 | +| 4 | C++ API 层 | C++ | 根据`*.yaml`自动生成(`paddle/phi/api/lib/api.cc`) | Kernel 选择调度 | ❌ 通常不改 | +| 5 | Kernel 层 | C++ | `paddle/phi/kernels/` | 实际计算逻辑实现 | ✅ **修改** | + +**示例 API 层级**: +```python +# Layer 1: Python 层 +def atan(x: Tensor, name: str | None = None) + +# Layer 2: Pybind 层(根据 ops.yaml 自动生成) +eager_api_abs(PyObject *self, PyObject *args, PyObject *kwargs) + +# Layer 3: Dygraph 层(根据 ops.yaml 自动生成) +paddle::Tensor atan_ad_func(const paddle::Tensor& x, ...) + +# Layer 4: C++ API 层(根据 ops.yaml 自动生成) +Tensor atan(const Tensor& x, ...) + +# Layer 5: Kernel 层 +void AtanKernel(const Context& dev_ctx, const DenseTensor& x, DenseTensor* out) +``` + +## 4.4 专业术语表 + +| 术语 | 定义 | 备注 | +|------|------|------| +| PyTorch | 深度学习框架,导入模块为`torch` | - | +| Paddle | 飞桨深度学习框架,导入模块为`paddle` | - | +| API | 应用程序接口 | 既可以是一个 Python 函数,也可以是一个 Python 类 | +| API 完整路径 | API 完整路径 | 如`torch.nn.functional.dropout`、`paddle.nn.functional.dropout`| +| API 相对引用路径 | API 完整路径在去掉框架导入模块(torch/paddle)后剩余的部分| 如`nn.functional.dropout` | +| PyTorch API | `torch.*` 系列接口 | 约 2000+个 API,是本项目的**对齐标准**| +| Paddle API | `paddle.*` 系列接口 | 约 2000+个 API,是本项目的**修改对象** | +| API 对齐 | 使两个 API 的行为完全对齐一致 | 对齐包括 API 相对引用路径、输入参数、返回值、计算逻辑等| +| API 中文文档 | 中文描述了该 API 的功能与行为 | 位于 docs/docs/api/paddle/目录,命名类似 tan_cn.rst | +| API 差异文档 | 中文描述了 Pytorch API 与 Paddle API 两者的行为差异 | 位于 docs/docs/guides/model_convert/convert_from_pytorch/api_difference/下的一级子目录,命名类似 torch.tan.md | +| compat 类型 API | 兼容性 API | 为保持后向兼容而添加的 API,能实现除 API 相对引用路径之外的完全对齐,实现之后差异分类将成为『仅 API 调用方式不一致』| + +## 4.5 类方法 API 实现原理 + +**概念说明**: +- 注意要区分**类方法 API**和**普通 API**,两者是不同的 API,不要混为一谈 +- **类方法 API**(如`torch.Tensor.abs`):`torch.Tensor`类方法 +- **普通 API**(如`torch.abs`):普通方法 + +Paddle 的 Tensor 类方法通过**patch 机制**实现,即将普通方法动态添加到`paddle.Tensor`(即`core.eager.Tensor`)类上成为类方法。 + +**实现机制**(参考`Paddle/python/paddle/base/dygraph/math_op_patch.py`): + +```python +# 从 paddle.tensor 模块获取方法定义 +import paddle.tensor + +# 将普通方法 patch 到 core.eager.Tensor 类上 +for method_name in paddle.tensor.tensor_method_func: + if hasattr(core.eager.Tensor, method_name): + continue + method_impl = getattr(paddle.tensor, method_name, None) + if method_impl: + setattr(core.eager.Tensor, method_name, method_impl) +``` + +**查找类方法实现时的注意事项**: +- ✅ **正确做法**:直接搜索对应的普通方法实现,如搜索`def abs(`或`def atan(` +- ❌ **错误做法**:不要搜索`class Tensor`或在 Tensor 类定义中查找方法 +- 原因:Tensor 类方法是通过`setattr`动态添加的,不在类定义的源码中直接体现 + +## 4.6 Inplace API 实现原理 + +**概念说明**: +- 注意要区分**inplace API**和**非 inplace API**,两者是不同的 API,不要混为一谈 +- **inplace API**(如`torch.abs_`):原地操作,直接修改输入 Tensor,其不应有 out 参数,如有 out 需删除 +- **非 inplace API**(如`torch.abs`):返回新 Tensor,不修改输入 Tensor +- Inplace API 无需测试静态图,只需测试动态图 + +**示例对比**: +```python +y = paddle.abs(x) # 非 inplace:返回新 Tensor,x 不变 +x.abs_() # inplace:原地修改 x +``` + +**自动生成机制**: +Paddle 支持自动生成 inplace API,无需在`ops.yaml`中单独配置。当定义了`inplace: (x -> out)`字段后,系统自动生成对应的 inplace 版本,复用原 API 的 Kernel 实现。 + +**配置示例**: +1. **OP 配置**(`ops.yaml`,第 10-22 行): +```yaml +- op : abs + args : (Tensor x) + output : Tensor(out) + inplace: (x -> out) # 关键字段:指定 x 和 out 可以 in-place + backward : abs_grad +``` + +2. **Python API 配置**(`python_api_info.yaml`,第 6-9 行): + - ⚠️ **仅在 C++下沉(方案 2)时需要配置** +```yaml +- op : abs_ + name : [paddle.abs_, paddle.Tensor.abs_] + args_alias : + use_default_mapping : True +``` + +# 五、代码修改规范 + +## 5.1 代码注释规范 +- ✅ 改动位置如果方便注释,可以注释`# Edit by AI Agent`,表明这是你完成的工作,但只能注释 1 次 + +## 5.2 代码质量规范 +- ✅ 保持代码风格与项目一致 +- ✅ 不破坏现有功能 +- ✅ 确保向后兼容性 + +## 5.3 测试规范 +- ✅ 修改后必须通过原有测试 +- ✅ 必须添加新的单元测试 +- ✅ 必须通过 PyTorch 对齐验证 + +## 5.4 文档规范 +- ✅ 同步更新中文文档 +- ✅ 文档格式符合 Paddle 规范 +- ✅ 准确描述 API 功能和参数 + + +# 六、标准工作流程 + +## 6.1 流程概览 + +``` +输入 API 列表 → Step1:所有 API 方案决策 → Step2:所有 API 代码修改 → Step3:所有 API 对齐验证 → Step4:所有 API 文档更新 → 全部完成(流程全自动推进,不用询问) +``` + +具体如下: +### Step 1:方案决策(API 改动方案决策智能体) + Step 1.1: 分析差异文档 + Step 1.2: 方案决策 + +### Step 2:代码修改 +#### 方案 1:Python 装饰器(Python 装饰器智能体) + Step 2.1: 差异分析与选择装饰器 + Step 2.2: 应用或开发装饰器 + Step 2.3: 添加 out 参数支持 + Step 2.4: 更新函数文档字符串 + Step 2.5: 添加测试用例 + Step 2.6: 编译并运行 +#### 方案 2:C++下沉(Cpp 下沉智能体) + Step 2.1: 配置 python_api_info.yaml + Step 2.2: 迁移文档到_paddle_docs.py + Step 2.3: 替换 Python 实现 + Step 2.4: 添加测试用例 + Step 2.5: 编译并运行 + +### Step 3:对齐验证(Pytorch 对齐验证智能体) + Step 3.1: 标记已对齐的 API + Step 3.2: 补充测试用例 + Step 3.3: 运行单元测试 + +### Step 4:文档更新(API 文档修改智能体) + Step 4.1: 获取代码变更信息 + Step 4.2: 更新 API 中文文档 + +**执行逻辑**: +1. 接收用户输入的待对齐 API 列表(如:`torch.argmax`, `torch.log2`, `torch.logsumexp`) +2. **批量处理模式**:按 Step 顺序依次执行,每个 Step 处理完所有 API 后才进入下一个 Step + - Step1:对**所有 API**进行方案决策,记录每个 API 的方案类型 + - Step2:对**所有 API**进行代码修改 + - Step3:对**所有 API**进行对齐验证 + - Step4:对**所有 API**更新文档 +3. **流程推进的豁免与放弃条件**: + - **豁免条件**(跳过后续步骤,但记录决策结果): + * 若决策不为方案 1/2,则该 API 跳过后续 Step2~4,无需自行处理 + - **放弃策略**(合理分配精力,最大化成功率): + * **放弃判断标准**: + - 当某个 API 在 Step2 或 Step3 经过多次尝试(建议 3 次)仍无法通过验证 + - 经分析判断短期内难以解决,继续投入时间成本过高 + * **放弃执行要求(必须严格遵守)**: + - ⚠️ 必须完整回退该 API 在 Step2 和 Step3 中的所有代码修改 + - ⚠️ 确保项目处于干净状态,不得保留任何"修改了但没改对"的中间状态 + - 在最终的对齐结果统计表中标记该 API 为"未对齐",并简要说明放弃原因 + * **整体策略原则**: + - 目标是最大化 API 列表的整体对齐成功率,而非执着于单个 API + - 优先处理更可能成功的 API,避免在困难 API 上消耗过多时间 + - 放弃是为了提高整体效率的理性决策,不是逃避问题 +4. 所有 API 都完成 4 个步骤(除被豁免或放弃外)后,任务结束 + + +## 6.2 详细步骤 + +### Step 1: 方案决策 ⚙️ + +**目标**:确定每个 API 的改动方案 + +**执行步骤**: +1. 输入:需要对齐的 PyTorch API 列表(如 `torch.atan`、`torch.asinh`) +2. 调用 `API 改动方案决策智能体` +3. 输出:方案类型、对应 Paddle API、差异分类、决策依据 + +**方案类型**: +- 无需改动 +- 方案 1:Python 装饰器 +- 方案 2:C++下沉 +- 方案 3:修改 API +- 方案 4:新增 API +- 方案 5:新增 compat 类型 API + +### Step 2: 代码修改 💻 + +**目标**:根据方案修改 Paddle API 代码 + +**执行步骤**: +1. 输入:方案类型、对应 Paddle API(如 `paddle.atan`、`paddle.asinh`)、差异分类、决策依据 +2. 根据方案类型,调用对应的子智能体,每个子智能体批量处理其所负责的 API: + - 方案 1 → `Python 装饰器智能体` + - 方案 2 → `Cpp 下沉智能体` + - 方案 3 → `修改 API 智能体`(豁免) + - 方案 4 → `新增 API 智能体`(豁免) + - 方案 5 → `新增 compat 类型 API 智能体`(豁免) +3. 输出:是否代码修改无误(即单测运行通过) + +**异常处理**: +- 子智能体多次调试仍异常时,主控智能体根据报错信息评估,是否需要返回执行前序步骤: + - 是否 Step1 中有 API 的方案决策错误? + + +### Step 3: 对齐验证 ✅ **(金标准)** + +**目标**:验证修改后的 Paddle API 能与 PyTorch API 完全对齐 + +**执行步骤**: +1. 输入:PyTorch API 列表(如 `torch.atan`、`torch.asinh`) +2. 调用 `Pytorch 对齐验证智能体` +3. 输出:是否通过对齐验证(即单测运行通过) + +**异常处理**: +- 子智能体多次调试仍异常时,主控智能体根据报错信息评估,是否需要返回执行前序步骤: + - 是否 Step1 中有 API 的方案决策错误? + - 是否 Step2 中有 API 的代码实现有误? + +### Step 4: 文档更新 📝 + +**目标**:更新 Paddle API 中文文档 + +**执行步骤**: +1. 调用 `API 文档修改智能体` +2. 确保文档编写正确 + + +## 6.3 重要约束 ⚠️ + +1. **流程正向推进原则** + - 正常情况下必须遵循 Step1 → Step2 → Step3 → Step4 的顺序 + - 每个步骤完成并验证通过后,才能进入下一步骤 + - 禁止跳过任何步骤(特别是 Step3 对齐验证步骤) + +2. **异常回溯调整原则** + - 当 Step2(代码修改)或 Step3(对齐验证)多次尝试仍无法通过时 + - 主智能体需要根据错误信息诊断问题根源: + * 若判断为方案选择错误 → 返回 Step1 重新决策 + * 若判断为代码实现有误 → 在 Step2 调整实现方式 + - 回溯后需从该步骤重新按流程向前推进,例如回溯到 Step2,则重新 Step2 → Step3 → Step4 + +3. **完整性保障** + - 每个 API 的 4 个步骤都必须完整执行(除被豁免或放弃外) + - 即使需要回溯调整,最终也要确保走完全流程 + - 所有步骤的产出物(代码、测试、文档)必须齐全 + + +## 6.4 工作示例 + +假设待对齐 API 为 `torch.argmax`: + +``` +1. Step1: 方案决策 → 得到『方案 2:C++下沉』 +2. Step2: 代码修改 → 修改 Paddle 目录,将 paddle.argmax 下沉到 C++ +3. Step3: 对齐验证 → 修改 PaConvert 目录,编写 Pytorch 单元测试,对比测试,验证对齐 +4. Step4: 文档更新 → 修改 docs 目录,更新 paddle.argmax 文档 +5. 完成: 确认输入的所有 API 已完全对齐 +``` + +# 七、子智能体体系 + +| 序号 | 智能体名称 | 负责步骤 | 主要职责 | 对应方案 | +|------|-----------|---------|---------|---------| +| 1 | **API 改动方案决策智能体** | Step 1 | 根据差异文档分析决策改动方案 | - | +| 2 | **Python 装饰器智能体** | Step 2 | 通过装饰器对齐参数签名 | 方案 1:Python 装饰器 | +| 3 | **Cpp 下沉智能体** | Step 2 | 将 API 从 Python 层下沉到 C++层 | 方案 2:C++下沉 | +| 4 | **修改 API 智能体**(暂未实现) | Step 2 | 修改现有 API 实现 | 方案 3:修改 API 方案 | +| 5 | **新增 API 智能体**(暂未实现) | Step 2 | 新增缺失的 API | 方案 4:新增 API 方案 | +| 6 | **新增 compat 类型 API 智能体**(暂未实现) | Step 2 | 添加兼容性 API | 方案 5:新增 compat 方案 | +| 7 | **Pytorch 对齐验证智能体** | Step 3 | 验证修改后的 Paddle API 能与 PyTorch API 完全对齐 | - | +| 8 | **API 文档修改智能体** | Step 4 | 更新 Paddle API 中文文档 | - | + + +# 八、注意事项 +1. 复盘记忆中的历史易错点,避免重复犯错 +2. 严格按标准工作流程执行,杜绝自行臆断和跳过步骤 diff --git a/docs/dev_guides/coding_agent_rules/api_compatibility/4-modify-docs.mdr b/docs/dev_guides/coding_agent/api_compatibility/api-docs-updater.mdr similarity index 81% rename from docs/dev_guides/coding_agent_rules/api_compatibility/4-modify-docs.mdr rename to docs/dev_guides/coding_agent/api_compatibility/api-docs-updater.mdr index 82c101559b6..4145a35a132 100644 --- a/docs/dev_guides/coding_agent_rules/api_compatibility/4-modify-docs.mdr +++ b/docs/dev_guides/coding_agent/api_compatibility/api-docs-updater.mdr @@ -1,7 +1,7 @@ --- -description: API文档修改智能体 -globs: -alwaysApply: false +name: API文档修改智能体 +description: 负责在API代码修改完成后,同步更新中文API文档,确保文档准确反映API的最新行为 +tools: grep_content, read_file, glob_path, codebase_search, list_dir, write_file, edit_file, delete_file, run_command --- # 一、角色定义 @@ -22,7 +22,7 @@ alwaysApply: false ## Step 1: 查找API英文文档 🔍 在Paddle目录中查找API英文文档,有两种可能存储位置: -1. 直接存储在API实现代码中,作为Python函数/类的__doc__文档字符串 +1. 直接存储在API实现代码中,作为Python函数/类的`__doc__`文档字符串 2. 集中存储在`_paddle_docs.py`文件中(完整路径为Paddle/python/paddle/_paddle_docs.py) ## Step 2: 更新API中文文档 📝 @@ -40,7 +40,9 @@ alwaysApply: false **适用场景**:API参数新增别名(常见于C++下沉方案) -**修改位置**:参数说明部分 +**修改位置**:参数部分 + +> 注:别名说明应放在该参数描述的末尾,格式为: 别名: ``alias_name`` ,多个别名描述为: 别名: ``alias_name1`` 或 ``alias_name2`` **修改示例**: ```rst @@ -58,7 +60,7 @@ alwaysApply: false #### 模式2:新增关键字参数 -**适用场景**:新增 `out` 参数支持 +**适用场景**:新增 `out` 参数 **修改位置**:函数签名 + 新增"关键字参数"小节 @@ -78,9 +80,9 @@ alwaysApply: false #### 模式3:签名重载(overload) -**适用场景**:有多种签名风格,API实现中有@overload标识 +**适用场景**:API实现中有@overload标识 -**修改位置**:在文档正文中分别描述两种签名,其他位置仍以Paddle签名为准 +**修改位置**:只需在文档正文中阐述两种签名(Paddle在前,Pytorch在后),文档其他位置(参数/返回)仍以Paddle风格签名为准 **修改示例**: ```rst @@ -110,7 +112,7 @@ Tensor, 与 ``inputs`` 数据类型相同。 **适用场景**:为已有API添加别名(如 `cat` → `concat`) -**文件操作**:创建新的.rst文件 +**文件操作**:创建新的.rst文件,并同时更新 `Overview_cn.rst` 添加索引项 **文档内容**: ```rst @@ -124,8 +126,6 @@ cat ``concat`` 的别名,请参考 :ref:`cn_api_paddle_concat`。 ``` -**同时更新**:`Overview_cn.rst` 添加索引项 - #### 模式5:新增完整API中文文档 **适用场景**:全新API(如 `broadcast_shapes`) @@ -164,11 +164,10 @@ COPY-FROM: paddle.api_name ### 文档格式规范 1. ✅ 使用rst格式,严格遵循缩进规则 -2. ✅ 参数说明使用 `- **参数名** (类型) - 说明。别名 ``alias``。` 格式 -3. ✅ 关键字参数单独一个小节,使用 `关键字参数` 标题 -4. ✅ 函数签名中 `*` 后的参数为关键字参数 -5. ✅ 交叉引用使用 `:ref:` 语法 -6. ✅ 代码示例使用 `COPY-FROM:` 自动生成 +2. ✅ 关键字参数单独一个小节,使用 `关键字参数` 标题 +3. ✅ 函数签名中 `*` 后的参数为关键字参数 +4. ✅ 交叉引用使用 `:ref:` 语法 +5. ✅ 代码示例使用 `COPY-FROM:` 自动生成 # 四、修改示例参考 @@ -270,7 +269,7 @@ COPY-FROM: paddle.broadcast_shapes ``` # 六、注意事项 -1. Tensor类方法(如paddle.Tensor.abs)没有中英文档,无需修改,请勿与普通函数方法(如paddle.abs)的文档`{api_name}_cn.rst`混淆。 -2. Inplace方法如果有对应普通方法,则只需更新签名即可,不需要修改文档内容,因为其文档内容一般无实质内容。 -3. overload签名重载情况下,只需在正文阐述两种签名(Paddle在前,Pytorch在后),其他位置(签名、参数、返回)仍以Paddle风格签名为准。 -4. 保留原有的中文文档风格和格式,不要删除中文文档原有内容,如有缺失内容可以新增。 +1. Tensor类方法(如paddle.Tensor.abs)没有文档,无需处理,请勿与普通方法(如paddle.abs)的文档`{api_name}_cn.rst`混淆。 +2. Inplace方法(如paddle.abs_等下划线API),只需要更新API签名,不需要修改文档 +3. 保留原有的文档风格和格式,不要大面积删除文档原内容 +4. 示例代码采用COPY-FROM: 格式,不要修改 diff --git a/docs/dev_guides/coding_agent_rules/api_compatibility/2-2-sink-to-cpp.mdr b/docs/dev_guides/coding_agent/api_compatibility/cpp-sink.mdr similarity index 83% rename from docs/dev_guides/coding_agent_rules/api_compatibility/2-2-sink-to-cpp.mdr rename to docs/dev_guides/coding_agent/api_compatibility/cpp-sink.mdr index a2be5f26b7c..721b0567f31 100644 --- a/docs/dev_guides/coding_agent_rules/api_compatibility/2-2-sink-to-cpp.mdr +++ b/docs/dev_guides/coding_agent/api_compatibility/cpp-sink.mdr @@ -1,7 +1,7 @@ --- -description: Cpp下沉智能体 -globs: -alwaysApply: false +name: Cpp下沉智能体 +description: 负责实施C++下沉方案的代码修改,通过该方案实现API对齐一致 +tools: grep_content, read_file, glob_path, codebase_search, write_file, edit_file, delete_file, run_command --- # 一、角色定义 @@ -44,27 +44,29 @@ alwaysApply: false **说明:** - `name`:指定对应的Python API名称(函数API和Tensor方法) -- `use_default_mapping: True`:自动将`input`映射为`x`(兼容torch),默认已配置如下字段映射: -```python -# 如果不在以下范围里,请配置自定义映射 -args_default_mapping = { - "x": ["input"], - "y": ["other"], - "axis": ["dim"], - "keepdims": ["keepdim"], -} +- `use_default_mapping : True`:自动配置如下字段映射: +```yaml +- op : op_name + name : [paddle.op_name, paddle.Tensor.op_name] + args_alias : + x: [input] + y: [other] + axis: [dim] + keepdims: [keepdim] ``` -- 若需自定义映射,使用格式: +- 不在上述字段映射范围里,允许配置自定义映射,格式: ```yaml -args_alias: -x : [input] -axis : [dim] +- op : op_name + name : [paddle.op_name, paddle.Tensor.op_name] + args_alias : + y : [exponent] ``` - 注意key和value不要配置反了,Paddle的参数名为key,Pytorch的参数名为value(列表) ### Step 2:迁移文档到 `_paddle_docs.py` -注意要更新函数文档字符,为有别名的参数添加Alias Support说明,如果有out还需要添加out说明,如下: +注意要更新函数文档字符,在文档的Args部分为有别名的参数添加Alias Support说明,如下: +> 注:Alias说明应放在该参数描述的末尾,格式为: Alias: ``alias_name`` ,多个Alias描述为: Alias: ``alias_name1`` or ``alias_name2`` ```python add_doc_and_signature( @@ -128,15 +130,34 @@ def log2( ) ``` +如果支持了out参数,还必须在文档字符串中描述out参数,out为keyword-only参数时在Keyword args部分描述,为位置参数时在Args部分描述,如下: +```python +# out为keyword-only参数 +""" +Args: + ... + +Keyword Args: + out (Tensor|optional): The output tensor. Default: None. + +Returns: + ... +""" + +# out为位置参数 +""" +Args: + out (Tensor, optional): The output Tensor. Default: None. + +Returns: + ... +""" +``` + **注意事项**: -- 如果API支持`out`参数,必须在_paddle_docs.py中添加`out`参数说明 -- Alias说明应放在参数描述的末尾 -- 使用`Alias: ``alias_name``.格式 -- 多个Alias别名描述为: `Alias: ``input`` or ``data``.` -- out参数使用关键字参数来描述 -- Tensor类方法(如paddle.Tensor.abs)没有文档,无需处理 -- Inplace方法如果有对应普通方法,则只需更新签名即可,不需要修改文档内容,因为其文档内容一般无实质内容 -- 注意文档格式规范,需符合 `_paddle_docs.py` 当前格式规范 +- Tensor类方法(如paddle.Tensor.abs)没有文档,无需处理,请勿与普通方法(如paddle.abs)混淆 +- Inplace方法(如paddle.abs_等下划线API),只需要更新API签名,不需要修改文档 +- 注意文档格式规范,需与 `_paddle_docs.py` 现有文档格式保持一致 ### Step 3:替换Python实现 @@ -154,22 +175,16 @@ from paddle._C_ops import log2 # noqa: F401 # ... ``` -### Step 4:添加测试用例到 `test_api_compatibility.py` +### Step 4:添加测试用例 -不要新建任何测试文件,直接在 `test/legacy_test/test_api_compatibility.py` 中添加测试: +不要新建任何测试文件,直接在 `test/legacy_test/test_api_compatibility[1-9]\.py` 中添加测试。严格按以下模板来编写: +**测试模板**: ```python -class Test(unittest.TestCase): +class TestAPI(unittest.TestCase): def setUp(self): np.random.seed(2025) - self.places = get_devices() - self.shape = [...] - self.dtype = 'float32' - self.init_data() - - def init_data(self): - self.np_x = np.random.rand(*self.shape).astype(self.dtype) - # Other initializations... + self.np_x = np.random.rand(...).astype(...) def test_dygraph_Compatibility(self): paddle.disable_static() @@ -181,7 +196,7 @@ class Test(unittest.TestCase): # 2. Paddle keyword arguments out2 = paddle.(x=x, ...) - # 3. Pytorch Positional arguments (if different with paddle args) + # 3. Pytorch Positional arguments (only if order different with paddle args) out3 = paddle.(x, ...) # 4. PyTorch keyword arguments (alias) @@ -190,15 +205,14 @@ class Test(unittest.TestCase): # 5. Mixed arguments out5 = paddle.(x, axis=...) - # 6. out parameter test (if supported) - if hasattr(self, 'supports_out') and self.supports_out(): - out6 = paddle.empty_like(x) - out7 = paddle.(x, ..., out=out5) + # 6. out parameter test (only if supported) + out6 = paddle.empty_like(x) + out7 = paddle.(x, ..., out=out6) - # 7. Tensor method - args + # 7. Tensor method - args (only if supported) out8 = x.(...) - # 8. Tensor method - kwargs + # 8. Tensor method - kwargs (only if supported) out9 = x.(axis=...) # Verify all outputs @@ -231,19 +245,32 @@ class Test(unittest.TestCase): np.testing.assert_allclose(out, ...) ``` -必须覆盖的场景: +**测试规范**: +动态图模式: +1. ✅ Paddle位置参数(全部位置参数) +2. ✅ Paddle关键字参数(全部关键字参数) +3. ✅ PyTorch位置参数(如果Pytorch与Paddle参数顺序不同) +4. ✅ PyTorch关键字参数(使用参数别名) +5. ✅ 混合参数(如果参数量>=2,位置+关键字) +6. ✅ out参数(如果API支持,inplace无需测) +7. ✅ 类方法Pytorch位置参数(如果有类方法) +8. ✅ 类方法Pytorch关键字参数(如果有类方法) + +静态图模式:(inplace无需测) 1. ✅ Paddle位置参数(全部位置参数) 2. ✅ Paddle关键字参数(全部关键字参数) -3. ✅ PyTorch位置参数(如与Paddle位置参数不同) -4. ✅ PyTorch关键字参数(使用别名) -5. ✅ 混合参数(位置+关键字) -6. ✅ out参数(如API支持) -7. ✅ 类方法调用(位置参数) -8. ✅ 类方法调用(关键字参数) -9. ✅ 动态图和静态图两种模式 -10. ✅ 异常参数(参数缺失、类型错误、关键字名错误) +3. ✅ PyTorch位置参数(如果Pytorch与Paddle参数顺序不同) +4. ✅ PyTorch关键字参数(使用参数别名) +5. ✅ 类方法Pytorch位置参数(如果有类方法) +6. ✅ 类方法Pytorch关键字参数(如果有类方法) -完整测试示例,请参考 `Paddle/test/legacy_test/test_api_compatibility.py` 中已有的测试类结构。 +注意: +1. 有些测试项是可选的,需要自行判断是否需要添加。 +2. 添加测试项需要遵循上述顺序,不要打乱。 +3. 输出结果序号需要保持连贯,每一个输出结果均需要检验,尽可能循环检验减少行数。 +3. 比对测试项,对于内容相同的测试项,不要重复添加。 + +完整测试示例,请参考 `Paddle/test/legacy_test/test_api_compatibility[1-9]\.py` 中已有的测试类结构。 ### Step 5:编译并运行 @@ -572,7 +599,28 @@ void ArgMaxMinMapper(PyObject* args, 3. **参数别名支持:** - 通过传入别名列表`{"x", "input"}`同时支持Paddle和Torch风格 -### Step 3~6:参考场景一的Step 2~5 +### Step 3: 迁移文档到 `_paddle_docs.py` +除了完成场景一的文档迁移操作之外,场景三文档迁移还需要额外注意: + +如果使用了自定义Mapper,则API有可能支持了签名重载,需要分别描述两种签名,如下: +> 注:只需在文档正文中阐述两种签名(Paddle在前,Pytorch在后),文档其他位置如Args/Returns仍以Paddle风格签名为准 + +```python +""" +This API has two signatures: + +1. ``paddle.sum(x, axis=None, dtype=None, keepdim=False, name=None, *, out=None)`` (Paddle-style) +2. ``paddle.sum(input, dim=None, keepdim=False, dtype=None, *, out=None)`` (PyTorch-style) + +Args: + ... + +Returns: + ... +""" +``` + +### Step 4~6:参考场景一的Step 3~5 ## 2.4 不同场景对比 diff --git a/docs/dev_guides/coding_agent_rules/api_compatibility/2-1-python-decorator.mdr b/docs/dev_guides/coding_agent/api_compatibility/python-decorator.md similarity index 57% rename from docs/dev_guides/coding_agent_rules/api_compatibility/2-1-python-decorator.mdr rename to docs/dev_guides/coding_agent/api_compatibility/python-decorator.md index e19451a07a8..871c2b7f2c0 100644 --- a/docs/dev_guides/coding_agent_rules/api_compatibility/2-1-python-decorator.mdr +++ b/docs/dev_guides/coding_agent/api_compatibility/python-decorator.md @@ -1,59 +1,59 @@ --- -description: Python装饰器智能体 -globs: -alwaysApply: false +name: Python 装饰器智能体 +description: 负责实施 Python 装饰器方案的代码修改,通过该方案实现 API 对齐一致 +tools: grep_content, read_file, glob_path, codebase_search, list_dir, write_file, edit_file, delete_file, run_command --- # 一、角色定义 -你擅长《Paddle API对齐PyTorch项目》中的**Python装饰器方案**的代码开发。通过Python装饰器,在Python层为Paddle API提供参数别名、参数顺序、参数类型和参数用法的兼容转换,实现PyTorch风格的API调用,并保持Paddle API的向后兼容性。 +你擅长《Paddle API 对齐 PyTorch 项目》中的**Python 装饰器方案**的代码开发。通过 Python 装饰器,在 Python 层为 Paddle API 提供参数别名、参数顺序、参数类型和参数用法的兼容转换,实现 PyTorch 风格的 API 调用,并保持 Paddle API 的向后兼容性。 **特点**: -- **零侵入性**:无需修改API的实现代码 -- **适用面广**:支持灵活处理各种API签名重载情况,如参数名不同、参数顺序不同、参数个数不同、参数类型不同、参数用法不同等 -- **向后兼容**:保持Paddle原有API调用方式 -- **开发效率**:相比C++下沉方案,修改更快速直接 -- **性能开销**:Python装饰器层会引入轻微性能开销 +- **零侵入性**:无需修改 API 的实现代码 +- **适用面广**:支持灵活处理各种 API 签名重载情况,如参数名不同、参数顺序不同、参数个数不同、参数类型不同、参数用法不同等 +- **向后兼容**:保持 Paddle 原有 API 调用方式 +- **开发效率**:相比 C++下沉方案,修改更快速直接 +- **性能开销**:Python 装饰器层会引入轻微性能开销 # 二、现有装饰器体系 -Paddle现有装饰器统一位于 `Paddle/python/paddle/utils/decorator_utils.py`,按功能分为两类: +Paddle 现有装饰器统一位于 `Paddle/python/paddle/utils/decorator_utils.py`,按功能分为两类: ## 2.1 通用别名装饰器 | 装饰器 | 支持参数数量 | 性能 | 使用场景 | 优先级 | |---------|-------------|------|----------|--------| -| `param_one_alias` | 1个 | 高 | 单个参数别名(如 x↔input) | ⭐⭐⭐ | -| `param_two_alias` | 2个 | 高 | 两个参数别名(如 x↔input, axis↔dim) | ⭐⭐⭐ | -| `ParamAliasDecorator` | 3个及以上 | 中 | 复杂参数映射场景 | ⭐⭐ | -| `param_two_alias_one_default` | 2个+默认值 | 低 | 需要默认值(median专用) | ⭐(不推荐)| +| `param_one_alias` | 1 个 | 高 | 单个参数别名(如 x↔input) | ⭐⭐⭐ | +| `param_two_alias` | 2 个 | 高 | 两个参数别名(如 x↔input, axis↔dim) | ⭐⭐⭐ | +| `ParamAliasDecorator` | 3 个及以上 | 中 | 复杂参数映射场景 | ⭐⭐ | +| `param_two_alias_one_default` | 2 个+默认值 | 低 | 需要默认值(median 专用) | ⭐(不推荐)| ## 2.2 专用装饰器 | 装饰器 | 功能描述 | 关键特性 | |--------|----------|----------| -| `index_select_decorator` | 参数别名 + 参数顺序转换 | 检测第2个位置参数是否为int来判断不同参数顺序 | -| `index_add_decorator` | 参数别名 + 参数顺序转换 | 检测第2个位置参数是否为int来判断不同参数顺序 | -| `transpose_decorator` | 参数别名 + 参数用法转换 | 通过dim0/dim1两个int来自动构造perm列表 | -| `size_args_decorator` | 参数别名 + 可变参数 | 合并全部int位置参数为shape列表 | -| `view_decorator` | 参数别名 + 可变参数 | 合并全部int位置参数为shape列表 | -| `reshape_decorator` | 参数别名 + 可变参数 | 第1个参数别名,合并后面多个int位置参数为shape列表 | -| `expand_decorator` | 参数别名 + 可变参数 | 第1个参数别名,合并后面多个int位置参数为shape列表 | -| `legacy_reduction_decorator` | 参数别名 + 报错信息增强 | 检测到size_average/reduce用法后,增强报错信息 | -| `lp_pool_function_decorator` | 参数别名 + 参数顺序转换 | 检测第5个位置参数是否为bool来判断不同参数顺序 | +| `index_select_decorator` | 参数别名 + 参数顺序转换 | 检测第 2 个位置参数是否为 int 来判断不同参数顺序 | +| `index_add_decorator` | 参数别名 + 参数顺序转换 | 检测第 2 个位置参数是否为 int 来判断不同参数顺序 | +| `transpose_decorator` | 参数别名 + 参数用法转换 | 通过 dim0/dim1 两个 int 来自动构造 perm 列表 | +| `size_args_decorator` | 参数别名 + 可变参数 | 合并全部 int 位置参数为 shape 列表 | +| `view_decorator` | 参数别名 + 可变参数 | 合并全部 int 位置参数为 shape 列表 | +| `reshape_decorator` | 参数别名 + 可变参数 | 第 1 个参数别名,合并后面多个 int 位置参数为 shape 列表 | +| `expand_decorator` | 参数别名 + 可变参数 | 第 1 个参数别名,合并后面多个 int 位置参数为 shape 列表 | +| `legacy_reduction_decorator` | 参数别名 + 报错信息增强 | 检测到 size_average/reduce 用法后,增强报错信息 | +| `lp_pool_function_decorator` | 参数别名 + 参数顺序转换 | 检测第 5 个位置参数是否为 bool 来判断不同参数顺序 | # 三、标准工作流程 ## Step 1: 差异分析与选择装饰器 -根据PyTorch API与Paddle API的**差异分析**来区分不同场景: +根据 PyTorch API 与 Paddle API 的**差异分析**来区分不同场景: ### 1. 仅参数名不同(参数顺序相同) -根据需要映射的参数数量选择: -- 1个参数 → `param_one_alias` -- 2个参数 → `param_two_alias` -- 3个及以上参数 → `ParamAliasDecorator` +根据需要映射的参数数量,选择对应的通用别名装饰器: +- 1 个参数 → `param_one_alias` +- 2 个参数 → `param_two_alias` +- 3 个及以上参数 → `ParamAliasDecorator` **使用示例**: ```python @@ -84,11 +84,11 @@ def normalize(x, p=2, axis=1, epsilon=1e-12, out=None, name=None): ### 2. 参数名不同 + 可变参数 -选择现有专用装饰器:`size_args_decorator`、`reshape_decorator`、`expand_decorator`、`view_decorator` +开发新的专用装饰器,可参考`size_args_decorator`、`reshape_decorator`、`expand_decorator`、`view_decorator` **使用示例**: ```python -# torch.reshape(x, 2, 5) # shape支持可变参数用法 +# torch.reshape(x, 2, 5) # shape 支持可变参数用法 # paddle.reshape(x, [2, 5]) from paddle.utils.decorator_utils import reshape_decorator @reshape_decorator() @@ -127,14 +127,13 @@ def transpose(x, perm=None, name=None): ## Step 2: 应用或开发装饰器 根据**Step1**中的不同场景: -- **场景 1 & 2**(仅参数名不同、可变参数):请进入 **方式一(使用现有装饰器)**。 -- **场景 3 & 4**(参数顺序不同、参数用法不同及其他情况):请进入 **方式二(开发新的专用装饰器)**。 +- **场景 1**(仅参数名不同):请进入 **方式一(通用别名装饰器)**。 +- **场景 3 & 4**(可变参数、参数顺序不同、参数用法不同及其他情况):请进入 **方式二(开发新的专用装饰器)**。 -### 方式一:使用现有装饰器 +### 方式一:通用别名装饰器 -1. 在API函数文件中导入装饰器 -2. 在API函数定义前添加装饰器 -3. 如需添加out参数,在函数签名中添加(见Step 3) +1. 在 API 函数文件中导入装饰器 +2. 在 API 函数定义前添加装饰器 **示例**: ```python @@ -149,7 +148,7 @@ def cumsum(x, axis=None, dtype=None, name=None): 1. 在`Paddle/python/paddle/utils/decorator_utils.py`中定义新装饰器 2. 按照以下模板和要点实现 -3. 在API函数上使用新装饰器 +3. 在 API 函数上使用新装饰器 **装饰器模板**: ```python @@ -173,7 +172,7 @@ def custom_decorator(): kwargs["x"] = kwargs.pop("input") # 2. 参数顺序转换或其他特殊处理 - # 根据需要调整args + # 根据需要调整 args # 3. 调用原函数 return func(*args, **kwargs) @@ -195,7 +194,7 @@ if "input" in kwargs and "x" not in kwargs: 2. **位置参数类型检测**(用于判断参数顺序) ```python if len(args) >= 2 and isinstance(args[1], int): - # 检测args第2个值是否为int,从而判断是torch用法还是paddle用法,并根据不同的args顺序统一匹配为kwargs + # 检测 args 第 2 个值是否为 int,从而判断是 torch 用法还是 paddle 用法,并根据不同的 args 顺序统一匹配为 kwargs ## torch.index_select(input, dim, index) ## paddle.index_select(x, index, axis) kwargs["x"] = args[0] @@ -205,7 +204,7 @@ if len(args) >= 2 and isinstance(args[1], int): 3. **可变参数处理** ```python -# 合并多个int位置参数为列表 +# 合并多个 int 位置参数为列表 if len(args) >= 2 and all(isinstance(arg, int) for arg in args[1:]): kwargs["shape"] = list(args[1:]) args = args[:1] @@ -224,9 +223,9 @@ def index_select_decorator(): if "dim" in kwargs and "axis" not in kwargs: kwargs["axis"] = kwargs.pop("dim") - # 2. PyTorch参数顺序匹配:识别不同的args顺序,统一处理为kwargs + # 2. PyTorch 参数顺序匹配:识别不同的 args 顺序,统一处理为 kwargs if len(args) >= 2 and isinstance(args[1], int): - # PyTorch顺序: (input, dim, index) → Paddle顺序: (x, index, axis) + # PyTorch 顺序: (input, dim, index) → Paddle 顺序: (x, index, axis) kwargs["x"] = args[0] kwargs["axis"] = args[1] if len(args) > 2: @@ -243,9 +242,9 @@ def index_select_decorator(): **注意事项**: 1. 尽可能参考 `Paddle/python/paddle/utils/decorator_utils.py` 中已有的专用装饰器来实现,在风格和逻辑上保持尽可能一致 -2. 如果两者API对应参数的顺序不同,则装饰器需要通过位置参数(args)类型检测来区分两者,并分别匹配不同的参数顺序 -3. 专用装饰器应该尽可能逻辑简单,只假定存在Paddle签名+Pytorch签名两种用法,其他情况不做判断,提升性能 -4. overload注解:为避免添加专用装饰器后原API签名可读性差的问题,需要针对Paddle原签名、Pytorch新签名分别添加overload注解(Paddle在前,Pytorch在后) +2. 如果两者 API 对应参数的顺序不同,则装饰器需要通过位置参数(args)类型检测来区分两者,并分别匹配不同的参数顺序 +3. 专用装饰器应该尽可能逻辑简单,只假定存在 Paddle 签名+Pytorch 签名两种用法,其他情况无需判断,提升性能 +4. overload 注解:专有装饰器需添加 overload 注解(通用别名装饰器无需注解),需针对 Paddle 签名、Pytorch 签名分别添加 overload 注解(Paddle 在前,Pytorch 在后) ```python @overload def gather( @@ -265,21 +264,23 @@ def gather( ) -> Tensor: ... ``` -## Step 3: 添加out参数支持(如需要) +## Step 3: 添加 out 参数支持 -### 方式一:直接指定out(推荐) +仅支持新增 out 参数,新增其他参数则需方案 3(修改 API 智能体)来开展。 + +### 方式一:直接指定 out(推荐) **适用条件**: -1. API最后一个逻辑是调用`_C_ops` -2. API调用了其他API,调用的最后一个其他API也支持out +1. 情况 1:API 最后一个逻辑是调用`_C_ops`;情况 2:API 调用了其他 API,调用的最后一个其他 API 也支持 out +2. out 参数只有一个 Tensor **示例**: ```python -# API最后一个逻辑是调用`_C_ops` +# 情况 1:API 最后一个逻辑是调用`_C_ops` @param_two_alias(["x", "input"], ["y", "other"]) def less_than(x, y, name=None, *, out=None) -> Tensor: """ - Args: + Keyword args: ... out (Tensor|None, optional): The output tensor. Default: None. """ @@ -288,12 +289,14 @@ def less_than(x, y, name=None, *, out=None) -> Tensor: else: ... -# API调用的最后一个其他API也支持out +# 情况 2:API 调用的最后一个其他 API 也支持 out @param_two_alias(["x", "input"], ["axis", "dim"]) def fft(x, n=None, axis=-1, norm="backward", name=None, *, out=None) -> Tensor: """ Args: ... + + Keyword args: out (Tensor|None, optional): The output tensor. Default: None. """ if is_integer(x) or is_floating_point(x): @@ -304,7 +307,7 @@ def fft(x, n=None, axis=-1, norm="backward", name=None, *, out=None) -> Tensor: return fft_c2c(x, n, axis, norm, forward=True, name=name, out=out) ``` -### 方式二:通过assign实现 +### 方式二:通过 assign 实现 **适用条件**:不符合方式一的情况 @@ -314,21 +317,32 @@ def func(x, axis=None, name=None, *, out: Tensor | None = None): """ Args: ... + + Keyword args: out (Tensor|None, optional): The output tensor. Default: None. """ + # case1: 只有 1 个 out 的情况 ret = <计算逻辑> - if out is not None: paddle.assign(ret, out) return out return ret + + # case2: 有多个 out 的情况 + ret1, ret2 = <计算逻辑> + if out is not None: + paddle.assign(ret1, out[0]) + paddle.assign(ret2, out[1]) + return out + return ret1, ret2 ``` -注意`out`参数需与Pytorch用法一致,一般情况下均是keyword-only参数(使用`*,`分隔) +注意在 API 签名中增加 out 参数,`out`参数需与 Pytorch 用法一致,一般情况下 out 均是 keyword-only 参数(使用`*,`分隔),少数情况下 out 是位置参数。 ## Step 4: 更新函数文档字符串 -如果使用的是通用别名装饰器,则在函数文档字符串中为有别名的参数添加Alias Support说明和out说明,如下: +如果使用的是通用别名装饰器,则在文档的 Args 部分为有别名的参数添加 Alias Support 说明,如下: +> 注:Alias 说明应放在该参数描述的末尾,格式为: Alias: ``alias_name`` ,多个 Alias 描述为: Alias: ``alias_name1`` or ``alias_name2`` ```python @param_two_alias(["x", "input"], ["axis", "dim"]) @@ -359,7 +373,8 @@ def fft( """ ``` -如果使用的是专用装饰器,则表明API支持了签名重载,需要分别描述两种签名,可以参考代码中的@overload注解,如下: +如果使用的是专用装饰器,则表明 API 支持了签名重载,需要分别描述两种签名,可以参考代码中的@overload 注解,如下: +> 注:只需在文档正文中阐述两种签名(Paddle 在前,Pytorch 在后),文档其他位置如 Args/Returns 仍以 Paddle 风格签名为准 ```python @overload @@ -387,31 +402,52 @@ def broadcast_tensors(input: Sequence[Tensor], name: str | None = None) -> list[ """ ``` +如果支持了 out 参数,必须在 API 文档中描述 out 参数,out 为 keyword-only 参数时在 Keyword args 部分描述,为位置参数时在 Args 部分描述,如下: +```python +# out 为 keyword-only 参数 +def func(x, name=None, *, out=None): + """ + func Operator. + + Args: + ... + + Keyword Args: + out (Tensor|optional): The output tensor. Default: None. + + Returns: + ... + """ + +# out 为位置参数 +def func(x, out=None, name=None): + """ + func Operator. + + Args: + x (Tensor): Input of Atan operator. + out (Tensor, optional): The output Tensor. Default: None. + name (str|None, optional): Name for the operation. + + Returns: + ... + """ +``` + **注意事项**: -- Alias说明应放在参数描述的末尾 -- 使用`Alias: ``alias_name``.格式 -- 多个Alias别名描述为: `Alias: ``input`` or ``data``.` -- out参数使用关键字参数来描述 -- Tensor类方法(如paddle.Tensor.abs)没有英文文档,无需处理 -- Inplace方法如果有对应普通方法,则只需更新签名即可,不需要修改文档内容,因为其文档内容一般无实质内容 -- overload签名重载情况下,只需在文档正文阐述两种签名(Paddle在前,Pytorch在后),其他位置如Args/Returns仍以Paddle风格签名为准。 +- Tensor 类方法(如 paddle.Tensor.abs)没有文档,无需处理,请勿与普通方法(如 paddle.abs)混淆 +- Inplace 方法(如 paddle.abs_等下划线 API),只需要更新 API 签名,不需要修改文档 ## Step 5: 添加测试用例 -不要新建任何测试文件,直接在 `test/legacy_test/test_api_compatibility.py` 中添加测试: +不要新建任何测试文件,直接在 `test/legacy_test/test_api_compatibility[1-9]\.py` 中添加测试。严格按以下模板来编写: +**测试模板**: ```python -class Test(unittest.TestCase): +class TestAPI(unittest.TestCase): def setUp(self): np.random.seed(2025) - self.places = get_devices() - self.shape = [...] - self.dtype = 'float32' - self.init_data() - - def init_data(self): - self.np_x = np.random.rand(*self.shape).astype(self.dtype) - # Other initializations... + self.np_x = np.random.rand(...).astype(...) def test_dygraph_Compatibility(self): paddle.disable_static() @@ -423,7 +459,7 @@ class Test(unittest.TestCase): # 2. Paddle keyword arguments out2 = paddle.(x=x, ...) - # 3. Pytorch Positional arguments (if different with paddle args) + # 3. Pytorch Positional arguments (only if order different with paddle args) out3 = paddle.(x, ...) # 4. PyTorch keyword arguments (alias) @@ -432,15 +468,14 @@ class Test(unittest.TestCase): # 5. Mixed arguments out5 = paddle.(x, axis=...) - # 6. out parameter test (if supported) - if hasattr(self, 'supports_out') and self.supports_out(): - out6 = paddle.empty_like(x) - out7 = paddle.(x, ..., out=out5) + # 6. out parameter test (only if supported) + out6 = paddle.empty_like(x) + out7 = paddle.(x, ..., out=out6) - # 7. Tensor method - args + # 7. Tensor method - args (only if supported) out8 = x.(...) - # 8. Tensor method - kwargs + # 8. Tensor method - kwargs (only if supported) out9 = x.(axis=...) # Verify all outputs @@ -473,19 +508,32 @@ class Test(unittest.TestCase): np.testing.assert_allclose(out, ...) ``` -必须覆盖的场景: -1. ✅ Paddle位置参数(全部位置参数) -2. ✅ Paddle关键字参数(全部关键字参数) -3. ✅ PyTorch位置参数(如与Paddle位置参数不同) -4. ✅ PyTorch关键字参数(使用别名) -5. ✅ 混合参数(位置+关键字) -6. ✅ out参数(如API支持) -7. ✅ 类方法调用(位置参数) -8. ✅ 类方法调用(关键字参数) -9. ✅ 动态图和静态图两种模式 -10. ✅ 异常参数(参数缺失、类型错误、关键字名错误) - -完整测试示例,请参考 `Paddle/test/legacy_test/test_api_compatibility.py` 中已有的测试类结构。 +**测试规范**: +动态图模式: +1. ✅ Paddle 位置参数(全部位置参数) +2. ✅ Paddle 关键字参数(全部关键字参数) +3. ✅ PyTorch 位置参数(如果 Pytorch 与 Paddle 参数顺序不同) +4. ✅ PyTorch 关键字参数(使用参数别名) +5. ✅ 混合参数(如果参数量>=2,位置+关键字) +6. ✅ out 参数(如果 API 支持,inplace 无需测) +7. ✅ 类方法 Pytorch 位置参数(如果有类方法) +8. ✅ 类方法 Pytorch 关键字参数(如果有类方法) + +静态图模式:(inplace 无需测) +1. ✅ Paddle 位置参数(全部位置参数) +2. ✅ Paddle 关键字参数(全部关键字参数) +3. ✅ PyTorch 位置参数(如果 Pytorch 与 Paddle 参数顺序不同) +4. ✅ PyTorch 关键字参数(使用参数别名) +5. ✅ 类方法 Pytorch 位置参数(如果有类方法) +6. ✅ 类方法 Pytorch 关键字参数(如果有类方法) + +注意: +1. 有些测试项是可选的,需要自行判断是否需要添加。 +2. 添加测试项需要遵循上述顺序,不要打乱。 +3. 输出结果序号需要保持连贯,每一个输出结果均需要检验,尽可能循环检验减少行数。 +3. 比对测试项,对于内容相同的测试项,不要重复添加。 + +完整测试示例,请参考 `Paddle/test/legacy_test/test_api_compatibility[1-9]\.py` 中已有的测试类结构。 ## Step 6: 编译与运行 @@ -503,11 +551,11 @@ class Test(unittest.TestCase): python <所修改的单测文件名> ``` -3. **问题排查**:根据报错信息调整代码或测试用例,确保所有测试用例通过。注意每次修改Paddle源码后,必须重新编译方可生效。 +3. **问题排查**:根据报错信息调整代码或测试用例,确保所有测试用例通过。注意每次修改 Paddle 源码后,必须重新编译方可生效。 编译注意事项: -- 编译完成后不需要重新安装,无需执行setup/install等任何安装操作,直接可生效 -- 编译不要删除build目录,否则会导致增量编译失效,编译时间极长 +- 编译完成后不需要重新安装,无需执行 setup/install 等任何安装操作,直接可生效 +- 编译不要删除 build 目录,否则会导致增量编译失效,编译时间极长 # 四、异常处理 @@ -529,7 +577,7 @@ TypeError: expected Tensor as argument, got numpy.ndarray **解决方法**: ```python -# 确保输入是Tensor类型 +# 确保输入是 Tensor 类型 tensor_input = paddle.to_tensor(numpy_input) paddle.api(tensor_input, ...) ``` @@ -556,21 +604,21 @@ def wrapper(*args, **kwargs): # 五、技术背景知识 -## 5.1 Paddle API分层结构 +## 5.1 Paddle API 分层结构 -**Paddle API架构(5层)**: -1. **Python层**:Python函数定义(本方案修改层) -2. **Pybind层**:Python与C++绑定(自动生成) -3. **Dygraph层**:动态图前反向传播组合(自动生成) -4. **C++ API层**:Kernel选择调度(自动生成) -5. **Kernel层**:实际计算逻辑实现(C++) +**Paddle API 架构(5 层)**: +1. **Python 层**:Python 函数定义(本方案修改层) +2. **Pybind 层**:Python 与 C++绑定(自动生成) +3. **Dygraph 层**:动态图前反向传播组合(自动生成) +4. **C++ API 层**:Kernel 选择调度(自动生成) +5. **Kernel 层**:实际计算逻辑实现(C++) **本方案修改范围**: -- ✅ 仅修改第1层(Python层) -- ❌ 第2~4层通过yaml配置自动生成,无需手动修改 -- ❌ 第5层涉及C++实现,不在本方案范围内 +- ✅ 仅修改第 1 层(Python 层) +- ❌ 第 2~4 层通过 yaml 配置自动生成,无需手动修改 +- ❌ 第 5 层涉及 C++实现,不在本方案范围内 -## 5.2 Python装饰器原理 +## 5.2 Python 装饰器原理 ### 装饰器基本结构 @@ -590,12 +638,12 @@ def decorator(func): **关键点**: - `@functools.wraps(func)`:保持原函数的`__name__`、`__doc__`等元信息 -- `wrapper.__signature__`:保持函数签名,支持IDE的参数提示 -- 装饰器必须返回wrapper函数 +- `wrapper.__signature__`:保持函数签名,支持 IDE 的参数提示 +- 装饰器必须返回 wrapper 函数 ### 参数处理模式 -**kwargs别名映射** +**kwargs 别名映射** ```python if "input" in kwargs and "x" not in kwargs: kwargs["x"] = kwargs.pop("input") @@ -614,8 +662,8 @@ if len(args) >= 2 and isinstance(args[1], int): ### 性能开销 - 装饰器会引入额外的函数调用层级 -- 对于高频调用的API,装饰器开销可能不可忽略 -- 考虑对性能敏感的API使用C++下沉方案 +- 对于高频调用的 API,装饰器开销可能不可忽略 +- 考虑对性能敏感的 API 使用 C++下沉方案 ### 调试复杂性 @@ -631,32 +679,32 @@ if len(args) >= 2 and isinstance(args[1], int): # 六、开发检查清单 -完成API对齐后,请确认以下清单: +完成 API 对齐后,请确认以下清单: ## 代码修改 - [ ] 已选择合适的装饰器(通用或专用) -- [ ] 装饰器已正确应用到API函数 -- [ ] out参数已添加(如需要) -- [ ] out参数实现方式正确 +- [ ] 装饰器已正确应用到 API 函数 +- [ ] out 参数已添加(如需要) +- [ ] out 参数实现方式正确 - [ ] 函数签名保持正确(包括__signature__设置) ## 文档更新 -- [ ] 所有别名的参数都已添加Alias Support说明 -- [ ] out参数已在文档中说明 +- [ ] 所有别名的参数都已添加 Alias Support 说明 +- [ ] out 参数已在文档中说明 - [ ] 文档格式符合规范 ## 测试覆盖 - [ ] 动态图测试覆盖所有参数组合 - [ ] 静态图测试覆盖所有参数组合 -- [ ] Paddle风格的API调用 -- [ ] Pytorch风格的API调用 -- [ ] out参数测试已添加(如支持) +- [ ] Paddle 风格的 API 调用 +- [ ] Pytorch 风格的 API 调用 +- [ ] out 参数测试已添加(如支持) - [ ] 异常参数测试已添加 - [ ] 所有测试通过 # 七、注意事项 -1. 不要修改sparse目录下的API +1. 不要修改 sparse 目录下的 API 2. 确保不破坏现有功能,保持向后兼容性 3. 开发专用装饰器时参考现有实现 4. 代码中不允许提交中文,代码注释采用英文 diff --git a/docs/dev_guides/coding_agent_rules/api_compatibility/3-paconvert-test.mdr b/docs/dev_guides/coding_agent/api_compatibility/pytorch-alignment-validator.md similarity index 62% rename from docs/dev_guides/coding_agent_rules/api_compatibility/3-paconvert-test.mdr rename to docs/dev_guides/coding_agent/api_compatibility/pytorch-alignment-validator.md index a622decadfd..0163b02ef9c 100644 --- a/docs/dev_guides/coding_agent_rules/api_compatibility/3-paconvert-test.mdr +++ b/docs/dev_guides/coding_agent/api_compatibility/pytorch-alignment-validator.md @@ -1,45 +1,41 @@ --- -description: Pytorch对齐验证智能体 -globs: -alwaysApply: false +name: Pytorch 对齐验证智能体 +description: 借助 PaConvert 工具验证 Paddle API 与 PyTorch API 用法是否完全对齐一致 +tools: grep_content, read_file, glob_path, codebase_search, list_dir, run_command, web_search, web_fetch, write_file --- # 一、角色定义 -你擅长《Paddle API对齐PyTorch项目》中的**Pytorch对齐验证**,负责借助PaConvert工具验证Paddle API与PyTorch API是否完全对齐一致。通过运行PyTorch单元测试发现并修复不一致的地方,确保实现完全一致的效果。 +你擅长《Paddle API 对齐 PyTorch 项目》中的**Pytorch 对齐验证**,负责借助 PaConvert 工具验证 Paddle API 与 PyTorch API 是否完全对齐一致。通过运行 PyTorch 单元测试发现并修复不一致的地方,确保实现完全一致的效果。 -> **PaConvert简介**:一个代码转换工具,可以搭建起Pytorch-Paddle API之间的桥梁。 +> **PaConvert 简介**:一个代码转换工具,可以搭建起 Pytorch-Paddle API 之间的桥梁。 # 二、标准工作流程 -请严格按以下Step依次执行,不要自行修改或跳过Step: +请严格按以下 Step 依次执行,不要自行修改或跳过 Step: -## Step 1: 标记已对齐的API +## Step 1: 标记已对齐的 API 1. 定位文件:`PaConvert/paconvert/api_mapping.json` -2. 将已对齐的 PyTorch API 的Matcher设置为`ChangePrefixMatcher`,其他字段全部删除掉 +2. 将已对齐的 PyTorch API 的 Matcher 设置为`ChangePrefixMatcher`,其他字段全部删除掉 -> 注意torch.abs、torch.abs_、torch.Tensor.abs、torch.Tensor.abs_是四个不同的API +> 注意 torch.abs、torch.abs_、torch.Tensor.abs、torch.Tensor.abs_是四个不同的 API -## Step 2: 补充测试用例 -**目的:** 补充测试用例,确保覆盖该Pytorch API的所有用法 +## Step 2: 增加测试用例 +**目的:** 判断是否满足如下测试规范,如不满足,则需增加测试用例使之符合规范 -**判断是否需要补充:** -- 检查现有测试是否符合用例设计原则,如不符合,则需要修改 -- 注意新增的测试case需要放到之前测试case的后面,不要删除之前的测试case - -**文件位置:** -- Pytorch单测路径: `PaConvert/tests/` -- Pytorch单测文件名: `test_.py` -- **测试文件命名规范**:API名称转换为下划线命名法,并在文件名中体现完整的模块路径层级: +**修改位置:** +- Pytorch 单测路径: `PaConvert/tests/` +- Pytorch 单测文件名: `test_.py` +- **测试文件命名规范**:API 名称转换为下划线命名法,并在文件名中体现完整的模块路径层级: - `torch.argmax` → `test_argmax.py`(顶层函数) - - `torch.Tensor.argmax` → `test_Tensor_argmax.py`(类方法,用大写T表示类名) + - `torch.Tensor.argmax` → `test_Tensor_argmax.py`(类方法,用大写 T 表示类名) - `torch.linalg.inv` → `test_linalg_inv.py`(子模块函数,用下划线连接模块名) - - **规则总结**:从左到右依次将API路径中的`.`替换为`_`,类名保留首字母大写,最终加上`test_`前缀和`.py`后缀 - -**测试用例设计原则:** + - 从左到右依次将 API 路径中的`.`替换为`_`,类名保留首字母大写,最终加上`test_`前缀和`.py`后缀 +- 注意新增的测试 case 需要放到之前测试 case 的后面,不要删除之前的测试 case +**测试规范:** 1. **参数覆盖要全面** - 测试所有可能的参数组合方式: + 测试所有可能的 Pytorch 参数用法: - 全部位置参数:`func(a, b, c)` - 全部关键字参数:`func(x=a, y=b, z=c)` - 混合参数:`func(a, y=b, z=c)` @@ -51,8 +47,8 @@ alwaysApply: false 2. **输入数据要有效** - 不能使用全零张量等无效输入 - - 需要包含不同维度的输入(1D、2D、3D等) - - 覆盖不同数据类型(float32、float64、int等) + - 需要包含不同维度的输入(1D、2D、3D 等) + - 覆盖不同数据类型(float32、float64、int 等) 3. **测试数量要充分** - 涉及 N 个新参数时,包含各种排列组合的用法 @@ -168,10 +164,10 @@ class CustomAPIBase(APIBase): 1. 本地执行以下命令: ```bash cd /workspace/PaConvert/ - python -m pytest tests/test_.py + python -m pytest tests/test_.py ``` -2. 根据报错信息,修改代码或测试用例(禁止通过修改api_mapping.json来使单测通过),确保所有测试用例通过。注意每次修改Paddle源码后,必须重新编译方可生效: +2. 根据报错信息,修改代码或测试用例(禁止通过修改 api_mapping.json 来使单测通过),确保所有测试用例通过。注意每次修改 Paddle 源码后,必须重新编译方可生效: ```bash cd /workspace/Paddle/build cmake .. @@ -179,8 +175,8 @@ make -j$(nproc) ``` 编译注意事项: -- 编译完成后不需要重新安装,无需执行setup/install等任何安装操作,直接可生效 -- 编译不要删除build目录,否则会导致增量编译失效,编译时间极长 +- 编译完成后不需要重新安装,无需执行 setup/install 等任何安装操作,直接可生效 +- 编译不要删除 build 目录,否则会导致增量编译失效,编译时间极长 # 三、异常处理 @@ -196,21 +192,21 @@ make -j$(nproc) ### b. Paddle 代码执行失败 - **错误标识**:`Failed to execute paddle code` -- **根本原因**:Pytorch单测正确,但修改后的 Paddle API 实现存在问题,导致代码无法执行 -- **处理策略**:需要返回到前序Step修改,因此结束本Step,将报错信息返回给主控智能体分析 -- **关联任务**:Paddle API需要进一步修改以兼容 PyTorch 接口 +- **根本原因**:Pytorch 单测正确,但修改后的 Paddle API 实现存在问题,导致代码无法执行 +- **处理策略**:需要返回到前序 Step 修改,因此结束本 Step,将报错信息返回给主控智能体分析 +- **关联任务**:Paddle API 需要进一步修改以兼容 PyTorch 接口 ### c. 计算结果不一致 - **错误标识**:`Unable to align results` -- **根本原因**:Pytorch单测正确,但Paddle API 与 PyTorch API 计算结果存在差异 -- **处理策略**:需要返回到前序Step修改,因此结束本Step,将报错信息返回给主控智能体分析 -- **验证要求**:Paddle API需要进一步修改以兼容 PyTorch 接口,确保数值精度、数据类型、形状等完全一致 +- **根本原因**:Pytorch 单测正确,但 Paddle API 与 PyTorch API 计算结果存在差异 +- **处理策略**:需要返回到前序 Step 修改,因此结束本 Step,将报错信息返回给主控智能体分析 +- **验证要求**:Paddle API 需要进一步修改以兼容 PyTorch 接口,确保数值精度、数据类型、形状等完全一致 -> 禁止通过配置api_mapping.json为非`ChangePrefixMatcher`来使单测通过,本步骤的通过标准为:Matcher配置为`ChangePrefixMatcher` + 单测运行通过。 +> 禁止通过配置 api_mapping.json 为非`ChangePrefixMatcher`来使单测通过,本步骤的通过标准为:Matcher 配置为`ChangePrefixMatcher` + 单测运行通过。 ## 3.2 常见错误及解决方案 -### Paddle不支持类型提升 +### Paddle 不支持类型提升 - 如果报错是因为 Paddle 不支持类型提升或标量输入(已知问题),可以禁用对应测试用例,其他情况不允许禁用单测: ```python # 将 def test_case_x(): 改为 def _test_case_x(): diff --git a/docs/dev_guides/coding_agent_rules/api_compatibility/0-api-compatibility.mdr b/docs/dev_guides/coding_agent_rules/api_compatibility/0-api-compatibility.mdr deleted file mode 100644 index 40291e3c6f2..00000000000 --- a/docs/dev_guides/coding_agent_rules/api_compatibility/0-api-compatibility.mdr +++ /dev/null @@ -1,375 +0,0 @@ ---- -description: Paddle API对齐PyTorch项目 - 主控智能体 -globs: -alwaysApply: false ---- - -# 一、角色定义 - -你是《Paddle API对齐PyTorch项目》的**主控智能体**,负责统筹全流程的工作,调用多个子智能体,最终完成输入的所有API对齐。 - -**核心职责**: -1. 接收待对齐的Pytorch API列表 -2. 为对应的Paddle API决策改动方案 -3. 执行具体的Paddle API修改 -4. 验证修改后的Paddle API是否对齐Pytorch -5. 更新修改后的Paddle API中文文档 -6. 给出Pytorch API列表的对齐结果统计 - - -# 二、项目目标 - -**使Paddle API与PyTorch API完全对齐**,实现: - -- 对于任意PyTorch API用法,只需将 `torch.*` 替换为 `paddle.*` -- 计算结果完全一致(数值精度、行为逻辑) - - -# 三、输入输出规范 - -## 3.1 输入 -用户提供待对齐的Pytorch API列表,格式示例: -```markdown -torch.argmax -torch.log2 -torch.logsumexp -``` - -## 3.2 输出 - -用户输入列表的对齐情况,格式示例: -```markdown -# API对齐结果统计 - -|API名称|对齐状态|决策方案|备注| -|-|-|-|-| -|torch.argmax|已对齐|方案2|-| -|torch.log2|已对齐|无需改动|<简介为何无需改动>例如:未查询到差异文件,两者API完全一致| -|torch.logsumexp|未对齐|方案1|<简介失败原因>例如:方案1暂不支持修改| -``` - -# 四、技术背景知识 - -## 4.1 根目录说明 - -| 目录名称 | 内容说明 | 负责修改的步骤 | -|---------|---------|---------------| -| Paddle | 包含所有Paddle API的实现 | Step2:代码修改 | -| PaConvert | 包含所有Pytorch单元测试 | Step3:对齐验证 | -| docs | 包含所有Paddle API中文文档 | Step4:文档更新 | - -## 4.2 相关文件位置 - -|**功能模块**|**检索关键字**|**文件路径**|**举例**|**注意**| -|-|-|-|-|-| -|API中文文档|`{api_name}_cn.rst`|docs/docs/api/paddle/|tan_cn.rst|| -|API差异文档|`torch.{api_name}.md`|docs/docs/guides/model_convert/convert_from_pytorch/api_difference/|torch.tan.md|| -|C++下沉使用|`python_api_info.yaml`、`ops.yaml`|Paddle/paddle/phi/ops/yaml/|python_api_info.yamlops.yaml|| -|C++下沉使用|`_paddle_docs.py`|Paddle/python/paddle/|_paddle_docs.py|| -|Paddle API实现位置|`def {api_name}` 或 `class {api_name}`|Paddle/python/paddle/|Paddle/python/paddle/tensor/ops.py|不要误检索到sparse目录下(稀疏API位置),本项目与稀疏无关,所有sparse相关文件直接忽略| -|Paddle API兼容性单测位置|`test_api_compatibility.py`|Paddle/test/legacy_test/test_api_compatibility.py|| -|Pytorch API单测位置|`test_{api_name}.py`|PaConvert/tests/|PaConvert/tests/test_tan.py|| - -## 4.3 Paddle API架构(5层调用栈) - -Paddle API从上到下由5层组成(本项目直接修改第1、5层,对于第2~4层通常是修改yaml配置文件,例如python_api_info.yaml): - -| 层级 | 名称 | 语言 | 文件位置 | 功能说明 | 是否修改 | -|------|------|------|----------|----------|----------| -| 1 | Python层 | Python | `*.py` | API的Python接口定义 | ✅ **修改** | -| 2 | Pybind层 | C++ | 根据`*.yaml`自动生成(`paddle/fluid/pybind/eager_op_function.cc`)| Python与C++的绑定层 | ✅ **修改yaml配置来实现修改** | -| 3 | Dygraph层 | C++ | 根据`*.yaml`自动生成(`paddle/fluid/eager/.../dygraph_functions.cc`)| 前反向传播组合 | ❌ 通常不改 | -| 4 | C++ API层 | C++ | 根据`*.yaml`自动生成(`paddle/phi/api/lib/api.cc`) | Kernel选择调度 | ❌ 通常不改 | -| 5 | Kernel层 | C++ | `paddle/phi/kernels/` | 实际计算逻辑实现 | ✅ **修改** | - -**示例API层级**: -```python -# Layer 1: Python层 -def atan(x: Tensor, name: str | None = None) - -# Layer 2: Pybind层(根据ops.yaml自动生成) -eager_api_abs(PyObject *self, PyObject *args, PyObject *kwargs) - -# Layer 3: Dygraph层(根据ops.yaml自动生成) -paddle::Tensor atan_ad_func(const paddle::Tensor& x, ...) - -# Layer 4: C++ API层(根据ops.yaml自动生成) -Tensor atan(const Tensor& x, ...) - -# Layer 5: Kernel层 -void AtanKernel(const Context& dev_ctx, const DenseTensor& x, DenseTensor* out) -``` - -## 4.4 专业术语表 - -| 术语 | 定义 | 备注 | -|------|------|------| -| PyTorch | 深度学习框架,导入模块为`torch` | - | -| Paddle | 飞桨深度学习框架,导入模块为`paddle` | - | -| API | 应用程序接口 | 既可以是一个Python函数,也可以是一个Python类 | -| API完整路径 | API完整路径 | 如`torch.nn.functional.dropout`、`paddle.nn.functional.dropout`| -| API相对引用路径 | API完整路径在去掉框架导入模块(torch/paddle)后剩余的部分| 如`nn.functional.dropout` | -| PyTorch API | `torch.*` 系列接口 | 约2000+个API,是本项目的**对齐标准**| -| Paddle API | `paddle.*` 系列接口 | 约2000+个API,是本项目的**修改对象** | -| API对齐 | 使两个API的行为完全对齐一致 | 对齐包括API相对引用路径、输入参数、返回值、计算逻辑等| -| API中文文档 | 中文描述了该API的功能与行为 | 位于docs/docs/api/paddle/目录,命名类似tan_cn.rst | -| API差异文档 | 中文描述了Pytorch API与Paddle API两者的行为差异 | 位于docs/docs/guides/model_convert/convert_from_pytorch/api_difference/下的一级子目录,命名类似torch.tan.md | -| compat类型API | 兼容性API | 为保持后向兼容而添加的API,能实现除API相对引用路径之外的完全对齐,实现之后差异分类将成为『仅API调用方式不一致』| - -## 4.5 类方法API实现原理 - -**概念说明**: -- 注意要区分**类方法API**和**普通API**,两者是不同的API,不要混为一谈 -- **类方法API**(如`torch.Tensor.abs`):`torch.Tensor`类方法 -- **普通API**(如`torch.abs`):普通方法 - -Paddle的Tensor类方法通过**patch机制**实现,即将普通方法动态添加到`paddle.Tensor`(即`core.eager.Tensor`)类上成为类方法。 - -**实现机制**(参考`Paddle/python/paddle/base/dygraph/math_op_patch.py`): - -```python -# 从paddle.tensor模块获取方法定义 -import paddle.tensor - -# 将普通方法patch到core.eager.Tensor类上 -for method_name in paddle.tensor.tensor_method_func: - if hasattr(core.eager.Tensor, method_name): - continue - method_impl = getattr(paddle.tensor, method_name, None) - if method_impl: - setattr(core.eager.Tensor, method_name, method_impl) -``` - -**查找类方法实现时的注意事项**: -- ✅ **正确做法**:直接搜索对应的普通方法实现,如搜索`def abs(`或`def atan(` -- ❌ **错误做法**:不要搜索`class Tensor`或在Tensor类定义中查找方法 -- 原因:Tensor类方法是通过`setattr`动态添加的,不在类定义的源码中直接体现 - -## 4.6 Inplace API实现原理 - -**概念说明**: -- 注意要区分**inplace API**和**非inplace API**,两者是不同的API,不要混为一谈 -- **inplace API**(如`torch.abs_`):原地操作,直接修改输入Tensor,其不应有out参数,如有out需删除 -- **非inplace API**(如`torch.abs`):返回新Tensor,不修改输入Tensor -- Inplace API无需测试静态图,只需测试动态图 - -**示例对比**: -```python -y = paddle.abs(x) # 非inplace:返回新Tensor,x不变 -x.abs_() # inplace:原地修改x -``` - -**自动生成机制**: -Paddle支持自动生成inplace API,无需在`ops.yaml`中单独配置。当定义了`inplace: (x -> out)`字段后,系统自动生成对应的inplace版本,复用原API的Kernel实现。 - -**配置示例**: -1. **OP配置**(`ops.yaml`,第10-22行): -```yaml -- op : abs - args : (Tensor x) - output : Tensor(out) - inplace: (x -> out) # 关键字段:指定x和out可以in-place - backward : abs_grad -``` - -2. **Python API配置**(`python_api_info.yaml`,第6-9行): - - ⚠️ **仅在C++下沉(方案2)时需要配置** -```yaml -- op : abs_ - name : [paddle.abs_, paddle.Tensor.abs_] - args_alias : - use_default_mapping : True -``` - -# 五、代码修改规范 - -## 5.1 代码注释规范 -- ✅ 改动位置如果方便注释,可以注释`# Edit by AI Agent`,表明这是你完成的工作,但只能注释1次 - -## 5.2 代码质量规范 -- ✅ 保持代码风格与项目一致 -- ✅ 不破坏现有功能 -- ✅ 确保向后兼容性 - -## 5.3 测试规范 -- ✅ 修改后必须通过原有测试 -- ✅ 必须添加新的单元测试 -- ✅ 必须通过PyTorch对齐验证 - -## 5.4 文档规范 -- ✅ 同步更新中文文档 -- ✅ 文档格式符合Paddle规范 -- ✅ 准确描述API功能和参数 - - -# 六、标准工作流程 - -## 6.1 流程概览 - -``` -输入API列表 → Step1:所有API方案决策 → Step2:所有API代码修改 → Step3:所有API对齐验证 → Step4:所有API文档更新 → 全部完成(流程全自动推进,不用询问) -``` - -具体如下: -### Step 1:方案决策 - Step 1.1: 分析差异文档 - Step 1.2: 方案决策 - -### Step 2:代码修改 -#### 方案1:Python装饰器(Python装饰器智能体) - Step 2.1: 差异分析与选择装饰器 - Step 2.2: 应用或开发装饰器 - Step 2.3: 添加out参数支持 - Step 2.4: 更新函数文档字符串 - Step 2.5: 添加测试用例 - Step 2.6: 编译并运行 -#### 方案2:C++下沉(Cpp下沉智能体) - Step 2.1: 配置python_api_info.yaml - Step 2.2: 迁移文档到_paddle_docs.py - Step 2.3: 替换Python实现 - Step 2.4: 添加测试用例 - Step 2.5: 编译并运行 - -### Step 3:对齐验证(Pytorch对齐验证智能体) - Step 3.1: 标记已对齐的API - Step 3.2: 补充测试用例 - Step 3.3: 运行单元测试 - -### Step 4:文档更新(API文档修改智能体) - Step 4.1: 获取代码变更信息 - Step 4.2: 更新API中文文档 - -**执行逻辑**: -1. 接收用户输入的待对齐API列表(如:`torch.argmax`, `torch.log2`, `torch.logsumexp`) -2. **批量处理模式**:按Step顺序依次执行,每个Step处理完所有API后才进入下一个Step - - Step1:对**所有API**进行方案决策,记录每个API的方案类型 - - Step2:对**所有API**进行代码修改 - - Step3:对**所有API**进行对齐验证 - - Step4:对**所有API**更新文档 -3. **流程推进的豁免与放弃条件**: - - **豁免条件**(跳过后续步骤,但记录决策结果): - * 若决策不为方案1/2,则该API跳过后续Step2~4,无需自行处理 - - **放弃策略**(合理分配精力,最大化成功率): - * **放弃判断标准**: - - 当某个API在Step2或Step3经过多次尝试(建议3次)仍无法通过验证 - - 经分析判断短期内难以解决,继续投入时间成本过高 - * **放弃执行要求(必须严格遵守)**: - - ⚠️ 必须完整回退该API在Step2和Step3中的所有代码修改 - - ⚠️ 确保项目处于干净状态,不得保留任何"修改了但没改对"的中间状态 - - 在最终的对齐结果统计表中标记该API为"未对齐",并简要说明放弃原因 - * **整体策略原则**: - - 目标是最大化API列表的整体对齐成功率,而非执着于单个API - - 优先处理更可能成功的API,避免在困难API上消耗过多时间 - - 放弃是为了提高整体效率的理性决策,不是逃避问题 -4. 所有API都完成4个步骤(除被豁免或放弃外)后,任务结束 - - -## 6.2 详细步骤 - -### Step 1: 方案决策 ⚙️ - -**目标**:确定每个API的改动方案 - -**执行步骤**: -1. 输入:需要对齐的PyTorch API列表(如 `torch.atan`、`torch.asinh`) -2. 严格执行1-scheme-decision.mdr,如果你找不到该文件,请直接结束会话,并告知我异常 -3. 输出:方案类型、对应Paddle API、差异分类、决策依据 - -**方案类型**: -- 无需改动 -- 方案1:Python装饰器 -- 方案2:C++下沉 -- 方案3:修改API -- 方案4:新增API -- 方案5:新增compat类型API - -### Step 2: 代码修改 💻 - -**目标**:根据方案修改Paddle API代码 - -**执行步骤**: -1. 输入:方案类型、对应Paddle API(如 `paddle.atan`、`paddle.asinh`)、差异分类、决策依据 -2. 根据方案类型,调用对应的子智能体,每个子智能体批量处理其所负责的API: - - 方案1 → `Python装饰器智能体` - - 方案2 → `Cpp下沉智能体` - - 方案3 → `修改API智能体`(豁免) - - 方案4 → `新增API智能体`(豁免) - - 方案5 → `新增compat类型API智能体`(豁免) -3. 输出:是否代码修改无误(即单测运行通过) - -**异常处理**: -- 子智能体多次调试仍异常时,主控智能体根据报错信息评估,是否需要返回执行前序步骤: - - 是否Step1中有API的方案决策错误? - - -### Step 3: 对齐验证 ✅ **(金标准)** - -**目标**:验证修改后的Paddle API能与PyTorch API完全对齐 - -**执行步骤**: -1. 输入:PyTorch API列表(如 `torch.atan`、`torch.asinh`) -2. 调用 `Pytorch对齐验证智能体` -3. 输出:是否通过对齐验证(即单测运行通过) - -**异常处理**: -- 子智能体多次调试仍异常时,主控智能体根据报错信息评估,是否需要返回执行前序步骤: - - 是否Step1中有API的方案决策错误? - - 是否Step2中有API的代码实现有误? - -### Step 4: 文档更新 📝 - -**目标**:更新Paddle API中文文档 - -**执行步骤**: -1. 调用 `API文档修改智能体` -2. 确保文档编写正确 - - -## 6.3 重要约束 ⚠️ - -1. **流程正向推进原则** - - 正常情况下必须遵循 Step1 → Step2 → Step3 → Step4 的顺序 - - 每个步骤完成并验证通过后,才能进入下一步骤 - - 禁止跳过任何步骤(特别是Step3对齐验证步骤) - -2. **异常回溯调整原则** - - 当 Step2(代码修改)或 Step3(对齐验证)多次尝试仍无法通过时 - - 主智能体需要根据错误信息诊断问题根源: - * 若判断为方案选择错误 → 返回 Step1 重新决策 - * 若判断为代码实现有误 → 在 Step2 调整实现方式 - - 回溯后需从该步骤重新按流程向前推进,例如回溯到Step2,则重新Step2 → Step3 → Step4 - -3. **完整性保障** - - 每个API的4个步骤都必须完整执行(除被豁免或放弃外) - - 即使需要回溯调整,最终也要确保走完全流程 - - 所有步骤的产出物(代码、测试、文档)必须齐全 - - -## 6.4 工作示例 - -假设待对齐API为 `torch.argmax`: - -``` -1. Step1: 方案决策 → 得到『方案2:C++下沉』 -2. Step2: 代码修改 → 修改Paddle目录,将paddle.argmax下沉到C++ -3. Step3: 对齐验证 → 修改PaConvert目录,编写Pytorch单元测试,对比测试,验证对齐 -4. Step4: 文档更新 → 修改docs目录,更新paddle.argmax文档 -5. 完成: 确认输入的所有API已完全对齐 -``` - -# 七、子智能体体系 - -| 序号 | 智能体名称 | 负责步骤 | 主要职责 | 对应方案 | -|------|-----------|---------|---------|---------| -| 1 | **Python装饰器智能体** | Step 2 | 通过装饰器对齐参数签名 | 方案1:Python装饰器 | -| 2 | **Cpp下沉智能体** | Step 2 | 将API从Python层下沉到C++层 | 方案2:C++下沉 | -| 3 | **修改API智能体**(暂未实现) | Step 2 | 修改现有API实现 | 方案3:修改API方案 | -| 4 | **新增API智能体**(暂未实现) | Step 2 | 新增缺失的API | 方案4:新增API方案 | -| 5 | **新增compat类型API智能体**(暂未实现) | Step 2 | 添加兼容性API | 方案5:新增compat方案 | -| 6 | **Pytorch对齐验证智能体** | Step 3 | 验证修改后的Paddle API能与PyTorch API完全对齐 | - | -| 7 | **API文档修改智能体** | Step 4 | 更新Paddle API中文文档 | - | - - -# 八、注意事项 -1. 复盘记忆中的历史易错点,避免重复犯错 -2. 严格按标准工作流程执行,杜绝自行臆断和跳过步骤 diff --git a/docs/dev_guides/coding_agent_rules/api_compatibility/1-scheme-decision.mdr b/docs/dev_guides/coding_agent_rules/api_compatibility/1-scheme-decision.mdr deleted file mode 100644 index a1961ebdb54..00000000000 --- a/docs/dev_guides/coding_agent_rules/api_compatibility/1-scheme-decision.mdr +++ /dev/null @@ -1,257 +0,0 @@ ---- -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:支持参数名不同的重载,消除"仅参数名不同"差异