Skip to content

New model: Anima - #1487

Merged
dxqb merged 57 commits into
Nerogar:mergefrom
dxqb:anima
Jul 4, 2026
Merged

New model: Anima#1487
dxqb merged 57 commits into
Nerogar:mergefrom
dxqb:anima

Conversation

@dxqb

@dxqb dxqb commented May 30, 2026

Copy link
Copy Markdown
Collaborator

Test in preview branch: https://github.com/Nerogar/OneTrainer/tree/preview

Includes:

dxqb and others added 9 commits March 25, 2026 00:39
- Bump requirements: transformers 4.57.6 → 5.9, huggingface-hub 0.34.4 → 1.16.1
- Remove HF_HUB_DISABLE_XET workaround from startup scripts; Xet is stable in hub 1.16
- Remove _prepare_sub_modules / snapshot_download prefetching; hub 1.16 fetches lazily on demand
- Delete thread_safety.py and apply_thread_safe_forward calls; workaround for transformers#42673
  was fixed upstream in v5
- Replace _remove_added_embeddings_from_tokenizer (relied on internal Trie, removed in v5) with
  orig_tokenizer deep-copies stored at load time; model savers pass use_original_tokenizers=True
  to create_pipeline() so saved checkpoints use the unmodified tokenizer
- Switch ErnieModelLoader to AutoTokenizer; eliminates the tokenization-logger suppress workaround
- Suppress httpx INFO logs; hub 1.16 uses httpx internally and logs every HTTP request

Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
Co-Authored-By: dxqb <183307934+dxqb@users.noreply.github.com>
@dxqb dxqb added the preview merged in the preview branch label May 30, 2026
@AmaelG

AmaelG commented Jun 1, 2026

Copy link
Copy Markdown

Unsure if this is in scope for this PR, but I think it would be useful to expose an optional toggle to train Anima's llm_adapter.
From my testing with multi-concept training, training the llm adapter seems to improve concept adherence, converge faster, and reach lower loss/val.
I know tdrussel recommends to avoid training it, but in my experiments I have not seen obvious degradation of general knowledge, while the trained concepts became more reliable.

@Silvicultor

This comment was marked as resolved.

@dxqb

dxqb commented Jun 2, 2026

Copy link
Copy Markdown
Collaborator Author

Unsure if this is in scope for this PR, but I think it would be useful to expose an optional toggle to train Anima's llm_adapter. From my testing with multi-concept training, training the llm adapter seems to improve concept adherence, converge faster, and reach lower loss/val. I know tdrussel recommends to avoid training it, but in my experiments I have not seen obvious degradation of general knowledge, while the trained concepts became more reliable.

training text components should be a thing of the past. it's always been a crutch for diffusion models that weren't very capable yet. So I'm hesitant to reintroduce this, with all the problems that come with it (such as having multiple learning rates and many more failure modes).
If there is strong community support that this is needed, maybe, but if even the model's creator advises against it...

dxqb added a commit to TheForgotten69/OneTrainer that referenced this pull request Jun 3, 2026
dxqb and others added 2 commits June 4, 2026 20:28
torch._dynamo.config overrides are thread-local. The existing call in
checkpointing_util runs in the main thread and is invisible to the
training thread spawned by the UI. This caused compiled optimizers
(e.g. AdamW_adv with compiled_optimizer=True) to hit the default
recompile_limit of 8 and abort with FailOnRecompileLimitHit when
training models with more than 8 distinct parameter shapes.

Fix: call init_compile() from GenericTrainer.__init__, which runs in
whichever thread/process owns training (UI thread, CLI main thread,
or torch.multiprocessing.spawn subprocess for multi-GPU).

Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
@dxqb

dxqb commented Jun 4, 2026

Copy link
Copy Markdown
Collaborator Author

torch._dynamo.exc.FailOnRecompileLimitHit: Hard failure due to fullgraph=True

fixed by #1495, merged into this PR

@dxqb dxqb mentioned this pull request Jun 4, 2026
@dxqb dxqb linked an issue Jun 4, 2026 that may be closed by this pull request
dxqb added a commit that referenced this pull request Jun 4, 2026
@FuouM

FuouM commented Jun 5, 2026

