From 71d82e44e5dabe216f64ac709bffde4a1004960a Mon Sep 17 00:00:00 2001 From: Ettore Di Giacinto Date: Fri, 29 Nov 2024 18:02:08 +0100 Subject: [PATCH 1/8] feat(backend): add stablediffusion-ggml Signed-off-by: Ettore Di Giacinto --- Makefile | 45 ++- .../go/image/stablediffusion-ggml/Makefile | 21 ++ .../go/image/stablediffusion-ggml/gosd.cpp | 292 ++++++++++++++++++ backend/go/image/stablediffusion-ggml/gosd.go | 59 ++++ backend/go/image/stablediffusion-ggml/gosd.h | 8 + backend/go/image/stablediffusion-ggml/main.go | 20 ++ 6 files changed, 438 insertions(+), 7 deletions(-) create mode 100644 backend/go/image/stablediffusion-ggml/Makefile create mode 100644 backend/go/image/stablediffusion-ggml/gosd.cpp create mode 100644 backend/go/image/stablediffusion-ggml/gosd.go create mode 100644 backend/go/image/stablediffusion-ggml/gosd.h create mode 100644 backend/go/image/stablediffusion-ggml/main.go diff --git a/Makefile b/Makefile index bbc8a7ddf8fd..737f73477462 100644 --- a/Makefile +++ b/Makefile @@ -30,6 +30,10 @@ TINYDREAM_VERSION?=c04fa463ace9d9a6464313aa5f9cd0f953b6c057 BARKCPP_REPO?=https://github.com/PABannier/bark.cpp.git BARKCPP_VERSION?=v1.0.0 +# bark.cpp +STABLEDIFFUSION_GGML_REPO?=https://github.com/leejet/stable-diffusion.cpp +STABLEDIFFUSION_GGML_VERSION?=4570715727f35e5a07a76796d823824c8f42206c + ONNX_VERSION?=1.20.0 ONNX_ARCH?=x64 ONNX_OS?=linux @@ -209,6 +213,7 @@ ALL_GRPC_BACKENDS+=backend-assets/grpc/whisper ifeq ($(ONNX_OS),linux) ifeq ($(ONNX_ARCH),x64) ALL_GRPC_BACKENDS+=backend-assets/grpc/bark-cpp + ALL_GRPC_BACKENDS+=backend-assets/grpc/stablediffusion-ggml endif endif @@ -244,15 +249,19 @@ sources/go-llama.cpp: git checkout $(GOLLAMA_VERSION) && \ git submodule update --init --recursive --depth 1 --single-branch +sources/go-llama.cpp/libbinding.a: sources/go-llama.cpp + $(MAKE) -C sources/go-llama.cpp BUILD_TYPE=$(STABLE_BUILD_TYPE) libbinding.a + +## bark.cpp sources/bark.cpp: - git clone --recursive https://github.com/PABannier/bark.cpp.git sources/bark.cpp && \ + git clone --recursive $(BARKCPP_REPO) sources/bark.cpp && \ cd sources/bark.cpp && \ git checkout $(BARKCPP_VERSION) && \ git submodule update --init --recursive --depth 1 --single-branch sources/bark.cpp/build/libbark.a: sources/bark.cpp cd sources/bark.cpp && \ - mkdir build && \ + mkdir -p build && \ cd build && \ cmake $(CMAKE_ARGS) .. && \ cmake --build . --config Release @@ -260,9 +269,6 @@ sources/bark.cpp/build/libbark.a: sources/bark.cpp backend/go/bark/libbark.a: sources/bark.cpp/build/libbark.a $(MAKE) -C backend/go/bark libbark.a -sources/go-llama.cpp/libbinding.a: sources/go-llama.cpp - $(MAKE) -C sources/go-llama.cpp BUILD_TYPE=$(STABLE_BUILD_TYPE) libbinding.a - ## go-piper sources/go-piper: mkdir -p sources/go-piper @@ -276,7 +282,7 @@ sources/go-piper: sources/go-piper/libpiper_binding.a: sources/go-piper $(MAKE) -C sources/go-piper libpiper_binding.a example/main piper.o -## stable diffusion +## stable diffusion (onnx) sources/go-stable-diffusion: mkdir -p sources/go-stable-diffusion cd sources/go-stable-diffusion && \ @@ -289,6 +295,30 @@ sources/go-stable-diffusion: sources/go-stable-diffusion/libstablediffusion.a: sources/go-stable-diffusion CPATH="$(CPATH):/usr/include/opencv4" $(MAKE) -C sources/go-stable-diffusion libstablediffusion.a +## stablediffusion (ggml) +sources/stablediffusion-ggml.cpp: + git clone --recursive $(STABLEDIFFUSION_GGML_REPO) sources/stablediffusion-ggml.cpp && \ + cd sources/stablediffusion-ggml.cpp && \ + git checkout $(STABLEDIFFUSION_GGML_VERSION) && \ + git submodule update --init --recursive --depth 1 --single-branch + +sources/stablediffusion-ggml.cpp/build/libstable-diffusion.a: sources/stablediffusion-ggml.cpp + cd sources/stablediffusion-ggml.cpp && \ + mkdir -p build && \ + cd build && \ + cmake $(CMAKE_ARGS) .. && \ + cmake --build . --config Release + +backend/go/image/stablediffusion-ggml/libsd.a: sources/stablediffusion-ggml.cpp/build/libstable-diffusion.a + $(MAKE) -C backend/go/image/stablediffusion-ggml libsd.a + +backend-assets/grpc/stablediffusion-ggml: backend/go/image/stablediffusion-ggml/libsd.a backend-assets/grpc + CGO_LDFLAGS="$(CGO_LDFLAGS)" C_INCLUDE_PATH=$(CURDIR)/backend/go/image/stablediffusion-ggml/ LIBRARY_PATH=$(CURDIR)/backend/go/image/stablediffusion-ggml/ \ + $(GOCMD) build -ldflags "$(LD_FLAGS)" -tags "$(GO_TAGS)" -o backend-assets/grpc/stablediffusion-ggml ./backend/go/image/stablediffusion-ggml/ +ifneq ($(UPX),) + $(UPX) backend-assets/grpc/stablediffusion-ggml +endif + sources/onnxruntime: mkdir -p sources/onnxruntime curl -L https://github.com/microsoft/onnxruntime/releases/download/v$(ONNX_VERSION)/onnxruntime-$(ONNX_OS)-$(ONNX_ARCH)-$(ONNX_VERSION).tgz -o sources/onnxruntime/onnxruntime-$(ONNX_OS)-$(ONNX_ARCH)-$(ONNX_VERSION).tgz @@ -329,7 +359,7 @@ sources/whisper.cpp: sources/whisper.cpp/libwhisper.a: sources/whisper.cpp cd sources/whisper.cpp && $(MAKE) libwhisper.a libggml.a -get-sources: sources/go-llama.cpp sources/go-piper sources/bark.cpp sources/whisper.cpp sources/go-stable-diffusion sources/go-tiny-dream backend/cpp/llama/llama.cpp +get-sources: sources/go-llama.cpp sources/go-piper sources/stablediffusion-ggml.cpp sources/bark.cpp sources/whisper.cpp sources/go-stable-diffusion sources/go-tiny-dream backend/cpp/llama/llama.cpp replace: $(GOCMD) mod edit -replace github.com/ggerganov/whisper.cpp=$(CURDIR)/sources/whisper.cpp @@ -372,6 +402,7 @@ clean: ## Remove build related file $(MAKE) -C backend/cpp/grpc clean $(MAKE) -C backend/go/bark clean $(MAKE) -C backend/cpp/llama clean + $(MAKE) -C backend/go/image/stablediffusion-ggml clean rm -rf backend/cpp/llama-* || true $(MAKE) dropreplace $(MAKE) protogen-clean diff --git a/backend/go/image/stablediffusion-ggml/Makefile b/backend/go/image/stablediffusion-ggml/Makefile new file mode 100644 index 000000000000..cca9bf6e89dd --- /dev/null +++ b/backend/go/image/stablediffusion-ggml/Makefile @@ -0,0 +1,21 @@ +INCLUDE_PATH := $(abspath ./) +LIBRARY_PATH := $(abspath ./) + +AR?=ar + +BUILD_TYPE?= +# keep standard at C11 and C++11 +CXXFLAGS = -I. -I$(INCLUDE_PATH)/../../../../sources/stablediffusion-ggml.cpp/thirdparty -I$(INCLUDE_PATH)/../../../../sources/stablediffusion-ggml.cpp/ggml/include -I$(INCLUDE_PATH)/../../../../sources/stablediffusion-ggml.cpp -O3 -DNDEBUG -std=c++17 -fPIC + +# warnings +CXXFLAGS += -Wall -Wextra -Wpedantic -Wcast-qual -Wno-unused-function + +gosd.o: + $(CXX) $(CXXFLAGS) gosd.cpp -o gosd.o -c + +libsd.a: gosd.o + cp $(INCLUDE_PATH)/../../../../sources/stablediffusion-ggml.cpp/build/libstable-diffusion.a ./libsd.a + $(AR) rcs libsd.a gosd.o + +clean: + rm -f gosd.o libsd.a \ No newline at end of file diff --git a/backend/go/image/stablediffusion-ggml/gosd.cpp b/backend/go/image/stablediffusion-ggml/gosd.cpp new file mode 100644 index 000000000000..1c6d2821142b --- /dev/null +++ b/backend/go/image/stablediffusion-ggml/gosd.cpp @@ -0,0 +1,292 @@ +#include +#include +#include +#include +#include +#include +#include +#include "gosd.h" + +// #include "preprocessing.hpp" +#include "flux.hpp" +#include "stable-diffusion.h" + +#define STB_IMAGE_IMPLEMENTATION +#define STB_IMAGE_STATIC +#include "stb_image.h" + +#define STB_IMAGE_WRITE_IMPLEMENTATION +#define STB_IMAGE_WRITE_STATIC +#include "stb_image_write.h" + +#define STB_IMAGE_RESIZE_IMPLEMENTATION +#define STB_IMAGE_RESIZE_STATIC +#include "stb_image_resize.h" + + + +const char* rng_type_to_str[] = { + "std_default", + "cuda", +}; + +// Names of the sampler method, same order as enum sample_method in stable-diffusion.h +const char* sample_method_str[] = { + "euler_a", + "euler", + "heun", + "dpm2", + "dpm++2s_a", + "dpm++2m", + "dpm++2mv2", + "ipndm", + "ipndm_v", + "lcm", +}; + +// Names of the sigma schedule overrides, same order as sample_schedule in stable-diffusion.h +const char* schedule_str[] = { + "default", + "discrete", + "karras", + "exponential", + "ays", + "gits", +}; + +const char* modes_str[] = { + "txt2img", + "img2img", + "img2vid", + "convert", +}; + +enum SDMode { + TXT2IMG, + IMG2IMG, + IMG2VID, + CONVERT, + MODE_COUNT +}; + +struct SDParams { + int n_threads = -1; + SDMode mode = TXT2IMG; + std::string model_path; + std::string clip_l_path; + std::string clip_g_path; + std::string t5xxl_path; + std::string diffusion_model_path; + std::string vae_path; + std::string taesd_path; + std::string esrgan_path; + std::string controlnet_path; + std::string embeddings_path; + std::string stacked_id_embeddings_path; + std::string input_id_images_path; + sd_type_t wtype = SD_TYPE_COUNT; + std::string lora_model_dir; + std::string output_path = "output.png"; + std::string input_path; + std::string control_image_path; + + std::string prompt; + std::string negative_prompt; + float min_cfg = 1.0f; + float cfg_scale = 7.0f; + float guidance = 3.5f; + float style_ratio = 20.f; + int clip_skip = -1; // <= 0 represents unspecified + int width = 512; + int height = 512; + int batch_count = 1; + + int video_frames = 6; + int motion_bucket_id = 127; + int fps = 6; + float augmentation_level = 0.f; + + sample_method_t sample_method = EULER_A; + schedule_t schedule = DEFAULT; + int sample_steps = 20; + float strength = 0.75f; + float control_strength = 0.9f; + rng_type_t rng_type = CUDA_RNG; + int64_t seed = 42; + bool verbose = false; + bool vae_tiling = false; + bool control_net_cpu = false; + bool normalize_input = false; + bool clip_on_cpu = false; + bool vae_on_cpu = false; + bool diffusion_flash_attn = false; + bool canny_preprocess = false; + bool color = false; + int upscale_repeats = 1; + + std::vector skip_layers = {7, 8, 9}; + float slg_scale = 0.; + float skip_layer_start = 0.01; + float skip_layer_end = 0.2; +}; + +void print_params(SDParams params) { + printf("Option: \n"); + printf(" n_threads: %d\n", params.n_threads); + printf(" mode: %s\n", modes_str[params.mode]); + printf(" model_path: %s\n", params.model_path.c_str()); + printf(" wtype: %s\n", params.wtype < SD_TYPE_COUNT ? sd_type_name(params.wtype) : "unspecified"); + printf(" clip_l_path: %s\n", params.clip_l_path.c_str()); + printf(" clip_g_path: %s\n", params.clip_g_path.c_str()); + printf(" t5xxl_path: %s\n", params.t5xxl_path.c_str()); + printf(" diffusion_model_path: %s\n", params.diffusion_model_path.c_str()); + printf(" vae_path: %s\n", params.vae_path.c_str()); + printf(" taesd_path: %s\n", params.taesd_path.c_str()); + printf(" esrgan_path: %s\n", params.esrgan_path.c_str()); + printf(" controlnet_path: %s\n", params.controlnet_path.c_str()); + printf(" embeddings_path: %s\n", params.embeddings_path.c_str()); + printf(" stacked_id_embeddings_path: %s\n", params.stacked_id_embeddings_path.c_str()); + printf(" input_id_images_path: %s\n", params.input_id_images_path.c_str()); + printf(" style ratio: %.2f\n", params.style_ratio); + printf(" normalize input image : %s\n", params.normalize_input ? "true" : "false"); + printf(" output_path: %s\n", params.output_path.c_str()); + printf(" init_img: %s\n", params.input_path.c_str()); + printf(" control_image: %s\n", params.control_image_path.c_str()); + printf(" clip on cpu: %s\n", params.clip_on_cpu ? "true" : "false"); + printf(" controlnet cpu: %s\n", params.control_net_cpu ? "true" : "false"); + printf(" vae decoder on cpu:%s\n", params.vae_on_cpu ? "true" : "false"); + printf(" diffusion flash attention:%s\n", params.diffusion_flash_attn ? "true" : "false"); + printf(" strength(control): %.2f\n", params.control_strength); + printf(" prompt: %s\n", params.prompt.c_str()); + printf(" negative_prompt: %s\n", params.negative_prompt.c_str()); + printf(" min_cfg: %.2f\n", params.min_cfg); + printf(" cfg_scale: %.2f\n", params.cfg_scale); + printf(" slg_scale: %.2f\n", params.slg_scale); + printf(" guidance: %.2f\n", params.guidance); + printf(" clip_skip: %d\n", params.clip_skip); + printf(" width: %d\n", params.width); + printf(" height: %d\n", params.height); + printf(" sample_method: %s\n", sample_method_str[params.sample_method]); + printf(" schedule: %s\n", schedule_str[params.schedule]); + printf(" sample_steps: %d\n", params.sample_steps); + printf(" strength(img2img): %.2f\n", params.strength); + printf(" rng: %s\n", rng_type_to_str[params.rng_type]); + printf(" seed: %ld\n", params.seed); + printf(" batch_count: %d\n", params.batch_count); + printf(" vae_tiling: %s\n", params.vae_tiling ? "true" : "false"); + printf(" upscale_repeats: %d\n", params.upscale_repeats); +} + + + sd_ctx_t* sd_c; + +int load_model(char *model, char *schedule_selected, int threads) { + + int schedule_found = -1; + for (int d = 0; d < N_SCHEDULES; d++) { + if (!strcmp(schedule_selected, schedule_str[d])) { + schedule_found = d; + } + } + if (schedule_found == -1) { + printf("invalid scheduler\n"); + return 1; + } + schedule_t schedule = (schedule_t)schedule_found; + + sd_ctx_t* sd_ctx = new_sd_ctx(model, + "", + "", + "", + "", + "", + "", + "", + "", + "", + "", + false, + false, + true, + threads, + SD_TYPE_COUNT, + STD_DEFAULT_RNG, + schedule, + false, + false, + false, + false); + + if (sd_ctx == NULL) { + printf("new_sd_ctx_t failed\n"); + return 1; + } + + sd_c = sd_ctx; + + return 0; +} + +int gen_image(char *text, char *negativeText, int width, int height, int steps, int seed , char* sample_method_selected, char *dst ) { + + sd_image_t* results; + + + int sample_method_found = -1; + for (int m = 0; m < N_SAMPLE_METHODS; m++) { + if (!strcmp(sample_method_selected, sample_method_str[m])) { + sample_method_found = m; + } + } + if (sample_method_found == -1) { + printf("generate failed\n"); + return 1; + } + sample_method_t sample_method = (sample_method_t)sample_method_found; + std::vector skip_layers = {7, 8, 9}; + results = txt2img(sd_c, + text, + negativeText, + -1, //clip_skip + 7.0f, // sfg_scale + 3.5f, + width, + height, + sample_method, + steps, + seed, + 1, + NULL, + 0.9f, + 20.f, + false, + "", + skip_layers.data(), + skip_layers.size(), + 0, + 0.01, + 0.2); + + if (results == NULL) { + printf("generate failed\n"); + return 1; + } + + if (results[0].data == NULL) { + printf("generate failed\n"); + return 1; + } + + stbi_write_png(dst, results[0].width, results[0].height, results[0].channel, + results[0].data, 0, ""); + printf("save result image to '%s'\n", dst); + free(results[0].data); + results[0].data = NULL; + + free(results); +} + +int unload() { + free_sd_ctx(sd_c); +} + diff --git a/backend/go/image/stablediffusion-ggml/gosd.go b/backend/go/image/stablediffusion-ggml/gosd.go new file mode 100644 index 000000000000..050ff80da5d9 --- /dev/null +++ b/backend/go/image/stablediffusion-ggml/gosd.go @@ -0,0 +1,59 @@ +package main + +// #cgo CXXFLAGS: -I${SRCDIR}/../../../../sources/stablediffusion-ggml.cpp/thirdparty -I${SRCDIR}/../../../../sources/stablediffusion-ggml.cpp -I${SRCDIR}/../../../../sources/stablediffusion-ggml.cpp/ggml/include +// #cgo LDFLAGS: -L${SRCDIR}/ -L${SRCDIR}/../../../../sources/stablediffusion-ggml.cpp/build/ggml/src/ggml-cpu -L${SRCDIR}/../../../../sources/stablediffusion-ggml.cpp/build/ggml/src -lsd -lstdc++ -lm -lggml -lggml-base -lggml-cpu -lgomp +// #include +// #include +import "C" + +import ( + "fmt" + "unsafe" + + "github.com/mudler/LocalAI/pkg/grpc/base" + pb "github.com/mudler/LocalAI/pkg/grpc/proto" +) + +type SDGGML struct { + base.SingleThread + threads int +} + +func (sd *SDGGML) Load(opts *pb.ModelOptions) error { + + sd.threads = int(opts.Threads) + + schedulerType := C.CString(opts.SchedulerType) + defer C.free(unsafe.Pointer(schedulerType)) + + modelFile := C.CString(opts.ModelFile) + defer C.free(unsafe.Pointer(modelFile)) + + ret := C.load_model(modelFile, schedulerType, C.int(opts.Threads)) + if ret != 0 { + return fmt.Errorf("inference failed") + } + + return nil +} + +func (sd *SDGGML) GenerateImage(opts *pb.GenerateImageRequest) error { + t := C.CString(opts.PositivePrompt) + defer C.free(unsafe.Pointer(t)) + + dst := C.CString(opts.Dst) + defer C.free(unsafe.Pointer(dst)) + + negative := C.CString(opts.NegativePrompt) + defer C.free(unsafe.Pointer(negative)) + + sampleMethod := C.CString(opts.EnableParameters) + defer C.free(unsafe.Pointer(sampleMethod)) + + ret := C.gen_image(t, negative, C.int(opts.Width), C.int(opts.Height), C.int(opts.Step), C.int(opts.Seed), sampleMethod, dst) + if ret != 0 { + return fmt.Errorf("inference failed") + } + + return nil +} diff --git a/backend/go/image/stablediffusion-ggml/gosd.h b/backend/go/image/stablediffusion-ggml/gosd.h new file mode 100644 index 000000000000..300bf0305a99 --- /dev/null +++ b/backend/go/image/stablediffusion-ggml/gosd.h @@ -0,0 +1,8 @@ +#ifdef __cplusplus +extern "C" { +#endif +int load_model(char *model, char *schedule_selected, int threads); +int gen_image(char *text, char *negativeText, int width, int height, int steps, int seed , char* sample_method_selected, char *dst ); +#ifdef __cplusplus +} +#endif \ No newline at end of file diff --git a/backend/go/image/stablediffusion-ggml/main.go b/backend/go/image/stablediffusion-ggml/main.go new file mode 100644 index 000000000000..acee74fac0d4 --- /dev/null +++ b/backend/go/image/stablediffusion-ggml/main.go @@ -0,0 +1,20 @@ +package main + +// Note: this is started internally by LocalAI and a server is allocated for each model +import ( + "flag" + + grpc "github.com/mudler/LocalAI/pkg/grpc" +) + +var ( + addr = flag.String("addr", "localhost:50051", "the address to connect to") +) + +func main() { + flag.Parse() + + if err := grpc.StartServer(*addr, &SDGGML{}); err != nil { + panic(err) + } +} From c0c4e0da21358cc46306947ea5c24772d99172a1 Mon Sep 17 00:00:00 2001 From: Ettore Di Giacinto Date: Fri, 29 Nov 2024 18:11:59 +0100 Subject: [PATCH 2/8] chore(ci): track stablediffusion-ggml Signed-off-by: Ettore Di Giacinto --- .github/workflows/bump_deps.yaml | 3 +++ 1 file changed, 3 insertions(+) diff --git a/.github/workflows/bump_deps.yaml b/.github/workflows/bump_deps.yaml index 8f30f1a0007c..092110df3aa2 100644 --- a/.github/workflows/bump_deps.yaml +++ b/.github/workflows/bump_deps.yaml @@ -18,6 +18,9 @@ jobs: - repository: "PABannier/bark.cpp" variable: "BARKCPP_VERSION" branch: "main" + - repository: "leejet/stable-diffusion.cpp" + variable: "STABLEDIFFUSION_GGML_VERSION" + branch: "master" - repository: "mudler/go-stable-diffusion" variable: "STABLEDIFFUSION_VERSION" branch: "master" From ba20cd7ff4287f93aebf21576c81cd03bdca6ffa Mon Sep 17 00:00:00 2001 From: Ettore Di Giacinto Date: Fri, 29 Nov 2024 18:13:05 +0100 Subject: [PATCH 3/8] fixups Signed-off-by: Ettore Di Giacinto --- Makefile | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/Makefile b/Makefile index 737f73477462..90626bf1cc43 100644 --- a/Makefile +++ b/Makefile @@ -30,7 +30,7 @@ TINYDREAM_VERSION?=c04fa463ace9d9a6464313aa5f9cd0f953b6c057 BARKCPP_REPO?=https://github.com/PABannier/bark.cpp.git BARKCPP_VERSION?=v1.0.0 -# bark.cpp +# stablediffusion.cpp (ggml) STABLEDIFFUSION_GGML_REPO?=https://github.com/leejet/stable-diffusion.cpp STABLEDIFFUSION_GGML_VERSION?=4570715727f35e5a07a76796d823824c8f42206c From 7cca1b212458cf994bc3a895d5083bb9674e2588 Mon Sep 17 00:00:00 2001 From: Ettore Di Giacinto Date: Fri, 29 Nov 2024 18:47:14 +0100 Subject: [PATCH 4/8] Use default scheduler and sampler if not specified Signed-off-by: Ettore Di Giacinto --- backend/go/image/stablediffusion-ggml/gosd.cpp | 12 ++++++++---- backend/go/image/stablediffusion-ggml/gosd.go | 2 +- 2 files changed, 9 insertions(+), 5 deletions(-) diff --git a/backend/go/image/stablediffusion-ggml/gosd.cpp b/backend/go/image/stablediffusion-ggml/gosd.cpp index 1c6d2821142b..a2c764689658 100644 --- a/backend/go/image/stablediffusion-ggml/gosd.cpp +++ b/backend/go/image/stablediffusion-ggml/gosd.cpp @@ -181,6 +181,7 @@ void print_params(SDParams params) { sd_ctx_t* sd_c; int load_model(char *model, char *schedule_selected, int threads) { + fprintf (stderr, "Loading model!\n"); int schedule_found = -1; for (int d = 0; d < N_SCHEDULES; d++) { @@ -189,9 +190,11 @@ int load_model(char *model, char *schedule_selected, int threads) { } } if (schedule_found == -1) { - printf("invalid scheduler\n"); - return 1; + fprintf (stderr, "Invalid scheduler! using DEFAULT\n"); + schedule_found = DEFAULT; } + + schedule_t schedule = (schedule_t)schedule_found; sd_ctx_t* sd_ctx = new_sd_ctx(model, @@ -218,7 +221,7 @@ int load_model(char *model, char *schedule_selected, int threads) { false); if (sd_ctx == NULL) { - printf("new_sd_ctx_t failed\n"); + fprintf (stderr, "Null context!\n"); return 1; } @@ -239,7 +242,8 @@ int gen_image(char *text, char *negativeText, int width, int height, int steps, } } if (sample_method_found == -1) { - printf("generate failed\n"); + fprintf(stderr, "Invalid sample method, default to EULER_A!\n"); + sample_method_found = EULER_A; return 1; } sample_method_t sample_method = (sample_method_t)sample_method_found; diff --git a/backend/go/image/stablediffusion-ggml/gosd.go b/backend/go/image/stablediffusion-ggml/gosd.go index 050ff80da5d9..5d2eafd774a4 100644 --- a/backend/go/image/stablediffusion-ggml/gosd.go +++ b/backend/go/image/stablediffusion-ggml/gosd.go @@ -31,7 +31,7 @@ func (sd *SDGGML) Load(opts *pb.ModelOptions) error { ret := C.load_model(modelFile, schedulerType, C.int(opts.Threads)) if ret != 0 { - return fmt.Errorf("inference failed") + return fmt.Errorf("could not load model") } return nil From 354928b914af224cdc45cb3acc31fe9d35e0a6cf Mon Sep 17 00:00:00 2001 From: Ettore Di Giacinto Date: Mon, 2 Dec 2024 17:11:46 +0100 Subject: [PATCH 5/8] fixups Signed-off-by: Ettore Di Giacinto --- backend/backend.proto | 2 + .../go/image/stablediffusion-ggml/gosd.cpp | 97 ++++++++++++++----- backend/go/image/stablediffusion-ggml/gosd.go | 54 +++++++++-- backend/go/image/stablediffusion-ggml/gosd.h | 4 +- core/backend/options.go | 1 + core/config/backend_config.go | 2 + 6 files changed, 124 insertions(+), 36 deletions(-) diff --git a/backend/backend.proto b/backend/backend.proto index d6e8f23635c5..48b0101b4b29 100644 --- a/backend/backend.proto +++ b/backend/backend.proto @@ -240,6 +240,8 @@ message ModelOptions { repeated string LoraAdapters = 60; repeated float LoraScales = 61; + + repeated string Options = 62; } message Result { diff --git a/backend/go/image/stablediffusion-ggml/gosd.cpp b/backend/go/image/stablediffusion-ggml/gosd.cpp index a2c764689658..c3aca2047836 100644 --- a/backend/go/image/stablediffusion-ggml/gosd.cpp +++ b/backend/go/image/stablediffusion-ggml/gosd.cpp @@ -180,29 +180,88 @@ void print_params(SDParams params) { sd_ctx_t* sd_c; -int load_model(char *model, char *schedule_selected, int threads) { +sample_method_t sample_method; + +int load_model(char *model, char* options[], int threads, int diff) { fprintf (stderr, "Loading model!\n"); + char *stableDiffusionModel = ""; + if (diff == 1 ) { + stableDiffusionModel = model; + model = ""; + } + + // decode options. Options are in form optname:optvale, or if booleans only optname. + char *clip_l_path = ""; + char *clip_g_path = ""; + char *t5xxl_path = ""; + char *vae_path = ""; + char *scheduler = ""; + char *sampler = ""; + + // If options is not NULL, parse options + for (int i = 0; options[i] != NULL; i++) { + char *optname = strtok(options[i], ":"); + char *optval = strtok(NULL, ":"); + if (optval == NULL) { + optval = "true"; + } + + if (!strcmp(optname, "clip_l_path")) { + clip_l_path = optval; + } + if (!strcmp(optname, "clip_g_path")) { + clip_g_path = optval; + } + if (!strcmp(optname, "t5xxl_path")) { + t5xxl_path = optval; + } + if (!strcmp(optname, "vae_path")) { + vae_path = optval; + } + if (!strcmp(optname, "scheduler")) { + scheduler = optval; + } + if (!strcmp(optname, "sampler")) { + sampler = optval; + } + } + + int sample_method_found = -1; + for (int m = 0; m < N_SAMPLE_METHODS; m++) { + if (!strcmp(sampler, sample_method_str[m])) { + sample_method_found = m; + } + } + if (sample_method_found == -1) { + fprintf(stderr, "Invalid sample method, default to EULER_A!\n"); + sample_method_found = EULER_A; + } + sample_method = (sample_method_t)sample_method_found; + int schedule_found = -1; for (int d = 0; d < N_SCHEDULES; d++) { - if (!strcmp(schedule_selected, schedule_str[d])) { + if (!strcmp(scheduler, schedule_str[d])) { schedule_found = d; + fprintf (stderr, "Found scheduler: %s\n", scheduler); + } } + if (schedule_found == -1) { fprintf (stderr, "Invalid scheduler! using DEFAULT\n"); schedule_found = DEFAULT; } - schedule_t schedule = (schedule_t)schedule_found; - + + fprintf (stderr, "Creating context\n"); sd_ctx_t* sd_ctx = new_sd_ctx(model, - "", - "", - "", - "", - "", + clip_l_path, + clip_g_path, + t5xxl_path, + stableDiffusionModel, + vae_path, "", "", "", @@ -221,38 +280,26 @@ int load_model(char *model, char *schedule_selected, int threads) { false); if (sd_ctx == NULL) { - fprintf (stderr, "Null context!\n"); + fprintf (stderr, "failed loading model (generic error)\n"); return 1; } + fprintf (stderr, "Created context: OK\n"); sd_c = sd_ctx; return 0; } -int gen_image(char *text, char *negativeText, int width, int height, int steps, int seed , char* sample_method_selected, char *dst ) { +int gen_image(char *text, char *negativeText, int width, int height, int steps, int seed , char *dst, float cfg_scale) { sd_image_t* results; - - int sample_method_found = -1; - for (int m = 0; m < N_SAMPLE_METHODS; m++) { - if (!strcmp(sample_method_selected, sample_method_str[m])) { - sample_method_found = m; - } - } - if (sample_method_found == -1) { - fprintf(stderr, "Invalid sample method, default to EULER_A!\n"); - sample_method_found = EULER_A; - return 1; - } - sample_method_t sample_method = (sample_method_t)sample_method_found; std::vector skip_layers = {7, 8, 9}; results = txt2img(sd_c, text, negativeText, -1, //clip_skip - 7.0f, // sfg_scale + cfg_scale, // sfg_scale 3.5f, width, height, diff --git a/backend/go/image/stablediffusion-ggml/gosd.go b/backend/go/image/stablediffusion-ggml/gosd.go index 5d2eafd774a4..d6d90633dabf 100644 --- a/backend/go/image/stablediffusion-ggml/gosd.go +++ b/backend/go/image/stablediffusion-ggml/gosd.go @@ -8,28 +8,67 @@ import "C" import ( "fmt" + "os" + "path/filepath" + "strings" "unsafe" "github.com/mudler/LocalAI/pkg/grpc/base" pb "github.com/mudler/LocalAI/pkg/grpc/proto" + "github.com/mudler/LocalAI/pkg/utils" ) type SDGGML struct { base.SingleThread - threads int + threads int + sampleMethod string + cfgScale float32 } func (sd *SDGGML) Load(opts *pb.ModelOptions) error { sd.threads = int(opts.Threads) - schedulerType := C.CString(opts.SchedulerType) - defer C.free(unsafe.Pointer(schedulerType)) - modelFile := C.CString(opts.ModelFile) defer C.free(unsafe.Pointer(modelFile)) - ret := C.load_model(modelFile, schedulerType, C.int(opts.Threads)) + var options **C.char + + size := C.size_t(unsafe.Sizeof((*C.char)(nil))) + length := C.size_t(len(opts.Options)) + options = (**C.char)(C.malloc(length * size)) + view := (*[1 << 30]*C.char)(unsafe.Pointer(options))[0:len(opts.Options):len(opts.Options)] + + var diffusionModel int + + var oo []string + for _, op := range opts.Options { + if op == "diffusion_model" { + diffusionModel = 1 + continue + } + + // If it's an option path, we resolve absolute path from the model path + if strings.Contains(op, ":") && strings.Contains(op, "path") { + data := strings.Split(op, ":") + data[1] = filepath.Join(opts.ModelPath, data[1]) + if err := utils.VerifyPath(data[1], opts.ModelPath); err == nil { + oo = append(oo, strings.Join(data, ":")) + } + } else { + oo = append(oo, op) + } + } + + fmt.Fprintf(os.Stderr, "Options: %+v\n", oo) + + for i, x := range oo { + view[i] = C.CString(x) + } + + sd.cfgScale = opts.CFGScale + + ret := C.load_model(modelFile, options, C.int(opts.Threads), C.int(diffusionModel)) if ret != 0 { return fmt.Errorf("could not load model") } @@ -47,10 +86,7 @@ func (sd *SDGGML) GenerateImage(opts *pb.GenerateImageRequest) error { negative := C.CString(opts.NegativePrompt) defer C.free(unsafe.Pointer(negative)) - sampleMethod := C.CString(opts.EnableParameters) - defer C.free(unsafe.Pointer(sampleMethod)) - - ret := C.gen_image(t, negative, C.int(opts.Width), C.int(opts.Height), C.int(opts.Step), C.int(opts.Seed), sampleMethod, dst) + ret := C.gen_image(t, negative, C.int(opts.Width), C.int(opts.Height), C.int(opts.Step), C.int(opts.Seed), dst, C.float(sd.cfgScale)) if ret != 0 { return fmt.Errorf("inference failed") } diff --git a/backend/go/image/stablediffusion-ggml/gosd.h b/backend/go/image/stablediffusion-ggml/gosd.h index 300bf0305a99..5297e87111ed 100644 --- a/backend/go/image/stablediffusion-ggml/gosd.h +++ b/backend/go/image/stablediffusion-ggml/gosd.h @@ -1,8 +1,8 @@ #ifdef __cplusplus extern "C" { #endif -int load_model(char *model, char *schedule_selected, int threads); -int gen_image(char *text, char *negativeText, int width, int height, int steps, int seed , char* sample_method_selected, char *dst ); +int load_model(char *model, char* options[], int threads, int diffusionModel); +int gen_image(char *text, char *negativeText, int width, int height, int steps, int seed, char *dst, float cfg_scale); #ifdef __cplusplus } #endif \ No newline at end of file diff --git a/core/backend/options.go b/core/backend/options.go index c65912222a58..6b4f1f10d303 100644 --- a/core/backend/options.go +++ b/core/backend/options.go @@ -132,6 +132,7 @@ func grpcModelOpts(c config.BackendConfig) *pb.ModelOptions { IMG2IMG: c.Diffusers.IMG2IMG, CLIPModel: c.Diffusers.ClipModel, CLIPSubfolder: c.Diffusers.ClipSubFolder, + Options: c.Options, CLIPSkip: int32(c.Diffusers.ClipSkip), ControlNet: c.Diffusers.ControlNet, ContextSize: int32(ctxSize), diff --git a/core/config/backend_config.go b/core/config/backend_config.go index 998f22a397f9..8bb02f89fb62 100644 --- a/core/config/backend_config.go +++ b/core/config/backend_config.go @@ -72,6 +72,8 @@ type BackendConfig struct { Description string `yaml:"description"` Usage string `yaml:"usage"` + + Options []string `yaml:"options"` } type File struct { From 606f21520bb47fe98af953673139e77921c4186f Mon Sep 17 00:00:00 2001 From: Ettore Di Giacinto Date: Mon, 2 Dec 2024 17:12:02 +0100 Subject: [PATCH 6/8] Move cfg scale out of diffusers block Signed-off-by: Ettore Di Giacinto --- core/backend/options.go | 2 +- core/config/backend_config.go | 21 ++++++++++--------- .../content/docs/features/image-generation.md | 6 ++++-- gallery/flux.yaml | 3 ++- 4 files changed, 18 insertions(+), 14 deletions(-) diff --git a/core/backend/options.go b/core/backend/options.go index 6b4f1f10d303..1f88122fc2b2 100644 --- a/core/backend/options.go +++ b/core/backend/options.go @@ -122,7 +122,7 @@ func grpcModelOpts(c config.BackendConfig) *pb.ModelOptions { CUDA: c.CUDA || c.Diffusers.CUDA, SchedulerType: c.Diffusers.SchedulerType, PipelineType: c.Diffusers.PipelineType, - CFGScale: c.Diffusers.CFGScale, + CFGScale: c.CFGScale, LoraAdapter: c.LoraAdapter, LoraScale: c.LoraScale, LoraAdapters: c.LoraAdapters, diff --git a/core/config/backend_config.go b/core/config/backend_config.go index 8bb02f89fb62..1de540f94382 100644 --- a/core/config/backend_config.go +++ b/core/config/backend_config.go @@ -99,16 +99,15 @@ type GRPC struct { } type Diffusers struct { - CUDA bool `yaml:"cuda"` - PipelineType string `yaml:"pipeline_type"` - SchedulerType string `yaml:"scheduler_type"` - EnableParameters string `yaml:"enable_parameters"` // A list of comma separated parameters to specify - CFGScale float32 `yaml:"cfg_scale"` // Classifier-Free Guidance Scale - IMG2IMG bool `yaml:"img2img"` // Image to Image Diffuser - ClipSkip int `yaml:"clip_skip"` // Skip every N frames - ClipModel string `yaml:"clip_model"` // Clip model to use - ClipSubFolder string `yaml:"clip_subfolder"` // Subfolder to use for clip model - ControlNet string `yaml:"control_net"` + CUDA bool `yaml:"cuda"` + PipelineType string `yaml:"pipeline_type"` + SchedulerType string `yaml:"scheduler_type"` + EnableParameters string `yaml:"enable_parameters"` // A list of comma separated parameters to specify + IMG2IMG bool `yaml:"img2img"` // Image to Image Diffuser + ClipSkip int `yaml:"clip_skip"` // Skip every N frames + ClipModel string `yaml:"clip_model"` // Clip model to use + ClipSubFolder string `yaml:"clip_subfolder"` // Subfolder to use for clip model + ControlNet string `yaml:"control_net"` } // LLMConfig is a struct that holds the configuration that are @@ -166,6 +165,8 @@ type LLMConfig struct { YarnAttnFactor float32 `yaml:"yarn_attn_factor"` YarnBetaFast float32 `yaml:"yarn_beta_fast"` YarnBetaSlow float32 `yaml:"yarn_beta_slow"` + + CFGScale float32 `yaml:"cfg_scale"` // Classifier-Free Guidance Scale } // AutoGPTQ is a struct that holds the configuration specific to the AutoGPTQ backend diff --git a/docs/content/docs/features/image-generation.md b/docs/content/docs/features/image-generation.md index 5bd12575f08a..864ea040ad37 100644 --- a/docs/content/docs/features/image-generation.md +++ b/docs/content/docs/features/image-generation.md @@ -194,8 +194,9 @@ diffusers: pipeline_type: StableDiffusionPipeline enable_parameters: "negative_prompt,num_inference_steps,clip_skip" scheduler_type: "k_dpmpp_sde" - cfg_scale: 8 clip_skip: 11 + +cfg_scale: 8 ``` #### Configuration parameters @@ -302,7 +303,8 @@ cuda: true diffusers: pipeline_type: StableDiffusionDepth2ImgPipeline enable_parameters: "negative_prompt,num_inference_steps,image" - cfg_scale: 6 + +cfg_scale: 6 ``` ```bash diff --git a/gallery/flux.yaml b/gallery/flux.yaml index bb75b53b1351..a859d8011019 100644 --- a/gallery/flux.yaml +++ b/gallery/flux.yaml @@ -11,4 +11,5 @@ config_file: | cuda: true enable_parameters: num_inference_steps pipeline_type: FluxPipeline - cfg_scale: 0 + + cfg_scale: 0 From bef0d4ffc91932507dae0be64974195b25627c10 Mon Sep 17 00:00:00 2001 From: Ettore Di Giacinto Date: Tue, 3 Dec 2024 19:25:09 +0100 Subject: [PATCH 7/8] Make it working Signed-off-by: Ettore Di Giacinto --- .../go/image/stablediffusion-ggml/gosd.cpp | 161 +++--------------- backend/go/image/stablediffusion-ggml/gosd.go | 1 + 2 files changed, 24 insertions(+), 138 deletions(-) diff --git a/backend/go/image/stablediffusion-ggml/gosd.cpp b/backend/go/image/stablediffusion-ggml/gosd.cpp index c3aca2047836..90019fb65d53 100644 --- a/backend/go/image/stablediffusion-ggml/gosd.cpp +++ b/backend/go/image/stablediffusion-ggml/gosd.cpp @@ -23,13 +23,6 @@ #define STB_IMAGE_RESIZE_STATIC #include "stb_image_resize.h" - - -const char* rng_type_to_str[] = { - "std_default", - "cuda", -}; - // Names of the sampler method, same order as enum sample_method in stable-diffusion.h const char* sample_method_str[] = { "euler_a", @@ -54,131 +47,7 @@ const char* schedule_str[] = { "gits", }; -const char* modes_str[] = { - "txt2img", - "img2img", - "img2vid", - "convert", -}; - -enum SDMode { - TXT2IMG, - IMG2IMG, - IMG2VID, - CONVERT, - MODE_COUNT -}; - -struct SDParams { - int n_threads = -1; - SDMode mode = TXT2IMG; - std::string model_path; - std::string clip_l_path; - std::string clip_g_path; - std::string t5xxl_path; - std::string diffusion_model_path; - std::string vae_path; - std::string taesd_path; - std::string esrgan_path; - std::string controlnet_path; - std::string embeddings_path; - std::string stacked_id_embeddings_path; - std::string input_id_images_path; - sd_type_t wtype = SD_TYPE_COUNT; - std::string lora_model_dir; - std::string output_path = "output.png"; - std::string input_path; - std::string control_image_path; - - std::string prompt; - std::string negative_prompt; - float min_cfg = 1.0f; - float cfg_scale = 7.0f; - float guidance = 3.5f; - float style_ratio = 20.f; - int clip_skip = -1; // <= 0 represents unspecified - int width = 512; - int height = 512; - int batch_count = 1; - - int video_frames = 6; - int motion_bucket_id = 127; - int fps = 6; - float augmentation_level = 0.f; - - sample_method_t sample_method = EULER_A; - schedule_t schedule = DEFAULT; - int sample_steps = 20; - float strength = 0.75f; - float control_strength = 0.9f; - rng_type_t rng_type = CUDA_RNG; - int64_t seed = 42; - bool verbose = false; - bool vae_tiling = false; - bool control_net_cpu = false; - bool normalize_input = false; - bool clip_on_cpu = false; - bool vae_on_cpu = false; - bool diffusion_flash_attn = false; - bool canny_preprocess = false; - bool color = false; - int upscale_repeats = 1; - - std::vector skip_layers = {7, 8, 9}; - float slg_scale = 0.; - float skip_layer_start = 0.01; - float skip_layer_end = 0.2; -}; - -void print_params(SDParams params) { - printf("Option: \n"); - printf(" n_threads: %d\n", params.n_threads); - printf(" mode: %s\n", modes_str[params.mode]); - printf(" model_path: %s\n", params.model_path.c_str()); - printf(" wtype: %s\n", params.wtype < SD_TYPE_COUNT ? sd_type_name(params.wtype) : "unspecified"); - printf(" clip_l_path: %s\n", params.clip_l_path.c_str()); - printf(" clip_g_path: %s\n", params.clip_g_path.c_str()); - printf(" t5xxl_path: %s\n", params.t5xxl_path.c_str()); - printf(" diffusion_model_path: %s\n", params.diffusion_model_path.c_str()); - printf(" vae_path: %s\n", params.vae_path.c_str()); - printf(" taesd_path: %s\n", params.taesd_path.c_str()); - printf(" esrgan_path: %s\n", params.esrgan_path.c_str()); - printf(" controlnet_path: %s\n", params.controlnet_path.c_str()); - printf(" embeddings_path: %s\n", params.embeddings_path.c_str()); - printf(" stacked_id_embeddings_path: %s\n", params.stacked_id_embeddings_path.c_str()); - printf(" input_id_images_path: %s\n", params.input_id_images_path.c_str()); - printf(" style ratio: %.2f\n", params.style_ratio); - printf(" normalize input image : %s\n", params.normalize_input ? "true" : "false"); - printf(" output_path: %s\n", params.output_path.c_str()); - printf(" init_img: %s\n", params.input_path.c_str()); - printf(" control_image: %s\n", params.control_image_path.c_str()); - printf(" clip on cpu: %s\n", params.clip_on_cpu ? "true" : "false"); - printf(" controlnet cpu: %s\n", params.control_net_cpu ? "true" : "false"); - printf(" vae decoder on cpu:%s\n", params.vae_on_cpu ? "true" : "false"); - printf(" diffusion flash attention:%s\n", params.diffusion_flash_attn ? "true" : "false"); - printf(" strength(control): %.2f\n", params.control_strength); - printf(" prompt: %s\n", params.prompt.c_str()); - printf(" negative_prompt: %s\n", params.negative_prompt.c_str()); - printf(" min_cfg: %.2f\n", params.min_cfg); - printf(" cfg_scale: %.2f\n", params.cfg_scale); - printf(" slg_scale: %.2f\n", params.slg_scale); - printf(" guidance: %.2f\n", params.guidance); - printf(" clip_skip: %d\n", params.clip_skip); - printf(" width: %d\n", params.width); - printf(" height: %d\n", params.height); - printf(" sample_method: %s\n", sample_method_str[params.sample_method]); - printf(" schedule: %s\n", schedule_str[params.schedule]); - printf(" sample_steps: %d\n", params.sample_steps); - printf(" strength(img2img): %.2f\n", params.strength); - printf(" rng: %s\n", rng_type_to_str[params.rng_type]); - printf(" seed: %ld\n", params.seed); - printf(" batch_count: %d\n", params.batch_count); - printf(" vae_tiling: %s\n", params.vae_tiling ? "true" : "false"); - printf(" upscale_repeats: %d\n", params.upscale_repeats); -} - - - sd_ctx_t* sd_c; +sd_ctx_t* sd_c; sample_method_t sample_method; @@ -295,6 +164,9 @@ int gen_image(char *text, char *negativeText, int width, int height, int steps, sd_image_t* results; std::vector skip_layers = {7, 8, 9}; + + fprintf (stderr, "Generating image\n"); + results = txt2img(sd_c, text, negativeText, @@ -319,22 +191,35 @@ int gen_image(char *text, char *negativeText, int width, int height, int steps, 0.2); if (results == NULL) { - printf("generate failed\n"); + fprintf (stderr, "NO results\n"); return 1; } if (results[0].data == NULL) { - printf("generate failed\n"); + fprintf (stderr, "Results with no data\n"); return 1; } - stbi_write_png(dst, results[0].width, results[0].height, results[0].channel, - results[0].data, 0, ""); - printf("save result image to '%s'\n", dst); + fprintf (stderr, "Writing PNG\n"); + + fprintf (stderr, "DST: %s\n", dst); + fprintf (stderr, "Width: %d\n", results[0].width); + fprintf (stderr, "Height: %d\n", results[0].height); + fprintf (stderr, "Channel: %d\n", results[0].channel); + fprintf (stderr, "Data: %p\n", results[0].data); + + stbi_write_png(dst, results[0].width, results[0].height, results[0].channel, + results[0].data, 0, NULL); + fprintf (stderr, "Saved resulting image to '%s'\n", dst); + + // TODO: free results. Why does it crash? + free(results[0].data); results[0].data = NULL; - free(results); + fprintf (stderr, "gen_image is done", dst); + + return 0; } int unload() { diff --git a/backend/go/image/stablediffusion-ggml/gosd.go b/backend/go/image/stablediffusion-ggml/gosd.go index d6d90633dabf..29d0033de96c 100644 --- a/backend/go/image/stablediffusion-ggml/gosd.go +++ b/backend/go/image/stablediffusion-ggml/gosd.go @@ -33,6 +33,7 @@ func (sd *SDGGML) Load(opts *pb.ModelOptions) error { defer C.free(unsafe.Pointer(modelFile)) var options **C.char + // prepare the options array to pass to C size := C.size_t(unsafe.Sizeof((*C.char)(nil))) length := C.size_t(len(opts.Options)) From c8964f01eefa01ceabc2b9361d270eb5759433c4 Mon Sep 17 00:00:00 2001 From: Ettore Di Giacinto Date: Tue, 3 Dec 2024 22:04:14 +0100 Subject: [PATCH 8/8] fix: set free_params_immediately to false to call the model in sequence https://github.com/leejet/stable-diffusion.cpp/issues/366 Signed-off-by: Ettore Di Giacinto --- backend/go/image/stablediffusion-ggml/gosd.cpp | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/backend/go/image/stablediffusion-ggml/gosd.cpp b/backend/go/image/stablediffusion-ggml/gosd.cpp index 90019fb65d53..8653aa1e235b 100644 --- a/backend/go/image/stablediffusion-ggml/gosd.cpp +++ b/backend/go/image/stablediffusion-ggml/gosd.cpp @@ -138,7 +138,7 @@ int load_model(char *model, char* options[], int threads, int diff) { "", false, false, - true, + false, threads, SD_TYPE_COUNT, STD_DEFAULT_RNG,