Skip to content

[bug]: Wan folder tokenizer maps unknown characters to <s> under transformers 5 #9984

Open

Description

@Pfannkuchensack

What happened

For a Wan 2.2 Diffusers folder (or a standalone UMT5 folder), invokeai/backend/model_manager/load/model_loaders/wan.py:618 loads the tokenizer with AutoTokenizer.from_pretrained. Under transformers 5.10.4 this returns a T5Tokenizer that rebuilds its own pipeline instead of using the folder's tokenizer.json:

  • it splits on whitespace;
  • it has no normalizer;
  • it hard-codes Unigram(unk_id=2) (transformers/models/t5/tokenization_t5.py:113-127). Id 2 is <s> in UMT5's vocabulary; <unk> is 3.

Measured against the folder's own tokenizer.json (Wan 2.2 TI2V-5B Diffusers), with prompts run through the Wan node's prompt_clean:

  • On 4021 fuzz strings, the folder path differs from tokenizer.json in 3785 cases.
  • Example: '\U0001D11E music' → folder [273, 2, 10129, 1], tokenizer.json [273, 3, 10129, 1].
  • Out-of-vocabulary characters become <s> instead of <unk>: several emoji, about 55 % of CJK Unified code points, most Hangul syllables.
  • A space before a literal </s> or <extra_id_N> also tokenizes differently.

The UMT5 GGUF tokenizer added in #9967 is built from the GGUF fields. It matches tokenizer.json exactly on the same set, so the two Wan encoder formats now condition differently on such prompts.

What you expected to happen

The folder tokenizer reproduces tokenizer.json, the tokenization Wan was trained with.

How to reproduce the problem

Load the Wan 2.2 Diffusers tokenizer/ with AutoTokenizer.from_pretrained and with PreTrainedTokenizerFast(tokenizer_file=…/tokenizer.json), and compare the ids for a prompt containing e.g. 𝄞.

Possible fix

Load the folder tokenizer from tokenizer.json as a PreTrainedTokenizerFast (or T5TokenizerFast), with the folder's special tokens.

Environment

main @ ea1056b, transformers 5.10.4.

Activity

  1. guishiw commented on Oct 27, 2026

    @guishiw
    Contributor

    Hi, I’d like to work on this issue. I’ve reproduced the tokenizer mismatch and completed a proposed fix on my personal fork:

    Branch: fix/9984-wan-folder-tokenizer

    Root cause

    Wan 2.2 uses a UMT5 vocabulary where token ID 2 is <s> and token ID 3 is <unk>.

    Under Transformers 5.10.4, loading the folder through AutoTokenizer or the T5TokenizerFast class declared in model_index.json does not reliably preserve the folder’s serialized tokenizer.json pipeline. The T5 implementation rebuilds a Unigram tokenizer with a hard-coded unk_id=2.

    Consequently, out-of-vocabulary characters—including many emoji, CJK characters, Hangul syllables, and other Unicode input—are encoded as <s> instead of <unk>. This produces conditioning that differs from the tokenizer used to train Wan and from InvokeAI’s GGUF tokenizer path.

    The problem affects both:

    • the tokenizer component of a normal Wan Diffusers model;
    • standalone Wan UMT5 encoder folders.

    Fix strategy

    • Route both the Wan Diffusers tokenizer path and the standalone UMT5 tokenizer path through a dedicated Wan tokenizer loader.
    • When tokenizer.json is present, load it directly as a PreTrainedTokenizerFast so the serialized Unigram pipeline and unk_id=3 are preserved.
    • Apply UMT5 special-token defaults only when the folder does not already define them.
    • Install the expected UMT5 EOS post-processor when it is missing, preserving correct sequence termination and padding masks.
    • For legacy folders containing only spiece.model, reconstruct the tokenizer from the SentencePiece protobuf while preserving:
      • the original unknown-token ID;
      • normalization and metaspace behavior;
      • EOS processing;
      • ordinary USER_DEFINED vocabulary pieces.
    • Add regression tests covering serialized JSON loading, unknown-character handling, missing token configuration, SentencePiece-only folders, user-defined tokens, and the real WanDiffusersModel loader route.

    The focused tests pass with 4 tests passed. I also compared the reconstructed SentencePiece path against the official Wan serialized tokenizer across 2,030 ordinary, Unicode, unknown, special-token, and user-defined-token cases, with 0 mismatches. Ruff, format, and diff checks also pass.

    Could you please assign this issue to me? If the approach looks good, I’ll open a pull request for review. Thank you!

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Metadata

Metadata

Assignees

Labels

backendPRs that change backend filesbugSomething isn't working

Type

No type

Projects

No projects

    Milestone

    No milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions