Description
Describe the bug
controlnet loader from_single_file was originally added via #4084
and method ControlNet.from_single_file()
works for non-converted controlnets.
but for controlnets in safetensors format that contain already converted state_dict, it errors out.
its not reasonable to expect from user to know what is the internal dict structure of the controlnet safetensors file
before he can use it.
even worse, some of the newer controlnets are distributed as single-file-only and are already in diffusers format
which makes them impossible to load in difufsers.
for example: https://huggingface.co/Laxhar/noob_openpose/tree/main
this issue was already mentioned several times, each time closed as "works as designed"
when in reality its just a failure that should be addressed as an issue.
see #8474 #9208 #8614 as examples of previous issues
Reproduction
scenario-1: works with non-converted controlnet
import torch
from diffusers import ControlNetModel
from huggingface_hub import hf_hub_download
local_path = hf_hub_download(repo_id='Aptronym/SDNext', filename='ControlNet11/controlnet11Models_canny.safetensors')
cn = ControlNetModel.from_single_file(local_path, torch_dtype=torch.float16)
print(cn.__class__)
scenario-1: fails for majority of controlnets available on huggingface
import torch
from diffusers import ControlNetModel
from huggingface_hub import hf_hub_download
local_path = hf_hub_download(repo_id='lllyasviel/sd_control_collection', filename='diffusers_xl_canny_small.safetensors')
cn = ControlNetModel.from_single_file(local_path, torch_dtype=torch.float16)
print(cn.__class__)
initial failure is nonsense
OSError: stable-diffusion-v1-5/stable-diffusion-v1-5 does not appear to have a file named config.json.
whats making this worse is that SD15 and SDXL share the same ControlNet
class which causes some
confusion on the base repo where to lookup config.
e.g,, here we're loading SDXL controlnet and error referrs to SD15 repo.
anyhow, trying to force correct config:
cn = ControlNetModel.from_single_file(local_path, torch_dtype=torch.float16, config='diffusers/controlnet-canny-sdxl-1.0-small')
results in even worse nonsense failure during loading of state_dict:
TypeError: is_floating_point(): argument 'input' (position 1) must be Tensor, not NoneType
System Info
diffusers=0.32.0.dev0
python==3.12.3
torch==2.5.1+cu124