Motivation
The current AFD model adaptation still carries model-owned MoE forward proxies and duplicated routing behavior:
- GPU and synchronous NPU Attention roles replace remote FFN/MoE execution with handwritten proxies such as
RemoteFFNProxy and AFDAttentionFusedMoE;
- NPU Attention-side routing uses
GateOnlyRemoteMoE plus a copied compute_gate_topk path;
- these implementations manually track upstream
FusedMoE signatures, internal-router behavior, EPLB interfaces, routing options, scaling, and reduction semantics.
This is one of the highest-drift parts of model adaptation. Every vLLM or vLLM-Ascend upgrade requires the plugin to re-check behavior that upstream already owns.
vLLM 0.26 provides a native extension point: FusedMoE is a factory that accepts runner_cls and routed_experts_cls and returns a MoERunner. vLLM-Ascend already uses the same mechanism to inject AscendMoERunner.
This RFC proposes moving AFD's MoE communication boundary into role-specific runner implementations so model-level MoE forward remains native.
Goals
- Keep native model MoE forward as the source of truth.
- Remove handwritten AFD copies of routing and MoE forward contracts.
- Reuse the existing connector protocols without changing payloads or ordering.
- Preserve role-aware construction and weight loading without allocating remote expert weights.
- Share the synchronous remote-experts behavior across GPU P2P NCCL and NPU CAMP2p.
- Map NPU CAMAsync directly onto native routing plus remote dispatch/combine.
- Establish a model-independent FFN MoE computation entry point in a follow-up phase.
Non-goals
- No vLLM or vLLM-Ascend source-tree changes.
- No connector wire-protocol or control-state-machine changes.
- No behavior change for dense, non-MoE layers.
- No attempt to move FFN communication into a MoE runner.
- No new support claim for sequence-parallel MoE, unsupported graph modes, models that do not use the
FusedMoE factory, or unvalidated backend/topology combinations.
- Phase 1 does not generalize the FFN-side model runner.
Proposed architecture
Inject an AFD runner through the existing FusedMoE(..., runner_cls=..., routed_experts_cls=...) factory boundary according to role, backend, connector, and gate placement.
| Path |
Attention-side runner behavior |
FFN-side behavior |
GPU P2pNcclAFDConnector, gate on FFN |
AFDAttentionMoERunner(MoERunner): send hidden states, yield for DBO when required, receive the final MoE output |
Existing driver receives at the layer boundary, runs native MoE, and sends the final output |
NPU CAMP2pAFDConnector, gate on FFN |
AFDNPUAttentionMoERunner(AscendMoERunner): same remote-experts behavior through a shared mixin |
Existing driver and native MoE forward remain unchanged |
NPU CAMAsyncAFDConnector, gate on Attention |
AFDNPUAttentionGateMoERunner(AscendMoERunner): retain native gate and select_experts, replace dispatch/combine with CAM async send/receive, and skip local expert computation |
Existing dispatched-expert kernel path remains unchanged in Phase 1 |
The GPU and CAMP2p implementations share an AFDRemoteExpertsForwardMixin. Their concrete classes differ only because one derives from MoERunner and the other from AscendMoERunner.
Attention roles also inject an AFDRemoteRoutedExperts implementation whose weight creation is a no-op, preventing allocation of expert weights that belong to the FFN role.
Why remote-experts runners override forward()
For gate-on-FFN paths, the connector returns the final FFN result after shared experts, routed scaling, and FFN-side reductions.
Overriding only _forward_impl() would send that final result through the remaining native MoERunner.forward() post-processing and could apply scaling or reductions twice. The remote-experts runners must therefore override the complete public forward(hidden_states, router_logits, input_ids=None) boundary and return the received result directly.
They must also report is_internal_router = True. The Attention role does not construct a gate for gate-on-FFN, but native model forward needs the internal-router branch so it does not attempt to call a missing local gate.
NPU CAMAsync mapping
CAMAsync already has dispatch/combine semantics:
- native Ascend gate and
select_experts produce topk_ids and topk_weights;
async_dispatch_send transfers routed tokens and routing metadata;
- the FFN role computes experts from the dispatched layout;
async_combine_recv returns the weighted, combined result.
The AFD runner should reuse native Ascend routing and replace only dispatch, local expert execution, and combine. This removes GateOnlyRemoteMoE and the copied compute_gate_topk implementation.
The implementation must explicitly verify that routed scaling, top-k weighting, shared-expert output, and final reduction are each applied exactly once.
Construction and patch boundary
Plugin-owned:
AFDRemoteExpertsForwardMixin;
- GPU and NPU Attention-side runner classes;
AFDRemoteRoutedExperts;
- role/backend/gate-position selection;
- existing role-aware parameter filtering and connector operations.
Exact-version compatibility work:
- the scoped wrapper around vLLM-Ascend's
_ascend_FusedMoE;
- any constructor patch needed to omit Attention-side gate/shared/expert allocation;
- load-order handling between the AFD and vLLM-Ascend factory wrappers.
Upstream-owned and unchanged:
- model-level
DeepseekV2MoE.forward;
- native gate and expert selection;
- ordinary MoE execution on the FFN role;
- native parameter paths and supported runner interfaces.
Every compatibility patch must follow AGENTS.md: exact upstream signature and return type, an immediate patch-reason comment, marked PATCH START/END AFD deltas, focused drift tests, and a removal or upstream plan.
Dense-layer and communication boundary
This refactor applies only to MoE layers.
Dense layers retain their current behavior:
- GPU and CAMP2p Attention roles continue using the existing remote FFN proxy;
- CAMAsync dense layers remain local to Attention;
- the FFN driver retains its existing dense-layer handling.
Communication stays in the FFN driver loop. Phase 2 may unify the MoE computation entry point, but it must not move connector state or send/receive operations into FFN runner forward.
Delivery plan
Phase 1: Attention-side MoERunner reuse
- Add
AFDRemoteRoutedExperts and AFDRemoteExpertsForwardMixin.
- Add the GPU remote-experts runner and replace
AFDAttentionFusedMoE.
- Add the CAMP2p remote-experts runner and construct an Attention-side MoE shell instead of replacing the complete MoE block.
- Add the CAMAsync local-routing runner and remove
GateOnlyRemoteMoE plus copied routing selection.
- Validate all three connector paths against the existing FFN implementations.
Phase 1 is independently mergeable because it preserves connector payloads, ordering, and FFN behavior.
Phase 2: Model-independent FFN MoE computation
Introduce AFDFFNMoERunner(MoERunner) and AFDNPUFFNMoERunner(AscendMoERunner) so FFN drivers invoke registered MoE runners instead of model-specific methods.
For CAMAsync, the NPU runner may expose a dispatched-expert computation entry point using its own routed-expert weights, quantization state, activation, and shared experts. The driver continues to own communication state.
Phase 2 must prove model independence with at least one non-DeepSeek MoE model. Dense layers and unusual MoE implementations outside the native factory remain explicit exceptions.
Validation plan
CPU-safe tests:
- role-aware construction for GPU P2P, NPU CAMP2p, and NPU CAMAsync;
- the expected runner class is injected for each path;
- Attention roles allocate no expert/shared-expert parameters outside their required gate;
- remote-experts forward sends and receives once, preserves DBO/stage metadata, and returns the connector result without extra scaling or reduction;
- CAMAsync passes native
topk_ids and topk_weights to dispatch;
- non-AFD construction and native registration remain unchanged;
- exact upstream signatures, wrapper ordering, and patch drift are checked.
Hardware validation:
- GPU P2P NCCL gate-on-FFN;
- NPU CAMP2p gate-on-FFN;
- NPU CAMAsync gate-on-Attention;
- eager plus currently supported CUDA/ACL/torchair graph paths;
- deterministic pre-/post-refactor logits comparison;
- repeated requests, DBO/uBatch where supported, failure cleanup, and process shutdown.
Risks and mitigations
- Double scaling or reduction: remote-experts paths override complete
forward(); CAMAsync tests each weighting and reduction boundary.
- Unexpected Attention-side weight allocation: inject no-op routed experts and assert role parameter inventories.
- Incorrect internal-router branch: both gate-on-FFN runners explicitly return
is_internal_router = True.
- vLLM-Ascend factory-wrapper ordering: install a scoped, exact-version wrapper after platform initialization and test non-AFD passthrough.
- Graph/compiler regressions: preserve registered connector custom operations and validate every currently claimed graph mode.
- CAMP2p boundary shift: verify that the experts-call input is the same post-norm hidden state previously sent at the MLP boundary.
- Premature model independence claim: require a non-DeepSeek Phase 2 validation and list dense/non-factory exceptions.
Acceptance criteria
Phase 1
Phase 2
Related work
Feedback requested
- Is the public
MoERunner.forward() boundary the correct seam for remote-experts paths?
- Is wrapping vLLM-Ascend's factory acceptable if the wrapper is role-scoped, exact-version guarded, and transparent for non-AFD construction?
- Should Phase 1 be split into GPU/CAMP2p first and CAMAsync second?
- Is the native MoE registration order sufficient for Phase 2, or should the plugin maintain an explicit per-layer runner registry?
- Which exact GPU/NPU model, topology, and graph cells must gate each phase?
Before submitting
Motivation
The current AFD model adaptation still carries model-owned MoE forward proxies and duplicated routing behavior:
RemoteFFNProxyandAFDAttentionFusedMoE;GateOnlyRemoteMoEplus a copiedcompute_gate_topkpath;FusedMoEsignatures, internal-router behavior, EPLB interfaces, routing options, scaling, and reduction semantics.This is one of the highest-drift parts of model adaptation. Every vLLM or vLLM-Ascend upgrade requires the plugin to re-check behavior that upstream already owns.
vLLM 0.26 provides a native extension point:
FusedMoEis a factory that acceptsrunner_clsandrouted_experts_clsand returns aMoERunner. vLLM-Ascend already uses the same mechanism to injectAscendMoERunner.This RFC proposes moving AFD's MoE communication boundary into role-specific runner implementations so model-level MoE forward remains native.
Goals
Non-goals
FusedMoEfactory, or unvalidated backend/topology combinations.Proposed architecture
Inject an AFD runner through the existing
FusedMoE(..., runner_cls=..., routed_experts_cls=...)factory boundary according to role, backend, connector, and gate placement.P2pNcclAFDConnector, gate on FFNAFDAttentionMoERunner(MoERunner): send hidden states, yield for DBO when required, receive the final MoE outputCAMP2pAFDConnector, gate on FFNAFDNPUAttentionMoERunner(AscendMoERunner): same remote-experts behavior through a shared mixinCAMAsyncAFDConnector, gate on AttentionAFDNPUAttentionGateMoERunner(AscendMoERunner): retain native gate andselect_experts, replace dispatch/combine with CAM async send/receive, and skip local expert computationThe GPU and CAMP2p implementations share an
AFDRemoteExpertsForwardMixin. Their concrete classes differ only because one derives fromMoERunnerand the other fromAscendMoERunner.Attention roles also inject an
AFDRemoteRoutedExpertsimplementation whose weight creation is a no-op, preventing allocation of expert weights that belong to the FFN role.Why remote-experts runners override
forward()For gate-on-FFN paths, the connector returns the final FFN result after shared experts, routed scaling, and FFN-side reductions.
Overriding only
_forward_impl()would send that final result through the remaining nativeMoERunner.forward()post-processing and could apply scaling or reductions twice. The remote-experts runners must therefore override the complete publicforward(hidden_states, router_logits, input_ids=None)boundary and return the received result directly.They must also report
is_internal_router = True. The Attention role does not construct a gate for gate-on-FFN, but native model forward needs the internal-router branch so it does not attempt to call a missing local gate.NPU CAMAsync mapping
CAMAsync already has dispatch/combine semantics:
select_expertsproducetopk_idsandtopk_weights;async_dispatch_sendtransfers routed tokens and routing metadata;async_combine_recvreturns the weighted, combined result.The AFD runner should reuse native Ascend routing and replace only dispatch, local expert execution, and combine. This removes
GateOnlyRemoteMoEand the copiedcompute_gate_topkimplementation.The implementation must explicitly verify that routed scaling, top-k weighting, shared-expert output, and final reduction are each applied exactly once.
Construction and patch boundary
Plugin-owned:
AFDRemoteExpertsForwardMixin;AFDRemoteRoutedExperts;Exact-version compatibility work:
_ascend_FusedMoE;Upstream-owned and unchanged:
DeepseekV2MoE.forward;Every compatibility patch must follow
AGENTS.md: exact upstream signature and return type, an immediate patch-reason comment, markedPATCH START/ENDAFD deltas, focused drift tests, and a removal or upstream plan.Dense-layer and communication boundary
This refactor applies only to MoE layers.
Dense layers retain their current behavior:
Communication stays in the FFN driver loop. Phase 2 may unify the MoE computation entry point, but it must not move connector state or send/receive operations into FFN runner forward.
Delivery plan
Phase 1: Attention-side MoERunner reuse
AFDRemoteRoutedExpertsandAFDRemoteExpertsForwardMixin.AFDAttentionFusedMoE.GateOnlyRemoteMoEplus copied routing selection.Phase 1 is independently mergeable because it preserves connector payloads, ordering, and FFN behavior.
Phase 2: Model-independent FFN MoE computation
Introduce
AFDFFNMoERunner(MoERunner)andAFDNPUFFNMoERunner(AscendMoERunner)so FFN drivers invoke registered MoE runners instead of model-specific methods.For CAMAsync, the NPU runner may expose a dispatched-expert computation entry point using its own routed-expert weights, quantization state, activation, and shared experts. The driver continues to own communication state.
Phase 2 must prove model independence with at least one non-DeepSeek MoE model. Dense layers and unusual MoE implementations outside the native factory remain explicit exceptions.
Validation plan
CPU-safe tests:
topk_idsandtopk_weightsto dispatch;Hardware validation:
Risks and mitigations
forward(); CAMAsync tests each weighting and reduction boundary.is_internal_router = True.Acceptance criteria
Phase 1
AFDAttentionFusedMoE,GateOnlyRemoteMoE, and copiedcompute_gate_topkbehavior are removed or no longer used.Phase 2
FusedMoEmodel demonstrates reuse.Related work
Feedback requested
MoERunner.forward()boundary the correct seam for remote-experts paths?Before submitting