#ifndef __PMI_HPP__ #define __PMI_HPP__ #include "ggml_extend.hpp" #include "clip.hpp" struct FuseBlock { // network hparams int in_dim; int out_dim; int hidden_dim; bool use_residue; // network params // in_layers // layer norm struct ggml_tensor* ln_w; // [in_dim, ] struct ggml_tensor* ln_b; // [in_dim, ] struct ggml_tensor* fc1_w; // [in_dim, hidden_dim] struct ggml_tensor* fc1_b; // [in_dim, ] struct ggml_tensor* fc2_w; // [hidden_dim, out_dim ] struct ggml_tensor* fc2_b; // [hidden_dim, ] FuseBlock(int i_d, int o_d, int h_d, bool use_residue = true) : in_dim(i_d), out_dim(o_d), hidden_dim(h_d), use_residue(use_residue){ } size_t calculate_mem_size(ggml_type wtype) { size_t mem_size = 0; mem_size += 2 * ggml_row_size(wtype, in_dim); mem_size += ggml_row_size(wtype, in_dim*hidden_dim); mem_size += ggml_row_size(wtype, out_dim); mem_size += ggml_row_size(wtype, hidden_dim*out_dim); mem_size += ggml_row_size(wtype, hidden_dim); return mem_size; } void init_params(struct ggml_context* ctx, ggml_type wtype, ggml_allocr* alloc) { ln_w = ggml_new_tensor_1d(ctx, wtype, in_dim); ln_b = ggml_new_tensor_1d(ctx, wtype, in_dim); fc1_b = ggml_new_tensor_1d(ctx, wtype, hidden_dim); fc1_w = ggml_new_tensor_2d(ctx, wtype, in_dim, hidden_dim); fc2_b = ggml_new_tensor_1d(ctx, wtype, out_dim); fc2_w = ggml_new_tensor_2d(ctx, wtype, hidden_dim, out_dim); // alloc all tensors linked to this context for (struct ggml_tensor* t = ggml_get_first_tensor(ctx); t != NULL; t = ggml_get_next_tensor(ctx, t)) { if (t->data == NULL) { ggml_allocr_alloc(alloc, t); } } } size_t get_num_tensors() { return 6; } void map_by_name(std::map& tensors, const std::string prefix) { tensors[prefix + "fc1.weight"] = fc1_w; tensors[prefix + "fc1.bias"] = fc1_b; tensors[prefix + "fc2.weight"] = fc2_w; tensors[prefix + "fc2.bias"] = fc2_b; tensors[prefix + "layernorm.weight"] = ln_w; tensors[prefix + "layernorm.bias"] = ln_b; } struct ggml_tensor* forward(struct ggml_context* ctx, struct ggml_tensor* x) { // x: [N, channels, h, w] // in_layers struct ggml_tensor* r = x; x = ggml_nn_layer_norm(ctx, x, ln_w, ln_b); x = ggml_add(ctx, ggml_mul_mat(ctx, fc1_w, x), fc1_b); x = ggml_gelu_inplace(ctx, x); x = ggml_add(ctx, ggml_mul_mat(ctx, fc2_w, x), fc2_b); if(use_residue) x = ggml_add(ctx, x, r); return x; } }; struct FuseModule{ // network hparams int embed_dim; struct FuseBlock mlp1; struct FuseBlock mlp2; // layer norm struct ggml_tensor* ln_w; // [in_dim, ] struct ggml_tensor* ln_b; // [in_dim, ] FuseModule(int imb_d): embed_dim(imb_d), mlp1(imb_d*2, imb_d, imb_d, false), mlp2(imb_d, imb_d, imb_d, true) { } void init_params(struct ggml_context* ctx, ggml_type wtype, ggml_allocr* alloc) { ln_w = ggml_new_tensor_1d(ctx, wtype, embed_dim); ln_b = ggml_new_tensor_1d(ctx, wtype, embed_dim); // alloc all tensors linked to this context mlp1.init_params(ctx, wtype, alloc); mlp2.init_params(ctx, wtype, alloc); for (struct ggml_tensor* t = ggml_get_first_tensor(ctx); t != NULL; t = ggml_get_next_tensor(ctx, t)) { if (t->data == NULL) { ggml_allocr_alloc(alloc, t); } } } void map_by_name(std::map& tensors, const std::string prefix) { tensors[prefix + "layer_norm.weight"] = ln_w; tensors[prefix + "layer_norm.bias"] = ln_b; mlp1.map_by_name(tensors, prefix + "mlp1."); mlp2.map_by_name(tensors, prefix + "mlp2."); } size_t get_num_tensors() { size_t n = mlp1.get_num_tensors(); n += mlp2.get_num_tensors(); n += 2; return n; } size_t calculate_mem_size(ggml_type wtype) { size_t mem_size = mlp1.calculate_mem_size(wtype); mem_size += mlp2.calculate_mem_size(wtype); mem_size += 2 * ggml_row_size(wtype, embed_dim); return mem_size; } struct ggml_tensor* fuse_fn(struct ggml_context* ctx, struct ggml_tensor* prompt_embeds, struct ggml_tensor* id_embeds) { auto prompt_embeds0 = ggml_cont(ctx, ggml_permute(ctx, prompt_embeds, 2, 0, 1, 3)); auto id_embeds0 = ggml_cont(ctx, ggml_permute(ctx, id_embeds, 2, 0, 1, 3)); // concat is along dim 2 auto stacked_id_embeds = ggml_concat(ctx, prompt_embeds0, id_embeds0); stacked_id_embeds = ggml_cont(ctx, ggml_permute(ctx, stacked_id_embeds, 1, 2, 0, 3)); stacked_id_embeds = mlp1.forward(ctx, stacked_id_embeds); stacked_id_embeds = ggml_add(ctx, stacked_id_embeds, prompt_embeds); stacked_id_embeds = mlp2.forward(ctx, stacked_id_embeds); stacked_id_embeds = ggml_nn_layer_norm(ctx, stacked_id_embeds, ln_w, ln_b); return stacked_id_embeds; } struct ggml_tensor* forward(struct ggml_context* ctx, struct ggml_tensor* prompt_embeds, struct ggml_tensor* id_embeds, struct ggml_tensor* class_tokens_mask, struct ggml_tensor* class_tokens_mask_pos, struct ggml_tensor* left, struct ggml_tensor* right) { // x: [N, channels, h, w] struct ggml_tensor * valid_id_embeds = id_embeds; // # slice out the image token embeddings struct ggml_tensor * image_token_embeds = ggml_get_rows(ctx, prompt_embeds, class_tokens_mask_pos); struct ggml_tensor *stacked_id_embeds = fuse_fn(ctx, image_token_embeds, valid_id_embeds); stacked_id_embeds = ggml_cont(ctx, ggml_permute(ctx, stacked_id_embeds, 0, 2, 1, 3)); if(left && right){ stacked_id_embeds = ggml_concat(ctx, left, stacked_id_embeds); stacked_id_embeds = ggml_concat(ctx, stacked_id_embeds, right); }else if(left){ stacked_id_embeds = ggml_concat(ctx, left, stacked_id_embeds); }else if(right){ stacked_id_embeds = ggml_concat(ctx, stacked_id_embeds, right); } stacked_id_embeds = ggml_cont(ctx, ggml_permute(ctx, stacked_id_embeds, 0, 2, 1, 3)); class_tokens_mask = ggml_cont(ctx, ggml_transpose(ctx, class_tokens_mask)); class_tokens_mask = ggml_repeat(ctx, class_tokens_mask, prompt_embeds); prompt_embeds = ggml_mul(ctx, prompt_embeds, class_tokens_mask); struct ggml_tensor * updated_prompt_embeds = ggml_add(ctx, prompt_embeds, stacked_id_embeds); return updated_prompt_embeds; } }; struct PhotoMakerIDEncoder : public GGMLModule { SDVersion version = VERSION_XL; CLIPVisionModel vision_model; FuseModule fuse_module; struct ggml_tensor* visual_projection_2; float style_strength; PhotoMakerIDEncoder(SDVersion version = VERSION_XL, float sty = 20.f) : version(version), fuse_module(2048), style_strength(sty){ vision_model = CLIPVisionModel(); } void init_params(ggml_type wtype) { ggml_allocr* alloc = ggml_allocr_new_from_buffer(params_buffer); vision_model.init_params(params_ctx, backend, wtype, alloc); fuse_module.init_params(params_ctx, wtype, alloc); visual_projection_2 = ggml_new_tensor_2d(params_ctx, wtype, 1024, 1280); // python [1024, 1280] ggml_allocr_alloc(alloc, visual_projection_2); ggml_allocr_free(alloc); } void map_by_name(std::map& tensors, const std::string prefix) { vision_model.map_by_name(tensors, prefix + "vision_model.", prefix); fuse_module.map_by_name(tensors, prefix + "fuse_module."); tensors[prefix + "visual_projection_2.weight"] = visual_projection_2; } size_t calculate_mem_size() { wtype = GGML_TYPE_F32; size_t mem_size = vision_model.calculate_mem_size(wtype); mem_size += fuse_module.calculate_mem_size(wtype); mem_size += ggml_row_size(wtype, 1280*1024); return mem_size; } size_t get_num_tensors() { size_t num_tensors = (3 + 2 + 37 * vision_model.num_hidden_layers); num_tensors += fuse_module.get_num_tensors() + 1; return num_tensors; } struct ggml_tensor* forward(struct ggml_context* ctx, struct ggml_tensor* id_pixel_values, struct ggml_tensor* prompt_embeds, struct ggml_tensor* class_tokens_mask, struct ggml_tensor* class_tokens_mask_pos, struct ggml_tensor* cls, struct ggml_tensor* class_embedding_temp, struct ggml_tensor* positions, struct ggml_tensor* left, struct ggml_tensor* right) { // x: [N, channels, h, w] struct ggml_tensor *shared_id_embeds = vision_model.forward(ctx, id_pixel_values, cls, class_embedding_temp, positions ); // [batch_size, seq_length, hidden_size] struct ggml_tensor *id_embeds = vision_model.visual_project(ctx, shared_id_embeds); // [batch_size, seq_length, proj_dim(768)] struct ggml_tensor *id_embeds_2 = ggml_mul_mat(ctx, visual_projection_2, shared_id_embeds); // [batch_size, seq_length, 1280] id_embeds = ggml_cont(ctx, ggml_permute(ctx, id_embeds, 2, 0, 1, 3)); id_embeds_2 = ggml_cont(ctx, ggml_permute(ctx, id_embeds_2, 2, 0, 1, 3)); id_embeds = ggml_concat(ctx, id_embeds, id_embeds_2); // [batch_size, seq_length, 1, 2048] check whether concat at dim 2 is right id_embeds = ggml_cont(ctx, ggml_permute(ctx, id_embeds, 1, 2, 0, 3)); struct ggml_tensor * updated_prompt_embeds = fuse_module.forward(ctx, prompt_embeds, id_embeds, class_tokens_mask, class_tokens_mask_pos, left, right); return updated_prompt_embeds; } struct ggml_cgraph* build_graph(struct ggml_allocr* allocr, struct ggml_tensor* id_pixel_values, struct ggml_tensor* prompt_embeds, std::vector &class_tokens_mask ) { // since we are using ggml-alloc, this buffer only needs enough space to hold the ggml_tensor and ggml_cgraph structs, but not the tensor data static size_t buf_size = ggml_tensor_overhead() * GGML_DEFAULT_GRAPH_SIZE + ggml_graph_overhead(); static std::vector buf(buf_size); struct ggml_init_params params = { /*.mem_size =*/buf_size, /*.mem_buffer =*/buf.data(), /*.no_alloc =*/true, // the tensors will be allocated later by ggml_allocr_alloc_graph() }; struct ggml_context* ctx0 = ggml_init(params); struct ggml_cgraph* gf = ggml_new_graph(ctx0); int64_t hidden_size = prompt_embeds->ne[0]; int64_t seq_length = prompt_embeds->ne[1]; ggml_type type = GGML_TYPE_F32; struct ggml_tensor* id_pixel_values_d = ggml_dup_tensor(ctx0, id_pixel_values); ggml_allocr_alloc(allocr, id_pixel_values_d); struct ggml_tensor* prompt_embeds_d = ggml_dup_tensor(ctx0, prompt_embeds); ggml_allocr_alloc(allocr, prompt_embeds_d); struct ggml_tensor* class_tokens_mask_d = ggml_new_tensor_1d(ctx0, type, class_tokens_mask.size()); ggml_allocr_alloc(allocr, class_tokens_mask_d); std::vector ctm; std::vector ctmf16; std::vector ctmpos; struct ggml_tensor* left = NULL; struct ggml_tensor* right = NULL; for(int i=0; i < class_tokens_mask.size(); i++){ if(class_tokens_mask[i]){ ctm.push_back(0.f); // here use 0.f instead of 1.f to make a scale mask ctmf16.push_back(ggml_fp32_to_fp16(0.f)); // here use 0.f instead of 1.f to make a scale mask ctmpos.push_back(i); }else{ ctm.push_back(1.f); // here use 1.f instead of 0.f to make a scale mask ctmf16.push_back(ggml_fp32_to_fp16(1.f)); // here use 0.f instead of 1.f to make a scale mask } } if(ctmpos[0] > 0){ left = ggml_new_tensor_3d(ctx0, type, hidden_size, 1, ctmpos[0]); ggml_allocr_alloc(allocr, left); } if(ctmpos[ctmpos.size()-1] < seq_length - 1){ right = ggml_new_tensor_3d(ctx0, type, hidden_size, 1, seq_length-ctmpos[ctmpos.size()-1]-1); ggml_allocr_alloc(allocr, right); } struct ggml_tensor* class_tokens_mask_pos = ggml_new_tensor_1d(ctx0, GGML_TYPE_I32, ctmpos.size()); ggml_allocr_alloc(allocr, class_tokens_mask_pos); const int image_size = id_pixel_values->ne[0]; int batch_size = id_pixel_values->ne[3]; const int num_patches = ((image_size / vision_model.patch_size) * (image_size / vision_model.patch_size)); const int num_positions = num_patches + 1; struct ggml_tensor * cls = ggml_new_tensor_1d(ctx0, GGML_TYPE_I32, batch_size); struct ggml_tensor * class_embedding_temp = ggml_new_tensor_4d(ctx0, type, vision_model.hidden_size, batch_size, 1, 1); struct ggml_tensor * positions = ggml_new_tensor_1d(ctx0, GGML_TYPE_I32, num_positions); ggml_allocr_alloc(allocr, cls); ggml_allocr_alloc(allocr, class_embedding_temp); ggml_allocr_alloc(allocr, positions); if (!ggml_allocr_is_measure(allocr)) { ggml_backend_tensor_set(id_pixel_values_d, id_pixel_values->data, 0, ggml_nbytes(id_pixel_values)); ggml_backend_tensor_set(prompt_embeds_d, prompt_embeds->data, 0, ggml_nbytes(prompt_embeds)); if(type == GGML_TYPE_F16) ggml_backend_tensor_set(class_tokens_mask_d, ctmf16.data(), 0, ggml_nbytes(class_tokens_mask_d)); else ggml_backend_tensor_set(class_tokens_mask_d, ctm.data(), 0, ggml_nbytes(class_tokens_mask_d)); std::vector cls_h; for (int b = 0; b < batch_size; b++) { cls_h.push_back(b * num_positions); } std::vector pos; for (int i = 0; i < num_positions; i++) { pos.push_back(i); } ggml_backend_tensor_set(cls, cls_h.data(), 0, ggml_nbytes(cls)); ggml_backend_tensor_set(positions, pos.data(), 0, ggml_nbytes(positions)); ggml_backend_tensor_set(class_tokens_mask_pos, ctmpos.data(), 0, ggml_nbytes(class_tokens_mask_pos)); if(left){ if(type == GGML_TYPE_F16){ std::vector zeros(ggml_nelements(left), ggml_fp32_to_fp16(0.f)); ggml_backend_tensor_set(left, zeros.data(), 0, ggml_nbytes(left)); }else{ std::vector zeros(ggml_nelements(left), 0.f); ggml_backend_tensor_set(left, zeros.data(), 0, ggml_nbytes(left)); } } if(right){ if(type == GGML_TYPE_F16){ std::vector zeros(ggml_nelements(right), ggml_fp32_to_fp16(0.f)); ggml_backend_tensor_set(right, zeros.data(), 0, ggml_nbytes(right)); }else{ std::vector zeros(ggml_nelements(right), 0.f); ggml_backend_tensor_set(right, zeros.data(), 0, ggml_nbytes(right)); } } } struct ggml_tensor* updated_prompt_embeds = forward(ctx0, id_pixel_values_d, prompt_embeds_d, class_tokens_mask_d, class_tokens_mask_pos, cls, class_embedding_temp, positions, left, right ); ggml_build_forward_expand(gf, updated_prompt_embeds); ggml_free(ctx0); return gf; } void alloc_compute_buffer(ggml_context* work_ctx, struct ggml_tensor* id_pixel_values, struct ggml_tensor* prompt_embeds, std::vector &class_tokens_mask) { auto get_graph = [&]() -> struct ggml_cgraph* { return build_graph(compute_allocr, id_pixel_values, prompt_embeds, class_tokens_mask); }; GGMLModule::alloc_compute_buffer(get_graph); } void compute(const int n_threads, struct ggml_tensor* id_pixel_values, struct ggml_tensor* prompt_embeds, std::vector &class_tokens_mask, struct ggml_tensor* updated_prompt_embeds) { auto get_graph = [&]() -> struct ggml_cgraph* { return build_graph(compute_allocr, id_pixel_values, prompt_embeds, class_tokens_mask); }; GGMLModule::compute(get_graph, n_threads, updated_prompt_embeds); } }; #define PM_LORA_GRAPH_SIZE 10240 struct PhotoMakerLoraModel : public GGMLModule { float multiplier = 1.f; std::map lora_tensors; std::vector lora_tensors_to_be_ignored; std::string file_path; ModelLoader model_loader; bool load_failed = false; PhotoMakerLoraModel(){ } PhotoMakerLoraModel(const std::string file_path) : file_path(file_path) { name = "photomaker lora"; if (!model_loader.init_from_file(file_path, "pmid.")) { load_failed = true; } } size_t get_num_tensors() { return PM_LORA_GRAPH_SIZE; } size_t calculate_mem_size() { return model_loader.cal_mem_size(NULL); } bool load_from_file(ggml_backend_t backend) { if (!alloc_params_buffer(backend)) { return false; } LOG_INFO("loading LoRA from '%s'", file_path.c_str()); if (load_failed) { LOG_ERROR("init lora model loader from file failed: '%s'", file_path.c_str()); return false; } ggml_allocr* alloc = ggml_allocr_new_from_buffer(params_buffer); auto on_new_tensor_cb = [&](const TensorStorage& tensor_storage, ggml_tensor** dst_tensor) -> bool { std::string name = tensor_storage.name; // LOG_INFO("loading LoRA tesnor '%s'", name.c_str()); if (!starts_with(name, "pmid.unet")){ // LOG_INFO("skipping LoRA tesnor '%s'", name.c_str()); return true; } // LOG_INFO("loading LoRA tesnor '%s'", name.c_str()); struct ggml_tensor* real = ggml_new_tensor(params_ctx, tensor_storage.type, tensor_storage.n_dims, tensor_storage.ne); ggml_allocr_alloc(alloc, real); *dst_tensor = real; lora_tensors_to_be_ignored.push_back(name); size_t k_pos = name.find(".processor"); if(k_pos != std::string::npos) name.replace(k_pos, strlen(".processor"), ""); // if(starts_with(name, "pmid.unet.down_blocks.2.attentions.1.transformer_blocks.9.attn2")) // print_ggml_tensor(real, true, name.c_str()); lora_tensors[name] = real; return true; }; model_loader.load_tensors(on_new_tensor_cb, backend); LOG_DEBUG("finished loaded lora"); ggml_allocr_free(alloc); return true; } std::pair find_ij0(int n){ int i, j; for(i = 0; i < 3; i++){ for(j = 0; j < 2; j++){ if((i*3+j+1) == n) return {i,j}; } } return {-1, -1}; } std::pair find_ij(int n){ int i, j; for(i = 0; i < 2; i++){ for(j = 0; j < 3; j++){ if((i*3+j) == n) return {i,j}; } } return {-1, -1}; } struct ggml_cgraph* build_graph(std::map model_tensors) { // make a graph to compute all lora, expected lora and models tensors are in the same backend // since we are using ggml-alloc, this buffer only needs enough space to hold the ggml_tensor and ggml_cgraph structs, but not the tensor data static size_t buf_size = ggml_tensor_overhead() * PM_LORA_GRAPH_SIZE + ggml_graph_overhead(); static std::vector buf(buf_size); struct ggml_init_params params = { /*.mem_size =*/buf_size, /*.mem_buffer =*/buf.data(), /*.no_alloc =*/true, // the tensors will be allocated later by ggml_allocr_alloc_graph() }; // LOG_DEBUG("mem_size %u ", params.mem_size); struct ggml_context* ctx0 = ggml_init(params); struct ggml_cgraph* gf = ggml_new_graph_custom(ctx0, PM_LORA_GRAPH_SIZE, false); std::set applied_lora_tensors; for (auto it : model_tensors) { std::string k_tensor = it.first; struct ggml_tensor* weight = model_tensors[it.first]; std::string full_name = k_tensor; // size_t k_pos = k_tensor.find(".weight"); size_t k_pos = k_tensor.find(".attn1"); if (k_pos == std::string::npos) { k_pos = k_tensor.find(".attn2"); if (k_pos == std::string::npos) { continue; } } if(ends_with(k_tensor, "bias")) continue; int block_kind = -1; int block_id = -1; if ((k_pos = k_tensor.find("input_blocks")) != std::string::npos) { block_id = atoi(k_tensor.substr(k_pos+strlen("input_blocks")+1).c_str()); block_kind = 0; // input -> down block }else if ((k_pos = k_tensor.find("output_blocks")) != std::string::npos) { block_id = atoi(k_tensor.substr(k_pos+strlen("output_blocks")+1).c_str()); block_kind = 1; // output -> up block }else{ k_pos = k_tensor.find("transformer_blocks"); block_id = atoi(k_tensor.substr(k_pos-4,1).c_str()); block_kind = 2; // middle block } std::string lora_up_name; std::string lora_down_name; std::string prefix = "pmid.unet"; if (block_kind == 0){ prefix = prefix + ".down_blocks"; k_pos = k_tensor.find(".weight"); k_tensor = k_tensor.substr(0, k_pos); k_pos = k_tensor.find("transformer_blocks"); k_tensor = k_tensor.substr(k_pos); if(ends_with(k_tensor, "0")){ k_tensor = k_tensor.substr(0, k_tensor.length()-2); } std::pair ij = find_ij0(block_id); if(ij.first == -1) continue; prefix = prefix + "."+std::to_string(ij.first)+".attentions."+std::to_string(ij.second)+"."; lora_up_name = prefix + k_tensor + "_lora.up.weight"; lora_down_name = prefix + k_tensor + "_lora.down.weight"; }else if (block_kind == 1){ prefix = prefix + ".up_blocks"; k_pos = k_tensor.find(".weight"); k_tensor = k_tensor.substr(0, k_pos); k_pos = k_tensor.find("transformer_blocks"); k_tensor = k_tensor.substr(k_pos); if(ends_with(k_tensor, "0")){ k_tensor = k_tensor.substr(0, k_tensor.length()-2); } std::pair ij = find_ij(block_id); if(ij.first == -1) continue; prefix = prefix + "."+std::to_string(ij.first)+".attentions."+std::to_string(ij.second)+"."; lora_up_name = prefix + k_tensor + "_lora.up.weight"; lora_down_name = prefix + k_tensor + "_lora.down.weight"; }else{ prefix = prefix + ".mid_block" + ".attentions.0."; k_pos = k_tensor.find(".weight"); k_tensor = k_tensor.substr(0, k_pos); k_pos = k_tensor.find("transformer_blocks"); k_tensor = k_tensor.substr(k_pos); if(ends_with(k_tensor, "0")){ k_tensor = k_tensor.substr(0, k_tensor.length()-2); } lora_up_name = prefix + k_tensor + "_lora.up.weight"; lora_down_name = prefix + k_tensor + "_lora.down.weight"; } // LOG_INFO("unet transformer tensor: %s ", full_name.c_str()); // LOG_INFO("corresponding up tensor: %s ", lora_up_name.c_str()); // LOG_INFO("corresponding dn tensor: %s ", lora_down_name.c_str()); ggml_tensor* lora_up = NULL; ggml_tensor* lora_down = NULL; if (lora_tensors.find(lora_up_name) != lora_tensors.end()) { lora_up = lora_tensors[lora_up_name]; } if (lora_tensors.find(lora_down_name) != lora_tensors.end()) { lora_down = lora_tensors[lora_down_name]; } if (lora_up == NULL || lora_down == NULL) { LOG_WARN("can not find: %s and %s k,id = (%d, %d)", lora_down_name.c_str(), lora_up_name.c_str(), block_kind, block_id); continue; } // print_ggml_tensor(lora_down, true, lora_down_name.c_str()); // print_ggml_tensor(lora_up, true, lora_up_name.c_str()); // ggml_tensor* lora_up_orig = lora_up; applied_lora_tensors.insert(lora_up_name); applied_lora_tensors.insert(lora_down_name); // ggml_mul_mat requires tensor b transposed // lora_down = ggml_cont(ctx0, ggml_transpose(ctx0, lora_down)); // struct ggml_tensor* updown = ggml_mul_mat(ctx0, lora_down, lora_up); // updown = ggml_cont(ctx0, updown); // same as in lora.hpp lora_down = ggml_cont(ctx0, ggml_transpose(ctx0, lora_down)); struct ggml_tensor* updown = ggml_mul_mat(ctx0, lora_up, lora_down); updown = ggml_cont(ctx0, ggml_transpose(ctx0, updown)); updown = ggml_reshape(ctx0, updown, weight); GGML_ASSERT(ggml_nelements(updown) == ggml_nelements(weight)); updown = ggml_scale_inplace(ctx0, updown, multiplier); ggml_tensor* final_weight; // if (weight->type != GGML_TYPE_F32 && weight->type != GGML_TYPE_F16) { // final_weight = ggml_new_tensor(ctx0, GGML_TYPE_F32, weight->n_dims, weight->ne); // final_weight = ggml_cpy_inplace(ctx0, weight, final_weight); // final_weight = ggml_add_inplace(ctx0, final_weight, updown); // final_weight = ggml_cpy_inplace(ctx0, final_weight, weight); // } else { // final_weight = ggml_add_inplace(ctx0, weight, updown); // } final_weight = ggml_add_inplace(ctx0, weight, updown); // apply directly ggml_build_forward_expand(gf, final_weight); } for (auto& kv : lora_tensors) { if (applied_lora_tensors.find(kv.first) == applied_lora_tensors.end()) { LOG_WARN("unused lora tensor %s", kv.first.c_str()); } } return gf; } void alloc_compute_buffer(std::map model_tensors) { auto get_graph = [&]() -> struct ggml_cgraph* { return build_graph(model_tensors); }; GGMLModule::alloc_compute_buffer(get_graph); } void apply(std::map model_tensors, int n_threads) { alloc_compute_buffer(model_tensors); auto get_graph = [&]() -> struct ggml_cgraph* { return build_graph(model_tensors); }; GGMLModule::compute(get_graph, n_threads); } }; #endif // __PMI_HPP__