Copy link
Copy Markdown

Thank you for your great work!

I've been training Anima LoRAs in OneTrainer and using the same dataset/settings in Kohya sd-scripts. Training itself works fine, but LoRAs saved from OneTrainer (preview branch) don't load correctly in ComfyUI when paired with the standard single-checkpoint Anima model (anima-base-v1.0.safetensors). I believe this is due to the LoRA key naming on export.

Example key:

  • sd-scripts: lora_unet_blocks_0_self_attn_q_proj.lora_down.weight
  • OneTrainer: transformer.transformer_blocks.0.attn1.to_q.lora_down.weight

Other model types in OneTrainer already handle this via convert_*_lora.py key sets (e.g. Flux, HiDream, SD3). Anima's AnimaLoRASaver and AnimaLoRALoader both return None from _get_convert_key_sets(), so no conversion runs on save or load.

Diffusers has the inverse mapping in _convert_non_diffusers_anima_lora_to_diffusers() (lora_conversion_utils.py), which lines up with the rename table already documented in AnimaModel.py (diffusers_to_original()).

I prototyped the conversion script as below. It might be missing things as I haven't tested exhaustively yet:

# convert_anima_lora.py
from modules.util.convert.lora.convert_lora_util import LoraConversionKeySet


def __map_anima_blocks(parent: LoraConversionKeySet) -> list[LoraConversionKeySet]:
    return [LoraConversionKeySet(
        omi_prefix=f"blocks.{i}",
        diffusers_prefix=f"transformer_blocks.{i}",
        legacy_diffusers_prefix=f"blocks_{i}",
        parent=parent,
        next_omi_prefix=f"blocks.{i + 1}",
        next_diffusers_prefix=f"transformer_blocks.{i + 1}",
    ) for i in range(100)]


def __map_transformer_block(key_prefix: LoraConversionKeySet) -> list[LoraConversionKeySet]:
    mappings = [
        ("self_attn.q_proj", "attn1.to_q", "self_attn_q_proj"),
        ("self_attn.k_proj", "attn1.to_k", "self_attn_k_proj"),
        ("self_attn.v_proj", "attn1.to_v", "self_attn_v_proj"),
        ("self_attn.output_proj", "attn1.to_out.0", "self_attn_output_proj"),
        ("cross_attn.q_proj", "attn2.to_q", "cross_attn_q_proj"),
        ("cross_attn.k_proj", "attn2.to_k", "cross_attn_k_proj"),
        ("cross_attn.v_proj", "attn2.to_v", "cross_attn_v_proj"),
        ("cross_attn.output_proj", "attn2.to_out.0", "cross_attn_output_proj"),
        ("mlp.layer1", "ff.net.0.proj", "mlp_layer1"),
        ("mlp.layer2", "ff.net.2", "mlp_layer2"),
    ]

    return [
        LoraConversionKeySet(omi, diffusers, legacy_diffusers_prefix=legacy, parent=key_prefix)
        for omi, diffusers, legacy in mappings
    ]


def convert_anima_lora_key_sets() -> list[LoraConversionKeySet]:
    keys = []

    transformer = LoraConversionKeySet(
        "lora_unet",
        "transformer",
        legacy_diffusers_prefix="lora_unet",
    )

    for block_prefix in __map_anima_blocks(transformer):
        keys += __map_transformer_block(block_prefix)

    return keys

After converting, the output in ComfyUI seems to be affected by the LoRA as expected.

@dxqb

dxqb commented Jun 5, 2026

Copy link
Copy Markdown
Collaborator Author

I've been training Anima LoRAs in OneTrainer and using the same dataset/settings in Kohya sd-scripts. Training itself works fine, but LoRAs saved from OneTrainer (preview branch) don't load correctly in ComfyUI when paired with the standard single-checkpoint Anima model (anima-base-v1.0.safetensors). I believe this is due to the LoRA key naming on export.

Comfy-Org/ComfyUI#14182

@Silvicultor

Copy link
Copy Markdown

I've been training Anima LoRAs in OneTrainer and using the same dataset/settings in Kohya sd-scripts. Training itself works fine, but LoRAs saved from OneTrainer (preview branch) don't load correctly in ComfyUI when paired with the standard single-checkpoint Anima model (anima-base-v1.0.safetensors). I believe this is due to the LoRA key naming on export.

Comfy-Org/ComfyUI#14182

Doesn't look like Comfyanon wants to merge this one and also keep in mind that other inference tools (at least the ones that aren't built upon Diffusers) would also have to make the same change to their code. So I say OneTrainer should include the above proposed conversion logic into it's code and settle for the de-facto standard already established. I know OT wants to use Diffusers keys whenever possible for consistency, and that's perfectly fine for all the models like Flux or Qwen, their original repos being Diffusers format, but this is a special case. Initial Anima release wasn't in Diffusers format, so it's hard to argue for the Diffusers keys.

@dxqb

dxqb commented Jun 5, 2026

Copy link
Copy Markdown
Collaborator Author

I've been training Anima LoRAs in OneTrainer and using the same dataset/settings in Kohya sd-scripts. Training itself works fine, but LoRAs saved from OneTrainer (preview branch) don't load correctly in ComfyUI when paired with the standard single-checkpoint Anima model (anima-base-v1.0.safetensors). I believe this is due to the LoRA key naming on export.

Comfy-Org/ComfyUI#14182

Doesn't look like Comfyanon wants to merge this one

if that is the case, they should close the PR. As for the other points, we already had this discussion on Discord.

@dxqb

dxqb commented Jun 5, 2026

Copy link
Copy Markdown
Collaborator Author

By the way, this PR already includes conversion code: https://github.com/dxqb/OneTrainer/blob/03b7156c49bac5c8f5a8f13de259357f94047d75/modules/model/AnimaModel.py#L31

It's just not used for LoRAs currently (only for full finetunes), because this was the consistent and accepted way to do things for all other models. If inference tools want to change that now, they should make that clear (by closing the PR, for example)

