diff --git a/expose.h b/expose.h index a70012d06..871661ace 100644 --- a/expose.h +++ b/expose.h @@ -239,6 +239,7 @@ struct sd_generation_outputs int animated = 0; const char * data = ""; const char * data_extra = ""; + const char * info = ""; }; struct sd_upscale_inputs { diff --git a/koboldcpp.py b/koboldcpp.py index 41755df37..1b1aca805 100755 --- a/koboldcpp.py +++ b/koboldcpp.py @@ -376,7 +376,8 @@ class sd_generation_outputs(ctypes.Structure): _fields_ = [("status", ctypes.c_int), ("animated", ctypes.c_int), ("data", ctypes.c_char_p), - ("data_extra", ctypes.c_char_p)] + ("data_extra", ctypes.c_char_p), + ("info", ctypes.c_char_p)] class sd_upscale_inputs(ctypes.Structure): _fields_ = [("init_images", ctypes.c_char_p), @@ -2468,12 +2469,14 @@ def sd_generate(genparams): ret = handle.sd_generate(inputs) data_main = "" data_extra = "" + info = {} animated = False if ret.status==1: data_main = ret.data.decode("UTF-8","ignore") data_extra = ret.data_extra.decode("UTF-8","ignore") + info = json.loads(ret.info.decode("UTF-8","ignore")) animated = True if ret.animated else False - return {"animated": animated, "data":data_main, "data_extra":data_extra} + return {"animated": animated, "data":data_main, "data_extra":data_extra, "info": info} def whisper_load_model(model_filename): @@ -5707,6 +5710,7 @@ Change Mode
gendat = gen["data"] genanim = gen["animated"] gendatextra = gen["data_extra"] + geninfo = json.dumps(gen["info"]) # sdapi really expects a stringified JSON genresp = None if is_comfyui_imggen: if gendat: @@ -5717,7 +5721,7 @@ Change Mode
elif is_oai_imggen: genresp = (json.dumps({"created":int(time.time()),"data":[{"b64_json":gendat}],"background":"opaque","output_format":"png","size":"1024x1024","quality":"medium"}).encode()) else: - genresp = (json.dumps({"images":[gendat],"parameters":{},"info":"","animated":genanim,"extra_data":gendatextra}).encode()) + genresp = (json.dumps({"images":[gendat],"parameters":{},"info":geninfo,"animated":genanim,"extra_data":gendatextra}).encode()) self.send_response(200) self.send_header('content-length', str(len(genresp))) self.end_headers(content_type='application/json') diff --git a/otherarch/sdcpp/sdtype_adapter.cpp b/otherarch/sdcpp/sdtype_adapter.cpp index 154b10995..d4e875d24 100644 --- a/otherarch/sdcpp/sdtype_adapter.cpp +++ b/otherarch/sdcpp/sdtype_adapter.cpp @@ -150,8 +150,6 @@ static SDParams * sd_params = nullptr; static sd_ctx_t * sd_ctx = nullptr; static upscaler_ctx_t* upscaler_ctx = nullptr; static int sddebugmode = 0; -static std::string recent_data = ""; -static std::string recent_data2 = ""; //for cases when we have 2 outputs static uint8_t * input_image_buffer = NULL; static uint8_t * input_mask_buffer = NULL; static uint8_t * upscale_src_buffer = NULL; @@ -164,12 +162,38 @@ static int cfg_tiled_vae_threshold = 0; static int cfg_square_limit = 0; static int cfg_side_limit = 0; static bool sd_is_quiet = false; -static std::string sdmodelfilename = ""; static bool photomaker_enabled = false; static bool is_vid_model = false; static bool remove_limits = false; +static struct { + std::string data; + std::string data_extra; + std::string info; + bool animated; + void reset() { + data = ""; + data_extra = ""; + info = "{}"; + animated = false; + } + sd_generation_outputs outputs(int status) { + sd_generation_outputs output; + output.status = status; + output.data = data.c_str(); + output.data_extra = data_extra.c_str(); + output.info = info.c_str(); + output.animated = animated; + return output; + } + sd_generation_outputs error(const char* message) { + reset(); + printf("\n%s\n", message); + return outputs(0); + } +} sd_generation; + static int get_loaded_sd_version(sd_ctx_t* ctx) { return ctx->sd->version; @@ -495,9 +519,6 @@ bool sdtype_load_model(const sd_load_model_inputs inputs) { is_vid_model = true; } - std::filesystem::path mpath(inputs.model_filename); - sdmodelfilename = mpath.filename().string(); - // preload the LoRAs with the initial multipliers std::vector lora_specs = sd_params->lora_map.get_lora_specs(lora_dynamic&& lora_cache); if(lora_specs.size()>0) @@ -529,6 +550,10 @@ bool sdtype_load_model(const sd_load_model_inputs inputs) { return true; } +static std::string friendly_model_name(std::filesystem::path model_path) { + return model_path.filename().stem().string(); +} + std::string clean_input_prompt(const std::string& input) { std::string result; result.reserve(input.size()); @@ -553,7 +578,11 @@ static std::string get_scheduler_name(scheduler_t scheduler, bool as_sampler_suf } } -static std::string get_image_params(const sd_img_gen_params_t & params, const std::string& lora_meta) { +static std::string get_image_params(const sd_img_gen_params_t & params, const std::string& lora_meta, int seed_offset) { + std::string model = sd_params->model_path; + if (model.empty()) + model = sd_params->diffusion_model_path; + model = friendly_model_name(model); std::stringstream ss; ss << std::setprecision(3) << "Prompt: " << params.prompt << lora_meta @@ -561,7 +590,7 @@ static std::string get_image_params(const sd_img_gen_params_t & params, const st << " | Steps: " << params.sample_params.sample_steps << " | CFGScale: " << params.sample_params.guidance.txt_cfg << " | Guidance: " << params.sample_params.guidance.distilled_guidance - << " | Seed: " << params.seed + << " | Seed: " << (params.seed + seed_offset) << " | Size: " << params.width << "x" << params.height << " | Sampler: " << sd_sample_method_name(params.sample_params.sample_method) << get_scheduler_name(params.sample_params.scheduler, true); @@ -570,8 +599,10 @@ static std::string get_image_params(const sd_img_gen_params_t & params, const st if (params.sample_params.flow_shift > 0.f && params.sample_params.flow_shift != INFINITY) ss << "| Flow Shift: " << params.sample_params.flow_shift; ss << " | Clip skip: " << params.clip_skip - << " | Model: " << sdmodelfilename - << " | Version: KoboldCpp"; + << " | Model: " << model; + if (sd_params->vae_path != "") + ss << " | VAE: " << friendly_model_name(sd_params->vae_path); + ss << " | Version: KoboldCpp"; return ss.str(); } @@ -954,22 +985,11 @@ static std::string raw_image_to_png_base64(const sd_image_t& img, std::string pa return result; } - sd_generation_outputs sdtype_generate(const sd_generation_inputs inputs) { - recent_data = ""; - recent_data2 = ""; - - sd_generation_outputs output; - if(sd_ctx == nullptr || sd_params == nullptr) { - printf("\nWarning: KCPP image generation not initialized!\n"); - output.data = ""; - output.data_extra = ""; - output.animated = 0; - output.status = 0; - return output; + return sd_generation.error("Warning: KCPP image generation not initialized!"); } sd_image_t * results = nullptr; @@ -1239,7 +1259,6 @@ sd_generation_outputs sdtype_generate(const sd_generation_inputs inputs) params.strength = sd_params->strength; params.vae_tiling_params.enabled = dotile; parse_cache_options(params.cache, sd_params->cache_mode, sd_params->cache_options); - params.batch_count = 1; LoraMap lora_map = sd_params->lora_map; if (sd_params->lora_dynamic) { @@ -1360,12 +1379,7 @@ sd_generation_outputs sdtype_generate(const sd_generation_inputs inputs) input_image_buffer = load_image_from_b64(img2img_data,nx,ny,img2imgW,img2imgH,3); if (!input_image_buffer) { - printf("\nKCPP SD: load image from memory failed!\n"); - output.data = ""; - output.data_extra = ""; - output.animated = 0; - output.status = 0; - return output; + return sd_generation.error("KCPP SD: load image from memory failed!"); } if(img2img_mask!="") @@ -1424,17 +1438,44 @@ sd_generation_outputs sdtype_generate(const sd_generation_inputs inputs) } if (!is_passthrough && results == NULL) { - printf("\nKCPP SD generate failed!\n"); - output.data = ""; - output.data_extra = ""; - output.animated = 0; - output.status = 0; - return output; + return sd_generation.error("KCPP SD generate failed!"); } bool isanim = (vid_req_frames>1 && generated_num_results>1 && is_vid_model); + nlohmann::json jsoninfo = nlohmann::json::object(); + if (!isanim) { + jsoninfo["prompt"] = params.prompt + lora_meta; + if (*params.negative_prompt) + jsoninfo["negative_prompt"] = params.negative_prompt; + jsoninfo["seed"] = params.seed; + jsoninfo["cfg_scale"] = params.sample_params.guidance.txt_cfg; + jsoninfo["width"] = params.width; + jsoninfo["height"] = params.height; + jsoninfo["steps"] = params.sample_params.sample_steps; + jsoninfo["sampler_name"] = sd_sample_method_name(params.sample_params.sample_method); + if (params.clip_skip > 0) + jsoninfo["clip_skip"] = params.clip_skip; + jsoninfo["extra_generation_params"] = nlohmann::json::object(); + if (params.sample_params.scheduler != scheduler_t::SCHEDULER_COUNT) + jsoninfo["extra_generation_params"]["Schedule type"] = get_scheduler_name(params.sample_params.scheduler); + if (is_img2img) + jsoninfo["denoising_strength"] = params.strength; + if (sd_params->model_path.empty()) + jsoninfo["sd_model_name"] = friendly_model_name(sd_params->diffusion_model_path); + else + jsoninfo["sd_model_name"] = friendly_model_name(sd_params->model_path); + if (sd_params->vae_path != "") + jsoninfo["sd_vae_name"] = friendly_model_name(sd_params->vae_path); + jsoninfo["infotexts"] = nlohmann::json::array(); + jsoninfo["all_prompts"] = nlohmann::json::array(); + jsoninfo["all_negative_prompts"] = nlohmann::json::array(); + jsoninfo["all_seeds"] = nlohmann::json::array(); + jsoninfo["version"] = "KoboldCpp"; + } sd_image_t upscaled_image; upscaled_image.data = nullptr; + std::string gen_data; + std::string gen_data2; if (is_passthrough) { @@ -1446,7 +1487,7 @@ sd_generation_outputs sdtype_generate(const sd_generation_inputs inputs) upscaled_image = upscale(upscaler_ctx, input_image, 2); result_image = &upscaled_image; } - recent_data = raw_image_to_png_base64(*result_image); + gen_data = raw_image_to_png_base64(*result_image); } else { @@ -1491,14 +1532,14 @@ sd_generation_outputs sdtype_generate(const sd_generation_inputs inputs) } if(status==0 && out_len>0) { - recent_data = kcpp_base64_encode(out_data, out_len); + gen_data = kcpp_base64_encode(out_data, out_len); free(out_data); } if (status2 == 0 && out_len2 > 0) { - if (recent_data == "") { - recent_data = kcpp_base64_encode(out_data2, out_len2); + if (gen_data == "") { + gen_data = kcpp_base64_encode(out_data2, out_len2); } else { - recent_data2 = kcpp_base64_encode(out_data2, out_len2); + gen_data2 = kcpp_base64_encode(out_data2, out_len2); } free(out_data2); } @@ -1512,8 +1553,12 @@ sd_generation_outputs sdtype_generate(const sd_generation_inputs inputs) upscaled_image = upscale(upscaler_ctx, results[i], 2); result_image = &upscaled_image; } - std::string meta_image_info = get_image_params(params, lora_meta); - recent_data = raw_image_to_png_base64(*result_image, meta_image_info); + std::string meta_image_info = get_image_params(params, lora_meta, i); + gen_data = raw_image_to_png_base64(*result_image, meta_image_info); + jsoninfo["infotexts"][i] = meta_image_info; + jsoninfo["all_seeds"][i] = params.seed + i; + jsoninfo["all_prompts"][i] = params.prompt; + jsoninfo["all_negative_prompts"][i] = params.negative_prompt; } free(results[i].data); @@ -1528,37 +1573,28 @@ sd_generation_outputs sdtype_generate(const sd_generation_inputs inputs) } free(results); - output.data = recent_data.c_str(); - output.data_extra = recent_data2.c_str(); - output.animated = (isanim?1:0); - output.status = 1; + total_img_gens += 1; if(!sd_is_quiet) { std::string ts = get_timestamp_str(); printf("[%s] Generating Media Complete\n",ts.c_str()); } - return output; + + sd_generation.data = gen_data; + sd_generation.data_extra = gen_data2; + sd_generation.animated = isanim; + sd_generation.info = jsoninfo.dump(); + return sd_generation.outputs(1); } sd_generation_outputs sdtype_upscale(const sd_upscale_inputs inputs) { - recent_data = ""; - recent_data2 = ""; + sd_generation.reset(); - sd_generation_outputs output; - output.data = ""; - output.data_extra = ""; - output.animated = 0; - output.status = 0; if(sd_ctx == nullptr || upscaler_ctx == nullptr || sd_params == nullptr) { - printf("\nWarning: KCPP image upscaling not initialized!\n"); - output.data = ""; - output.data_extra = ""; - output.animated = 0; - output.status = 0; - return output; + return sd_generation.error("Warning: KCPP image upscaling not initialized!"); } std::string rawb64 = inputs.init_images; @@ -1573,6 +1609,7 @@ sd_generation_outputs sdtype_upscale(const sd_upscale_inputs inputs) sd_image_t upscaled_image; source_img.data = nullptr; upscaled_image.data = nullptr; + std::string result; if(upscale_src_buffer) { source_img.width = nx; @@ -1581,15 +1618,17 @@ sd_generation_outputs sdtype_upscale(const sd_upscale_inputs inputs) source_img.data = upscale_src_buffer; upscaled_image = upscale(upscaler_ctx, source_img, inputs.upscaling_resize); - recent_data = raw_image_to_png_base64(upscaled_image); + result = raw_image_to_png_base64(upscaled_image); free(upscaled_image.data); - output.data = recent_data.c_str(); - output.data_extra = recent_data2.c_str(); - output.animated = 0; - output.status = 1; + } - return output; + if (result == "") { + return sd_generation.error("Warning: KCPP failed to upscale image"); + } + + sd_generation.data = result; + return sd_generation.outputs(1); } sd_info_outputs sdtype_get_info()