-
Notifications
You must be signed in to change notification settings - Fork 2.5k
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
Fix begin and end validation used in ControlNets. #7605
base: main
Are you sure you want to change the base?
Conversation
Fixed logic to match the error message - begin should be <= end.
Changed string to a literal
Does anything happen when they are the same value (e.g. a single step w/ the control)? |
No, if they are the same value then it appears to do nothing. I think that's better behavior than an exception as it lets you leave a ControlNet in a workflow but set values (algorithmically) to 0 to disable it. |
This seems like a workaround for a mute function. |
Sorry, I misunderstood what you were asking. If you set start and end to the same value in |
I think you thought @hipsterusername 's reply was from me - you did answer my question initially. But I agree that this change seems like a workaround for a mute feature more than a fix. If we make this a no-op, why not make |
So this means that it's impossible to make a workflow where you set start and end points for the control independently of generation, i.e. I want the control to be for overall steps 0 to 0.2 and generation to be split into two separate prompts from 0 to 0.3 and 0.3 to 1. The math works fine if I set the control to go for longer than 0.3 but not if I want to cut it off early; I have to modify my workflow every time I want to change cutoffs. See the following for how I implement it after the patch is in place (duration being the length of the control and split being when to split generation steps): |
Though I don't fully understand what you are doing, I do understand that the current behaviour makes it difficult. I think this may be an XY problem, where changing the constraints is a way to address a narrow use-case (i.e. lets you do what you want to do without changing any other nodes), but doesn't address a broader need. I wonder if there's a way to handle the math stuff such that we don't need to compromise the technical accuracy of the fields. |
Definitely a way using float math nodes to do a max or min |
You can't use the same value for control begin steps percent and end steps percent, or the exception gets thrown and the workflow fails. Even the most basic case of having the node as part of a workflow and (you hope) disabled by setting both begin and end to 0 causes an exception to be thrown. To me this seems like a problem in the code logic, especially given the error that I didn't change that says only less than is problematic:
In other words, I made the code match the exception that's thrown rather than changing the exception to match the code. I don't think there's a way to work around the exception since all node paths get evaluated and there's no conditional execution logic. I thought the change I made would be harmless and the easiest and least controversial path - guess not! |
Thanks for the explanation, I see how it's difficult to do what you want without this change (or a I'll just ask for @RyanJDick's opinion on the change. PS: A future field type might be a number tuple that renders as a range slider. Like with two thumbs. Would be pretty useful. |
I think I understand the motivation. My main concern would be that people set start == end and expect the controlnet to be disabled, but it still might run for 2 steps. In a few places, we have logic that looks something like the following. This will always run the controlnet for at least 1 step, and will often run it for 2 steps (due to floor/ceil). first_control_step = math.floor(control_datum.begin_step_percent * total_step_count)
last_control_step = math.ceil(control_datum.end_step_percent * total_step_count)
if step_index >= first_control_step and step_index <= last_control_step:
... I can understand why the original author chose to make the range inclusive on both ends - it makes it more natural when you want to run the controlnet for all steps. But, it makes things awkward when you are trying to do more fine-grained intermediate start/stop control. To do this 'right', I think we'd probably want to handle it like we do for FLUX denoising start/end with epsilon-close equality checks ( InvokeAI/invokeai/backend/flux/sampling_utils.py Lines 62 to 97 in 7daff46
I see a few paths forward. Want to hear other opinions based on this additional context:
|
Summary
Setting a ControlNet beginning and ending to the same value results in a pydantic error.
Related Issues / Discussions
https://discord.com/channels/1020123559063990373/1149506274971631688/1333866963256086589
QA Instructions
Validation now works as expected when the beginning and ending are the same value.
Checklist
What's New
copy (if doing a release after this PR)