Open StudioDUzes opened 1 month ago
I want it to be compatible with Gradio 4. forge
Error is: KeyError: 'sd-webui-ar.py'
I think this is a Forge problem, not an extension.
Hello, I also have my own fork here, with the same issue.
I noticed that there are no issues with the buttons which are explicitly initialized from ToolButton - rather than the AR and Static Res buttons which are subclassed and inherit from ToolButton.
For reasons beyond my comprehension, these buttons in particular are not inheriting properly (or something), because later on the 'module_name' value is the name of the extension instead of the name of the ui_components module.
If I just brute force it, the script works (note in my case the error is sd-webui-ar-plusplus.py
).
File "E:\0-FORGE\venv\lib\site-packages\gradio\components\base.py", line 118, in get_component_class_id
module_path = sys.modules[module_name].__file__
KeyError: 'sd-webui-ar-plus-plus.py'
So if I open up base.py
and edit it like this, the script works fine.
@classmethod
def get_component_class_id(cls) -> str:
module_name = cls.__module__
if module_name == 'sd-webui-ar-plusplus.py':
module_name = 'modules.ui_components'
module_path = sys.modules[module_name].__file__
module_hash = hashlib.md5(f"{cls.__name__}_{module_path}".encode()).hexdigest()
return module_hash
I've been at this for hours but am making basically zero progress beyond this here.
Not sure if this is correct but with my limited Python knowledge it seems that the classes like txt2imgARButtons that inherit ToolButton causes the issue?
Indeed, they don’t seem to properly inherit from ToolButton anymore… via super init. idk if this is a consequence of Gradio 4, or how Illyasviel implemented gradio in Forge. I couldn’t finagle it.
@altoiddealer: Python programmer here.
For reasons beyond my comprehension, these buttons in particular are not inheriting properly (or something), because later on the 'module_name' value is the name of the extension instead of the name of the ui_components module.
This is because the custom button class is defined in sd-webui-ar-plusplus.py
, hence it gets this as its __module__
. See e.g. here and here.
Thus, seems a Gradio problem, but since Python goes to superhuman lengths to expose its moving parts [as put by Evelyn Woods, 2017], one possible hacky fix is to just manually override the __module__
attribute on each affected class.
So, after your last class definition, let's inject the value Gradio expects to see:
# Hack for Gradio 4.0; see `get_component_class_id` in `venv/lib/site-packages/gradio/components/base.py`
txt2imgARButtons.__module__ = "modules.ui_components"
img2imgARButtons.__module__ = "modules.ui_components"
txt2imgResButtons.__module__ = "modules.ui_components"
img2imgResButtons.__module__ = "modules.ui_components"
The result works with unmodified base.py
. The extension loads and the buttons work fine.
This shouldn't have any ill effects, since the __module__
attribute is (AFAIK) only used as debug info.
But now, I'm seeing a second issue. The resolution buttons have neither a label nor a tooltip, they look completely blank. Running a fresh copy of your extension on Forge f2.0.1v1.10.1-previous-317-g4bb56139 (4bb5613916604196b7a33b3e2e2072d0c2408e63), pulled just a few hours ago. Have you encountered this?
Note that the AR buttons show their labels and tooltips correctly, so it can't be related to the hacky fix.
@altoiddealer: Python programmer here.
Heya, first of all thank you so much for checking this out. I am a persistent bastard, and can usually solve things on my own once I try every possible solution, but this is one that eluded me.
So, after your last class definition, let's inject the value Gradio expects to see:
This worked! I was very close to this solution... what I had tried previously was within each Class, just before the super().__init__(**kwargs)
, I had tried self.__module__ = "modules.ui_components"
. I'm unsure exactly why your solution works while this did not, but no matter! You've saved me!
But now, I'm seeing a second issue. The resolution buttons have neither a label nor a tooltip, they look completely blank. Running a fresh copy of your extension on Forge f2.0.1v1.10.1-previous-317-g4bb56139 (4bb5613916604196b7a33b3e2e2072d0c2408e63), pulled just a few hours ago. Have you encountered this?
I had noticed this issue too (on "new forge", with my base.py
hack).
I think there were 2 "previous" release packages to choose from, which just recently has been consolidated to just one "previous" release package. I had only tried the "older previous" without seeing the issue.
Regardless! This is something I am confident I can work out, I was ignoring this completely in lieu of the larger issue.
I'll have time tomorrow to check compatibility of this fix with all the WebUIs, and resolve the static res buttons, as well as hopefully figure out a cleaner solution to the button layout... the buttons scaled nicely on previous versions, now they are spilling into additional rows.
@LEv145
See 2 comments up https://github.com/LEv145/--sd-webui-ar-plus/issues/24#issuecomment-2295038866
You should just need to add that after the img2imgResButtons()
block
Thank you all for your help!
I hope I understood everything correctly) Test if the problem is fixed now on dev branch: https://github.com/LEv145/--sd-webui-ar-plus/tree/dev
@altoiddealer, @LEv145: I'm happy to help with small things like this. :)
Both your extensions are great. In my opinion, having quick buttons for AR and resolution are essential for the UX of A1111 and Forge. (Especially when you can easily pick the most appropriate AR and resolution for your inpaint region.)
@altoiddealer:
This worked! I was very close to this solution... what I had tried previously was within each Class, just before the
super().__init__(**kwargs)
, I had triedself.__module__ = "modules.ui_components"
. I'm unsure exactly why your solution works while this did not, but no matter! You've saved me!
This is because __init__
is an instance method, so self
points to the object instance being constructed.
EDIT: Hence, self.__module__ = ...
writes to the __module__
attribute in the object instance namespace.
However, looking at get_component_class_id
in venv/lib/site-packages/gradio/components/base.py
:
@classmethod
def get_component_class_id(cls) -> str:
module_name = cls.__module__
module_path = sys.modules[module_name].__file__
module_hash = hashlib.md5(f"{cls.__name__}_{module_path}".encode()).hexdigest()
return module_hash
This is a class method, so it doesn't see the object instance namespace at all. The expression cls.__module__
begins looking up the __module__
attribute directly in the class namespace.
(If it wasn't found immediately, then the lookup would bubble up the MRO, which follows the C3 ordering. But in the case discussed here, Python populates the __module__
attribute by default, so it's present by default on each class.)
(EDIT: On the other hand, when you have an object instance obj
, the expression obj.x
begins looking up the attribute x
in the object instance namespace. If not found there, then it looks for it in the class namespace, and then follows the MRO.)
In common wisdom, in Python, __init__
is the object constructor, but that's only almost correct.
When a new object instance is being constructed, Python first calls __new__
, which is a class method. That __new__
is the actual constructor that allocates memory for the new object instance, typically by calling super().__new__(...)
, which bottoms out into some magic in the Python interpreter itself. Then (now be very careful!) Python takes whatever object instance was returned by __new__
, and hands it over to __init__
, as the self
argument, for initialization.
The __new__
class method is another customizable part of Python. You can e.g. implement the singleton pattern (from the C++ world) by implementing a custom __new__
that only ever allocates one instance (per process) of your class.
For a concrete example, see here how to use this to make a Lisp-like symbol type in Python. :)
Also, keep in mind that in Python, classes themselves are just objects. The class
statement effectively instantiates such an object when it runs. Also keep in mind that in Python, definitions have no special role. They run when encountered, just like any other statement. A definition typically, as an important side effect, saves the instantiated thing (class, method or function) into the namespace in which the definition appeared.
Ask me if there's anything else. I can't guarantee that I'll have the answer, but I've done some Python metaprogramming (e.g. [1], [2]), where one tends to need to consider details like this.
I had noticed this issue too (on "new forge", with my
base.py
hack). I think there were 2 "previous" release packages to choose from, which just recently has been consolidated to just one "previous" release package. I had only tried the "older previous" without seeing the issue.Regardless! This is something I am confident I can work out, I was ignoring this completely in lieu of the larger issue.
I'll have time tomorrow to check compatibility of this fix with all the WebUIs, and resolve the static res buttons, as well as hopefully figure out a cleaner solution to the button layout... the buttons scaled nicely on previous versions, now they are spilling into additional rows.
Thanks. I'll wait for your update, then :)
I hope I understood everything correctly) Test if the problem is fixed now on dev branch: https://github.com/LEv145/--sd-webui-ar-plus/tree/dev
Hi and thanks for the quick commit! My first test looks like this, default resolutions/aspect fresh install
Edit: I forgot to mention, the buttons all work, it's just the text is not displayed on any of them.
CHv1.8.11: Set Proxy:
Error calling: I:\SD\forge\webui\extensions\--sd-webui-ar-plus\scripts\sd-webui-ar.py/ui
Traceback (most recent call last):
File "I:\SD\forge\webui\modules\scripts.py", line 545, in wrap_call
return func(*args, **kwargs)
File "I:\SD\forge\webui\extensions\--sd-webui-ar-plus\scripts\sd-webui-ar.py", line 455, in ui
arc_calc_height = gr.Button(value="Calculate Height").style(
AttributeError: 'Button' object has no attribute 'style'
Error calling: I:\SD\forge\webui\extensions\--sd-webui-ar-plus\scripts\sd-webui-ar.py/ui
Traceback (most recent call last):
File "I:\SD\forge\webui\modules\scripts.py", line 545, in wrap_call
return func(*args, **kwargs)
File "I:\SD\forge\webui\extensions\--sd-webui-ar-plus\scripts\sd-webui-ar.py", line 455, in ui
arc_calc_height = gr.Button(value="Calculate Height").style(
AttributeError: 'Button' object has no attribute 'style'
@derpina-ai I updated the code in the dev branch a bit, the problem should be solved
https://github.com/LEv145/--sd-webui-ar-plus/tree/7b501bf5ac09905d8105ec34f7dbb922f3c287e8
@derpina-ai I updated the code in the dev branch a bit, the problem should be solved
https://github.com/LEv145/--sd-webui-ar-plus/tree/7b501bf5ac09905d8105ec34f7dbb922f3c287e8
Hi, latest made the extension load without error but disappear completely in the UI.
maybe unrelated getting weird errors like : RuntimeError: stack expects each tensor to be equal size, but got [256, 4096] at entry 0 and [257, 4096] at entry 1, where 256 is the length of my prompt in tokens
@derpina-ai It seems I forgot to import module Try the new version
https://github.com/LEv145/--sd-webui-ar-plus/tree/1f268df1010ff791b429c2e4856123394f5497aa
still blank on my end.
My other error was unrelated though, some weird apostrophes from an external software ended in my prompt.
I do not yet know how to fix the invisible text, because I do not have Forge, but if there is a way, I think I will put all the patches in the main branch
In Forge (Gradio 4), the buttons are requiring a value string to be provided for each button.
If the string is not provided, it is appearing blank.
In the for loop when creating the buttons, it seems to be critical that the value
arg is in the first position, regardless the fact that all the args are labelled.
What is driving me insane atm, is that my static resolution buttons are working... as is... although they are blank,
As soon as I update the code to assign value
first, they do correctly display the labels - but the buttons are initializing as disabled (greyed out). I've tried everything I could possibly think of to figure out why it is - and explicitly passing interactive=True
in various ways. Again... 3 hours down the drain trying to make the buttons enabled with the labels present at all costs, to no avail.
I'll probably take another stab at it tomorrow.
I think now the text on buttons should be displayed correctly Try the new version
https://github.com/LEv145/--sd-webui-ar-plus/tree/3d534f36d5c63cdfbbd87179f174a6c9e7e4c8b2 UPD: https://github.com/LEv145/--sd-webui-ar-plus/tree/1da3bc6d2705488fd3766db4260c1300fed73530
UPD: https://github.com/LEv145/--sd-webui-ar-plus/tree/1da3bc6d2705488fd3766db4260c1300fed73530
I tried your changes out, and it has the same problems that I was having... except for some reason my AR buttons were at least working (But not the "Res" - they were all disabled).
The buttons are all initializing as "disabled" for whatever reason. There must be some tiny detail that is causing it to be instantly disabled.
It seems that the interactive=False
parameter is responsible for this behavior of the code
The strange thing is that this parameter is not in the code
Hmm..
I tried to move away from inheritance Maybe it will work without a problem
https://github.com/LEv145/--sd-webui-ar-plus/tree/LEv145-buttons-without-inheritance
I'll check it out - but I actually had the same idea last night, and tried the same exact thing... probably at the exacty same time as you lol.
I'm strongly thinking that the issue here is not with Gradio 4, but upstream - something in the way Illyasviel implemented gradio in the new Forge. I think I'm onto something right now...
I tried to move away from inheritance Maybe it will work without a problem
https://github.com/LEv145/--sd-webui-ar-plus/tree/LEv145-buttons-without-inheritance
OK I just deleted a big message I wrote - because I tested your new branch and it absolutely worked with flying colors.
I had the same idea, but must have flawed the execution. Amazing work!!
To add - I think there definitely is something wrong in the Forge gradio implementation, this issue with inheritance is likely on them
Someone will need to test the buttons in auto1111 and forge, and then it will be possible to release it in main
Someone will need to test the buttons in auto1111 and forge, and then it will be possible to release it in main
It will be awhile before I can claim to be a true coder, I'm just a hack piggy backing from the work of true coders.
With that said, Chat GPT was able to help me rework my implementation based on your solution.
Your approach was way more technical than what I was trying to do, which was mere child's play by comparison.
I'll thoroughly test your extension in A1111 / Forge / ReForge and report back
File "C:\Users\OFFICE\AppData\Local\Programs\Python\Python310\lib\copy.py", line 271, in _reconstruct
state = deepcopy(state, memo)
File "C:\Users\OFFICE\AppData\Local\Programs\Python\Python310\lib\copy.py", line 146, in deepcopy
y = copier(x, memo)
File "C:\Users\OFFICE\AppData\Local\Programs\Python\Python310\lib\copy.py", line 231, in _deepcopy_dict
y[deepcopy(key, memo)] = deepcopy(value, memo)
File "C:\Users\OFFICE\AppData\Local\Programs\Python\Python310\lib\copy.py", line 161, in deepcopy
rv = reductor(4)
The above 4 lines repeat many times before...
TypeError: cannot pickle '_thread.lock' object
Traceback (most recent call last):
File "D:\0_AI\stable-diffusion-webui-forge\venv\lib\site-packages\gradio\queueing.py", line 536, in process_events
response = await route_utils.call_process_api(
File "D:\0_AI\stable-diffusion-webui-forge\venv\lib\site-packages\gradio\route_utils.py", line 285, in call_process_api
output = await app.get_blocks().process_api(
File "D:\0_AI\stable-diffusion-webui-forge\venv\lib\site-packages\gradio\blocks.py", line 1923, in process_api
result = await self.call_function(
File "D:\0_AI\stable-diffusion-webui-forge\venv\lib\site-packages\gradio\blocks.py", line 1508, in call_function
prediction = await anyio.to_thread.run_sync( # type: ignore
File "D:\0_AI\stable-diffusion-webui-forge\venv\lib\site-packages\anyio\to_thread.py", line 33, in run_sync
return await get_asynclib().run_sync_in_worker_thread(
File "D:\0_AI\stable-diffusion-webui-forge\venv\lib\site-packages\anyio\_backends\_asyncio.py", line 877, in run_sync_in_worker_thread
return await future
File "D:\0_AI\stable-diffusion-webui-forge\venv\lib\site-packages\anyio\_backends\_asyncio.py", line 807, in run
result = context.run(func, *args)
File "D:\0_AI\stable-diffusion-webui-forge\venv\lib\site-packages\gradio\utils.py", line 818, in wrapper
response = f(*args, **kwargs)
File "D:\0_AI\stable-diffusion-webui-forge\extensions\--sd-webui-ar-plus\scripts\sd-webui-ar.py", line 442, in get_dims
width = img.size[0]
AttributeError: 'str' object has no attribute 'size'
everything is working correctly.
Even that little button on the right (in Img2Img panel) does not error when clicked.
It seems that only this needs to be fixed for full support: https://github.com/LEv145/--sd-webui-ar-plus/issues/28
But for the fix, I will need to install Forge and run debugger👀
On the other hand, it's a small problem
Already up to date.