Skip to content
Merged
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
4 changes: 4 additions & 0 deletions knowledge/repos/afd-plugin/_index.md
Original file line number Diff line number Diff line change
Expand Up @@ -44,3 +44,7 @@ sources:
| 核对 connector/graph/DBO 当前支持组合 | [execution-platforms](components/execution-platforms/architecture.md) | v0.26 CUDA/Ascend 平台现状 |

默认 briefing 只加载本入口和仓库规则;深层 owner 页面由 changed-file route 或 `doc_search` / `doc_read` 按需读取。
- [AFD plugin 仓库规则](rules-init.md)
- [上游 API 漂移与兼容边界(afd-plugin)](rules-seed-vllm-omni-rebase-upstream-api-drift.md)
Comment on lines +47 to +48

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

P2 Badge Route the generated rules through their actual owners

For Direct reviews of connector or compatibility changes, adapters/afd_plugin/manifest.yaml routes to the corresponding component page and the briefing includes only rules.md plus _index.md; _review_knowledge() never returns either of these newly linked pages. Consequently constraints such as AFD-I1–I3/I10 and AFD-I13–I23 are absent from the review context for precisely the files they govern. Split or merge them into the nearest routed component rules.md pages, rather than relying on links from the repository index.

AGENTS.md reference: AGENTS.md:L12-L17

Useful? React with 👍 / 👎.

