feat: t5 encoder gguf support - #9324
Conversation
Add loading support for single-file GGUF T5 encoders (e.g. city96/t5-v1_1-xxl-encoder-gguf, llama.cpp naming), mirroring the existing Qwen3 GGUF encoder path. - Add T5Encoder_GGUF_Config (single-file, detects enc.blk.* keys + GGML tensors) and register it in the AnyModelConfig union - Add T5EncoderGGUFModel loader: remaps llama.cpp T5 keys to transformers naming, infers T5Config from tensor shapes, dequantizes token/relative-attention-bias embeddings, ties embed_tokens to shared - Work around transformers T5DenseGatedActDense casting activations to the uint8 GGML weight dtype (int8 guard doesn't cover uint8), which would corrupt the feed-forward output - Reject T5 encoders in the Qwen3 GGUF/checkpoint configs so the two stay mutually exclusive (both carry token_embd.weight; the factory resolves multi-matches from a set, so this is not order-safe) Reuse the vendored T5-XXL tokenizer instead of downloading it: move it out of Anima into a neutral invokeai/backend/t5 module shared by Anima and the GGUF loader, and update the package-data path accordingly.
…support # Conflicts: # invokeai/frontend/web/src/services/api/schema.ts
…FFN patch guard - Add unit coverage for the pure, high-risk parts of T5EncoderGGUFModel: key remapping (_convert_t5_gguf_to_transformers), config inference (_infer_t5_config_from_state_dict), and the wo-dtype workaround. - Make _make_feed_forward_gguf_safe raise if it patches no feed-forward modules, so a future transformers class rename fails loudly at load time instead of silently corrupting encoder output. Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
…ssumptions - Inline tensor.shape in _infer_t5_config_from_state_dict: GGMLTensor.shape already returns the dequantized (logical) shape, so the _shape_of helper's fallback branch was unreachable. Remove the helper. - Document that config inference targets the T5 v1.1 XXL family and that the hardcoded architectural constants (rel-attention max distance, layer-norm epsilon, gated-gelu) are that family's defaults. Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
Review + merge-to-main updateBrought the branch up to date with Merge to
|
…pport Resolves conflicts with upstream video generation (invoke-ai#9163), Ideogram 4 (invoke-ai#9303), T5 GGUF encoder (invoke-ai#9324) and the Qwen VAE device fix (invoke-ai#9373). Notable resolutions: - qwen_image_latents_to_image: keep the as_qwen_image_vae() reinterpretation but adopt upstream's vae_info.compute_device fix (invoke-ai#9373) - graphBuilderUtils: keep the allow-list isMainModelWithoutUnet predicate, which covers wan_model_loader automatically - generationSettingsVisibility: add 'wan' and 'ideogram-4' to
Summary
Feature: Load GGUF-quantized T5 text encoders, and show/recall the T5 encoder in image metadata.
Adds support for single-file GGUF T5 text encoders (e.g. city96/t5-v1_1-xxl-encoder-gguf, llama.cpp
enc.blk.*naming) so users can run FLUX/SD3 with a small quantized T5 instead of the full ~9GB encoder. The GGUF infrastructure already existed (used by FLUX/Qwen3/Z-Image); this wires T5 into it, mirroring the existing Qwen3 GGUF encoder path.Backend
T5Encoder_GGUF_Config(single-file; detectsenc.blk.*keys + GGML tensors) registered in theAnyModelConfigunion.T5EncoderGGUFModelloader: remaps llama.cpp T5 keys → transformers T5, infersT5Configfrom tensor shapes, keeps transformer weights asGGMLTensors for the autocast cache, eagerly dequantizes the token/relative-attention-bias embeddings (embedding lookups can't run on quantized tensors) and tiesencoder.embed_tokens→shared.T5DenseGatedActDense.forwardcasts activations toself.wo.weight.dtypeunless it'storch.int8(a bitsandbytes guard). GGML weights aretorch.uint8, which slips past the guard and corrupts the feed-forward output. Worked around by rebinding the FF forward to only cast for floating-pointwoweights.token_embd.weight; the config factory resolves multi-matches from aset, so they must be mutually exclusive — disambiguated on theenc.blk.*prefix).backend/animainto a neutral sharedbackend/t5module used by both Anima and the GGUF loader (updatedpyproject.tomlpackage-data accordingly).Frontend
t5_encoder), but it wasn't shown in the Recall Parameters tab. Added aT5EncoderModelmetadata handler (mirrorsQwen3EncoderModel) and registered it in both the handler registry (for "Recall All") and the metadata viewer's display list, plus an i18n label.Related Issues / Discussions
https://discord.com/channels/1020123559063990373/1149510134058471514/1521658213836001291
#8421
QA Instructions
city96/t5-v1_1-xxl-encoder-Q6_K.gguf) and install it via the Model Manager — it should be detected as a T5 Encoder (GGUF) model.Q3_K_S) also loads and generates.Validated locally on
Q3_K_SandQ6_K: unique model classification, correct config inference (T5 v1.1 XXL), finite bf16 forward on CUDA, and cross-quant cosine-similarity 0.94–0.999 on content tokens (confirms the key mapping). Backend config/probe tests and frontend metadata tests pass.Merge Plan
Standard merge. No DB schema or redux migration changes.
pyproject.tomlpackage-data path changed (invokeai.backend.anima→invokeai.backend.t5) — a clean build picks up the vendored tokenizer at its new location.Checklist
What's Newcopy (if doing a release after this PR)