@dxqb dxqb changed the title Anima New model: Anima Jun 6, 2026
dxqb and others added 2 commits June 13, 2026 14:47
Several model savers (Ernie, Flux2, Z-Image, ...) duplicate the same
deepcopy + tokenizer __deepcopy__ workaround to produce a dtype-converted
copy of a diffusers pipeline for saving. Extract it into a shared helper
so new savers can reuse it.

Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
Adds a tokenizer_attrs parameter (default ("tokenizer",)) so savers with
extra/different tokenizer attributes (Flux's tokenizer_2, SD3's
tokenizer_3, HiDream's tokenizer_3/tokenizer_4) can use the same helper.
Replaces the duplicated deepcopy + tokenizer __deepcopy__ workaround in
Chroma, Ernie, Flux, Flux2, HiDream, HunyuanVideo, PixArtAlpha, Qwen,
Sana, StableDiffusion3 and Z-Image with calls to the shared helper.
No behavior change.

Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
@dxqb
dxqb changed the base branch from master to merge July 1, 2026 05:19
dxqb added 4 commits July 1, 2026 07:38
Resolves the Ctk/PySide6 view-controller split against the LoRA/full-model
output-format rework: LoRAModule.py keeps the fusion check while dropping
the rank check (upstream Nerogar#1549); ModelTab.py's split becomes
BaseModelTabView.py + ModelTabController.py, with the output-format
selection logic living in the controller (get_output_formats), matching
the TopBarController pattern.
Brings in Nerogar's Ctk/PySide6 view split (branch merge) plus the
LoRA/full-model output-format rework, with no anima-specific conflicts
since this base branch carries no Anima code yet.
Ports Anima's model-tab/top-bar/training-tab UI hooks onto the new
Base/Ctk/PySide6 view-controller split (branch merge): __setup_anima_ui in
BaseModelTabView.py and BaseTrainingTabView.py, and the Anima entries in
ConvertModelUIController's and TopBarController's model-type lists.
@dxqb

dxqb commented Jul 1, 2026

Copy link
Copy Markdown
Collaborator Author

Anima now has the new LoRA saver merged. You can select output formats. Both Kohya and Comfy are loaded successfully by Comfy.

@Silvicultor

Copy link
Copy Markdown

I tested the new output format "Comfy" with Forge-neo and I can confirm that LoRA and also LoKr can be loaded (and affects the output), without having to convert anything manually now.

dxqb and others added 22 commits July 1, 2026 22:00
Wire attention backend selection into Anima setup (mask=False: Anima's
predict() passes no attention_mask/encoder_attention_mask into
model.transformer, only a pixel-space padding_mask for the conv, which is
unrelated) and pass controller through the Anima UI base2 frame.
FusedModuleGroup._leaf_forward_N called the inner peft module's forward
once per leaf, and that forward's orig_forward is the synthetic fused
base recomputing all N leaves' base output every time -- N real base
computes per leaf, N^2 total for a group of N. Add PeftBase.delta_forward,
an optional hook returning just the adapter's own contribution (the term
added to orig_forward(x)) without touching the base. LoRAModule and
LoHaModule implement it (their deltas never read the base weight);
FusedModuleGroup uses it, when available, to add each leaf's real,
unfused base once instead. DoRA/OFT/LoKr keep the slower generic path
(delta_forward defaults to None) since their forwards recompose the base
weight itself and aren't expressible this way.

Also replace the functools.partial(self._leaf_forward, leaf_index) hook
with four fixed _leaf_forward_0..3 methods: torch.compile guards on
leaf.forward's function identity, and a partial rebuilt on every
hook_to_module() call was a fresh object each time, forcing a recompile
on every hook/unhook cycle.

Co-Authored-By: Claude Sonnet 5 <noreply@anthropic.com>
Remove non-explanatory/out-of-place comments, drop the untrue Cascade
bracket note on LEGACY_LORA, and revert unnecessary learning_rate
notation-only changes in a few presets.

Co-Authored-By: Claude Sonnet 5 <noreply@anthropic.com>
…uess

Mirrors the saver's _convert_legacy opt-in default: a model gets LEGACY
load support only by explicitly declaring its historical layout, not by
inheriting a generic reconstruction that happens to be right for most
models but silently wrong for any that isn't. Flux/Flux2/HunyuanVideo/SD3
opt in via the extracted _mixture_legacy_conversion() helper; Sana's now-
redundant None override is removed.

Co-Authored-By: Claude Sonnet 5 <noreply@anthropic.com>
Trims explanatory-only comments, converts ModelType's LEGACY/ORIGINAL_TRANSFORMER
format support from denylists to allow-lists (new models default to unsupported
until a saver implements them), drops the qkv-group matching's dependency on a
literal "i" placeholder name (matched_leaf_groups works with any/no placeholder),
removes dead fuse_qkv/fuse_split duplication in favor of a single variadic fuse(),
and removes the _denoising_body_conversion identity wrapper.
…ression

- Add required base-model-name field to the convert tool for LoRA/embedding conversion
- Fix convert_model.py CLI crashing on any LoRA/embedding conversion
- Inline the unused _check_fusion_match indirection in LoRASaverMixin
- Fix Flux2 LEGACY LoRA output regression and remove leftover debug print
Squashed review fixes: centralize the LoRA param allowlist and derive
SUPPORTED_PARAM_PREFIXES from FACTOR_PREFIXES, filter absent text
encoders, drop dead guards, fix the DoRA chunk-swap, and trim duplicate
comments.

Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
…rmats merge

The lora-output-formats merge silently converted this from a denylist
(everything except Sana/Wuerstchen) to an allowlist that predates Anima,
dropping full-model transformer output support for it.
# Conflicts:
#	modules/module/FusedModule.py
#	modules/ui/BaseModelTabView.py
#	modules/util/enum/ModelType.py
# Conflicts:
#	modules/ui/BaseModelTabView.py
#	modules/util/enum/ModelType.py
Remove dead TE-related guards (Anima never supports TE/embedding
training, TE is always loaded), drop unused text_encoder_lora, freeze
text_conditioner explicitly, remove stray comments, and repin mgds to
Nerogar/mgds@bae73e5.

Co-Authored-By: Claude Sonnet 5 <noreply@anthropic.com>
@dxqb
dxqb merged commit 9547963 into Nerogar:merge Jul 4, 2026
1 check passed
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

preview merged in the preview branch

Projects

None yet

Development

Successfully merging this pull request may close these issues.

[Feat]: Anima support

4 participants