Open
Conversation
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
Add this suggestion to a batch that can be applied as a single commit.This suggestion is invalid because no changes were made to the code.Suggestions cannot be applied while the pull request is closed.Suggestions cannot be applied while viewing a subset of changes.Only one suggestion per line can be applied in a batch.Add this suggestion to a batch that can be applied as a single commit.Applying suggestions on deleted lines is not supported.You must change the existing code in this line in order to create a valid suggestion.Outdated suggestions cannot be applied.This suggestion has been applied or marked resolved.Suggestions cannot be applied from pending reviews.Suggestions cannot be applied on multi-line comments.Suggestions cannot be applied while the pull request is queued to merge.Suggestion cannot be applied right now. Please check back later.
Summary
This updates to Transformers 5.1.0. Transformers 5.0 adds support for the SAM3 model. My end goal is to add support for SAM3 in Invoke.
I have performed this update with AI assistance, I am certainly out of my depth with evaluating the true impact of these changes. However, I have produced a test plan with the help of AI and validated every scenario in the test plan. See the test plan at the bottom of this PR, which details every change and the reasoning for it.
NOTE: There is one dependency of InvokeAI which does NOT support Transformers 5.0+ -> The Compel project, which is used for prompt weighting: https://github.com/damian0815/compel
I have opened an issue on their repo here to bump their version: damian0815/compel#128
For now, I have added Transformers 5.1.0 to
override-dependencies- And faced no issues after doing so. I have evaluated prompt weighting (which can be hard to validate by eye) and it appears to still work properly within my tests.The most substantial code in this PR is the update to how the huggingface session is handled. My understanding, is that this new code only applies to test cases due to deprecation of a module which Invoke was using to produce mock callouts in the test environment, and that it has no effect on production functionality.
Related Issues / Discussions
QA Instructions
I have followed the testing plan at the bottom of this document. The testing plan was produced with AI assistance.
Merge Plan
Checklist
What's Newcopy (if doing a release after this PR)Change Description & Test Plan (Generated with AI Assistance)
Regression Testing Plan: Transformers 5.1.0 + HuggingFace Hub Migration
Below is a change-by-change plan. Each section explains what changed, why, and how to test it. Tests are ordered from quickest smoke tests to longer end-to-end runs.
Change 1:
CLIPFeatureExtractor→CLIPImageProcessorFile:
invokeai/backend/stable_diffusion/diffusers_pipeline.pyWhy:
CLIPFeatureExtractorwas removed in transformers 5.x in favour ofCLIPImageProcessor.python -c "from invokeai.backend.stable_diffusion.diffusers_pipeline import StableDiffusionGeneratorPipeline"— should not raiseImportError"a cat on a couch"). Confirm the image generates without errors. This exercises the fullStableDiffusionGeneratorPipelineincluding the feature extractor type.Change 2:
AutoFeatureExtractor→AutoImageProcessor+ removedsafe_serializationFile:
invokeai/backend/image_util/safety_checker.pyWhy: All vision
FeatureExtractorclasses were removed in transformers 5.x. Thesafe_serializationparameter was also removed fromsave_pretrained(safetensors is now the only format).python -c "from invokeai.backend.image_util.safety_checker import SafetyChecker"<root>/models/core/convert/stable-diffusion-safety-checker/if it exists. Enable the NSFW checker in config (nsfw_checker: true). Generate any SD 1.5 image. Confirm the safety checker downloads, saves to disk (nosafe_serializationerror), and the image either passes or is correctly blurred.AutoImageProcessor.from_pretrained()without re-downloading.Change 3:
T5TokenizerFast→T5Tokenizer(4 files)Files:
invokeai/app/invocations/flux_text_encoder.pyinvokeai/app/invocations/sd3_text_encoder.pyinvokeai/backend/model_manager/load/model_util.pyinvokeai/backend/model_manager/load/model_loaders/flux.pyWhy: Transformers 5.x unified slow/fast tokenizers —
T5TokenizerFastno longer exists as a separate class.T5Tokenizernow uses the Rust backend by default.python -c "from invokeai.app.invocations.flux_text_encoder import FluxTextEncoderInvocation", same forsd3_text_encoder,model_util, and the flux loader module."a lighthouse on a cliff at sunset". This exercisesT5Tokenizer.from_pretrained()in the loader and theisinstance(t5_tokenizer, T5Tokenizer)assertion in the text encoder invocation.batch_decodefor truncation warnings.isinstance(model, T5Tokenizer)path inmodel_util.py). No crash = pass.Change 4:
configure_http_backendremoved + session-aware metadata fetchingFiles:
invokeai/backend/model_manager/metadata/metadata_base.py— removedconfigure_http_backendimport and callinvokeai/backend/model_manager/metadata/fetch/huggingface.py— removedconfigure_http_backend, added_model_info_via_session()fallback, added_has_custom_sessionflagWhy (root cause chain):
transformers>=5.1.0pulls inhuggingface_hub>=1.0.0as a dependency.huggingface_hub1.0 switched its HTTP backend fromrequeststohttpxand removed theconfigure_http_backend()function entirely.configure_http_backend(backend_factory=lambda: session)in two places to inject a customrequests.Session— this was used in production fordownload_urls()and, critically, in tests to inject aTestSessionwith mock HTTP adapters so tests could run without real network calls.HfApi()now useshttpxinternally and works fine for real HTTP). However, it broke the test suite:HfApi().model_info()now bypasses the mockrequests.TestSessionentirely and hits the real HuggingFace API, causingRepositoryNotFoundErrorfor test-only repos likeInvokeAI-test/textual_inversion_tests.HuggingFaceMetadataFetchnow tracks whether a custom session was injected (_has_custom_session). When true,from_id()calls a new_model_info_via_session()method that uses the injectedrequests.Sessionto query the HF API directly (matching the URL patterns the test mocks expect). When false (production), it usesHfApi()as before.python -c "from invokeai.backend.model_manager.metadata.fetch import HuggingFaceMetadataFetch"pytest tests/app/services/model_install/test_model_install.py -x -v— all 19 tests should pass, especiallytest_heuristic_import_with_type,test_huggingface_install, andtest_huggingface_repo_idwhich depend on mock HF API responses via the injected session.stabilityai/sd-turbo). Confirm the metadata (name, description, tags) is correctly fetched and displayed, and the model downloads successfully. This exercises the productionHfApi().model_info()path, plushf_hub_url()anddownload_urls().Change 5:
HfFolder→huggingface_hub.get_token()File:
invokeai/app/services/model_install/model_install_default.pyWhy:
HfFolderwas removed inhuggingface_hub1.0+. The replacement is the top-levelget_token()function.python -c "from invokeai.app.services.model_install.model_install_default import ModelInstallService"huggingface-cli login), try installing a gated model (e.g.black-forest-labs/FLUX.1-dev). Confirm the token is automatically injected and the download succeeds.get_token()returnsNonegracefully and the install proceeds.Change 6:
transformers>=5.1.0override for compelFile:
pyproject.toml—override-dependenciesWhy:
compel==2.1.1requirestransformers ~= 4.25(<5.0). The uv override forces past this constraint."a (red:1.5) car on a (blue:0.5) road". Compare to an unweighted"a red car on a blue road". The weighted version should show noticeably more red and less blue. This is the core compel functionality."a photo of a dog"and negative prompt"blurry, low quality". Confirm it generates without crash.SDXLCompelPromptInvocation)."a photo of a cat".blend("a photo of a dog", 0.5)or("a cat", "a dog").blend(0.5, 0.5). This exercises deeper compel internals.Change 7: T5 shared-weight assertion →
model.tie_weights()Files:
invokeai/backend/model_manager/load/model_loaders/flux.py—_load_state_dict_into_t5()classmethodinvokeai/backend/quantization/scripts/quantize_t5_xxl_bnb_llm_int8.py—load_state_dict_into_t5()functionWhy (root cause chain):
model.shared.weightandmodel.encoder.embed_tokens.weightshould refer to the same tensor.nn.Parameterobject, soa is bwasTrue._tie_weights()/tie_weights(). The two attributes may be distinctnn.Parameterobjects that are kept in sync by the framework, soa is bcan beFalse.model.load_state_dict(state_dict, strict=False, assign=True). Theassign=Trueflag replaces parameters in-place rather than copying data into existing tensors. This severs even the parameter-level tie that transformers 5.x establishes.model.encoder.embed_tokens.weight is model.shared.weight, which was guaranteedTruein 4.x but fails in 5.x afterassign=True.model.tie_weights(), which re-establishes the tie regardless of how it is internally implemented. This is forward-compatible and is the officially recommended approach.python -c "from invokeai.backend.model_manager.load.model_loaders.flux import FluxBnbQuantizednf4bCheckpointModel"_load_state_dict_into_t5(). The generation should complete withoutAssertionError. (Same as test 3b — this change and Change 3 are both exercised together.)FluxBnbQuantizednf4bCheckpointModelloader which also calls_load_state_dict_into_t5().quantize_t5_xxl_bnb_llm_int8.pyand confirm it completes without assertion errors.Change 8:
HFTokenHelper.get_status()— null token guard forget_token_permission()File:
invokeai/app/api/routers/model_manager.pyWhy (root cause chain):
HFTokenHelper.get_status()callshuggingface_hub.get_token_permission(huggingface_hub.get_token())to check whether a valid HF token is present.get_token()returnsNone.get_token_permission(None)returned a falsy value, so the code fell through toreturn HFTokenStatus.INVALID— correct behavior.get_token_permission(None)raises an exception (it now validates the input and rejectsNone).except Exceptioncatch returnedHFTokenStatus.UNKNOWN, which the frontend interprets as a network error, showing the misleading message: "Unable to Verify HF Token — Unable to verify HuggingFace token. This is likely due to a network error."get_token()forNonefirst and returnINVALIDimmediately, before ever callingget_token_permission(). This restores the correct "no token" UI message.~/.cache/huggingface/token), clear$env:HF_TOKEN, restart InvokeAI. The UI should show the proper "no token" message, not the "unable to verify / network error" message.huggingface-cli login), restart InvokeAI. The UI should show the token as valid.black-forest-labs/FLUX.1-dev). The UI should clearly indicate a token is needed, not a network error.Automated Test Suite
pytest ./tests -x -m "not slow"-xflag stops on first failure for quick feedback.pytest ./tests -x -m "slow"Quick Smoke Test Script (all imports at once)
Run this to verify none of the changed files crash on import:
If this prints
All imports OK, you've passed the baseline. Then proceed to the UI-based tests in priority order: 6a → 3b/7b → 3d → 4b → 5c → 2b → 1b.