Skip to main content

veomni-patchgen-model

Author or refresh a VeOmni model's patchgen-generated modeling under generated/ — GPU and/or NPU config, dense or MoE, text / VLM / Omni. Covers the patchgen decorators, sharing patches across sibling models via name_map, MoE fused-expert weight loading, Ulysses SP in multimodal forwards, __init__.py registration, running codegen, and the test cases. This is the modeling step of adding a new model, not only of refreshing an existing one. Trigger: 'add patchgen for a model', 'write a patch_gen_config', 'regenerate the generated modeling', 'add NPU patchgen', 'port a model to patchgen', 'transformers v5 migration'. Never hand-edit anything under generated/.

インストールへ移動

ソース情報

リポジトリ
ByteDance-Seed/VeOmni
ソースの最終更新活動
2026年9月11日 13:00
検出された SKILL.md の言語
英語
スター
2,212
フォーク
274

インストール方法

デフォルトでは、最初にソースを確認する Prompt が選択されています。直接コマンドに切り替えるか、ローカルコピーをダウンロードすることもできます。

ソースファイルを確認

インストールを決める前に、SKILL.md と SkillsMP に表示されている付属ファイルをお読みください。

ファイルエクスプローラー
4 ファイル

SKILL.md を表示中

SKILL.md
ソースの指示 · 読み取り専用プレビュー
name
veomni-patchgen-model
description
Author or refresh a VeOmni model's patchgen-generated modeling under generated/ — GPU and/or NPU config, dense or MoE, text / VLM / Omni. Covers the patchgen decorators, sharing patches across sibling models via name_map, MoE fused-expert weight loading, Ulysses SP in multimodal forwards, __init__.py registration, running codegen, and the test cases. This is the modeling step of adding a new model, not only of refreshing an existing one. Trigger: 'add patchgen for a model', 'write a patch_gen_config', 'regenerate the generated modeling', 'add NPU patchgen', 'port a model to patchgen', 'transformers v5 migration'. Never hand-edit anything under generated/.
# VeOmni Patchgen Modeling Protocol Purpose: add or refresh a model's patchgen-generated modeling under `veomni/models/transformers/<model>/generated/`. VeOmni pins `transformers==5.16.1` and ships patchgen-generated modeling for every supported transformers-family model. The non-transformers architectures (`flux`, `movqgan`, `wan`) have no `generated/` directory and are out of scope. **References (read first, load on demand):** - `docs/design/patchgen.md` — patchgen DSL, CLI, CI drift check - `docs/transformers_v5/transformers_v5_moe_weight_loading.md` — MoE fused-expert layout + runtime converter - `docs/transformers_v5/veomni_flash_attention_kernel_adapter.md` — FA custom-name adapter - `docs/transformers_v5/testing_new_model.md` — test case SOP for a new model ## What to read for your model This file is the spine: it applies to every model. The category-specific material lives in `references/` — load only what your model needs. | Your model | Also read | |---|---| | Any model, before Phase 1 | `references/model-examples.md` — pick the closest existing model and mirror it | | Has routed experts (MoE) | `references/moe.md` — Phase 2 expert patches, Phase 3 checkpoint converter, MoE pitfalls | | Has a vision / audio / speech tower (VLM or Omni) | `references/multimodal.md` — SP-aware multimodal forward, metadata precompute, `dummy_forward`, subtree pruning, VLM/Omni pitfalls | | Text-only and dense | neither — the spine plus the examples file is the whole protocol | A text-only dense GPU model therefore reads this file plus the examples, and skips about 380 lines of MoE and multimodal material. A VLM+MoE model reads everything. Read the spine first either way; the reference files add to it and never replace a phase. --- ## Phase 0: Environment + Reference Setup ### 0.1 Verify transformers venv Patchgen runs against `transformers==5.16.1`. Before touching code: ```bash source .venv/bin/activate python -c "import transformers; print(transformers.__version__)" ``` If not `5.16.1`, re-sync the default env: ```bash uv sync --frozen --extra gpu --group dev source .venv/bin/activate ``` ### 0.2 (Strongly recommended) Drop HF reference source into `.agents_workspace/` `.agents_workspace/` is gitignored. Keeping the upstream HF source next to your patchgen config is the single biggest accelerator for catching subtle signature/contract drift while iterating. Use the pinned version as the directory name so several pins can coexist: ```bash PIN=$(python -c "import transformers; print(transformers.__version__)") mkdir -p ".agents_workspace/hf_reference/<m>/v${PIN}" curl -fsSL -o ".agents_workspace/hf_reference/<m>/v${PIN}/modeling_<m>.py" \ "https://github.com/huggingface/transformers/raw/v${PIN}/src/transformers/models/<m>/modeling_<m>.py" ``` `-f` matters: without it a missing tag or renamed module returns 404 and curl writes the error page into `modeling_<m>.py` with exit status 0, so you would diff against an HTML page and not notice. For VLMs also grab `processing_<m>.py` / `image_processing_<m>.py` / `configuration_<m>.py` if you expect processor-side or config-shape work. If you are **refreshing** an existing patchgen-generated file across a transformers minor bump (the pin the generated file was produced against → the new pin), pull both versions side-by-side and diff to spot contract drift — substitute the `<old_ver>` / `<new_ver>` tags with the actual versions you are migrating between: ```bash mkdir -p .agents_workspace/hf_reference/<m>/{old,new} curl -fsSL -o .agents_workspace/hf_reference/<m>/old/modeling_<m>.py \ "https://github.com/huggingface/transformers/raw/<old_ver>/src/transformers/models/<m>/modeling_<m>.py" curl -fsSL -o .agents_workspace/hf_reference/<m>/new/modeling_<m>.py \ "https://github.com/huggingface/transformers/raw/<new_ver>/src/transformers/models/<m>/modeling_<m>.py" diff -u .agents_workspace/hf_reference/<m>/{old,new}/modeling_<m>.py | less ``` ### 0.3 For a pin bump: survey signature drift across *all* configs first `patchgen <config>` (without `--dry-run`) runs the generated file through ruff, so a patch body referencing a symbol upstream no longer defines fails loudly with `F821` / `F811`. That catches removed *names*. It does **not** catch a patch whose target still exists but whose **signature changed** — the patch keeps applying and silently runs against the wrong contract. Before touching any config, index both upstream versions with `ast` and compare the parameter lists of every target named in each config's `override_method` / `replace_class` / `replace_function` call. Targets missing from *both* versions are VeOmni-added methods (patchgen uses `override_method` to inject them) and should be filtered out, or they drown the real findings. `docs/transformers_v5/upgrade_5_9_to_5_16.md` records what that survey turned up for the 5.9 → 5.16 bump and how each class of breakage was resolved — read it before starting a new bump, the categories repeat. Note that `--dry-run` returns before the ruff step, so it reports success on files that cannot even import. Never use it as the pass/fail signal. Things to watch for in upstream contracts: - `@can_return_tuple`, `@capture_outputs`, `@merge_with_config_defaults`, `@auto_docstring` decorators → affect behavior of your `override_method`. When you `override_method` on a `@auto_docstring`-decorated method, **every parameter you declare in the new signature must also appear in the patched docstring's `Args:` block** — otherwise `auto_docstring` will emit warnings at import time about "undocumented parameter". For Omni-style overrides that add params like `audio_feature_lengths`, `feature_lens`, `aftercnn_lens`, `rope_deltas`, `image_grid_thw`, `video_grid_thw`, etc., copy the upstream docstring and append minimal one-line entries for every new param. - **`attention_mask` may be a dict** — HF v5 routinely passes `attention_mask={"full_attention": <tensor>, ...}` keyed by attention type. Any patched forward that forwards `attention_mask` to `compute_3d_position_ids` / `get_rope_index` / other tensor-expecting helpers must defensively unwrap `attention_mask.get("full_attention", None)` when it's a dict. VLM and Omni models have four more upstream contracts to check before writing any patch — placeholder masks, `get_{image,video}_features` return shapes, the packed position-ids layout and mrope shape collapse. See `references/multimodal.md`, "Phase 0: upstream contracts". Keep this directory around through commit; delete it after the PR merges (it's already gitignored so it won't leak into the repo). --- ## Before You Start: Create a Plan Track the phases with whatever todo/plan tool the running agent provides. Suggested plan: ```text Phase 0: Verify venv + drop HF reference files -> in_progress Phase 1: Scope & audit upstream surface -> pending Phase 2: Draft <model>_gpu_patch_gen_config.py -> pending Phase 3: (MoE only) Add checkpoint converter -> pending Phase 4: Wire __init__.py to expose generated classes -> pending Phase 5: Run patchgen + verify diff -> pending Phase 6: Add test cases -> pending Phase 7: Run tests (single-GPU + e2e) -> pending Phase 8: Docs + commit; review before PR or substantive update -> pending ``` Drop phases that don't apply (e.g. Phase 3 for non-MoE models). --- ## Phase 1: Scope & Audit **Input**: model name `<M>` (e.g. `qwen3_5`, `glm_moe_dsa`). **Operations:** 1. Locate `veomni/models/transformers/<M>/`. If the directory does not exist yet you are being called as the modeling step of `/veomni-new-model`: create it, and read that skill's Phase 1 first so the category (text / VLM / Omni, dense / MoE, GPU-only or GPU+NPU) is already decided when you get here. 2. If a patchgen-generated file already exists under `veomni/models/transformers/<M>/generated/` you are **refreshing** an existing config (e.g. picking up upstream changes, adding NPU sibling, fixing a bug). Otherwise you are writing the first config for this model. Either way, the rest of this protocol applies identically. 3. Decide backend coverage: - GPU only → one `<m>_gpu_patch_gen_config.py` + one `generated/patched_modeling_<m>_gpu.py`. - GPU + NPU → add sibling `<m>_npu_patch_gen_config.py` that writes `generated/patched_modeling_<m>_npu.py`; mirror the `glm_moe_dsa` or `qwen3_vl` layout. 4. Check model category. Each entry below names the closest existing model; `references/model-examples.md` says what to copy out of it, file by file. - Text-only LLM → reference `qwen3/` (or `llama/` for the minimal example) - MoE → reference `qwen3_moe/` (plus converter work in Phase 3) - VLM (non-MoE) → reference `qwen3_vl/` - VLM + MoE → reference `qwen3_vl_moe/` (multimodal forward + SP scatter, ViT dummy forward, Flash-attn kwargs popping, `get_position_id_func`) - Omni (non-MoE thinker + speech subtree to exclude) → reference `qwen2_5_omni/` (audio/vision SP + dummy_forward, talker/token2wav/BigVGAN exclusion, `log_probs`/`entropy` output dataclass, no parallel_plan/converter) - Omni MoE → reference `qwen3_omni_moe/` 5. Check upstream source (`from transformers.models.<m> import modeling_<m>`). Confirm class/function names still exist; MoE expert layouts especially diverge between sibling models — see `docs/transformers_v5/transformers_v5_moe_weight_loading.md`. 6. Note related configs/loaders to preserve: `MODELING_REGISTRY`, `MODEL_CONFIG_REGISTRY` in `veomni/models/loader.py`; any auto-config registrations. 7. Look for a **sibling model** you can borrow patches from: e.g. qwen3_5_moe reuses GatedDeltaNet/ViT patches from `qwen3_5` via direct import + `name_map={"Qwen3_5": "Qwen3_5Moe"}`. Prefer reuse over copy-paste when the upstream classes are structural duplicates with only a name-prefix difference. 8. Compare upstream and VeOmni parameter keys, including constructor overrides and nested modules. For any mismatch, follow [the user-decision rule in veomni-new-model](../veomni-new-model/SKILL.md#checkpoint-key-conflicts-require-a-user-decision) before choosing a model rename or checkpoint conversion. This also applies to refreshes and dependency upgrades. A resolution already authorized in the current task does not require another confirmation. **Validation**: you have a concrete list of patches to apply, the reference model directory to mirror, and the backend/category decision pinned down. --- ## Phase 2: Draft `<M>_gpu_patch_gen_config.py` Create `veomni/models/transformers/<M>/<M>_gpu_patch_gen_config.py` at the model root. **Skeleton (mirror `qwen3_gpu_patch_gen_config.py`):** ```python from veomni.patchgen.patch_spec import PatchConfig, create_patch_from_external config = PatchConfig( source_module="transformers.models.<m>.modeling_<m>", target_file="patched_modeling_<m>_gpu.py", description="<M> with LigerKernel GPU replacements + VeOmni SP/fused-loss patches", ) ``` **Patch primitives:** | Effect | patchgen decorator / API | | --------------------------------------------- | ------------------------------------------------------ | | Replace whole class (RMSNorm, MLP, Experts) | `@config.replace_class("<Class>")` or `create_patch_from_external(...)` for liger | | Replace module-level function (rotary, loss) | `@config.replace_function("<name>")` | | Override a single method (Attention.forward, Model.forward, ForCausalLM.forward) | `@config.override_method("<Class>.<method>")` | | Add attribute / extra `super().__init__()` wiring | `@config.modify_init("<Class>")` | | Reuse patch from a sibling config (name-prefix difference) | `config.override_method("<NewClass>.<m>", replacement=<imported_fn>, name_map={"OldPrefix": "NewPrefix"})` — non-decorator form. **Caveat**: name_map only rewrites symbol *names* at the AST level; it does NOT align field sets between sibling output dataclasses (e.g. dense `ModelOutputWithPast` vs MoE `ModelOutputWithPast` with extra `router_logits`). Any `<OldClass>Output(...)` constructor call in the body gets its name rewritten but keeps the original arg list, silently dropping MoE-only fields. Clone the body when return dataclasses differ. | | Supporting import needed in generated file | `config.add_import("<module>", names=[...])` (or `alias=..., is_from_import=False`) | | Remove an upstream import the generated file should NOT keep | `config.drop_import_names("<symbol>", ...)` | | Inject raw code (try/except import fallback, helper fn used by patched code) near top of generated file | `config.add_post_import_block("""...""")` | | Remove unused class from output | `config.exclude_from_output("<Class>")` | | Inherit an entire sibling GPU config into an NPU config (reuse helpers / imports / post-import blocks; only override device-specific kernels) | `config.helpers.extend(gpu_config.helpers)` + `config.post_import_blocks.extend(gpu_config.post_import_blocks)` + `config.additional_imports.extend(gpu_config.additional_imports)` + import each `<fn>_patched` and re-register via `config.override_method(...)`. See `qwen3_vl_npu_patch_gen_config.py` | **Cross-config reuse pattern** (qwen3_5_moe reusing qwen3_5): ```python from veomni.models.transformers.qwen3_5.qwen3_5_gpu_patch_gen_config import ( qwen3_5_gated_deltanet_forward_patched, qwen3_5_vision_model_forward, # ... ) _NAME_MAP = {"Qwen3_5": "Qwen3_5Moe"} config.override_method(
GitHubで見る
この SKILL.md は非常に大きいため、SkillsMP では最初のセクションだけを表示しています。 GitHubで見る