Reorganize xorl.ops: vendored quarantine, objectives split, ops/exact, ops/families (#78 phases 1-5) - #81
Reorganize xorl.ops: vendored quarantine, objectives split, ops/exact, ops/families (#78 phases 1-5)#81qywu wants to merge 14 commits into
Conversation
git-mv ops/quack -> ops/_vendored/quack and ops/linear_attention/flashqla -> ops/_vendored/flashqla. In-repo imports are rewritten to the new paths; the old paths remain as alias stubs (sys.modules aliasing) for one deprecation cycle. The lint/format/codespell excludes and the pyproject vendoring note collapse to the single _vendored/ prefix, and the ops/README.md map is updated.
The RL and supervised objective functions (policy_loss, grpo_loss, cispo_loss, importance_sampling_loss, opd_loss, opd_streaming_kl, causallm_loss, reducers, loss_output) and the loss registry move out of xorl.ops.loss into a new xorl.objectives package; ops/loss keeps only the cross-entropy/selected-logprob kernel stack. In-repo imports are rewritten; the old module paths remain as compat stubs, and xorl.ops.loss / xorl.ops re-export the objective API lazily (PEP 562) for one deprecation cycle — lazily because the objectives import the kernels, so an eager re-export is an import cycle.
Physically moves the seven first-party contract modules (rope_class_b, canonical_moe_leaf, canonical_moe_cast, kernel_config_pin, bi_gemm_configs, block_fp8_native, fused_silu_and_mul) into xorl.ops.exact, rewriting in-repo imports and leaving compat stubs at the old paths. Three members are aliased in place rather than moved, deviating deliberately from the original #78 sketch: - bi_families_v2.py is sha256-gated byte-identical against the serving copy; - batch_invariant_ops.py turned out to be vendored-adapted from SGLang's srt/batch_invariant_ops — splitting or moving it would destroy side-by-side diffability with the serving twin, so the planned 4-way split is dropped; - exact_sampling_transforms.py is under active rewrite in #74; the canonical direction flips to ops/exact/sampling_transforms.py after #74 lands.
- ops/glm5_kernels -> ops/families/glm5 and ops/dsv4 -> ops/families/dsv4. Deliberate deviation from the #78 sketch: the kernels stay under ops/ rather than moving into models/transformers/<family>/ because those packages have import side effects (DSV4 mutates the HF Auto registries on import) and kernels must be importable without them. Old paths are sys.modules alias stubs. - The GatedDeltaNet and Mamba2Mixer nn.Module layer classes move from ops/linear_attention/layers and ops/ssm/layers to xorl.models.layers; ops keeps only kernels. The old package paths re-export the classes lazily (PEP 562) for one deprecation cycle. - In-repo imports rewritten; the kernel-adjacent contract modules (linear_attention/modules, ssm/modules) stay in ops by design.
Every export (build_sorted_indices, group_tokens_by_expert{,_v2},
DeepEPScatter, DeepEPWeightedGather, deepep_scatter, deepep_weighted_gather)
has zero importers in src/, tests/, benchmarks/, or certification/ — the
DeepEP dispatch paths in ops/moe grew their own implementations. The #78
plan said 'merge into moe/'; deleting dead code beats moving it.
The vendored-path rewrite matched 'xorl.ops.linear_attention.flashqla' as a prefix of the first-party module 'flashqla_cp', mispointing backend.py and the CP equivalence test at a nonexistent _vendored.flashqla_cp.
Broly Security ScanNote ✅ Clean scan Note Re-scan this PR anytime with
|
don't think this is good |
Per kiddyboots216 on #78/#81: the three 'aliased in place' modules are now physically moved. - New ops/sglang/ package for the literal serving-engine twins: bi_families_v2.py (moved byte-identical — same git blob as main; the sha256 gate hashes content, not paths) and batch_invariant_ops.py (vendored-adapted from sglang/srt/batch_invariant_ops; kept a single diffable file). The package docstring states the paired-edit policy; the format/rewrite excludes follow the new path. - exact_sampling_transforms.py -> ops/exact/sampling_transforms.py, making the replay contract physically canonical under ops/exact. - Old module paths are sys.modules alias stubs (full-fidelity, including underscore names) for one deprecation cycle; in-repo imports codemodded.
|
Done in cc8f635 — no aliases left. You were right that the constraint was narrower than I stated: the sha256 gate hashes content, not paths, so moving the file is safe (the moved Per your #78 suggestion there's now an |
|
a lot of the file names etc. are kind of artifact-y, like the "rope class b" is just nomenclature from the blog post, i think we should feel free to take a high-level look at the kernels / ops breakdown and see how we can name things to not be so inscrutable / opaque. there's too much scar tissue in the names. |
Decoder ring for the historical jargon (bi_, K3, Class-B, canonical MoE reduce, one-round SwiGLU, families v1/v2, GKN, exact) pending the rename pass discussed on #78 — several terms are user-facing config fields or vocabulary shared with the serving engine and need coordinated renames.
|
Agreed on the scar tissue. Two-part response: Done now (abed122): a name glossary in Needs your sign-off before executing — most of these names are load-bearing beyond file names, so renames have blast radii:
Say which rows you want and I'll execute them as one rename commit here (module renames with alias stubs) plus a follow-up for the config-field deprecations. |
'Class-B' was blog-post nomenclature; the descriptive name says what it is: one fp32 chain with a single final round. Module, functions, internal config stamps, and the YAML field are renamed; 'rope_class_b:' remains accepted as a deprecated alias in both entry points (DeprecationWarning), and XORL_ROPE_CLASS_B stays an env alias. The ops module docstring keeps the Class-A/Class-B mapping as historical context.
#81 review, row 3) Module and Python-level function names spell out what 'canonical' meant: the pinned fixed-order expert-contribution reduction. The cross-engine contract key CANONICAL_MOE_REDUCE_VERSION and the registered torch.library op names (xorl_k3::_canonical_moe_*) are pinned identifiers and keep their strings.
Matches the existing _exact_one_round_swiglu resolution stamp vocabulary; a deprecated module-level alias keeps the old callable importable.
…review, row 2) - ce_mode canonical value is now 'batch_invariant'; 'bi_fused' remains an accepted deprecated alias normalized (with a DeprecationWarning) in both argument entry points, and the CrossEntropyMode Literal accepts both. - ops/loss/bi_fused_lm_head.py -> batch_invariant_lm_head.py; bi_fused_per_token_ce / bi_fused_vocab_parallel_per_token_ce / resolve_bi_fused_lm_head_tp_groups spell out batch_invariant_*. - ops/exact/bi_gemm_configs.py -> batch_invariant_gemm_configs.py. - Prose, error messages, examples, and docs updated; test files renamed (incl. the tests/distributed shard claim). - The bi_ prefix survives only inside the serving twins (bi_families_v2, batch_invariant_ops' bi_* kernels, bi_fused_gdn_gating) whose symbol names must match the engine. - Alias regression tests cover rope_class_b and ce_mode='bi_fused'.
|
All table rows executed (4 commits,
Glossary updated to lead with the new names (old terms noted as "formerly"). Alias regression tests added for both config deprecations. Verified: full pre-commit, arguments suites, the batch-invariant head + golden-gate + rmsnorm-family + exact-head + trainers surfaces all green locally. |
…rity-bot finding) The sentinel alone is not sufficient authorization: whoever controls XORL_EXACT_KERNEL_CONFIG_DIR could pre-place it anywhere. Deletion now also requires the resolved target to live strictly inside the (resolved) pin directory and refuses symlinked targets, bounding any rmtree to the pin tree. Pre-existing behavior surfaced by the phase-3 file move.
Phases 1–5 of #78, one commit per phase, stacked on the phase-0 PR #80 (base branch
reorg/phase0-vendored-markers; retarget tomainafter #80 lands). Every move leaves a compat stub or lazy re-export at the old import path for one deprecation cycle, and every in-repo import was codemodded to the new canonical path in the same commit.Phase 1 — vendored quarantine
ops/quack→ops/_vendored/quack,ops/linear_attention/flashqla→ops/_vendored/flashqla(~30k lines out of the first-party namespace). Old paths aresys.modulesalias stubs (deep submodule imports through them create a duplicate module instance — noted in the stub docstrings). Lint/format/codespell excludes collapse to the single_vendored/prefix.Phase 2 — objectives out of ops/loss
New
xorl.objectivespackage:policy_loss,grpo_loss,cispo_loss,importance_sampling_loss,opd_loss,opd_streaming_kl,causallm_loss,reducers,loss_output, and the loss registry.ops/losskeeps only the CE/selected-logprob kernel stack. The old package paths re-export the objective API lazily (PEP 562) — eager re-export is an import cycle, since the objectives import the kernels.Phase 3 — the exact-contract family under ops/exact (+ ops/sglang, per review)
Physically moved:
rope_class_b,canonical_moe_leaf,canonical_moe_cast,kernel_config_pin,bi_gemm_configs,block_fp8_native,fused_silu_and_mul, and (after review feedback, commit cc8f635)exact_sampling_transforms.py→ops/exact/sampling_transforms.py.Per @kiddyboots216's suggestion on #78, the literal serving-engine twins get their own
ops/sglang/package:bi_families_v2.py(moved byte-identical — same git blob asmain; the sha256 gate hashes content, not paths) andbatch_invariant_ops.py(vendored-adapted fromsglang/srt/batch_invariant_ops). One deviation from the issue sketch stands:batch_invariant_ops.pyis not split — it must remain a single file diffable against the serving twin. The taxonomy is three-way:_vendored/(untouchable snapshots),sglang/(parity twins, paired-edit policy), first-party everything else.Phase 4 — one home per family; layers out of ops
ops/glm5_kernels→ops/families/glm5,ops/dsv4→ops/families/dsv4. Deviation from the issue sketch: they stay underops/rather than moving intomodels/transformers/<family>/because those packages have import side effects (DSV4 mutates the HF Auto registries on import) and kernels must be importable without them. TheGatedDeltaNetandMamba2Mixerlayer classes move toxorl.models.layers; the kernel-adjacent contract modules (linear_attention/modules,ssm/modules) stay in ops by design.Phase 5 — dead code
ops/ep_kernelshad zero importers for any of its seven exports — deleted rather than merged intomoe/as sketched.Verification
pre-commit run --all-files(the lint CI command) green after every phase.tests/ops(90 passed), catch-alltestsminus server/distributed/ops (501 passed),tests/server -m cpu(green),tests/distributed -m cpu(153 passed; 1 failure —test_native_fp8_meta_materialization_preserves_fsdp2_dtensors— fails identically on unmodifiedmain).main, unrelated to this PR: 14 tilelang-compile failures (dsv4 indexer/sparse-MLA + flashqla contract pins; nvcc/CUDA-13 header mismatch), 2 model-snapshot tests, 1 native-FP8 FSDP2 materialization test, and 2pytest_asyncio-missing collection errors intests/server/orchestrator.…flashqlaas a prefix of the first-partyflashqla_cpmodule.Closes nothing by itself; tracks #78 (phases 1–5). The deprecation-stub deletion sweep is the future final phase.