mirror of
https://github.com/leejet/stable-diffusion.cpp.git
synced 2026-11-14 12:56:33 +00:00
Merge branch 'master' into server
This commit is contained in:
commit
96aea6340c
38 files changed
+1044
-504
No files matched your search
+27
-8
@@ -31,8 +31,6 @@
|
||||
|
||||
#include "common/common.hpp"
|
||||
|
||||
namespace fs = std::filesystem;
|
||||
|
||||
const char* previews_str[] = {
|
||||
"none",
|
||||
"proj",
|
||||
@@ -45,6 +43,7 @@ struct SDCliParams {
|
||||
std::string output_path = "output.png";
|
||||
|
||||
bool verbose = false;
|
||||
bool version = false;
|
||||
bool canny_preprocess = false;
|
||||
|
||||
preview_t preview_method = PREVIEW_NONE;
|
||||
@@ -87,6 +86,10 @@ struct SDCliParams {
|
||||
"--verbose",
|
||||
"print extra info",
|
||||
true, &verbose},
|
||||
{"",
|
||||
"--version",
|
||||
"print stable-diffusion.cpp version",
|
||||
true, &version},
|
||||
{"",
|
||||
"--color",
|
||||
"colors the logging tags according to level",
|
||||
@@ -130,18 +133,18 @@ struct SDCliParams {
|
||||
return -1;
|
||||
}
|
||||
const char* preview = argv[index];
|
||||
int preview_method = -1;
|
||||
int preview_found = -1;
|
||||
for (int m = 0; m < PREVIEW_COUNT; m++) {
|
||||
if (!strcmp(preview, previews_str[m])) {
|
||||
preview_method = m;
|
||||
preview_found = m;
|
||||
}
|
||||
}
|
||||
if (preview_method == -1) {
|
||||
if (preview_found == -1) {
|
||||
fprintf(stderr, "error: preview method %s\n",
|
||||
preview);
|
||||
return -1;
|
||||
}
|
||||
preview_method = (preview_t)preview_method;
|
||||
preview_method = (preview_t)preview_found;
|
||||
return 1;
|
||||
};
|
||||
|
||||
@@ -202,6 +205,7 @@ struct SDCliParams {
|
||||
};
|
||||
|
||||
void print_usage(int argc, const char* argv[], const std::vector<ArgOptions>& options_list) {
|
||||
std::cout << version_string() << "\n";
|
||||
std::cout << "Usage: " << argv[0] << " [options]\n\n";
|
||||
std::cout << "CLI Options:\n";
|
||||
options_list[0].print();
|
||||
@@ -219,7 +223,9 @@ void parse_args(int argc, const char** argv, SDCliParams& cli_params, SDContextP
|
||||
exit(cli_params.normal_exit ? 0 : 1);
|
||||
}
|
||||
|
||||
if (!cli_params.process_and_check() || !ctx_params.process_and_check(cli_params.mode) || !gen_params.process_and_check(cli_params.mode)) {
|
||||
if (!cli_params.process_and_check() ||
|
||||
!ctx_params.process_and_check(cli_params.mode) ||
|
||||
!gen_params.process_and_check(cli_params.mode, ctx_params.lora_model_dir)) {
|
||||
print_usage(argc, argv, options_vec);
|
||||
exit(1);
|
||||
}
|
||||
@@ -484,11 +490,19 @@ void step_callback(int step, int frame_count, sd_image_t* image, bool is_noisy,
|
||||
}
|
||||
|
||||
int main(int argc, const char* argv[]) {
|
||||
if (argc > 1 && std::string(argv[1]) == "--version") {
|
||||
std::cout << version_string() << "\n";
|
||||
return EXIT_SUCCESS;
|
||||
}
|
||||
|
||||
SDCliParams cli_params;
|
||||
SDContextParams ctx_params;
|
||||
SDGenerationParams gen_params;
|
||||
|
||||
parse_args(argc, argv, cli_params, ctx_params, gen_params);
|
||||
if (cli_params.verbose || cli_params.version) {
|
||||
std::cout << version_string() << "\n";
|
||||
}
|
||||
if (gen_params.video_frames > 4) {
|
||||
size_t last_dot_pos = cli_params.preview_path.find_last_of(".");
|
||||
std::string base_path = cli_params.preview_path;
|
||||
@@ -724,6 +738,8 @@ int main(int argc, const char* argv[]) {
|
||||
|
||||
if (cli_params.mode == IMG_GEN) {
|
||||
sd_img_gen_params_t img_gen_params = {
|
||||
gen_params.lora_vec.data(),
|
||||
static_cast<uint32_t>(gen_params.lora_vec.size()),
|
||||
gen_params.prompt.c_str(),
|
||||
gen_params.negative_prompt.c_str(),
|
||||
gen_params.clip_skip,
|
||||
@@ -755,6 +771,8 @@ int main(int argc, const char* argv[]) {
|
||||
num_results = gen_params.batch_count;
|
||||
} else if (cli_params.mode == VID_GEN) {
|
||||
sd_vid_gen_params_t vid_gen_params = {
|
||||
gen_params.lora_vec.data(),
|
||||
static_cast<uint32_t>(gen_params.lora_vec.size()),
|
||||
gen_params.prompt.c_str(),
|
||||
gen_params.negative_prompt.c_str(),
|
||||
gen_params.clip_skip,
|
||||
@@ -791,7 +809,8 @@ int main(int argc, const char* argv[]) {
|
||||
upscaler_ctx_t* upscaler_ctx = new_upscaler_ctx(ctx_params.esrgan_path.c_str(),
|
||||
ctx_params.offload_params_to_cpu,
|
||||
ctx_params.diffusion_conv_direct,
|
||||
ctx_params.n_threads);
|
||||
ctx_params.n_threads,
|
||||
gen_params.upscale_tile_size);
|
||||
|
||||
if (upscaler_ctx == nullptr) {
|
||||
printf("new_upscaler_ctx failed\n");
|
||||
|
||||
+205
-4
@@ -6,15 +6,19 @@
|
||||
#include <sstream>
|
||||
#include <string>
|
||||
#include <vector>
|
||||
#include <filesystem>
|
||||
|
||||
#include <json.hpp>
|
||||
using json = nlohmann::json;
|
||||
namespace fs = std::filesystem;
|
||||
|
||||
#if defined(_WIN32)
|
||||
#define NOMINMAX
|
||||
#include <windows.h>
|
||||
#endif // _WIN32
|
||||
|
||||
#include "stable-diffusion.h"
|
||||
|
||||
#define SAFE_STR(s) ((s) ? (s) : "")
|
||||
#define BOOL_STR(b) ((b) ? "true" : "false")
|
||||
|
||||
@@ -312,6 +316,9 @@ struct SDContextParams {
|
||||
std::string tensor_type_rules;
|
||||
std::string lora_model_dir;
|
||||
|
||||
std::map<std::string, std::string> embedding_map;
|
||||
std::vector<sd_embedding_t> embedding_vec;
|
||||
|
||||
rng_type_t rng_type = CUDA_RNG;
|
||||
rng_type_t sampler_rng_type = RNG_TYPE_COUNT;
|
||||
bool offload_params_to_cpu = false;
|
||||
@@ -326,7 +333,7 @@ struct SDContextParams {
|
||||
bool chroma_use_t5_mask = false;
|
||||
int chroma_t5_mask_pad = 1;
|
||||
|
||||
prediction_t prediction = DEFAULT_PRED;
|
||||
prediction_t prediction = PREDICTION_COUNT;
|
||||
lora_apply_mode_t lora_apply_mode = LORA_APPLY_AUTO;
|
||||
|
||||
sd_tiling_params_t vae_tiling_params = {false, 0, 0, 0.5f, 0.0f, 0.0f};
|
||||
@@ -639,6 +646,37 @@ struct SDContextParams {
|
||||
return options;
|
||||
}
|
||||
|
||||
void build_embedding_map() {
|
||||
static const std::vector<std::string> valid_ext = {".pt", ".safetensors", ".gguf"};
|
||||
|
||||
if (!fs::exists(embedding_dir) || !fs::is_directory(embedding_dir)) {
|
||||
return;
|
||||
}
|
||||
|
||||
for (auto& p : fs::directory_iterator(embedding_dir)) {
|
||||
if (!p.is_regular_file())
|
||||
continue;
|
||||
|
||||
auto path = p.path();
|
||||
std::string ext = path.extension().string();
|
||||
|
||||
bool valid = false;
|
||||
for (auto& e : valid_ext) {
|
||||
if (ext == e) {
|
||||
valid = true;
|
||||
break;
|
||||
}
|
||||
}
|
||||
if (!valid)
|
||||
continue;
|
||||
|
||||
std::string key = path.stem().string();
|
||||
std::string value = path.string();
|
||||
|
||||
embedding_map[key] = value;
|
||||
}
|
||||
}
|
||||
|
||||
bool process_and_check(SDMode mode) {
|
||||
if (mode != UPSCALE && model_path.length() == 0 && diffusion_model_path.length() == 0) {
|
||||
fprintf(stderr, "error: the following arguments are required: model_path/diffusion_model\n");
|
||||
@@ -656,10 +694,24 @@ struct SDContextParams {
|
||||
n_threads = sd_get_num_physical_cores();
|
||||
}
|
||||
|
||||
build_embedding_map();
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
std::string to_string() const {
|
||||
std::ostringstream emb_ss;
|
||||
emb_ss << "{\n";
|
||||
for (auto it = embedding_map.begin(); it != embedding_map.end(); ++it) {
|
||||
emb_ss << " \"" << it->first << "\": \"" << it->second << "\"";
|
||||
if (std::next(it) != embedding_map.end()) {
|
||||
emb_ss << ",";
|
||||
}
|
||||
emb_ss << "\n";
|
||||
}
|
||||
emb_ss << " }";
|
||||
|
||||
std::string embeddings_str = emb_ss.str();
|
||||
std::ostringstream oss;
|
||||
oss << "SDContextParams {\n"
|
||||
<< " n_threads: " << n_threads << ",\n"
|
||||
@@ -677,6 +729,7 @@ struct SDContextParams {
|
||||
<< " esrgan_path: \"" << esrgan_path << "\",\n"
|
||||
<< " control_net_path: \"" << control_net_path << "\",\n"
|
||||
<< " embedding_dir: \"" << embedding_dir << "\",\n"
|
||||
<< " embeddings: " << embeddings_str << "\n"
|
||||
<< " wtype: " << sd_type_name(wtype) << ",\n"
|
||||
<< " tensor_type_rules: \"" << tensor_type_rules << "\",\n"
|
||||
<< " lora_model_dir: \"" << lora_model_dir << "\",\n"
|
||||
@@ -709,6 +762,15 @@ struct SDContextParams {
|
||||
}
|
||||
|
||||
sd_ctx_params_t to_sd_ctx_params_t(bool vae_decode_only, bool free_params_immediately, bool taesd_preview) {
|
||||
embedding_vec.clear();
|
||||
embedding_vec.reserve(embedding_map.size());
|
||||
for (const auto& kv : embedding_map) {
|
||||
sd_embedding_t item;
|
||||
item.name = kv.first.c_str();
|
||||
item.path = kv.second.c_str();
|
||||
embedding_vec.emplace_back(item);
|
||||
}
|
||||
|
||||
sd_ctx_params_t sd_ctx_params = {
|
||||
model_path.c_str(),
|
||||
clip_l_path.c_str(),
|
||||
@@ -723,7 +785,8 @@ struct SDContextParams {
|
||||
taesd_path.c_str(),
|
||||
control_net_path.c_str(),
|
||||
lora_model_dir.c_str(),
|
||||
embedding_dir.c_str(),
|
||||
embedding_vec.data(),
|
||||
static_cast<uint32_t>(embedding_vec.size()),
|
||||
photo_maker_path.c_str(),
|
||||
tensor_type_rules.c_str(),
|
||||
vae_decode_only,
|
||||
@@ -777,6 +840,15 @@ static std::string vec_str_to_string(const std::vector<std::string>& v) {
|
||||
return oss.str();
|
||||
}
|
||||
|
||||
static bool is_absolute_path(const std::string& p) {
|
||||
#ifdef _WIN32
|
||||
// Windows: C:/path or C:\path
|
||||
return p.size() > 1 && std::isalpha(static_cast<unsigned char>(p[0])) && p[1] == ':';
|
||||
#else
|
||||
return !p.empty() && p[0] == '/';
|
||||
#endif
|
||||
}
|
||||
|
||||
struct SDGenerationParams {
|
||||
std::string prompt;
|
||||
std::string negative_prompt;
|
||||
@@ -817,7 +889,12 @@ struct SDGenerationParams {
|
||||
std::string pm_id_embed_path;
|
||||
float pm_style_strength = 20.f;
|
||||
|
||||
int upscale_repeats = 1;
|
||||
int upscale_repeats = 1;
|
||||
int upscale_tile_size = 128;
|
||||
|
||||
std::map<std::string, float> lora_map;
|
||||
std::map<std::string, float> high_noise_lora_map;
|
||||
std::vector<sd_lora_t> lora_vec;
|
||||
|
||||
SDGenerationParams() {
|
||||
sd_sample_params_init(&sample_params);
|
||||
@@ -910,6 +987,10 @@ struct SDGenerationParams {
|
||||
"--upscale-repeats",
|
||||
"Run the ESRGAN upscaler this many times (default: 1)",
|
||||
&upscale_repeats},
|
||||
{"",
|
||||
"--upscale-tile-size",
|
||||
"tile size for ESRGAN upscaling (default: 128)",
|
||||
&upscale_tile_size},
|
||||
};
|
||||
|
||||
options.float_options = {
|
||||
@@ -1251,7 +1332,88 @@ struct SDGenerationParams {
|
||||
return true;
|
||||
}
|
||||
|
||||
bool process_and_check(SDMode mode) {
|
||||
void extract_and_remove_lora(const std::string& lora_model_dir) {
|
||||
static const std::regex re(R"(<lora:([^:>]+):([^>]+)>)");
|
||||
static const std::vector<std::string> valid_ext = {".pt", ".safetensors", ".gguf"};
|
||||
std::smatch m;
|
||||
|
||||
std::string tmp = prompt;
|
||||
|
||||
while (std::regex_search(tmp, m, re)) {
|
||||
std::string raw_path = m[1].str();
|
||||
const std::string raw_mul = m[2].str();
|
||||
|
||||
float mul = 0.f;
|
||||
try {
|
||||
mul = std::stof(raw_mul);
|
||||
} catch (...) {
|
||||
tmp = m.suffix().str();
|
||||
prompt = std::regex_replace(prompt, re, "", std::regex_constants::format_first_only);
|
||||
continue;
|
||||
}
|
||||
|
||||
bool is_high_noise = false;
|
||||
static const std::string prefix = "|high_noise|";
|
||||
if (raw_path.rfind(prefix, 0) == 0) {
|
||||
raw_path.erase(0, prefix.size());
|
||||
is_high_noise = true;
|
||||
}
|
||||
|
||||
fs::path final_path;
|
||||
if (is_absolute_path(raw_path)) {
|
||||
final_path = raw_path;
|
||||
} else {
|
||||
final_path = fs::path(lora_model_dir) / raw_path;
|
||||
}
|
||||
if (!fs::exists(final_path)) {
|
||||
bool found = false;
|
||||
for (const auto& ext : valid_ext) {
|
||||
fs::path try_path = final_path;
|
||||
try_path += ext;
|
||||
if (fs::exists(try_path)) {
|
||||
final_path = try_path;
|
||||
found = true;
|
||||
break;
|
||||
}
|
||||
}
|
||||
if (!found) {
|
||||
printf("can not found lora %s\n", final_path.lexically_normal().string().c_str());
|
||||
tmp = m.suffix().str();
|
||||
prompt = std::regex_replace(prompt, re, "", std::regex_constants::format_first_only);
|
||||
continue;
|
||||
}
|
||||
}
|
||||
|
||||
const std::string key = final_path.lexically_normal().string();
|
||||
|
||||
if (is_high_noise)
|
||||
high_noise_lora_map[key] += mul;
|
||||
else
|
||||
lora_map[key] += mul;
|
||||
|
||||
prompt = std::regex_replace(prompt, re, "", std::regex_constants::format_first_only);
|
||||
|
||||
tmp = m.suffix().str();
|
||||
}
|
||||
|
||||
for (const auto& kv : lora_map) {
|
||||
sd_lora_t item;
|
||||
item.is_high_noise = false;
|
||||
item.path = kv.first.c_str();
|
||||
item.multiplier = kv.second;
|
||||
lora_vec.emplace_back(item);
|
||||
}
|
||||
|
||||
for (const auto& kv : high_noise_lora_map) {
|
||||
sd_lora_t item;
|
||||
item.is_high_noise = true;
|
||||
item.path = kv.first.c_str();
|
||||
item.multiplier = kv.second;
|
||||
lora_vec.emplace_back(item);
|
||||
}
|
||||
}
|
||||
|
||||
bool process_and_check(SDMode mode, const std::string& lora_model_dir) {
|
||||
if (width <= 0) {
|
||||
fprintf(stderr, "error: the width must be greater than 0\n");
|
||||
return false;
|
||||
@@ -1350,6 +1512,10 @@ struct SDGenerationParams {
|
||||
return false;
|
||||
}
|
||||
|
||||
if (upscale_tile_size < 1) {
|
||||
return false;
|
||||
}
|
||||
|
||||
if (mode == UPSCALE) {
|
||||
if (init_image_path.length() == 0) {
|
||||
fprintf(stderr, "error: upscale mode needs an init image (--init-img)\n");
|
||||
@@ -1362,14 +1528,44 @@ struct SDGenerationParams {
|
||||
seed = rand();
|
||||
}
|
||||
|
||||
extract_and_remove_lora(lora_model_dir);
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
std::string to_string() const {
|
||||
char* sample_params_str = sd_sample_params_to_str(&sample_params);
|
||||
char* high_noise_sample_params_str = sd_sample_params_to_str(&high_noise_sample_params);
|
||||
|
||||
std::ostringstream lora_ss;
|
||||
lora_ss << "{\n";
|
||||
for (auto it = lora_map.begin(); it != lora_map.end(); ++it) {
|
||||
lora_ss << " \"" << it->first << "\": \"" << it->second << "\"";
|
||||
if (std::next(it) != lora_map.end()) {
|
||||
lora_ss << ",";
|
||||
}
|
||||
lora_ss << "\n";
|
||||
}
|
||||
lora_ss << " }";
|
||||
std::string loras_str = lora_ss.str();
|
||||
|
||||
lora_ss = std::ostringstream();
|
||||
;
|
||||
lora_ss << "{\n";
|
||||
for (auto it = high_noise_lora_map.begin(); it != high_noise_lora_map.end(); ++it) {
|
||||
lora_ss << " \"" << it->first << "\": \"" << it->second << "\"";
|
||||
if (std::next(it) != high_noise_lora_map.end()) {
|
||||
lora_ss << ",";
|
||||
}
|
||||
lora_ss << "\n";
|
||||
}
|
||||
lora_ss << " }";
|
||||
std::string high_noise_loras_str = lora_ss.str();
|
||||
|
||||
std::ostringstream oss;
|
||||
oss << "SDGenerationParams {\n"
|
||||
<< " loras: \"" << loras_str << "\",\n"
|
||||
<< " high_noise_loras: \"" << high_noise_loras_str << "\",\n"
|
||||
<< " prompt: \"" << prompt << "\",\n"
|
||||
<< " negative_prompt: \"" << negative_prompt << "\",\n"
|
||||
<< " clip_skip: " << clip_skip << ",\n"
|
||||
@@ -1405,9 +1601,14 @@ struct SDGenerationParams {
|
||||
<< " control_strength: " << control_strength << ",\n"
|
||||
<< " seed: " << seed << ",\n"
|
||||
<< " upscale_repeats: " << upscale_repeats << ",\n"
|
||||
<< " upscale_tile_size: " << upscale_tile_size << ",\n"
|
||||
<< "}";
|
||||
free(sample_params_str);
|
||||
free(high_noise_sample_params_str);
|
||||
return oss.str();
|
||||
}
|
||||
};
|
||||
|
||||
static std::string version_string() {
|
||||
return std::string("stable-diffusion.cpp version ") + sd_version() + ", commit " + sd_commit();
|
||||
}
|
||||
@@ -134,6 +134,7 @@ struct SDSvrParams {
|
||||
};
|
||||
|
||||
void print_usage(int argc, const char* argv[], const std::vector<ArgOptions>& options_list) {
|
||||
std::cout << version_string() << "\n";
|
||||
std::cout << "Usage: " << argv[0] << " [options]\n\n";
|
||||
std::cout << "Svr Options:\n";
|
||||
options_list[0].print();
|
||||
@@ -362,7 +363,7 @@ int main(int argc, const char** argv) {
|
||||
return;
|
||||
}
|
||||
|
||||
if (!gen_params.process_and_check(IMG_GEN)) {
|
||||
if (!gen_params.process_and_check(IMG_GEN, ctx_params.lora_model_dir)) {
|
||||
res.status = 400;
|
||||
res.set_content(R"({"error":"invalid params"})", "application/json");
|
||||
return;
|
||||
@@ -378,6 +379,8 @@ int main(int argc, const char** argv) {
|
||||
std::vector<sd_image_t> pmid_images;
|
||||
|
||||
sd_img_gen_params_t img_gen_params = {
|
||||
gen_params.lora_vec.data(),
|
||||
static_cast<uint32_t>(gen_params.lora_vec.size()),
|
||||
gen_params.prompt.c_str(),
|
||||
gen_params.negative_prompt.c_str(),
|
||||
gen_params.clip_skip,
|
||||
|
||||
Reference in new issue
Block a user