-
Notifications
You must be signed in to change notification settings - Fork 26.9k
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
Add a way for API txt2img and img2img requests to pass args to always on scripts #8187
Conversation
Added 2 additional possible entries in the api request: alwayson_script_name, a string list, and, alwayson_script_args, a list of list containing the args of each script. This allows us to send args to always on script and keep backwards compatibility with old script_name and script_arg api params
I'd prefer if it was a dictionary like this:
|
… alwayson_scripts param dict
Changed to the proposed format and updated the PR description. |
报错! controlnet 参数根本不知道咋传,全靠猜,还不对! |
@Vespinian |
The examples in the |
I saw that you used the above parameter passing method, but I used this way to report the parameter error; I can use the following method to pass parameters, but I feel that the above method is the latest method, the following method will be deprecated;
|
What I posted is no longer valid after the latest commits in the controlnet extension repo, The way you posted below is the right way to do it. What is being deprecated is not the method to pass the args you posted below, it's the controlnet api routes |
I've followed the recent ControlNet's api changes a bit but I'm still unsure how to proceed with other scripts. Do they need a customized handler to consume the DynamicPrompts and Cutoff are two interesting scripts that I'm trying to use via API, however, I don't know what to pass into the call payload. I assume that the dictionary method is a custom implementation provided by the ControlNet guys but if we can send a mixed type list how should we define what arguments to send and in what order? Maybe the |
Yes Controlnet made a dict out of it's args to make it more user friendly (That being said, the value of "args" is still a list of args, except each arg is a controlnetunit dict). For other scripts, it should just be the order the args are passed to the process function. So, looking at the code, I would assume for Cutoff it would look something like this.
It should be the same list that the ui function returns L178:
If it's not neatly laid out in the code you'll have to deduce it yourself (you could add prints and try to work it out with the ui, that's what I did with additional networks). I don't really know if there's something you can do about that at the webui's level as we only provide a reserved location in the script_arg list without really knowing what the script does with it. The API just takes the list you provided it in "args" and dumps it in the script's reserved slots in the script_args list. |
Thanks for the reply @Vespinian I was just editing my comment to say that further testing proved fruitful, I managed to make Cutoff work following my assumptions. In case anyone is interested in it as well check that discussion. Thanks a lot for the PR this is very useful stuff! |
Add a way for API txt2img and img2img requests to pass args to always on scripts
Is there straightforward documentation for this anywhere? Or a more generic way we could expose how to use these APIs to the user? Or a better way we could expose this to the user in general? For the life of me, I can't figure out how to 1) choose "img2img alternative test" as a script for On a broader note: how feasible would it be to add something like a button to the UI that lets the user reproduce the payload required to reproduce the current web UI request? |
@dellis23 There are 2 types of scripts in the WebUI, the ones that stay always on and can be called upon simultaneously with other always on scripts. Not a requirement but these are the ones that usually introduce something new to the UI like ControlNet's expandable panel or a new Tab at the top. On the other hand you have the scripts that only run when you pick them from the Scripts list on Txt2Img or Img2Img modes. The main difference is that you can only activate 1 of these scripts per generation. For example, To know if the script falls into a particular category, just open the main Knowing this is relevant because the way you call them via the api will depend on their type. If you check the Swagger documentation page for the Txt2Img or Img2Img POST endpoints you'll notice that the payload can have both "script_name" and the new "alwayson_scripts" properties. You use "script_name" if you want to call a regular script (like you're trying to do) and "alwayson_scripts" for the other type. Now for the arguments. There is also a "script_args" property that you must use for regular scripts. For "alwayson_scripts" the args must be sent as a dictionary with the scripts name as key. To know the script's title check the The args must be sent in the order they are consumed by the webui's internal script runner, so you must check what they are and their proper order. I like to start by looking at the So, As for the arguments, this is the def run(self, p, _, override_sampler, override_prompt, original_prompt, original_negative_prompt, override_steps, st, override_strength, cfg, randomness, sigma_adjustment): Like I said you must ignore I'm not familiarized with that script and their types but if you compare the variable names with what is displayed in the ui you can easily reverse engineer what must be sent. Checking the Here is an example payload: {
... // Img2Img info you want to send like input image as base64 string, prompt, negative prompt, seed, sampler, etc.
"script_name": "img2img alternative test",
"script_args": [
0, // _
false, // override_sampler: bool
"some text", // override_prompt: string
"some other text", // original_prompt: string
"yet more text", // original_negative_prompt: string
true, // override_steps: bool
25, // st: int (value for Decode Steps)
false, // override_strength: bool
7.5, // cfg: float
0.32, // randomness: float
true // sigma_adjustment: bool
]
} As I said, I never used the script and don't know what these values do but checking the If by button to send the payload you mean to test things out, you can use Swagger for that, there is an Api link in the bottom of the web ui that redirects to that page but it's in the |
Thank you @Hugo-Matias, that helps a ton. I'm unfortunately not getting the same results I get when I run things in the web ui, but at least I'm a lot closer in debugging now. |
And re:
I mean something like: if I get the query working perfectly correctly in the web UI, it would be nice to have some way to simply get the required json payload to use for the API to recreate the exact same request (though I realize images would make that tricky). On multiple occasions I've tried to recreate a web ui result using the API and am unable to get the same results. |
Good luck, it will take some experimentation and I'm not 100% that's what you need to pass as arguments but I would start from there. Also, if you want to call ControlNet you need to pass it in as an "alwayson_script" alongside the regular script like: {
...
"script_name": "img2img alternative test",
"script_args": [
...
],
"alwayson_scripts": {
"ControlNet": {
"args": [
...
]
}
}
}
Yeah that would be a neat feature to have and would certainly make things easier but I don't think there is something like that available. However, this isn't too complicated, once you figure it out the first time, you can easily extrapolate that same workflow to other scripts. |
A button would be nice maybe you could open an enhancement issue because I don't think many people will see this suggestion in a closed PR. An extension that can load the api param from an image might be possible too, I don't know if the extra info would have everything though. In the mean time, if you are feeling hacky you could add prints to all the params passed in modules/img2img.py and modules/txt2img.py. That should be an almost 1 to 1 with the api parameters. |
Thanks, created #9120 |
Also, in case anyone else is searching for information on this and ends up here, here's a payload that ultimately worked for me: url = "http://localhost:7860/sdapi/v1/img2img"
body = {
"resize_mode": 0,
"sampler_index": "Euler",
"sampler_name": "Euler",
"steps": 20,
"width": 912,
"height": 512,
"batch_size": 1,
"cfg_scale": 2,
"denoising_strength": 0.2,
"seed": -1,
"subseed": -1,
"subseed_strength": 0,
"init_images": [b64_image],
"prompt": prompt,
"negative_prompt": negative_prompt,
"alwayson_scripts": {
"ControlNet": {
"args": [
{
"input_image": b64_controlnet_image,
"module": 'canny', # aka preprocessor
"mask": "",
"model": "control_scribble-fp16 [c508311e]",
"weight": 1.0,
"resize_mode": "Scale to Fit (Inner Fit)",
"lowvram": False,
"processor_res": 512,
"threshold_a": 100,
"threshold_b": 200,
"guidance": 1,
"guidance_start": 0,
"guidance_end": 1,
"guessmode": False,
}
]
}
},
"script_name": "img2img alternative test",
"script_args": [
None, # A dropped argument?
True, # Override sampling method
True, # Override prompt
prompt,
negative_prompt,
True, # Override sampling steps
50, # Decode steps
True, # Override denoising strength
2, # Decode CFG
0, # Randomness
True, # sigma adjustment
],
} |
It was the old version about the webui API. Did you updated it and test this code could run? |
Describe what this pull request is trying to achieve.
UPDATE:
Changed to add 1 param, a dictionary, to the api for txt2img and img2img (alwayson_scripts) in the format proposed in the comment below.
These changes add 2 params to the api for txt2img and img2img (alwayson_script_name, alwayson_script_args).alwayson_script_name
is a list of string containing the name of the always on scripts you want to pass args toexemple: ["Additional networks for generating", "ControlNet"]
alwayson_script_args
is a list of lists containing args for script mentioned in alwayson_script_nameexemple: "alwayson_script_args": [[true, false, "LoRA", "None", 1, 1, "LoRA", "None", 1, 1, "LoRA", "None", 1, 1, "LoRA", "None", 1, 1, "LoRA", "None", 1, 1, "Refresh models"] , [!Controlnet args here!]]
The goal is to pass args to always on scripts like controlnet or additional-networks without them having to duplicate or hijack parts of the API just to have access to them. Some adjustment on the part of the extensions might be needed if they want to support it. For exemple, controlnet might have to detect that the images are a base64 string instead of an Image but it shouldn't require much work.
To test this, I had to do a small change to additional_network because it would throw an error. I believe it was checking the 0 index of a possibly empty tuple to see if it existed.
These changes should not affect how the api works currently, selectable scripts should be working exactly like before.
Environment this was tested in
List the environment you have developed / tested this on. As per the contributing page, changes should be able to work on Windows out of the box.
Exemple txt2img request with additional network as an alwayson_script:
closes #8253