- [每次审查 AFD PR 都先套用的通用审查规则。AFD 特有的门禁再看本仓库的规则页。](../../general/review/rules.md)
- [以下情况先读这页,判断是否应该先改上游:新增或刷新 compat patch、从 vLLM/vLLM-Ascend 复制函数,或在插件里重写上游逻辑(MoE routing、DP metadata、graph capture、EngineC](../../general/review/guides/upstream-first-for-algorithm.md)
24 changes: 23 additions & 1 deletion knowledge/repos/afd-plugin/components/compatibility/rules.md
Original file line number Diff line number Diff line change
@@ -1,7 +1,7 @@
---
title: "AFD compatibility 规则"
created: 2026-08-06
updated: 2026-08-06
updated: 2026-09-30
type: rule
tags: [afd-plugin, components, compatibility, review]
sources:
Expand Down Expand Up @@ -33,3 +33,25 @@ confidence: high
- 验收:当前 pinned signature 对齐,故意缺失字段不会被 fallback 吞掉,保存的 original 不会在 reload 时被 wrapper 覆盖。

patch 生命周期见 [architecture](architecture.md),版本支持声明见 [仓库规则](../../rules.md)。

## AFD-I5 — 升级 vLLM 或 vLLM-Ascend 基线时,需要同步修改多个文件并做完整审计

- vLLM 目标版本出现在三个地方:`pyproject.toml` 的 extra pin、`afd_plugin/compat/vllm.py` 的版本检查、README(Overview、Known gaps、GPU installation)。三处必须一致。
- 插件注册用 `strict=False` 调版本检查,版本不符只告警。不能把“注册成功”当作新版本受支持的证据(`PATCH-INV-003`)。
- `engine_core.py` 和 `npu/force_load_balance.py` 没有 patch 内的版本守卫,只能靠 review 把关。
- `async_dp_engine.py` 里复制的 coordinator 只在 `0.26.0` 精确版本下生效,守卫要跟着更新。
- `attention_model_runner.py` 里规避 DBO metadata cache 的代码:等 vLLM #48659 进入 pin 的版本后删除。
- 连接器进程组用到的私有 PyTorch 和 vLLM 符号。
- `pyproject.toml` 没有声明 vLLM-Ascend 依赖。刷新 Ascend 侧时,必须引用确切的 vLLM-Ascend 源码 commit(当前是 `80d8c194f`),同步 README 的 Ascend 基线表,并附上 NPU 单元测试和 E2E 证据。

<!-- kb:rule status=active since=init-9cae2d2ddaae -->

## AFD-I6 — 临时替换上游符号的代码必须在 `finally` 里还原,并登记到兼容文档

- 这类临时替换包括:包装 `create_forward_context`、在 `Worker.init_device()` 期间替换 runner 符号、包装 V2 capture 的输入准备、安装 full-graph replay hook、给 DBO 临时关闭 metadata cache。它们都必须在 `finally` 里恢复符号和 runner 状态,异常路径也要恢复。
- 需要有测试覆盖恢复逻辑和错误路径。参考 `test_attention_model_runner.py` 对 DBO 规避代码的覆盖。
- 新增的这类替换要写进 `docs/design/module/compatibility_and_patches.md` 的 scoped adaptation 列表,否则升级审计会漏掉它。
- 需要在整个进程生效的替换,应放到 `afd_plugin/compat/patches/`,并走 patch 审查流程。反过来,AFD 自己的功能不要借全局 hook 藏进 patch 模块。
- 保存了原函数的 patch,在模块重载时不能用自己的 wrapper 覆盖已保存的原函数。

<!-- kb:rule status=active since=init-9cae2d2ddaae -->
123 changes: 123 additions & 0 deletions knowledge/repos/afd-plugin/rules-init.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,123 @@
---
title: "AFD plugin 仓库规则"
created: 2026-09-30
updated: 2026-09-30
type: rule
tags: [afd-plugin]
sources: []
---

# AFD plugin 仓库规则

## AFD-I1 — 新增或重命名 connector 时,必须同时更新 factory 注册、配置白名单和 connector 自有 schema

- 只在 `AFDConnectorFactory` 注册还不够。配置层另有一份硬编码白名单,它不是从注册表推导出来的。名字不在白名单里的 connector,会在配置校验阶段被拒绝。
- 检查 PR 是否同时更新了以下内容:白名单、README 里 `connector` 可选值的说明、README 的 connector 支持表。
- 新 connector 必须实现 `parse_extra_config()`,schema 是封闭的,未知字段直接报错。原因是 `compat/npu/feature_validation.py` 会通过 factory 复用同一个 schema 做前置校验,不能在别处另写一套校验。
- 实现要放进对应的后端包:只用于 GPU 的放 `afd_plugin.connectors.gpu`,只用于 NPU 的放 `afd_plugin.connectors.npu`。
- factory 的注册方法仍是 draft。不要在文档里把它写成公开扩展契约。

<!-- kb:rule status=active since=init-9cae2d2ddaae -->

## AFD-I2 — 判断走控制面驱动还是 connector 驱动,只能看 `connector.control_plane` 是否为 `None`

- 不能用 `isinstance` 或 connector 类名来选择执行路径(`CAP-INV-001`)。调用 `send_dp_metadata_list()`、`recv_dp_metadata_list()` 或 `update_state_from_dp_metadata()` 之前,必须先检查 `control_plane`。
- GPU 只支持控制面驱动:`GPUFFNModelRunner` 构造时会断言 `control_plane` 不为 `None`;GPU daemon 遇到 `None` 会抛 `NotImplementedError`。所以任何新的 GPU connector 都必须在构造阶段装好 `AFDControlPlane`。
- `control_plane is None` 的 connector(目前只有 `CAMAsyncAFDConnector`)不能进 FFN graph cache 路径,因为 cache key 依赖 DP metadata。这类 connector 必须保持 eager-only。Attention 在这种情况下会跳过 DP metadata 协调,所以路由和 token 元数据必须随 dispatch payload 一起发送。
- 控制面对象属于 connector,没有独立的生命周期。不要给它单独加 close 或所有权逻辑。

<!-- kb:rule status=active since=init-9cae2d2ddaae -->

## AFD-I3 — connector 构造只做轻量工作,跨角色的集合通信必须等权重加载完成后再做

- 构造函数和 `parse_extra_config()` 里不能创建进程组、communicator、算子注册,也不能加载 CANN 算子。这些都属于 `init_afd_connector()`。
- Attention 端:`init_afd_connector()` 必须放在 `load_model()` 末尾,并且在 ubatch wrapper 安装之后。
- FFN 端:`init_afd_connector()` 必须在 `initialize_from_config()` 里调用,位置在空 KV-cache 初始化之后、daemon 线程启动之前。
- 如果把 rendezvous 提前到 `init_device()` 或构造阶段,两个角色的权重加载就不能再重叠。无论怎么改,rendezvous 都必须在 Attention 显存 profiling 和首次 forward 之前完成。
- 对未初始化或只初始化了一部分的 connector,`close()` 必须安全,并且之后仍能再次关闭。connector 的改动要附带清理测试,以及重试或重新初始化测试。
- 缺少原生算子时,要在 connector 初始化时报错,不能在包 import 时报错。

<!-- kb:rule status=active since=init-9cae2d2ddaae -->

## AFD-I4 — 保持 CPU-safe import 边界:没有 CUDA、vLLM 或 torch_npu 时,默认测试也必须能跑

- `vllm` 是可选 extra,默认的 `uv run pytest` 要能在没有 CUDA 的环境里运行。
- 以下模块在 import 时不能引入 torch、vLLM 或 torch_npu:顶层包、通用配置和校验、版本检查、graph policy helper(`v1/worker/cuda_graph.py` 里的 `validate_cuda_graph_mode()`)。
- `AFDConnectorFactory` 只保存懒加载器。新增 connector 时,不能在 factory 模块顶层 import CUDA 或 Ascend 的具体实现。
- 只针对 CUDA 的插件注册路径不能 import vLLM-Ascend。Ascend 的 patch 必须等 Ascend 插件完成平台初始化之后再应用。
- `afd_plugin._C_ascend` 只能在 connector 初始化时由 `ensure_cam_p2p_ops_available()` 懒加载。
- CUDA 和 Ascend 的 runtime 模块可以直接 import 设备依赖。依赖 NPU 的测试属于 Ascend 环境的测试套件,不属于默认 CPU 测试。

<!-- kb:rule status=active since=init-9cae2d2ddaae -->

## AFD-I7 — `compute_gate_on_attention` 允许什么值,要同时看 connector、runner 版本和模型

- `P2pNcclAFDConnector`(CUDA V1):`true` 和 `false` 都可以。
- `CAMP2pAFDConnector`:通用字段和 `connector_extra_config` 里的同名字段都必须是 `false`。
- `CAMAsyncAFDConnector`:文档里的配置要求通用字段为 `true`,开启 `async_moe_ubatching` 时也要求 `true`。
- 任何 ModelRunnerV2 配对都要求 `false`。
- Qwen3 MoE 和 Qwen3.5/Qwen3.6 MoE 都拒绝 `true`。
- 修改其中一个维度的校验时,要核对另外两个维度,不能只在 connector parser 或只在模型层做校验。V2 的限制由 Attention 和 FFN 两个角色共用同一个校验器。
- 通用字段 `compute_gate_on_attention` 是模型路由的选择开关;CAMP2P 的同名局部字段是算子契约。两者不能互相替代。
- 同步更新 README 的模型表、connector 表和 Known gaps。

<!-- kb:rule status=active since=init-9cae2d2ddaae -->

## AFD-I8 — README 和设计文档对 ModelRunnerV2 的说法相互矛盾,改动 V2 时必须明确对齐

- 设计文档和 E2E 契约描述了受支持的 CUDA V2(`AFDAttentionModelRunnerV2`),CI 在 `l4_4` 上按节点 ID 运行 `afd-v2-*-dp2` 和 `afd-v2-*-tp2` 四个用例。
- Ascend V2 只有单元测试证据。
- 涉及 V2 的 PR 要说明以哪份文档为准,并同步修改另一份。
- 不能依据 README 删除 V2 代码路径或 CI 用例,也不能宣称 Ascend V2 经过了硬件验证。
- V2 的约束由 Attention 和 FFN 共用同一个校验器,只改一端属于缺陷。约束包括:
- `compute_gate_on_attention=false`;
- PP、PCP、DCP 均为 1;
- 角色 rank 数等于 DP x TP;
- 静态 EP;
- 不用 DBO 或 ubatching;
- 图模式有平台差异:CUDA V2 只支持 eager 和 `FULL_DECODE_ONLY`,Ascend V2 还支持 `FULL`。不要把 Ascend 的 `FULL` 放宽到 CUDA。另外 README 的 connector 表把 CAMP2P 写成只支持 `FULL_DECODE_ONLY`,修改时要一并对齐。

<!-- kb:rule status=active since=init-9cae2d2ddaae -->

## AFD-I9 — AFD metadata 只能放在 `forward_context.additional_kwargs['afd_metadata']`

- CUDA 和 Ascend、Attention 和 FFN、V1 和 V2,全部读写同一个键。不要重新引入 NPU 独立的 metadata 镜像,也不要新增其他 forward context 属性。
- Ascend FFN 有两条路径:V1 用 `set_ascend_forward_context`;V2 配对用原生 `set_forward_context` 加 MRV2 profile override。修改 `compat/npu/forward_context.py` 时,两条路径都要测。
- CUDA 空闲 DP rank 走的 dummy-batch 路径会绕过 `_model_forward()`,metadata 在这条路径上是惰性安装的。修改 metadata 的安装位置时,要检查这条路径。
- `AFDForwardContextMetadata` 的结构和其中的 live connector 引用都不是稳定 API(#86、#88、#105 仍未解决)。不要在对外接口里承诺它们。

<!-- kb:rule status=active since=init-9cae2d2ddaae -->

## AFD-I10 — 修改控制面 payload 的字段,发送端、接收端和编解码都要同步

- `AFDControlPayload` 只能携带插件自有的原始数据:整数 stage key、token count 列表、max count,以及 graph、warmup、profile 布尔标志。它经 JSON 编码后,先发长度再发 `uint8` tensor。不能序列化 vLLM 的 `DPMetadata` 或其他 vLLM 内部对象(`XFER-INV-001`)。
- 新增字段时(`is_profile` 就是一个例子),以下内容都要一起更新:
- `P2pNcclAFDControlPlane`(NCCL)和 `CAMP2pAFDControlPlane`(Gloo);
- Attention 的所有发送点:非 ubatch、原生 ubatch、padded full-graph、V2 的 capture 和 replay hook;
- FFN daemon 的 profile、warmup、capture、replay 分支;
- 如果字段影响形状,还要改 `make_ffn_graph_key()` 或 ACL graph key。
- 控制面必须先调用 `update_state_from_dp_metadata()` 更新本地 connector 状态,再发送。FFN 必须在进入 `torch.cuda.graph(...)` 或 `torch.npu.graph(...)` 之前完成状态更新,控制面的副作用不能被录进图里。

<!-- kb:rule status=active since=init-9cae2d2ddaae -->

## AFD-I11 — worker 自动选择和显式指定 worker 路径必须同时可用

- `worker_cls="auto"` 在上游平台规范化之后,由 `compat/patches/config_validation.py` 映射到 CUDA 或标准 Ascend 的角色 worker。显式指定的 worker 路径和非 AFD 配置不能被改写。
- 显式 AFD worker 路径仍然接受(兼容旧命令),但不是稳定接口。
- 不要删掉 NPU worker 里非 SP 场景的 all-to-all 修正。auto 路径在配置规范化时已经做了同样的改写,但显式指定 worker 的旧式启动还依赖 worker 里这份修正作为兜底。
- `config_validation` 和其他核心 patch 在同一个 best-effort `try` 块里导入,失败时可能只在 debug 日志里出现,映射就静默丢了。因此 worker 初始化遇到隐式或错误的 worker class 时,必须明确报错,不能猜。
- 没有 `--afd-config` 这个参数。配置只能从 `additional_config["afd"]` 进入(`afd_role` 等兼容别名除外)。

<!-- kb:rule status=active since=init-9cae2d2ddaae -->

## AFD-I12 — E2E:分清 PR 门禁、每周门禁和只在本地跑的用例

- PR 门禁用例最多使用 4 个设备,AFD 门禁用例必须是 2A2F。2A1F 用例(包括 README 本地冒烟示例里的 `afd-eager-2a1f`)不能加入 PR 门禁。
- 一处说 2A1F 用例 “run outside CI”;
- 另一处的每周门禁包含 DeepSeek `afd-graph-dbo-2a1f`,以及 Qwen3 MoE 和 Qwen3.6 的用例,其中 Qwen3.6 套件是 2A1F。
- 修改 CI 选择时,要同步更新 `docs/design/module/e2e_testing.md` 和 `tests/e2e/README.md`,不要让这处矛盾继续扩大。
- 按通用规则,harness 升级到 `SIGKILL` 就必须判用例失败。通过 `/proc/*/environ` 标记扫描再发 `SIGKILL` 的例外,只适用于 NPU async CAM 场景(`afd-eager-async-cam`、`afd-dsv4-flash-async-cam-dp2tp4-ep8`)。新场景不能沿用这个例外。
- CI 不能设置 `AFD_GSM8K_LIMIT`,也不能调低 `AFD_GSM8K_THRESHOLD`。DBO 场景需要 12 路并发、至少 24 个样本,并断言至少记录到一次实际运行的双 ubatch 步骤。
- 门禁用例不能用 `skip` 或 `xfail`。新行为需要单元测试加真实硬件证据;Ascend V2 目前只有单元测试证据,不能当作先例。

<!-- kb:rule status=active since=init-9cae2d2ddaae -->
Loading
Loading