From 79f84c8bf7341c9bef426093932de1549a71d517 Mon Sep 17 00:00:00 2001 From: Wagner Bruna Date: Wed, 17 Sep 2025 22:11:57 -0300 Subject: [PATCH 1/6] sd: add backend support for choosing the default sampler --- otherarch/sdcpp/sdtype_adapter.cpp | 24 +++++++++++++++++------- 1 file changed, 17 insertions(+), 7 deletions(-) diff --git a/otherarch/sdcpp/sdtype_adapter.cpp b/otherarch/sdcpp/sdtype_adapter.cpp index 0da9d00c9f9..809a2dec136 100644 --- a/otherarch/sdcpp/sdtype_adapter.cpp +++ b/otherarch/sdcpp/sdtype_adapter.cpp @@ -67,7 +67,7 @@ struct SDParams { int width = 512; int height = 512; - sample_method_t sample_method = EULER_A; + sample_method_t sample_method = SAMPLE_METHOD_DEFAULT; int sample_steps = 20; float strength = 0.75f; int64_t seed = 42; @@ -519,23 +519,29 @@ static void sd_fix_resolution(int &width, int &height, int img_hard_limit, int i static enum sample_method_t sampler_from_name(const std::string& sampler) { - if(sampler=="euler a"||sampler=="k_euler_a"||sampler=="euler_a") //all lowercase + // all lowercase + enum sample_method_t result = str_to_sample_method(sampler.c_str()); + if (result != sample_method_t::SAMPLE_METHOD_COUNT) + { + return result; + } + else if(sampler=="euler a"||sampler=="k_euler_a") { return sample_method_t::EULER_A; } - else if(sampler=="euler"||sampler=="k_euler") + else if(sampler=="k_euler") { return sample_method_t::EULER; } - else if(sampler=="heun"||sampler=="k_heun") + else if(sampler=="k_heun") { return sample_method_t::HEUN; } - else if(sampler=="dpm2"||sampler=="k_dpm_2") + else if(sampler=="k_dpm_2") { return sample_method_t::DPM2; } - else if(sampler=="lcm"||sampler=="k_lcm") + else if(sampler=="k_lcm") { return sample_method_t::LCM; } @@ -549,7 +555,7 @@ static enum sample_method_t sampler_from_name(const std::string& sampler) } else { - return sample_method_t::EULER_A; + return sample_method_t::SAMPLE_METHOD_DEFAULT; } } @@ -682,6 +688,10 @@ sd_generation_outputs sdtype_generate(const sd_generation_inputs inputs) sd_params->clip_skip = inputs.clip_skip; sd_params->sample_method = sampler_from_name(inputs.sample_method); + if (sd_params->sample_method == SAMPLE_METHOD_DEFAULT) { + sd_params->sample_method = sd_get_default_sample_method(sd_ctx); + } + auto loadedsdver = get_loaded_sd_version(sd_ctx); bool is_img2img = img2img_data != ""; bool is_wan = (loadedsdver == SDVersion::VERSION_WAN2 || loadedsdver == SDVersion::VERSION_WAN2_2_I2V || loadedsdver == SDVersion::VERSION_WAN2_2_TI2V); From 40ac7d1eb60cf44870f072bf79b9c8e16f024185 Mon Sep 17 00:00:00 2001 From: Wagner Bruna Date: Tue, 30 Sep 2025 16:30:24 -0300 Subject: [PATCH 2/6] use the default sampler on the API --- koboldcpp.py | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/koboldcpp.py b/koboldcpp.py index 2a16076b8dd..d1b2ef52f80 100644 --- a/koboldcpp.py +++ b/koboldcpp.py @@ -1822,7 +1822,7 @@ def sd_generate(genparams): seed = tryparseint(genparams.get("seed", -1),-1) if seed < 0: seed = random.randint(100000, 999999) - sample_method = genparams.get("sampler_name", "k_euler_a") + sample_method = genparams.get("sampler_name", "default") clip_skip = tryparseint(genparams.get("clip_skip", -1),-1) vid_req_frames = tryparseint(genparams.get("frames", 1),1) vid_req_frames = 1 if (not vid_req_frames or vid_req_frames < 1) else vid_req_frames From e80ce44066043ea495479804dd31d96a5d9fb1f0 Mon Sep 17 00:00:00 2001 From: Wagner Bruna Date: Tue, 30 Sep 2025 18:18:39 -0300 Subject: [PATCH 3/6] sd: add backend support for the scheduler --- expose.h | 1 + koboldcpp.py | 3 +++ otherarch/sdcpp/sdtype_adapter.cpp | 30 ++++++++++++++++++++++++------ 3 files changed, 28 insertions(+), 6 deletions(-) diff --git a/expose.h b/expose.h index 7e8b8252b88..7b751e36672 100644 --- a/expose.h +++ b/expose.h @@ -202,6 +202,7 @@ struct sd_generation_inputs const int height = 0; const int seed = 0; const char * sample_method = nullptr; + const char * scheduler = nullptr; const int clip_skip = -1; const int vid_req_frames = 1; const int vid_req_avi = 0; diff --git a/koboldcpp.py b/koboldcpp.py index d1b2ef52f80..2bbaf8b90a2 100644 --- a/koboldcpp.py +++ b/koboldcpp.py @@ -316,6 +316,7 @@ class sd_generation_inputs(ctypes.Structure): ("height", ctypes.c_int), ("seed", ctypes.c_int), ("sample_method", ctypes.c_char_p), + ("scheduler", ctypes.c_char_p), ("clip_skip", ctypes.c_int), ("vid_req_frames", ctypes.c_int), ("vid_req_avi", ctypes.c_int)] @@ -1823,6 +1824,7 @@ def sd_generate(genparams): if seed < 0: seed = random.randint(100000, 999999) sample_method = genparams.get("sampler_name", "default") + scheduler = genparams.get("scheduler", "default") clip_skip = tryparseint(genparams.get("clip_skip", -1),-1) vid_req_frames = tryparseint(genparams.get("frames", 1),1) vid_req_frames = 1 if (not vid_req_frames or vid_req_frames < 1) else vid_req_frames @@ -1858,6 +1860,7 @@ def sd_generate(genparams): inputs.height = height inputs.seed = seed inputs.sample_method = sample_method.lower().encode("UTF-8") + inputs.scheduler = scheduler.lower().encode("UTF-8") inputs.clip_skip = clip_skip inputs.vid_req_frames = vid_req_frames inputs.vid_req_avi = vid_req_avi diff --git a/otherarch/sdcpp/sdtype_adapter.cpp b/otherarch/sdcpp/sdtype_adapter.cpp index 809a2dec136..a21667e0727 100644 --- a/otherarch/sdcpp/sdtype_adapter.cpp +++ b/otherarch/sdcpp/sdtype_adapter.cpp @@ -68,6 +68,7 @@ struct SDParams { int height = 512; sample_method_t sample_method = SAMPLE_METHOD_DEFAULT; + scheduler_t scheduler = scheduler_t::DEFAULT; int sample_steps = 20; float strength = 0.75f; int64_t seed = 42; @@ -404,8 +405,8 @@ std::string clean_input_prompt(const std::string& input) { } static std::string get_image_params(const sd_img_gen_params_t & params) { - std::stringstream parameter_string; - parameter_string << std::setprecision(3) + std::stringstream ss; + ss << std::setprecision(3) << "Prompt: " << params.prompt << " | NegativePrompt: " << params.negative_prompt << " | Steps: " << params.sample_params.sample_steps @@ -413,11 +414,13 @@ static std::string get_image_params(const sd_img_gen_params_t & params) { << " | Guidance: " << params.sample_params.guidance.distilled_guidance << " | Seed: " << params.seed << " | Size: " << params.width << "x" << params.height - << " | Sampler: " << sd_sample_method_name(params.sample_params.sample_method) - << " | Clip skip: " << params.clip_skip + << " | Sampler: " << sd_sample_method_name(params.sample_params.sample_method); + if (params.sample_params.scheduler != scheduler_t::DEFAULT) + ss << " " << sd_schedule_name(params.sample_params.scheduler); + ss << " | Clip skip: " << params.clip_skip << " | Model: " << sdmodelfilename << " | Version: KoboldCpp"; - return parameter_string.str(); + return ss.str(); } static inline int rounddown_64(int n) { @@ -559,7 +562,6 @@ static enum sample_method_t sampler_from_name(const std::string& sampler) } } - uint8_t* load_image_from_b64(const std::string & b64str, int& width, int& height, int expected_width = 0, int expected_height = 0, int expected_channel = 3) { std::vector decoded_buf = kcpp_base64_decode(b64str); @@ -650,6 +652,19 @@ uint8_t* load_image_from_b64(const std::string & b64str, int& width, int& height image_buffer = resized_image_buffer; } return image_buffer; + +} + +static enum scheduler_t scheduler_from_name(const char * scheduler) +{ + if (scheduler) { + enum scheduler_t result = str_to_schedule(scheduler); + if (result != scheduler_t::SCHEDULE_COUNT) + { + return result; + } + } + return scheduler_t::DEFAULT; } sd_generation_outputs sdtype_generate(const sd_generation_inputs inputs) @@ -687,6 +702,7 @@ sd_generation_outputs sdtype_generate(const sd_generation_inputs inputs) sd_params->strength = inputs.denoising_strength; sd_params->clip_skip = inputs.clip_skip; sd_params->sample_method = sampler_from_name(inputs.sample_method); + sd_params->scheduler = scheduler_from_name(inputs.scheduler); if (sd_params->sample_method == SAMPLE_METHOD_DEFAULT) { sd_params->sample_method = sd_get_default_sample_method(sd_ctx); @@ -854,6 +870,7 @@ sd_generation_outputs sdtype_generate(const sd_generation_inputs inputs) params.width = sd_params->width; params.height = sd_params->height; params.sample_params.sample_method = sd_params->sample_method; + params.sample_params.scheduler = sd_params->scheduler; params.sample_params.sample_steps = sd_params->sample_steps; params.seed = sd_params->seed; params.strength = sd_params->strength; @@ -932,6 +949,7 @@ sd_generation_outputs sdtype_generate(const sd_generation_inputs inputs) << "\nCFGSCLE:" << params.sample_params.guidance.txt_cfg << "\nSIZE:" << params.width << "x" << params.height << "\nSM:" << sd_sample_method_name(params.sample_params.sample_method) + << "\nSCHED:" << sd_schedule_name(params.sample_params.scheduler) << "\nSTEP:" << params.sample_params.sample_steps << "\nSEED:" << params.seed << "\nBATCH:" << params.batch_count From b44afd97b23273ef48975cc9d2466dbe85c33eec Mon Sep 17 00:00:00 2001 From: Wagner Bruna Date: Tue, 30 Sep 2025 23:21:03 -0300 Subject: [PATCH 4/6] sd: add backend support for distilled guidance --- expose.h | 1 + koboldcpp.py | 6 ++++++ otherarch/sdcpp/sdtype_adapter.cpp | 5 +++++ 3 files changed, 12 insertions(+) diff --git a/expose.h b/expose.h index 7b751e36672..b831f4d4b28 100644 --- a/expose.h +++ b/expose.h @@ -197,6 +197,7 @@ struct sd_generation_inputs const bool flip_mask = false; const float denoising_strength = 0.0f; const float cfg_scale = 0.0f; + const float distilled_guidance = -1.0f; const int sample_steps = 0; const int width = 0; const int height = 0; diff --git a/koboldcpp.py b/koboldcpp.py index 2bbaf8b90a2..c01023177d4 100644 --- a/koboldcpp.py +++ b/koboldcpp.py @@ -311,6 +311,7 @@ class sd_generation_inputs(ctypes.Structure): ("flip_mask", ctypes.c_bool), ("denoising_strength", ctypes.c_float), ("cfg_scale", ctypes.c_float), + ("distilled_guidance", ctypes.c_float), ("sample_steps", ctypes.c_int), ("width", ctypes.c_int), ("height", ctypes.c_int), @@ -1817,6 +1818,7 @@ def sd_generate(genparams): flip_mask = genparams.get("inpainting_mask_invert", 0) denoising_strength = tryparsefloat(genparams.get("denoising_strength", 0.6),0.6) cfg_scale = tryparsefloat(genparams.get("cfg_scale", 5),5) + distilled_guidance = tryparsefloat(genparams.get("distilled_guidance", None), None) sample_steps = tryparseint(genparams.get("steps", 20),20) width = tryparseint(genparams.get("width", 512),512) height = tryparseint(genparams.get("height", 512),512) @@ -1836,6 +1838,8 @@ def sd_generate(genparams): #clean vars cfg_scale = (1 if cfg_scale < 1 else (25 if cfg_scale > 25 else cfg_scale)) + if distilled_guidance is not None and (distilled_guidance < 0 or distilled_guidance > 100): + distilled_guidance = None # fall back to the default sample_steps = (1 if sample_steps < 1 else (forced_steplimit if sample_steps > forced_steplimit else sample_steps)) vid_req_frames = (1 if vid_req_frames < 1 else (100 if vid_req_frames > 100 else vid_req_frames)) @@ -1854,6 +1858,8 @@ def sd_generate(genparams): inputs.extra_images[n] = extra_image.encode("UTF-8") inputs.flip_mask = flip_mask inputs.cfg_scale = cfg_scale + if distilled_guidance is not None: + inputs.distilled_guidance = distilled_guidance inputs.denoising_strength = denoising_strength inputs.sample_steps = sample_steps inputs.width = width diff --git a/otherarch/sdcpp/sdtype_adapter.cpp b/otherarch/sdcpp/sdtype_adapter.cpp index a21667e0727..32eae1e3c21 100644 --- a/otherarch/sdcpp/sdtype_adapter.cpp +++ b/otherarch/sdcpp/sdtype_adapter.cpp @@ -70,6 +70,7 @@ struct SDParams { sample_method_t sample_method = SAMPLE_METHOD_DEFAULT; scheduler_t scheduler = scheduler_t::DEFAULT; int sample_steps = 20; + float distilled_guidance = -1.0f; float strength = 0.75f; int64_t seed = 42; bool clip_on_cpu = false; @@ -695,6 +696,7 @@ sd_generation_outputs sdtype_generate(const sd_generation_inputs inputs) sd_params->prompt = cleanprompt; sd_params->negative_prompt = cleannegprompt; sd_params->cfg_scale = inputs.cfg_scale; + sd_params->distilled_guidance = inputs.distilled_guidance; sd_params->sample_steps = inputs.sample_steps; sd_params->seed = inputs.seed; sd_params->width = inputs.width; @@ -867,6 +869,9 @@ sd_generation_outputs sdtype_generate(const sd_generation_inputs inputs) params.clip_skip = sd_params->clip_skip; params.sample_params.guidance.txt_cfg = sd_params->cfg_scale; params.sample_params.guidance.img_cfg = sd_params->cfg_scale; + if (sd_params->distilled_guidance >= 0.f) { + params.sample_params.guidance.distilled_guidance = sd_params->distilled_guidance; + } params.width = sd_params->width; params.height = sd_params->height; params.sample_params.sample_method = sd_params->sample_method; From 9c7eef06b092fc73932837f77110c2e9eeeaaeaa Mon Sep 17 00:00:00 2001 From: Wagner Bruna Date: Wed, 1 Oct 2025 08:53:01 -0300 Subject: [PATCH 5/6] sd: add backend support for timestep-shift --- expose.h | 1 + koboldcpp.py | 6 ++++++ otherarch/sdcpp/sdtype_adapter.cpp | 5 +++++ 3 files changed, 12 insertions(+) diff --git a/expose.h b/expose.h index b831f4d4b28..0c98624b369 100644 --- a/expose.h +++ b/expose.h @@ -198,6 +198,7 @@ struct sd_generation_inputs const float denoising_strength = 0.0f; const float cfg_scale = 0.0f; const float distilled_guidance = -1.0f; + const int shifted_timestep = 0; const int sample_steps = 0; const int width = 0; const int height = 0; diff --git a/koboldcpp.py b/koboldcpp.py index c01023177d4..36375f25430 100644 --- a/koboldcpp.py +++ b/koboldcpp.py @@ -312,6 +312,7 @@ class sd_generation_inputs(ctypes.Structure): ("denoising_strength", ctypes.c_float), ("cfg_scale", ctypes.c_float), ("distilled_guidance", ctypes.c_float), + ("shifted_timestep", ctypes.c_int), ("sample_steps", ctypes.c_int), ("width", ctypes.c_int), ("height", ctypes.c_int), @@ -1819,6 +1820,7 @@ def sd_generate(genparams): denoising_strength = tryparsefloat(genparams.get("denoising_strength", 0.6),0.6) cfg_scale = tryparsefloat(genparams.get("cfg_scale", 5),5) distilled_guidance = tryparsefloat(genparams.get("distilled_guidance", None), None) + shifted_timestep = tryparseint(genparams.get("shifted_timestep", None), None) sample_steps = tryparseint(genparams.get("steps", 20),20) width = tryparseint(genparams.get("width", 512),512) height = tryparseint(genparams.get("height", 512),512) @@ -1840,6 +1842,8 @@ def sd_generate(genparams): cfg_scale = (1 if cfg_scale < 1 else (25 if cfg_scale > 25 else cfg_scale)) if distilled_guidance is not None and (distilled_guidance < 0 or distilled_guidance > 100): distilled_guidance = None # fall back to the default + if shifted_timestep is not None and (shifted_timestep < 0 or shifted_timestep > 1000): + shifted_timestep = None # fall back to the default sample_steps = (1 if sample_steps < 1 else (forced_steplimit if sample_steps > forced_steplimit else sample_steps)) vid_req_frames = (1 if vid_req_frames < 1 else (100 if vid_req_frames > 100 else vid_req_frames)) @@ -1861,6 +1865,8 @@ def sd_generate(genparams): if distilled_guidance is not None: inputs.distilled_guidance = distilled_guidance inputs.denoising_strength = denoising_strength + if shifted_timestep is not None: + inputs.shifted_timestep = shifted_timestep inputs.sample_steps = sample_steps inputs.width = width inputs.height = height diff --git a/otherarch/sdcpp/sdtype_adapter.cpp b/otherarch/sdcpp/sdtype_adapter.cpp index 32eae1e3c21..49d9b010f82 100644 --- a/otherarch/sdcpp/sdtype_adapter.cpp +++ b/otherarch/sdcpp/sdtype_adapter.cpp @@ -71,6 +71,7 @@ struct SDParams { scheduler_t scheduler = scheduler_t::DEFAULT; int sample_steps = 20; float distilled_guidance = -1.0f; + float shifted_timestep = 0; float strength = 0.75f; int64_t seed = 42; bool clip_on_cpu = false; @@ -418,6 +419,8 @@ static std::string get_image_params(const sd_img_gen_params_t & params) { << " | Sampler: " << sd_sample_method_name(params.sample_params.sample_method); if (params.sample_params.scheduler != scheduler_t::DEFAULT) ss << " " << sd_schedule_name(params.sample_params.scheduler); + if (params.sample_params.shifted_timestep != 0) + ss << "| Timestep Shift: " << params.sample_params.shifted_timestep; ss << " | Clip skip: " << params.clip_skip << " | Model: " << sdmodelfilename << " | Version: KoboldCpp"; @@ -698,6 +701,7 @@ sd_generation_outputs sdtype_generate(const sd_generation_inputs inputs) sd_params->cfg_scale = inputs.cfg_scale; sd_params->distilled_guidance = inputs.distilled_guidance; sd_params->sample_steps = inputs.sample_steps; + sd_params->shifted_timestep = inputs.shifted_timestep; sd_params->seed = inputs.seed; sd_params->width = inputs.width; sd_params->height = inputs.height; @@ -877,6 +881,7 @@ sd_generation_outputs sdtype_generate(const sd_generation_inputs inputs) params.sample_params.sample_method = sd_params->sample_method; params.sample_params.scheduler = sd_params->scheduler; params.sample_params.sample_steps = sd_params->sample_steps; + params.sample_params.shifted_timestep = sd_params->shifted_timestep; params.seed = sd_params->seed; params.strength = sd_params->strength; params.vae_tiling_params.enabled = dotile; From b58389024c33ffe4c5832d806818687aa2409377 Mon Sep 17 00:00:00 2001 From: Wagner Bruna Date: Tue, 30 Sep 2025 18:35:35 -0300 Subject: [PATCH 6/6] sd: add a config field to set default image gen options --- koboldcpp.py | 68 ++++++++++++++++++++++++++++++++++++++++++++++++---- 1 file changed, 64 insertions(+), 4 deletions(-) diff --git a/koboldcpp.py b/koboldcpp.py index 36375f25430..8ad73c0e513 100644 --- a/koboldcpp.py +++ b/koboldcpp.py @@ -396,6 +396,8 @@ class embeddings_generation_outputs(ctypes.Structure): ("count", ctypes.c_int), ("data", ctypes.c_char_p)] + + def getdirpath(): return os.path.dirname(os.path.realpath(__file__)) def getabspath(): @@ -1791,9 +1793,58 @@ def sd_comfyui_tranform_params(genparams): print("Warning: ComfyUI Payload Missing!") return genparams +def sd_process_meta_fields(fields, config): + # aliases to match sd.cpp command-line options + aliases = { + 'cfg-scale': 'cfg_scale', + 'guidance': 'distilled_guidance', + 'sampler': 'sampler_name', + 'sampling-method': 'sampler_name', + 'timestep-shift': 'shifted_timestep', + } + fields_dict = {aliases.get(k, k): v for k, v in fields} + # whitelist accepted parameters + whitelist = ['scheduler', 'shifted_timestep', 'distilled_guidance'] + if config: + # note the current UI always set these + whitelist += ['sampler_name', 'cfg_scale'] + fields_dict = {k: v for k, v in fields_dict.items() if k in whitelist} + return fields_dict + +# json with top-level dict +def sd_parse_meta_field(prompt, config=False): + jfields = {} + try: + jfields = json.loads(prompt) + except json.JSONDecodeError: + # accept "field":"value",... without {} (also empty strings) + try: + jfields = json.loads('{ ' + prompt + ' }') + except json.JSONDecodeError: + print("Warning: couldn't parse meta prompt; it should be valid JSON.") + if not isinstance(jfields, dict): + jfields = {} + kv_dict = sd_process_meta_fields(jfields.items(), config) + return kv_dict + + def sd_generate(genparams): global maxctx, args, currentusergenkey, totalgens, pendingabortkey, chatcompl_adapter + sdgendefaults = sd_parse_meta_field(args.sdgendefaults or '', config=True) + params = dict() + defparams = dict() + for k, v in sdgendefaults.items(): + if k in ['sampler_name', 'scheduler']: + # these can be explicitely set to 'default'; process later + # TODO should we consider values like 'clip_skip=-1' as 'default' too? + defparams[k] = v + else: + params[k] = v + # apply most of the defaults + params.update(genparams) + genparams = params + default_adapter = {} if chatcompl_adapter is None else chatcompl_adapter adapter_obj = genparams.get('adapter', default_adapter) forced_negprompt = adapter_obj.get("add_sd_negative_prompt", "") @@ -1827,8 +1878,12 @@ def sd_generate(genparams): seed = tryparseint(genparams.get("seed", -1),-1) if seed < 0: seed = random.randint(100000, 999999) - sample_method = genparams.get("sampler_name", "default") - scheduler = genparams.get("scheduler", "default") + sample_method = (genparams.get("sampler_name") or "default").lower() + if sample_method == 'default' and 'sampler_name' in defparams: + sample_method = (defparams.get("sampler_name") or "default").lower() + scheduler = (genparams.get("scheduler") or "default").lower() + if scheduler == 'default' and 'scheduler' in defparams: + scheduler = (defparams.get("scheduler") or "default").lower() clip_skip = tryparseint(genparams.get("clip_skip", -1),-1) vid_req_frames = tryparseint(genparams.get("frames", 1),1) vid_req_frames = 1 if (not vid_req_frames or vid_req_frames < 1) else vid_req_frames @@ -1871,8 +1926,8 @@ def sd_generate(genparams): inputs.width = width inputs.height = height inputs.seed = seed - inputs.sample_method = sample_method.lower().encode("UTF-8") - inputs.scheduler = scheduler.lower().encode("UTF-8") + inputs.sample_method = sample_method.encode("UTF-8") + inputs.scheduler = scheduler.encode("UTF-8") inputs.clip_skip = clip_skip inputs.vid_req_frames = vid_req_frames inputs.vid_req_avi = vid_req_avi @@ -4690,6 +4745,7 @@ def hide_tooltip(event): sd_clamped_soft_var = ctk.StringVar(value="0") sd_threads_var = ctk.StringVar(value=str(default_threads)) sd_quant_var = ctk.StringVar(value=sd_quant_choices[0]) + sd_gen_defaults_var = ctk.StringVar() whisper_model_var = ctk.StringVar() tts_model_var = ctk.StringVar() @@ -5465,6 +5521,7 @@ def toggletaesd(a,b,c): makecheckbox(images_tab, "Model CPU Offload", sd_offload_cpu_var, 50,padx=8, tooltiptxt="Offload image weights in RAM to save VRAM, swap into VRAM when needed.") makecheckbox(images_tab, "VAE on CPU", sd_vae_cpu_var, 50,padx=160, tooltiptxt="Force VAE to CPU only for image generation.") makecheckbox(images_tab, "CLIP on GPU", sd_clip_gpu_var, 50,padx=280, tooltiptxt="Put CLIP and T5 to GPU for image generation. Otherwise, CLIP will use CPU.") + makelabelentry(images_tab, "Default Params:", sd_gen_defaults_var, 52, 280, padx=110, singleline=True, tooltip='Default image generation parameters when not specified by the UI or API.\nSpecified as JSON fields: {"KEY1":"VALUE1", "KEY2":"VALUE2"...}') # audio tab audio_tab = tabcontent["Audio"] @@ -5738,6 +5795,7 @@ def export_vars(): args.sdloramult = float(sd_loramult_var.get()) else: args.sdlora = "" + args.sdgendefaults = sd_gen_defaults_var.get() if whisper_model_var.get() != "": args.whispermodel = whisper_model_var.get() @@ -5964,6 +6022,7 @@ def import_vars(dict): sd_lora_var.set(dict["sdlora"] if ("sdlora" in dict and dict["sdlora"]) else "") sd_loramult_var.set(str(dict["sdloramult"]) if ("sdloramult" in dict and dict["sdloramult"]) else "1.0") + sd_gen_defaults_var.set(dict.get("sdgendefaults", "")) whisper_model_var.set(dict["whispermodel"] if ("whispermodel" in dict and dict["whispermodel"]) else "") @@ -7797,6 +7856,7 @@ def range_checker(arg: str): sdparsergrouplora.add_argument("--sdlora", metavar=('[filename]'), help="Specify an image generation LORA safetensors model to be applied.", default="") sdparsergroup.add_argument("--sdloramult", metavar=('[amount]'), help="Multiplier for the image LORA model to be applied.", type=float, default=1.0) sdparsergroup.add_argument("--sdtiledvae", metavar=('[maxres]'), help="Adjust the automatic VAE tiling trigger for images above this size. 0 disables vae tiling.", type=int, default=default_vae_tile_threshold) + sdparsergroup.add_argument("--sdgendefaults", metavar=('{"parameter":"value",...}'), help="Sets default parameters for image generation, as a JSON string.", default="") whisperparsergroup = parser.add_argument_group('Whisper Transcription Commands') whisperparsergroup.add_argument("--whispermodel", metavar=('[filename]'), help="Specify a Whisper .bin model to enable Speech-To-Text transcription.", default="")