mirror of
https://github.com/leejet/stable-diffusion.cpp.git
synced 2026-10-04 19:31:32 +08:00
Compare commits
7
Commits
| Author | SHA1 | Date | |
|---|---|---|---|
|
|
e8eb3791c8 | ||
|
|
aa44e06890 | ||
|
|
6448430dbb | ||
|
|
347710f68f | ||
|
|
59ebdf0bb5 | ||
|
|
4ffcbcaed7 | ||
|
|
694f0d9235 |
+102
-18
@@ -65,7 +65,7 @@ jobs:
|
||||
|
||||
- name: Get commit hash
|
||||
id: commit
|
||||
if: ${{ ( github.event_name == 'push' && github.ref == 'refs/heads/main' ) || github.event.inputs.create_release == 'true' }}
|
||||
if: ${{ ( github.event_name == 'push' && github.ref == 'refs/heads/master' ) || github.event.inputs.create_release == 'true' }}
|
||||
uses: pr-mpt/actions-commit-hash@v2
|
||||
|
||||
- name: Fetch system info
|
||||
@@ -118,7 +118,7 @@ jobs:
|
||||
|
||||
- name: Get commit hash
|
||||
id: commit
|
||||
if: ${{ ( github.event_name == 'push' && github.ref == 'refs/heads/main' ) || github.event.inputs.create_release == 'true' }}
|
||||
if: ${{ ( github.event_name == 'push' && github.ref == 'refs/heads/master' ) || github.event.inputs.create_release == 'true' }}
|
||||
uses: pr-mpt/actions-commit-hash@v2
|
||||
|
||||
- name: Fetch system info
|
||||
@@ -164,8 +164,6 @@ jobs:
|
||||
defines: "-DGGML_NATIVE=OFF -DGGML_AVX512=ON -DGGML_AVX=ON -DGGML_AVX2=ON -DSD_BUILD_SHARED_LIBS=ON"
|
||||
- build: "cuda12"
|
||||
defines: "-DSD_CUDA=ON -DSD_BUILD_SHARED_LIBS=ON -DCMAKE_CUDA_ARCHITECTURES=90;89;86;80;75"
|
||||
# - build: "rocm5.5"
|
||||
# defines: '-G Ninja -DCMAKE_C_COMPILER=clang -DCMAKE_CXX_COMPILER=clang++ -DSD_HIPBLAS=ON -DCMAKE_BUILD_TYPE=Release -DAMDGPU_TARGETS="gfx1100;gfx1102;gfx1030" -DSD_BUILD_SHARED_LIBS=ON'
|
||||
- build: 'vulkan'
|
||||
defines: "-DSD_VULKAN=ON -DSD_BUILD_SHARED_LIBS=ON"
|
||||
steps:
|
||||
@@ -184,22 +182,9 @@ jobs:
|
||||
method: "network"
|
||||
sub-packages: '["nvcc", "cudart", "cublas", "cublas_dev", "thrust", "visual_studio_integration"]'
|
||||
|
||||
- name: Install rocm-toolkit
|
||||
id: rocm-toolkit
|
||||
if: ${{ matrix.build == 'rocm5.5' }}
|
||||
uses: Cyberhan123/rocm-toolkit@v0.1.0
|
||||
with:
|
||||
rocm: "5.5.0"
|
||||
|
||||
- name: Install Ninja
|
||||
id: install-ninja
|
||||
if: ${{ matrix.build == 'rocm5.5' }}
|
||||
uses: urkle/action-get-ninja@v1
|
||||
with:
|
||||
version: 1.11.1
|
||||
- name: Install Vulkan SDK
|
||||
id: get_vulkan
|
||||
if: ${{ matrix.build == 'vulkan' }} https://sdk.lunarg.com/sdk/download/1.4.328.1/windows/vulkansdk-windows-X64-1.4.328.1.exe
|
||||
if: ${{ matrix.build == 'vulkan' }}
|
||||
run: |
|
||||
curl.exe -o $env:RUNNER_TEMP/VulkanSDK-Installer.exe -L "https://sdk.lunarg.com/sdk/download/${env:VULKAN_VERSION}/windows/vulkansdk-windows-X64-${env:VULKAN_VERSION}.exe"
|
||||
& "$env:RUNNER_TEMP\VulkanSDK-Installer.exe" --accept-licenses --default-answer --confirm-command install
|
||||
@@ -277,6 +262,104 @@ jobs:
|
||||
path: |
|
||||
sd-${{ env.BRANCH_NAME }}-${{ steps.commit.outputs.short }}-bin-win-${{ matrix.build }}-x64.zip
|
||||
|
||||
windows-latest-cmake-hip:
|
||||
runs-on: windows-2022
|
||||
|
||||
env:
|
||||
HIPSDK_INSTALLER_VERSION: "25.Q3"
|
||||
GPU_TARGETS: "gfx1151;gfx1200;gfx1201;gfx1100;gfx1101;gfx1102;gfx1030;gfx1031;gfx1032"
|
||||
|
||||
steps:
|
||||
- uses: actions/checkout@v3
|
||||
with:
|
||||
submodules: recursive
|
||||
|
||||
- name: Cache ROCm Installation
|
||||
id: cache-rocm
|
||||
uses: actions/cache@v4
|
||||
with:
|
||||
path: C:\Program Files\AMD\ROCm
|
||||
key: rocm-${{ env.HIPSDK_INSTALLER_VERSION }}-${{ runner.os }}
|
||||
|
||||
- name: ccache
|
||||
uses: ggml-org/ccache-action@v1.2.16
|
||||
with:
|
||||
key: windows-latest-cmake-hip-${{ env.HIPSDK_INSTALLER_VERSION }}-x64
|
||||
evict-old-files: 1d
|
||||
|
||||
- name: Install ROCm
|
||||
if: steps.cache-rocm.outputs.cache-hit != 'true'
|
||||
run: |
|
||||
$ErrorActionPreference = "Stop"
|
||||
write-host "Downloading AMD HIP SDK Installer"
|
||||
Invoke-WebRequest -Uri "https://download.amd.com/developer/eula/rocm-hub/AMD-Software-PRO-Edition-${{ env.HIPSDK_INSTALLER_VERSION }}-WinSvr2022-For-HIP.exe" -OutFile "${env:RUNNER_TEMP}\rocm-install.exe"
|
||||
write-host "Installing AMD HIP SDK"
|
||||
$proc = Start-Process "${env:RUNNER_TEMP}\rocm-install.exe" -ArgumentList '-install' -NoNewWindow -PassThru
|
||||
$completed = $proc.WaitForExit(600000)
|
||||
if (-not $completed) {
|
||||
Write-Error "ROCm installation timed out after 10 minutes. Killing the process"
|
||||
$proc.Kill()
|
||||
exit 1
|
||||
}
|
||||
if ($proc.ExitCode -ne 0) {
|
||||
Write-Error "ROCm installation failed with exit code $($proc.ExitCode)"
|
||||
exit 1
|
||||
}
|
||||
write-host "Completed AMD HIP SDK installation"
|
||||
|
||||
- name: Verify ROCm
|
||||
run: |
|
||||
# Find and test ROCm installation
|
||||
$clangPath = Get-ChildItem 'C:\Program Files\AMD\ROCm\*\bin\clang.exe' | Select-Object -First 1
|
||||
if (-not $clangPath) {
|
||||
Write-Error "ROCm installation not found"
|
||||
exit 1
|
||||
}
|
||||
& $clangPath.FullName --version
|
||||
# Set HIP_PATH environment variable for later steps
|
||||
echo "HIP_PATH=$(Resolve-Path 'C:\Program Files\AMD\ROCm\*\bin\clang.exe' | split-path | split-path)" >> $env:GITHUB_ENV
|
||||
|
||||
- name: Build
|
||||
run: |
|
||||
mkdir build
|
||||
cd build
|
||||
$env:CMAKE_PREFIX_PATH="${env:HIP_PATH}"
|
||||
cmake .. `
|
||||
-G "Unix Makefiles" `
|
||||
-DSD_HIPBLAS=ON `
|
||||
-DSD_BUILD_SHARED_LIBS=ON `
|
||||
-DGGML_NATIVE=OFF `
|
||||
-DCMAKE_C_COMPILER=clang `
|
||||
-DCMAKE_CXX_COMPILER=clang++ `
|
||||
-DCMAKE_BUILD_TYPE=Release `
|
||||
-DGPU_TARGETS="${{ env.GPU_TARGETS }}"
|
||||
cmake --build . --config Release --parallel ${env:NUMBER_OF_PROCESSORS}
|
||||
|
||||
- name: Get commit hash
|
||||
id: commit
|
||||
if: ${{ ( github.event_name == 'push' && github.ref == 'refs/heads/master' ) || github.event.inputs.create_release == 'true' }}
|
||||
uses: pr-mpt/actions-commit-hash@v2
|
||||
|
||||
- name: Pack artifacts
|
||||
if: ${{ ( github.event_name == 'push' && github.ref == 'refs/heads/master' ) || github.event.inputs.create_release == 'true' }}
|
||||
run: |
|
||||
md "build\bin\rocblas\library\"
|
||||
md "build\bin\hipblaslt\library"
|
||||
cp "${env:HIP_PATH}\bin\hipblas.dll" "build\bin\"
|
||||
cp "${env:HIP_PATH}\bin\hipblaslt.dll" "build\bin\"
|
||||
cp "${env:HIP_PATH}\bin\rocblas.dll" "build\bin\"
|
||||
cp "${env:HIP_PATH}\bin\rocblas\library\*" "build\bin\rocblas\library\"
|
||||
cp "${env:HIP_PATH}\bin\hipblaslt\library\*" "build\bin\hipblaslt\library\"
|
||||
7z a sd-${{ env.BRANCH_NAME }}-${{ steps.commit.outputs.short }}-bin-win-rocm-x64.zip .\build\bin\*
|
||||
|
||||
- name: Upload artifacts
|
||||
if: ${{ ( github.event_name == 'push' && github.ref == 'refs/heads/master' ) || github.event.inputs.create_release == 'true' }}
|
||||
uses: actions/upload-artifact@v4
|
||||
with:
|
||||
name: sd-${{ env.BRANCH_NAME }}-${{ steps.commit.outputs.short }}-bin-win-rocm-x64.zip
|
||||
path: |
|
||||
sd-${{ env.BRANCH_NAME }}-${{ steps.commit.outputs.short }}-bin-win-rocm-x64.zip
|
||||
|
||||
release:
|
||||
if: ${{ ( github.event_name == 'push' && github.ref == 'refs/heads/master' ) || github.event.inputs.create_release == 'true' }}
|
||||
|
||||
@@ -286,6 +369,7 @@ jobs:
|
||||
- ubuntu-latest-cmake
|
||||
- macOS-latest-cmake
|
||||
- windows-latest-cmake
|
||||
- windows-latest-cmake-hip
|
||||
|
||||
steps:
|
||||
- name: Clone
|
||||
|
||||
@@ -936,7 +936,7 @@ struct CLIPTextModelRunner : public GGMLRunner {
|
||||
size_t max_token_idx = 0,
|
||||
bool return_pooled = false,
|
||||
int clip_skip = -1) {
|
||||
struct ggml_cgraph* gf = ggml_new_graph(compute_ctx);
|
||||
struct ggml_cgraph* gf = new_graph_custom(2048);
|
||||
|
||||
input_ids = to_backend(input_ids);
|
||||
|
||||
|
||||
+8
-18
@@ -182,31 +182,21 @@ protected:
|
||||
int64_t dim_in;
|
||||
int64_t dim_out;
|
||||
|
||||
void init_params(struct ggml_context* ctx, const String2TensorStorage& tensor_storage_map = {}, std::string prefix = "") override {
|
||||
enum ggml_type wtype = get_type(prefix + "proj.weight", tensor_storage_map, GGML_TYPE_F32);
|
||||
enum ggml_type bias_wtype = GGML_TYPE_F32;
|
||||
params["proj.weight"] = ggml_new_tensor_2d(ctx, wtype, dim_in, dim_out * 2);
|
||||
params["proj.bias"] = ggml_new_tensor_1d(ctx, bias_wtype, dim_out * 2);
|
||||
}
|
||||
|
||||
public:
|
||||
GEGLU(int64_t dim_in, int64_t dim_out)
|
||||
: dim_in(dim_in), dim_out(dim_out) {}
|
||||
: dim_in(dim_in), dim_out(dim_out) {
|
||||
blocks["proj"] = std::shared_ptr<GGMLBlock>(new Linear(dim_in, dim_out * 2));
|
||||
}
|
||||
|
||||
struct ggml_tensor* forward(GGMLRunnerContext* ctx, struct ggml_tensor* x) override {
|
||||
// x: [ne3, ne2, ne1, dim_in]
|
||||
// return: [ne3, ne2, ne1, dim_out]
|
||||
struct ggml_tensor* w = params["proj.weight"];
|
||||
struct ggml_tensor* b = params["proj.bias"];
|
||||
auto proj = std::dynamic_pointer_cast<Linear>(blocks["proj"]);
|
||||
|
||||
auto x_w = ggml_view_2d(ctx->ggml_ctx, w, w->ne[0], w->ne[1] / 2, w->nb[1], 0); // [dim_out, dim_in]
|
||||
auto x_b = ggml_view_1d(ctx->ggml_ctx, b, b->ne[0] / 2, 0); // [dim_out, dim_in]
|
||||
auto gate_w = ggml_view_2d(ctx->ggml_ctx, w, w->ne[0], w->ne[1] / 2, w->nb[1], w->nb[1] * w->ne[1] / 2); // [dim_out, ]
|
||||
auto gate_b = ggml_view_1d(ctx->ggml_ctx, b, b->ne[0] / 2, b->nb[0] * b->ne[0] / 2); // [dim_out, ]
|
||||
|
||||
auto x_in = x;
|
||||
x = ggml_ext_linear(ctx->ggml_ctx, x_in, x_w, x_b); // [ne3, ne2, ne1, dim_out]
|
||||
auto gate = ggml_ext_linear(ctx->ggml_ctx, x_in, gate_w, gate_b); // [ne3, ne2, ne1, dim_out]
|
||||
x = proj->forward(ctx, x); // [ne3, ne2, ne1, dim_out*2]
|
||||
auto x_vec = ggml_ext_chunk(ctx->ggml_ctx, x, 2, 0);
|
||||
x = x_vec[0]; // [ne3, ne2, ne1, dim_out]
|
||||
auto gate = x_vec[1]; // [ne3, ne2, ne1, dim_out]
|
||||
|
||||
gate = ggml_gelu_inplace(ctx->ggml_ctx, gate);
|
||||
|
||||
|
||||
+78
-4
@@ -34,6 +34,7 @@ struct Conditioner {
|
||||
virtual void free_params_buffer() = 0;
|
||||
virtual void get_param_tensors(std::map<std::string, struct ggml_tensor*>& tensors) = 0;
|
||||
virtual size_t get_params_buffer_size() = 0;
|
||||
virtual void set_weight_adapter(const std::shared_ptr<WeightAdapter>& adapter) {}
|
||||
virtual std::tuple<SDCondition, std::vector<bool>> get_learned_condition_with_trigger(ggml_context* work_ctx,
|
||||
int n_threads,
|
||||
const ConditionerParams& conditioner_params) {
|
||||
@@ -108,10 +109,17 @@ struct FrozenCLIPEmbedderWithCustomWords : public Conditioner {
|
||||
return buffer_size;
|
||||
}
|
||||
|
||||
void set_weight_adapter(const std::shared_ptr<WeightAdapter>& adapter) override {
|
||||
text_model->set_weight_adapter(adapter);
|
||||
if (sd_version_is_sdxl(version)) {
|
||||
text_model2->set_weight_adapter(adapter);
|
||||
}
|
||||
}
|
||||
|
||||
bool load_embedding(std::string embd_name, std::string embd_path, std::vector<int32_t>& bpe_tokens) {
|
||||
// the order matters
|
||||
ModelLoader model_loader;
|
||||
if (!model_loader.init_from_file(embd_path)) {
|
||||
if (!model_loader.init_from_file_and_convert_name(embd_path)) {
|
||||
LOG_ERROR("embedding '%s' failed", embd_name.c_str());
|
||||
return false;
|
||||
}
|
||||
@@ -270,13 +278,30 @@ struct FrozenCLIPEmbedderWithCustomWords : public Conditioner {
|
||||
const std::string& curr_text = item.first;
|
||||
float curr_weight = item.second;
|
||||
// printf(" %s: %f \n", curr_text.c_str(), curr_weight);
|
||||
int32_t clean_index = 0;
|
||||
if (curr_text == "BREAK" && curr_weight == -1.0f) {
|
||||
// Pad token array up to chunk size at this point.
|
||||
// TODO: This is a hardcoded chunk_len, like in stable-diffusion.cpp, make it a parameter for the future?
|
||||
// Also, this is 75 instead of 77 to leave room for BOS and EOS tokens.
|
||||
int padding_size = 75 - (tokens_acc % 75);
|
||||
for (int j = 0; j < padding_size; j++) {
|
||||
clean_input_ids.push_back(tokenizer.EOS_TOKEN_ID);
|
||||
clean_index++;
|
||||
}
|
||||
|
||||
// After padding, continue to the next iteration to process the following text as a new segment
|
||||
tokens.insert(tokens.end(), clean_input_ids.begin(), clean_input_ids.end());
|
||||
weights.insert(weights.end(), padding_size, curr_weight);
|
||||
continue;
|
||||
}
|
||||
|
||||
// Regular token, process normally
|
||||
std::vector<int> curr_tokens = tokenizer.encode(curr_text, on_new_token_cb);
|
||||
int32_t clean_index = 0;
|
||||
for (uint32_t i = 0; i < curr_tokens.size(); i++) {
|
||||
int token_id = curr_tokens[i];
|
||||
if (token_id == image_token)
|
||||
if (token_id == image_token) {
|
||||
class_token_index.push_back(clean_index - 1);
|
||||
else {
|
||||
} else {
|
||||
clean_input_ids.push_back(token_id);
|
||||
clean_index++;
|
||||
}
|
||||
@@ -379,6 +404,22 @@ struct FrozenCLIPEmbedderWithCustomWords : public Conditioner {
|
||||
for (const auto& item : parsed_attention) {
|
||||
const std::string& curr_text = item.first;
|
||||
float curr_weight = item.second;
|
||||
|
||||
if (curr_text == "BREAK" && curr_weight == -1.0f) {
|
||||
// Pad token array up to chunk size at this point.
|
||||
// TODO: This is a hardcoded chunk_len, like in stable-diffusion.cpp, make it a parameter for the future?
|
||||
// Also, this is 75 instead of 77 to leave room for BOS and EOS tokens.
|
||||
size_t current_size = tokens.size();
|
||||
size_t padding_size = (75 - (current_size % 75)) % 75; // Ensure no negative padding
|
||||
|
||||
if (padding_size > 0) {
|
||||
LOG_DEBUG("BREAK token encountered, padding current chunk by %zu tokens.", padding_size);
|
||||
tokens.insert(tokens.end(), padding_size, tokenizer.EOS_TOKEN_ID);
|
||||
weights.insert(weights.end(), padding_size, 1.0f);
|
||||
}
|
||||
continue; // Skip to the next item after handling BREAK
|
||||
}
|
||||
|
||||
std::vector<int> curr_tokens = tokenizer.encode(curr_text, on_new_token_cb);
|
||||
tokens.insert(tokens.end(), curr_tokens.begin(), curr_tokens.end());
|
||||
weights.insert(weights.end(), curr_tokens.size(), curr_weight);
|
||||
@@ -764,6 +805,18 @@ struct SD3CLIPEmbedder : public Conditioner {
|
||||
return buffer_size;
|
||||
}
|
||||
|
||||
void set_weight_adapter(const std::shared_ptr<WeightAdapter>& adapter) override {
|
||||
if (clip_l) {
|
||||
clip_l->set_weight_adapter(adapter);
|
||||
}
|
||||
if (clip_g) {
|
||||
clip_g->set_weight_adapter(adapter);
|
||||
}
|
||||
if (t5) {
|
||||
t5->set_weight_adapter(adapter);
|
||||
}
|
||||
}
|
||||
|
||||
std::vector<std::pair<std::vector<int>, std::vector<float>>> tokenize(std::string text,
|
||||
size_t max_length = 0,
|
||||
bool padding = false) {
|
||||
@@ -1160,6 +1213,15 @@ struct FluxCLIPEmbedder : public Conditioner {
|
||||
return buffer_size;
|
||||
}
|
||||
|
||||
void set_weight_adapter(const std::shared_ptr<WeightAdapter>& adapter) {
|
||||
if (clip_l) {
|
||||
clip_l->set_weight_adapter(adapter);
|
||||
}
|
||||
if (t5) {
|
||||
t5->set_weight_adapter(adapter);
|
||||
}
|
||||
}
|
||||
|
||||
std::vector<std::pair<std::vector<int>, std::vector<float>>> tokenize(std::string text,
|
||||
size_t max_length = 0,
|
||||
bool padding = false) {
|
||||
@@ -1400,6 +1462,12 @@ struct T5CLIPEmbedder : public Conditioner {
|
||||
return buffer_size;
|
||||
}
|
||||
|
||||
void set_weight_adapter(const std::shared_ptr<WeightAdapter>& adapter) override {
|
||||
if (t5) {
|
||||
t5->set_weight_adapter(adapter);
|
||||
}
|
||||
}
|
||||
|
||||
std::tuple<std::vector<int>, std::vector<float>, std::vector<float>> tokenize(std::string text,
|
||||
size_t max_length = 0,
|
||||
bool padding = false) {
|
||||
@@ -1589,6 +1657,12 @@ struct Qwen2_5_VLCLIPEmbedder : public Conditioner {
|
||||
return buffer_size;
|
||||
}
|
||||
|
||||
void set_weight_adapter(const std::shared_ptr<WeightAdapter>& adapter) override {
|
||||
if (qwenvl) {
|
||||
qwenvl->set_weight_adapter(adapter);
|
||||
}
|
||||
}
|
||||
|
||||
std::tuple<std::vector<int>, std::vector<float>> tokenize(std::string text,
|
||||
size_t max_length = 0,
|
||||
size_t system_prompt_length = 0,
|
||||
|
||||
+2
-2
@@ -380,7 +380,7 @@ struct ControlNet : public GGMLRunner {
|
||||
struct ggml_tensor* timesteps,
|
||||
struct ggml_tensor* context,
|
||||
struct ggml_tensor* y = nullptr) {
|
||||
struct ggml_cgraph* gf = ggml_new_graph_custom(compute_ctx, CONTROL_NET_GRAPH_SIZE, false);
|
||||
struct ggml_cgraph* gf = new_graph_custom(CONTROL_NET_GRAPH_SIZE);
|
||||
|
||||
x = to_backend(x);
|
||||
if (guided_hint_cached) {
|
||||
@@ -442,7 +442,7 @@ struct ControlNet : public GGMLRunner {
|
||||
std::set<std::string> ignore_tensors;
|
||||
|
||||
ModelLoader model_loader;
|
||||
if (!model_loader.init_from_file(file_path)) {
|
||||
if (!model_loader.init_from_file_and_convert_name(file_path)) {
|
||||
LOG_ERROR("init control net model loader from file failed: '%s'", file_path.c_str());
|
||||
return false;
|
||||
}
|
||||
|
||||
+23
-2
@@ -35,8 +35,9 @@ struct DiffusionModel {
|
||||
virtual void free_compute_buffer() = 0;
|
||||
virtual void get_param_tensors(std::map<std::string, struct ggml_tensor*>& tensors) = 0;
|
||||
virtual size_t get_params_buffer_size() = 0;
|
||||
virtual int64_t get_adm_in_channels() = 0;
|
||||
virtual void set_flash_attn_enabled(bool enabled) = 0;
|
||||
virtual void set_weight_adapter(const std::shared_ptr<WeightAdapter>& adapter){};
|
||||
virtual int64_t get_adm_in_channels() = 0;
|
||||
virtual void set_flash_attn_enabled(bool enabled) = 0;
|
||||
};
|
||||
|
||||
struct UNetModel : public DiffusionModel {
|
||||
@@ -73,6 +74,10 @@ struct UNetModel : public DiffusionModel {
|
||||
return unet.get_params_buffer_size();
|
||||
}
|
||||
|
||||
void set_weight_adapter(const std::shared_ptr<WeightAdapter>& adapter) override {
|
||||
unet.set_weight_adapter(adapter);
|
||||
}
|
||||
|
||||
int64_t get_adm_in_channels() override {
|
||||
return unet.unet.adm_in_channels;
|
||||
}
|
||||
@@ -130,6 +135,10 @@ struct MMDiTModel : public DiffusionModel {
|
||||
return mmdit.get_params_buffer_size();
|
||||
}
|
||||
|
||||
void set_weight_adapter(const std::shared_ptr<WeightAdapter>& adapter) override {
|
||||
mmdit.set_weight_adapter(adapter);
|
||||
}
|
||||
|
||||
int64_t get_adm_in_channels() override {
|
||||
return 768 + 1280;
|
||||
}
|
||||
@@ -188,6 +197,10 @@ struct FluxModel : public DiffusionModel {
|
||||
return flux.get_params_buffer_size();
|
||||
}
|
||||
|
||||
void set_weight_adapter(const std::shared_ptr<WeightAdapter>& adapter) override {
|
||||
flux.set_weight_adapter(adapter);
|
||||
}
|
||||
|
||||
int64_t get_adm_in_channels() override {
|
||||
return 768;
|
||||
}
|
||||
@@ -251,6 +264,10 @@ struct WanModel : public DiffusionModel {
|
||||
return wan.get_params_buffer_size();
|
||||
}
|
||||
|
||||
void set_weight_adapter(const std::shared_ptr<WeightAdapter>& adapter) override {
|
||||
wan.set_weight_adapter(adapter);
|
||||
}
|
||||
|
||||
int64_t get_adm_in_channels() override {
|
||||
return 768;
|
||||
}
|
||||
@@ -313,6 +330,10 @@ struct QwenImageModel : public DiffusionModel {
|
||||
return qwen_image.get_params_buffer_size();
|
||||
}
|
||||
|
||||
void set_weight_adapter(const std::shared_ptr<WeightAdapter>& adapter) override {
|
||||
qwen_image.set_weight_adapter(adapter);
|
||||
}
|
||||
|
||||
int64_t get_adm_in_channels() override {
|
||||
return 768;
|
||||
}
|
||||
|
||||
+9
-32
@@ -12,38 +12,15 @@ Here's a simple example:
|
||||
|
||||
`../models/marblesh.safetensors` or `../models/marblesh.ckpt` will be applied to the model
|
||||
|
||||
# Support matrix
|
||||
# Lora Apply Mode
|
||||
|
||||
> ℹ️ CUDA `get_rows` support is defined here:
|
||||
> [ggml-org/ggml/src/ggml-cuda/getrows.cu#L156](https://github.com/ggml-org/ggml/blob/7dee1d6a1e7611f238d09be96738388da97c88ed/src/ggml-cuda/getrows.cu#L156)
|
||||
> Currently only the basic types + Q4/Q5/Q8 are implemented. K-quants are **not** supported.
|
||||
There are two ways to apply LoRA: **immediately** and **at_runtime**. You can specify it using the `--lora-apply-mode` parameter.
|
||||
|
||||
NOTE: The other backends may have different support.
|
||||
By default, the mode is selected automatically:
|
||||
|
||||
* If the model weights contain any quantized parameters, the **at_runtime** mode is used;
|
||||
* Otherwise, the **immediately** mode is used.
|
||||
|
||||
The **immediately** mode may have precision and compatibility issues with quantized parameters, but it usually offers faster inference speed and, in some cases, lower memory usage.
|
||||
In contrast, the **at_runtime** mode provides better compatibility and higher precision, but inference may be slower and memory usage may be higher in some cases.
|
||||
|
||||
| Quant / Type | CUDA | Vulkan |
|
||||
|--------------|------|--------|
|
||||
| F32 | ✔️ | ✔️ |
|
||||
| F16 | ✔️ | ✔️ |
|
||||
| BF16 | ✔️ | ✔️ |
|
||||
| I32 | ✔️ | ❌ |
|
||||
| Q4_0 | ✔️ | ✔️ |
|
||||
| Q4_1 | ✔️ | ✔️ |
|
||||
| Q5_0 | ✔️ | ✔️ |
|
||||
| Q5_1 | ✔️ | ✔️ |
|
||||
| Q8_0 | ✔️ | ✔️ |
|
||||
| Q2_K | ❌ | ❌ |
|
||||
| Q3_K | ❌ | ❌ |
|
||||
| Q4_K | ❌ | ❌ |
|
||||
| Q5_K | ❌ | ❌ |
|
||||
| Q6_K | ❌ | ❌ |
|
||||
| Q8_K | ❌ | ❌ |
|
||||
| IQ1_S | ❌ | ✔️ |
|
||||
| IQ1_M | ❌ | ✔️ |
|
||||
| IQ2_XXS | ❌ | ✔️ |
|
||||
| IQ2_XS | ❌ | ✔️ |
|
||||
| IQ2_S | ❌ | ✔️ |
|
||||
| IQ3_XXS | ❌ | ✔️ |
|
||||
| IQ3_S | ❌ | ✔️ |
|
||||
| IQ4_XS | ❌ | ✔️ |
|
||||
| IQ4_NL | ❌ | ✔️ |
|
||||
| MXFP4 | ❌ | ✔️ |
|
||||
|
||||
+2
-2
@@ -169,7 +169,7 @@ struct ESRGAN : public GGMLRunner {
|
||||
LOG_INFO("loading esrgan from '%s'", file_path.c_str());
|
||||
|
||||
ModelLoader model_loader;
|
||||
if (!model_loader.init_from_file(file_path)) {
|
||||
if (!model_loader.init_from_file_and_convert_name(file_path)) {
|
||||
LOG_ERROR("init esrgan model loader from file failed: '%s'", file_path.c_str());
|
||||
return false;
|
||||
}
|
||||
@@ -344,7 +344,7 @@ struct ESRGAN : public GGMLRunner {
|
||||
if (!rrdb_net)
|
||||
return nullptr;
|
||||
constexpr int kGraphNodes = 1 << 16; // 65k
|
||||
struct ggml_cgraph* gf = ggml_new_graph_custom(compute_ctx, kGraphNodes, /*grads*/ false);
|
||||
struct ggml_cgraph* gf = new_graph_custom(kGraphNodes);
|
||||
x = to_backend(x);
|
||||
|
||||
auto runner_ctx = get_context();
|
||||
|
||||
@@ -99,6 +99,12 @@ Options:
|
||||
--sampling-method sampling method, one of [euler, euler_a, heun, dpm2, dpm++2s_a, dpm++2m, dpm++2mv2, ipndm, ipndm_v, lcm, ddim_trailing,
|
||||
tcd] (default: euler for Flux/SD3/Wan, euler_a otherwise)
|
||||
--prediction prediction type override, one of [eps, v, edm_v, sd3_flow, flux_flow]
|
||||
--lora-apply-mode the way to apply LoRA, one of [auto, immediately, at_runtime], default is auto. In auto mode, if the model weights
|
||||
contain any quantized parameters, the at_runtime mode will be used; otherwise,
|
||||
immediately will be used.The immediately mode may have precision and
|
||||
compatibility issues with quantized parameters, but it usually offers faster inference
|
||||
speed and, in some cases, lower memory usage. The at_runtime mode, on the other
|
||||
hand, is exactly the opposite.
|
||||
--scheduler denoiser sigma scheduler, one of [discrete, karras, exponential, ays, gits, smoothstep, sgm_uniform, simple], default:
|
||||
discrete
|
||||
--skip-layers layers to skip for SLG steps (default: [7,8,9])
|
||||
@@ -113,4 +119,4 @@ Options:
|
||||
--vae-relative-tile-size relative tile size for vae tiling, format [X]x[Y], in fraction of image size if < 1, in number of tiles per dim if >=1
|
||||
(overrides --vae-tile-size)
|
||||
--preview preview method. must be one of the following [none, proj, tae, vae] (default is none)
|
||||
```
|
||||
```
|
||||
|
||||
+26
-1
@@ -137,7 +137,8 @@ struct SDParams {
|
||||
int chroma_t5_mask_pad = 1;
|
||||
float flow_shift = INFINITY;
|
||||
|
||||
prediction_t prediction = DEFAULT_PRED;
|
||||
prediction_t prediction = DEFAULT_PRED;
|
||||
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};
|
||||
bool force_sdxl_vae_conv_scale = false;
|
||||
@@ -209,6 +210,7 @@ void print_params(SDParams params) {
|
||||
printf(" high_noise_sample_params: %s\n", SAFE_STR(high_noise_sample_params_str));
|
||||
printf(" moe_boundary: %.3f\n", params.moe_boundary);
|
||||
printf(" prediction: %s\n", sd_prediction_name(params.prediction));
|
||||
printf(" lora_apply_mode: %s\n", sd_lora_apply_mode_name(params.lora_apply_mode));
|
||||
printf(" flow_shift: %.2f\n", params.flow_shift);
|
||||
printf(" strength(img2img): %.2f\n", params.strength);
|
||||
printf(" rng: %s\n", sd_rng_type_name(params.rng_type));
|
||||
@@ -926,6 +928,20 @@ void parse_args(int argc, const char** argv, SDParams& params) {
|
||||
return 1;
|
||||
};
|
||||
|
||||
auto on_lora_apply_mode_arg = [&](int argc, const char** argv, int index) {
|
||||
if (++index >= argc) {
|
||||
return -1;
|
||||
}
|
||||
const char* arg = argv[index];
|
||||
params.lora_apply_mode = str_to_lora_apply_mode(arg);
|
||||
if (params.lora_apply_mode == LORA_APPLY_MODE_COUNT) {
|
||||
fprintf(stderr, "error: invalid lora apply model %s\n",
|
||||
arg);
|
||||
return -1;
|
||||
}
|
||||
return 1;
|
||||
};
|
||||
|
||||
auto on_sample_method_arg = [&](int argc, const char** argv, int index) {
|
||||
if (++index >= argc) {
|
||||
return -1;
|
||||
@@ -1123,6 +1139,14 @@ void parse_args(int argc, const char** argv, SDParams& params) {
|
||||
"--prediction",
|
||||
"prediction type override, one of [eps, v, edm_v, sd3_flow, flux_flow]",
|
||||
on_prediction_arg},
|
||||
{"",
|
||||
"--lora-apply-mode",
|
||||
"the way to apply LoRA, one of [auto, immediately, at_runtime], default is auto. "
|
||||
"In auto mode, if the model weights contain any quantized parameters, the at_runtime mode will be used; otherwise, immediately will be used."
|
||||
"The immediately mode may have precision and compatibility issues with quantized parameters, "
|
||||
"but it usually offers faster inference speed and, in some cases, lower memory usage. "
|
||||
"The at_runtime mode, on the other hand, is exactly the opposite.",
|
||||
on_lora_apply_mode_arg},
|
||||
{"",
|
||||
"--scheduler",
|
||||
"denoiser sigma scheduler, one of [discrete, karras, exponential, ays, gits, smoothstep, sgm_uniform, simple], default: discrete",
|
||||
@@ -1738,6 +1762,7 @@ int main(int argc, const char* argv[]) {
|
||||
params.wtype,
|
||||
params.rng_type,
|
||||
params.prediction,
|
||||
params.lora_apply_mode,
|
||||
params.offload_params_to_cpu,
|
||||
params.clip_on_cpu,
|
||||
params.control_net_cpu,
|
||||
|
||||
@@ -1243,7 +1243,7 @@ namespace Flux {
|
||||
bool increase_ref_index = false,
|
||||
std::vector<int> skip_layers = {}) {
|
||||
GGML_ASSERT(x->ne[3] == 1);
|
||||
struct ggml_cgraph* gf = ggml_new_graph_custom(compute_ctx, FLUX_GRAPH_SIZE, false);
|
||||
struct ggml_cgraph* gf = new_graph_custom(FLUX_GRAPH_SIZE);
|
||||
|
||||
struct ggml_tensor* mod_index_arange = nullptr;
|
||||
struct ggml_tensor* dct = nullptr; // for chroma radiance
|
||||
@@ -1398,7 +1398,7 @@ namespace Flux {
|
||||
ggml_type model_data_type = GGML_TYPE_Q8_0;
|
||||
|
||||
ModelLoader model_loader;
|
||||
if (!model_loader.init_from_file(file_path, "model.diffusion_model.")) {
|
||||
if (!model_loader.init_from_file_and_convert_name(file_path, "model.diffusion_model.")) {
|
||||
LOG_ERROR("init model loader from file failed: '%s'", file_path.c_str());
|
||||
return;
|
||||
}
|
||||
|
||||
+129
-12
@@ -959,12 +959,15 @@ __STATIC_INLINE__ struct ggml_tensor* ggml_ext_linear(struct ggml_context* ctx,
|
||||
int64_t ne3 = x->ne[3];
|
||||
x = ggml_reshape_2d(ctx, x, x->ne[0], x->ne[1] * x->ne[2] * x->ne[3]);
|
||||
x = ggml_mul_mat(ctx, w, x);
|
||||
x = ggml_reshape_4d(ctx, x, x->ne[0], x->ne[1] / ne2 / ne3, ne2, ne3);
|
||||
if (force_prec_f32) {
|
||||
ggml_mul_mat_set_prec(x, GGML_PREC_F32);
|
||||
}
|
||||
x = ggml_reshape_4d(ctx, x, x->ne[0], x->ne[1] / ne2 / ne3, ne2, ne3);
|
||||
} else {
|
||||
x = ggml_mul_mat(ctx, w, x);
|
||||
}
|
||||
if (force_prec_f32) {
|
||||
ggml_mul_mat_set_prec(x, GGML_PREC_F32);
|
||||
if (force_prec_f32) {
|
||||
ggml_mul_mat_set_prec(x, GGML_PREC_F32);
|
||||
}
|
||||
}
|
||||
if (scale != 1.f) {
|
||||
x = ggml_scale(ctx, x, 1.f / scale);
|
||||
@@ -1119,6 +1122,18 @@ __STATIC_INLINE__ struct ggml_tensor* ggml_ext_ones(struct ggml_context* ctx,
|
||||
return ggml_ext_full(ctx, 1.f, ne0, ne1, ne2, ne3);
|
||||
}
|
||||
|
||||
__STATIC_INLINE__ ggml_tensor* ggml_ext_cast_f32(ggml_context* ctx, ggml_tensor* a) {
|
||||
auto out = ggml_reshape_2d(ctx, a, 1, ggml_nelements(a));
|
||||
ggml_tensor* one = ggml_ext_ones(ctx, 1, 1, 1, 1); // [1,]
|
||||
if (ggml_is_transposed(out)) {
|
||||
out = ggml_mul_mat(ctx, one, out);
|
||||
} else {
|
||||
out = ggml_mul_mat(ctx, out, one);
|
||||
}
|
||||
out = ggml_reshape(ctx, out, a);
|
||||
return out;
|
||||
}
|
||||
|
||||
// q: [N * n_head, n_token, d_head]
|
||||
// k: [N * n_head, n_k, d_head]
|
||||
// v: [N * n_head, d_head, n_k]
|
||||
@@ -1460,11 +1475,43 @@ __STATIC_INLINE__ size_t ggml_tensor_num(ggml_context* ctx) {
|
||||
#define MAX_PARAMS_TENSOR_NUM 32768
|
||||
#define MAX_GRAPH_SIZE 327680
|
||||
|
||||
struct WeightAdapter {
|
||||
struct ForwardParams {
|
||||
enum class op_type_t {
|
||||
OP_LINEAR,
|
||||
OP_CONV2D,
|
||||
} op_type;
|
||||
struct {
|
||||
bool force_prec_f32 = false;
|
||||
float scale = 1.f;
|
||||
} linear;
|
||||
struct {
|
||||
int s0 = 1;
|
||||
int s1 = 1;
|
||||
int p0 = 0;
|
||||
int p1 = 0;
|
||||
int d0 = 1;
|
||||
int d1 = 1;
|
||||
bool direct = false;
|
||||
float scale = 1.f;
|
||||
} conv2d;
|
||||
};
|
||||
virtual ggml_tensor* patch_weight(ggml_context* ctx, ggml_tensor* weight, const std::string& weight_name) = 0;
|
||||
virtual ggml_tensor* forward_with_lora(ggml_context* ctx,
|
||||
ggml_tensor* x,
|
||||
ggml_tensor* w,
|
||||
ggml_tensor* b,
|
||||
const std::string& prefix,
|
||||
ForwardParams forward_params) = 0;
|
||||
virtual size_t get_extra_graph_size() = 0;
|
||||
};
|
||||
|
||||
struct GGMLRunnerContext {
|
||||
ggml_backend_t backend = nullptr;
|
||||
ggml_context* ggml_ctx = nullptr;
|
||||
bool flash_attn_enabled = false;
|
||||
bool conv2d_direct_enabled = false;
|
||||
ggml_backend_t backend = nullptr;
|
||||
ggml_context* ggml_ctx = nullptr;
|
||||
bool flash_attn_enabled = false;
|
||||
bool conv2d_direct_enabled = false;
|
||||
std::shared_ptr<WeightAdapter> weight_adapter = nullptr;
|
||||
};
|
||||
|
||||
struct GGMLRunner {
|
||||
@@ -1486,6 +1533,8 @@ protected:
|
||||
struct ggml_context* compute_ctx = nullptr;
|
||||
struct ggml_gallocr* compute_allocr = nullptr;
|
||||
|
||||
std::shared_ptr<WeightAdapter> weight_adapter = nullptr;
|
||||
|
||||
std::vector<float> one_vec = {1.f};
|
||||
ggml_tensor* one_tensor = nullptr;
|
||||
|
||||
@@ -1565,11 +1614,20 @@ protected:
|
||||
ggml_build_forward_expand(gf, one_tensor);
|
||||
}
|
||||
|
||||
struct ggml_cgraph* new_graph_custom(size_t graph_size) {
|
||||
if (weight_adapter) {
|
||||
graph_size += weight_adapter->get_extra_graph_size();
|
||||
}
|
||||
return ggml_new_graph_custom(compute_ctx, graph_size, false);
|
||||
}
|
||||
|
||||
struct ggml_cgraph* get_compute_graph(get_graph_cb_t get_graph) {
|
||||
prepare_build_in_tensor_before();
|
||||
struct ggml_cgraph* gf = get_graph();
|
||||
auto result = ggml_graph_node(gf, -1);
|
||||
ggml_set_name(result, final_result_name.c_str());
|
||||
if (ggml_graph_n_nodes(gf) > 0) {
|
||||
auto result = ggml_graph_node(gf, -1);
|
||||
ggml_set_name(result, final_result_name.c_str());
|
||||
}
|
||||
prepare_build_in_tensor_after(gf);
|
||||
return gf;
|
||||
}
|
||||
@@ -1758,6 +1816,7 @@ public:
|
||||
runner_ctx.backend = runtime_backend;
|
||||
runner_ctx.flash_attn_enabled = flash_attn_enabled;
|
||||
runner_ctx.conv2d_direct_enabled = conv2d_direct_enabled;
|
||||
runner_ctx.weight_adapter = weight_adapter;
|
||||
return runner_ctx;
|
||||
}
|
||||
|
||||
@@ -1889,6 +1948,10 @@ public:
|
||||
void set_conv2d_direct_enabled(bool enabled) {
|
||||
conv2d_direct_enabled = enabled;
|
||||
}
|
||||
|
||||
void set_weight_adapter(const std::shared_ptr<WeightAdapter>& adapter) {
|
||||
weight_adapter = adapter;
|
||||
}
|
||||
};
|
||||
|
||||
class GGMLBlock {
|
||||
@@ -2004,8 +2067,10 @@ protected:
|
||||
bool force_f32;
|
||||
bool force_prec_f32;
|
||||
float scale;
|
||||
std::string prefix;
|
||||
|
||||
void init_params(struct ggml_context* ctx, const String2TensorStorage& tensor_storage_map = {}, const std::string prefix = "") override {
|
||||
this->prefix = prefix;
|
||||
enum ggml_type wtype = get_type(prefix + "weight", tensor_storage_map, GGML_TYPE_F32);
|
||||
if (in_features % ggml_blck_size(wtype) != 0 || force_f32) {
|
||||
wtype = GGML_TYPE_F32;
|
||||
@@ -2037,6 +2102,13 @@ public:
|
||||
if (bias) {
|
||||
b = params["bias"];
|
||||
}
|
||||
if (ctx->weight_adapter) {
|
||||
WeightAdapter::ForwardParams forward_params;
|
||||
forward_params.op_type = WeightAdapter::ForwardParams::op_type_t::OP_LINEAR;
|
||||
forward_params.linear.force_prec_f32 = force_prec_f32;
|
||||
forward_params.linear.scale = scale;
|
||||
return ctx->weight_adapter->forward_with_lora(ctx->ggml_ctx, x, w, b, prefix, forward_params);
|
||||
}
|
||||
return ggml_ext_linear(ctx->ggml_ctx, x, w, b, force_prec_f32, scale);
|
||||
}
|
||||
};
|
||||
@@ -2096,8 +2168,10 @@ protected:
|
||||
std::pair<int, int> dilation;
|
||||
bool bias;
|
||||
float scale = 1.f;
|
||||
std::string prefix;
|
||||
|
||||
void init_params(struct ggml_context* ctx, const String2TensorStorage& tensor_storage_map, const std::string prefix = "") override {
|
||||
this->prefix = prefix;
|
||||
enum ggml_type wtype = GGML_TYPE_F16;
|
||||
params["weight"] = ggml_new_tensor_4d(ctx, wtype, kernel_size.second, kernel_size.first, in_channels, out_channels);
|
||||
if (bias) {
|
||||
@@ -2136,6 +2210,19 @@ public:
|
||||
if (bias) {
|
||||
b = params["bias"];
|
||||
}
|
||||
if (ctx->weight_adapter) {
|
||||
WeightAdapter::ForwardParams forward_params;
|
||||
forward_params.op_type = WeightAdapter::ForwardParams::op_type_t::OP_CONV2D;
|
||||
forward_params.conv2d.s0 = stride.second;
|
||||
forward_params.conv2d.s1 = stride.first;
|
||||
forward_params.conv2d.p0 = padding.second;
|
||||
forward_params.conv2d.p1 = padding.first;
|
||||
forward_params.conv2d.d0 = dilation.second;
|
||||
forward_params.conv2d.d1 = dilation.first;
|
||||
forward_params.conv2d.direct = ctx->conv2d_direct_enabled;
|
||||
forward_params.conv2d.scale = scale;
|
||||
return ctx->weight_adapter->forward_with_lora(ctx->ggml_ctx, x, w, b, prefix, forward_params);
|
||||
}
|
||||
return ggml_ext_conv_2d(ctx->ggml_ctx,
|
||||
x,
|
||||
w,
|
||||
@@ -2207,8 +2294,10 @@ protected:
|
||||
std::tuple<int, int, int> padding;
|
||||
std::tuple<int, int, int> dilation;
|
||||
bool bias;
|
||||
std::string prefix;
|
||||
|
||||
void init_params(struct ggml_context* ctx, const String2TensorStorage& tensor_storage_map, const std::string prefix = "") override {
|
||||
this->prefix = prefix;
|
||||
enum ggml_type wtype = GGML_TYPE_F16;
|
||||
params["weight"] = ggml_new_tensor_4d(ctx,
|
||||
wtype,
|
||||
@@ -2240,8 +2329,17 @@ public:
|
||||
struct ggml_tensor* forward(GGMLRunnerContext* ctx, struct ggml_tensor* x) {
|
||||
struct ggml_tensor* w = params["weight"];
|
||||
struct ggml_tensor* b = nullptr;
|
||||
if (ctx->weight_adapter) {
|
||||
w = ctx->weight_adapter->patch_weight(ctx->ggml_ctx, w, prefix + "weight");
|
||||
if (w->type != GGML_TYPE_F16) {
|
||||
w = ggml_cast(ctx->ggml_ctx, w, GGML_TYPE_F16);
|
||||
}
|
||||
}
|
||||
if (bias) {
|
||||
b = params["bias"];
|
||||
if (ctx->weight_adapter) {
|
||||
b = ctx->weight_adapter->patch_weight(ctx->ggml_ctx, b, prefix + "bias");
|
||||
}
|
||||
}
|
||||
return ggml_ext_conv_3d(ctx->ggml_ctx, x, w, b, in_channels,
|
||||
std::get<2>(stride), std::get<1>(stride), std::get<0>(stride),
|
||||
@@ -2256,8 +2354,10 @@ protected:
|
||||
float eps;
|
||||
bool elementwise_affine;
|
||||
bool bias;
|
||||
std::string prefix;
|
||||
|
||||
void init_params(struct ggml_context* ctx, const String2TensorStorage& tensor_storage_map = {}, const std::string prefix = "") override {
|
||||
this->prefix = prefix;
|
||||
if (elementwise_affine) {
|
||||
enum ggml_type wtype = GGML_TYPE_F32;
|
||||
params["weight"] = ggml_new_tensor_1d(ctx, wtype, normalized_shape);
|
||||
@@ -2284,8 +2384,14 @@ public:
|
||||
|
||||
if (elementwise_affine) {
|
||||
w = params["weight"];
|
||||
if (ctx->weight_adapter) {
|
||||
w = ctx->weight_adapter->patch_weight(ctx->ggml_ctx, w, prefix + "weight");
|
||||
}
|
||||
if (bias) {
|
||||
b = params["bias"];
|
||||
if (ctx->weight_adapter) {
|
||||
b = ctx->weight_adapter->patch_weight(ctx->ggml_ctx, b, prefix + "bias");
|
||||
}
|
||||
}
|
||||
}
|
||||
return ggml_ext_layer_norm(ctx->ggml_ctx, x, w, b, eps);
|
||||
@@ -2298,8 +2404,10 @@ protected:
|
||||
int64_t num_channels;
|
||||
float eps;
|
||||
bool affine;
|
||||
std::string prefix;
|
||||
|
||||
void init_params(struct ggml_context* ctx, const String2TensorStorage& tensor_storage_map = {}, const std::string prefix = "") override {
|
||||
this->prefix = prefix;
|
||||
if (affine) {
|
||||
enum ggml_type wtype = GGML_TYPE_F32;
|
||||
enum ggml_type bias_wtype = GGML_TYPE_F32;
|
||||
@@ -2324,6 +2432,10 @@ public:
|
||||
if (affine) {
|
||||
w = params["weight"];
|
||||
b = params["bias"];
|
||||
if (ctx->weight_adapter) {
|
||||
w = ctx->weight_adapter->patch_weight(ctx->ggml_ctx, w, prefix + "weight");
|
||||
b = ctx->weight_adapter->patch_weight(ctx->ggml_ctx, b, prefix + "bias");
|
||||
}
|
||||
}
|
||||
return ggml_ext_group_norm(ctx->ggml_ctx, x, w, b, num_groups);
|
||||
}
|
||||
@@ -2339,8 +2451,10 @@ class RMSNorm : public UnaryBlock {
|
||||
protected:
|
||||
int64_t hidden_size;
|
||||
float eps;
|
||||
std::string prefix;
|
||||
|
||||
void init_params(struct ggml_context* ctx, const String2TensorStorage& tensor_storage_map = {}, std::string prefix = "") override {
|
||||
this->prefix = prefix;
|
||||
enum ggml_type wtype = GGML_TYPE_F32;
|
||||
params["weight"] = ggml_new_tensor_1d(ctx, wtype, hidden_size);
|
||||
}
|
||||
@@ -2353,8 +2467,11 @@ public:
|
||||
|
||||
struct ggml_tensor* forward(GGMLRunnerContext* ctx, struct ggml_tensor* x) {
|
||||
struct ggml_tensor* w = params["weight"];
|
||||
x = ggml_rms_norm(ctx->ggml_ctx, x, eps);
|
||||
x = ggml_mul_inplace(ctx->ggml_ctx, x, w);
|
||||
if (ctx->weight_adapter) {
|
||||
w = ctx->weight_adapter->patch_weight(ctx->ggml_ctx, w, prefix + "weight");
|
||||
}
|
||||
x = ggml_rms_norm(ctx->ggml_ctx, x, eps);
|
||||
x = ggml_mul_inplace(ctx->ggml_ctx, x, w);
|
||||
return x;
|
||||
}
|
||||
};
|
||||
|
||||
@@ -870,7 +870,7 @@ struct MMDiTRunner : public GGMLRunner {
|
||||
struct ggml_tensor* context,
|
||||
struct ggml_tensor* y,
|
||||
std::vector<int> skip_layers = std::vector<int>()) {
|
||||
struct ggml_cgraph* gf = ggml_new_graph_custom(compute_ctx, MMDIT_GRAPH_SIZE, false);
|
||||
struct ggml_cgraph* gf = new_graph_custom(MMDIT_GRAPH_SIZE);
|
||||
|
||||
x = to_backend(x);
|
||||
context = to_backend(context);
|
||||
@@ -961,7 +961,7 @@ struct MMDiTRunner : public GGMLRunner {
|
||||
mmdit->get_param_tensors(tensors, "model.diffusion_model");
|
||||
|
||||
ModelLoader model_loader;
|
||||
if (!model_loader.init_from_file(file_path)) {
|
||||
if (!model_loader.init_from_file_and_convert_name(file_path)) {
|
||||
LOG_ERROR("init model loader from file failed: '%s'", file_path.c_str());
|
||||
return;
|
||||
}
|
||||
|
||||
@@ -25,6 +25,7 @@
|
||||
#include "ggml-cpu.h"
|
||||
#include "ggml.h"
|
||||
|
||||
#include "name_conversion.h"
|
||||
#include "stable-diffusion.h"
|
||||
|
||||
#ifdef SD_USE_METAL
|
||||
@@ -75,15 +76,6 @@ uint16_t read_short(uint8_t* buffer) {
|
||||
|
||||
/*================================================= Preprocess ==================================================*/
|
||||
|
||||
std::string self_attn_names[] = {
|
||||
"self_attn.q_proj.weight",
|
||||
"self_attn.k_proj.weight",
|
||||
"self_attn.v_proj.weight",
|
||||
"self_attn.q_proj.bias",
|
||||
"self_attn.k_proj.bias",
|
||||
"self_attn.v_proj.bias",
|
||||
};
|
||||
|
||||
const char* unused_tensors[] = {
|
||||
"betas",
|
||||
"alphas_cumprod_prev",
|
||||
@@ -97,9 +89,9 @@ const char* unused_tensors[] = {
|
||||
"posterior_mean_coef1",
|
||||
"posterior_mean_coef2",
|
||||
"cond_stage_model.transformer.text_model.embeddings.position_ids",
|
||||
"cond_stage_model.1.model.text_model.embeddings.position_ids",
|
||||
"cond_stage_model.transformer.vision_model.embeddings.position_ids",
|
||||
"cond_stage_model.model.logit_scale",
|
||||
"cond_stage_model.model.text_projection",
|
||||
"conditioner.embedders.0.transformer.text_model.embeddings.position_ids",
|
||||
"conditioner.embedders.0.model.logit_scale",
|
||||
"conditioner.embedders.1.model.logit_scale",
|
||||
@@ -110,6 +102,7 @@ const char* unused_tensors[] = {
|
||||
"model_ema.diffusion_model",
|
||||
"embedding_manager",
|
||||
"denoiser.sigmas",
|
||||
"edm_vpred.sigma_max",
|
||||
"text_encoders.t5xxl.transformer.encoder.embed_tokens.weight", // only used during training
|
||||
"text_encoders.qwen2vl.output.weight",
|
||||
"text_encoders.qwen2vl.lm_head.",
|
||||
@@ -124,622 +117,6 @@ bool is_unused_tensor(std::string name) {
|
||||
return false;
|
||||
}
|
||||
|
||||
std::unordered_map<std::string, std::string> open_clip_to_hf_clip_model = {
|
||||
{"model.ln_final.bias", "transformer.text_model.final_layer_norm.bias"},
|
||||
{"model.ln_final.weight", "transformer.text_model.final_layer_norm.weight"},
|
||||
{"model.positional_embedding", "transformer.text_model.embeddings.position_embedding.weight"},
|
||||
{"model.token_embedding.weight", "transformer.text_model.embeddings.token_embedding.weight"},
|
||||
{"model.text_projection", "transformer.text_model.text_projection"},
|
||||
{"model.visual.class_embedding", "transformer.vision_model.embeddings.class_embedding"},
|
||||
{"model.visual.conv1.weight", "transformer.vision_model.embeddings.patch_embedding.weight"},
|
||||
{"model.visual.ln_post.bias", "transformer.vision_model.post_layernorm.bias"},
|
||||
{"model.visual.ln_post.weight", "transformer.vision_model.post_layernorm.weight"},
|
||||
{"model.visual.ln_pre.bias", "transformer.vision_model.pre_layernorm.bias"},
|
||||
{"model.visual.ln_pre.weight", "transformer.vision_model.pre_layernorm.weight"},
|
||||
{"model.visual.positional_embedding", "transformer.vision_model.embeddings.position_embedding.weight"},
|
||||
{"model.visual.proj", "transformer.visual_projection.weight"},
|
||||
};
|
||||
|
||||
std::unordered_map<std::string, std::string> open_clip_to_hf_clip_resblock = {
|
||||
{"attn.in_proj_bias", "self_attn.in_proj.bias"},
|
||||
{"attn.in_proj_weight", "self_attn.in_proj.weight"},
|
||||
{"attn.out_proj.bias", "self_attn.out_proj.bias"},
|
||||
{"attn.out_proj.weight", "self_attn.out_proj.weight"},
|
||||
{"ln_1.bias", "layer_norm1.bias"},
|
||||
{"ln_1.weight", "layer_norm1.weight"},
|
||||
{"ln_2.bias", "layer_norm2.bias"},
|
||||
{"ln_2.weight", "layer_norm2.weight"},
|
||||
{"mlp.c_fc.bias", "mlp.fc1.bias"},
|
||||
{"mlp.c_fc.weight", "mlp.fc1.weight"},
|
||||
{"mlp.c_proj.bias", "mlp.fc2.bias"},
|
||||
{"mlp.c_proj.weight", "mlp.fc2.weight"},
|
||||
};
|
||||
|
||||
std::unordered_map<std::string, std::string> cond_model_name_map = {
|
||||
{"transformer.vision_model.pre_layrnorm.weight", "transformer.vision_model.pre_layernorm.weight"},
|
||||
{"transformer.vision_model.pre_layrnorm.bias", "transformer.vision_model.pre_layernorm.bias"},
|
||||
};
|
||||
|
||||
std::unordered_map<std::string, std::string> vae_decoder_name_map = {
|
||||
{"first_stage_model.decoder.mid.attn_1.to_k.bias", "first_stage_model.decoder.mid.attn_1.k.bias"},
|
||||
{"first_stage_model.decoder.mid.attn_1.to_k.weight", "first_stage_model.decoder.mid.attn_1.k.weight"},
|
||||
{"first_stage_model.decoder.mid.attn_1.to_out.0.bias", "first_stage_model.decoder.mid.attn_1.proj_out.bias"},
|
||||
{"first_stage_model.decoder.mid.attn_1.to_out.0.weight", "first_stage_model.decoder.mid.attn_1.proj_out.weight"},
|
||||
{"first_stage_model.decoder.mid.attn_1.to_q.bias", "first_stage_model.decoder.mid.attn_1.q.bias"},
|
||||
{"first_stage_model.decoder.mid.attn_1.to_q.weight", "first_stage_model.decoder.mid.attn_1.q.weight"},
|
||||
{"first_stage_model.decoder.mid.attn_1.to_v.bias", "first_stage_model.decoder.mid.attn_1.v.bias"},
|
||||
{"first_stage_model.decoder.mid.attn_1.to_v.weight", "first_stage_model.decoder.mid.attn_1.v.weight"},
|
||||
};
|
||||
|
||||
std::unordered_map<std::string, std::string> pmid_v2_name_map = {
|
||||
{"pmid.qformer_perceiver.perceiver_resampler.layers.0.1.1.weight",
|
||||
"pmid.qformer_perceiver.perceiver_resampler.layers.0.1.1.fc1.weight"},
|
||||
{"pmid.qformer_perceiver.perceiver_resampler.layers.0.1.3.weight",
|
||||
"pmid.qformer_perceiver.perceiver_resampler.layers.0.1.1.fc2.weight"},
|
||||
{"pmid.qformer_perceiver.perceiver_resampler.layers.1.1.1.weight",
|
||||
"pmid.qformer_perceiver.perceiver_resampler.layers.1.1.1.fc1.weight"},
|
||||
{"pmid.qformer_perceiver.perceiver_resampler.layers.1.1.3.weight",
|
||||
"pmid.qformer_perceiver.perceiver_resampler.layers.1.1.1.fc2.weight"},
|
||||
{"pmid.qformer_perceiver.perceiver_resampler.layers.2.1.1.weight",
|
||||
"pmid.qformer_perceiver.perceiver_resampler.layers.2.1.1.fc1.weight"},
|
||||
{"pmid.qformer_perceiver.perceiver_resampler.layers.2.1.3.weight",
|
||||
"pmid.qformer_perceiver.perceiver_resampler.layers.2.1.1.fc2.weight"},
|
||||
{"pmid.qformer_perceiver.perceiver_resampler.layers.3.1.1.weight",
|
||||
"pmid.qformer_perceiver.perceiver_resampler.layers.3.1.1.fc1.weight"},
|
||||
{"pmid.qformer_perceiver.perceiver_resampler.layers.3.1.3.weight",
|
||||
"pmid.qformer_perceiver.perceiver_resampler.layers.3.1.1.fc2.weight"},
|
||||
{"pmid.qformer_perceiver.token_proj.0.bias",
|
||||
"pmid.qformer_perceiver.token_proj.fc1.bias"},
|
||||
{"pmid.qformer_perceiver.token_proj.2.bias",
|
||||
"pmid.qformer_perceiver.token_proj.fc2.bias"},
|
||||
{"pmid.qformer_perceiver.token_proj.0.weight",
|
||||
"pmid.qformer_perceiver.token_proj.fc1.weight"},
|
||||
{"pmid.qformer_perceiver.token_proj.2.weight",
|
||||
"pmid.qformer_perceiver.token_proj.fc2.weight"},
|
||||
};
|
||||
|
||||
std::unordered_map<std::string, std::string> qwenvl_name_map{
|
||||
{"token_embd.", "model.embed_tokens."},
|
||||
{"blk.", "model.layers."},
|
||||
{"attn_q.", "self_attn.q_proj."},
|
||||
{"attn_k.", "self_attn.k_proj."},
|
||||
{"attn_v.", "self_attn.v_proj."},
|
||||
{"attn_output.", "self_attn.o_proj."},
|
||||
{"attn_norm.", "input_layernorm."},
|
||||
{"ffn_down.", "mlp.down_proj."},
|
||||
{"ffn_gate.", "mlp.gate_proj."},
|
||||
{"ffn_up.", "mlp.up_proj."},
|
||||
{"ffn_norm.", "post_attention_layernorm."},
|
||||
{"output_norm.", "model.norm."},
|
||||
};
|
||||
|
||||
std::unordered_map<std::string, std::string> qwenvl_vision_name_map{
|
||||
{"mm.", "merger.mlp."},
|
||||
{"v.post_ln.", "merger.ln_q."},
|
||||
{"v.patch_embd.weight", "patch_embed.proj.0.weight"},
|
||||
{"patch_embed.proj.0.weight.1", "patch_embed.proj.1.weight"},
|
||||
{"v.patch_embd.weight.1", "patch_embed.proj.1.weight"},
|
||||
{"v.blk.", "blocks."},
|
||||
{"attn_q.", "attn.q_proj."},
|
||||
{"attn_k.", "attn.k_proj."},
|
||||
{"attn_v.", "attn.v_proj."},
|
||||
{"attn_out.", "attn.proj."},
|
||||
{"ffn_down.", "mlp.down_proj."},
|
||||
{"ffn_gate.", "mlp.gate_proj."},
|
||||
{"ffn_up.", "mlp.up_proj."},
|
||||
{"ln1.", "norm1."},
|
||||
{"ln2.", "norm2."},
|
||||
};
|
||||
|
||||
std::string convert_cond_model_name(const std::string& name) {
|
||||
std::string new_name = name;
|
||||
std::string prefix;
|
||||
if (contains(new_name, ".enc.")) {
|
||||
// llama.cpp naming convention for T5
|
||||
size_t pos = new_name.find(".enc.");
|
||||
if (pos != std::string::npos) {
|
||||
new_name.replace(pos, 5, ".encoder.");
|
||||
}
|
||||
pos = new_name.find("blk.");
|
||||
if (pos != std::string::npos) {
|
||||
new_name.replace(pos, 4, "block.");
|
||||
}
|
||||
pos = new_name.find("output_norm.");
|
||||
if (pos != std::string::npos) {
|
||||
new_name.replace(pos, 12, "final_layer_norm.");
|
||||
}
|
||||
pos = new_name.find("attn_k.");
|
||||
if (pos != std::string::npos) {
|
||||
new_name.replace(pos, 7, "layer.0.SelfAttention.k.");
|
||||
}
|
||||
pos = new_name.find("attn_v.");
|
||||
if (pos != std::string::npos) {
|
||||
new_name.replace(pos, 7, "layer.0.SelfAttention.v.");
|
||||
}
|
||||
pos = new_name.find("attn_o.");
|
||||
if (pos != std::string::npos) {
|
||||
new_name.replace(pos, 7, "layer.0.SelfAttention.o.");
|
||||
}
|
||||
pos = new_name.find("attn_q.");
|
||||
if (pos != std::string::npos) {
|
||||
new_name.replace(pos, 7, "layer.0.SelfAttention.q.");
|
||||
}
|
||||
pos = new_name.find("attn_norm.");
|
||||
if (pos != std::string::npos) {
|
||||
new_name.replace(pos, 10, "layer.0.layer_norm.");
|
||||
}
|
||||
pos = new_name.find("ffn_norm.");
|
||||
if (pos != std::string::npos) {
|
||||
new_name.replace(pos, 9, "layer.1.layer_norm.");
|
||||
}
|
||||
pos = new_name.find("ffn_up.");
|
||||
if (pos != std::string::npos) {
|
||||
new_name.replace(pos, 7, "layer.1.DenseReluDense.wi_1.");
|
||||
}
|
||||
pos = new_name.find("ffn_down.");
|
||||
if (pos != std::string::npos) {
|
||||
new_name.replace(pos, 9, "layer.1.DenseReluDense.wo.");
|
||||
}
|
||||
pos = new_name.find("ffn_gate.");
|
||||
if (pos != std::string::npos) {
|
||||
new_name.replace(pos, 9, "layer.1.DenseReluDense.wi_0.");
|
||||
}
|
||||
pos = new_name.find("attn_rel_b.");
|
||||
if (pos != std::string::npos) {
|
||||
new_name.replace(pos, 11, "layer.0.SelfAttention.relative_attention_bias.");
|
||||
}
|
||||
} else if (contains(name, "qwen2vl")) {
|
||||
if (contains(name, "qwen2vl.visual")) {
|
||||
for (auto kv : qwenvl_vision_name_map) {
|
||||
size_t pos = new_name.find(kv.first);
|
||||
if (pos != std::string::npos) {
|
||||
new_name.replace(pos, kv.first.size(), kv.second);
|
||||
}
|
||||
}
|
||||
} else {
|
||||
for (auto kv : qwenvl_name_map) {
|
||||
size_t pos = new_name.find(kv.first);
|
||||
if (pos != std::string::npos) {
|
||||
new_name.replace(pos, kv.first.size(), kv.second);
|
||||
}
|
||||
}
|
||||
}
|
||||
} else if (name == "text_encoders.t5xxl.transformer.token_embd.weight") {
|
||||
new_name = "text_encoders.t5xxl.transformer.shared.weight";
|
||||
}
|
||||
|
||||
if (starts_with(new_name, "conditioner.embedders.0.open_clip.")) {
|
||||
prefix = "cond_stage_model.";
|
||||
new_name = new_name.substr(strlen("conditioner.embedders.0.open_clip."));
|
||||
} else if (starts_with(new_name, "conditioner.embedders.0.")) {
|
||||
prefix = "cond_stage_model.";
|
||||
new_name = new_name.substr(strlen("conditioner.embedders.0."));
|
||||
} else if (starts_with(new_name, "conditioner.embedders.1.")) {
|
||||
prefix = "cond_stage_model.1.";
|
||||
new_name = new_name.substr(strlen("conditioner.embedders.0."));
|
||||
} else if (starts_with(new_name, "cond_stage_model.")) {
|
||||
prefix = "cond_stage_model.";
|
||||
new_name = new_name.substr(strlen("cond_stage_model."));
|
||||
} else if (ends_with(new_name, "vision_model.visual_projection.weight")) {
|
||||
prefix = new_name.substr(0, new_name.size() - strlen("vision_model.visual_projection.weight"));
|
||||
new_name = prefix + "visual_projection.weight";
|
||||
return new_name;
|
||||
} else if (ends_with(new_name, "transformer.text_projection.weight")) {
|
||||
prefix = new_name.substr(0, new_name.size() - strlen("transformer.text_projection.weight"));
|
||||
new_name = prefix + "transformer.text_model.text_projection";
|
||||
return new_name;
|
||||
} else {
|
||||
return new_name;
|
||||
}
|
||||
|
||||
if (new_name == "model.text_projection.weight") {
|
||||
new_name = "transformer.text_model.text_projection";
|
||||
}
|
||||
|
||||
if (open_clip_to_hf_clip_model.find(new_name) != open_clip_to_hf_clip_model.end()) {
|
||||
new_name = open_clip_to_hf_clip_model[new_name];
|
||||
}
|
||||
|
||||
if (cond_model_name_map.find(new_name) != cond_model_name_map.end()) {
|
||||
new_name = cond_model_name_map[new_name];
|
||||
}
|
||||
|
||||
std::string open_clip_resblock_prefix = "model.transformer.resblocks.";
|
||||
std::string hf_clip_resblock_prefix = "transformer.text_model.encoder.layers.";
|
||||
|
||||
auto replace_suffix = [&]() {
|
||||
if (new_name.find(open_clip_resblock_prefix) == 0) {
|
||||
std::string remain = new_name.substr(open_clip_resblock_prefix.length());
|
||||
std::string idx = remain.substr(0, remain.find("."));
|
||||
std::string suffix = remain.substr(idx.length() + 1);
|
||||
|
||||
if (open_clip_to_hf_clip_resblock.find(suffix) != open_clip_to_hf_clip_resblock.end()) {
|
||||
std::string new_suffix = open_clip_to_hf_clip_resblock[suffix];
|
||||
new_name = hf_clip_resblock_prefix + idx + "." + new_suffix;
|
||||
}
|
||||
}
|
||||
};
|
||||
|
||||
replace_suffix();
|
||||
|
||||
open_clip_resblock_prefix = "model.visual.transformer.resblocks.";
|
||||
hf_clip_resblock_prefix = "transformer.vision_model.encoder.layers.";
|
||||
|
||||
replace_suffix();
|
||||
|
||||
return prefix + new_name;
|
||||
}
|
||||
|
||||
std::string convert_vae_decoder_name(const std::string& name) {
|
||||
if (vae_decoder_name_map.find(name) != vae_decoder_name_map.end()) {
|
||||
return vae_decoder_name_map[name];
|
||||
}
|
||||
return name;
|
||||
}
|
||||
|
||||
std::string convert_pmid_v2_name(const std::string& name) {
|
||||
if (pmid_v2_name_map.find(name) != pmid_v2_name_map.end()) {
|
||||
return pmid_v2_name_map[name];
|
||||
}
|
||||
return name;
|
||||
}
|
||||
|
||||
/* If not a SDXL LoRA the unet" prefix will have already been replaced by this
|
||||
* point and "te2" and "te1" don't seem to appear in non-SDXL only "te_" */
|
||||
std::string convert_sdxl_lora_name(std::string tensor_name) {
|
||||
const std::pair<std::string, std::string> sdxl_lora_name_lookup[] = {
|
||||
{"unet", "model_diffusion_model"},
|
||||
{"te2", "cond_stage_model_1_transformer"},
|
||||
{"te1", "cond_stage_model_transformer"},
|
||||
{"text_encoder_2", "cond_stage_model_1_transformer"},
|
||||
{"text_encoder", "cond_stage_model_transformer"},
|
||||
};
|
||||
for (auto& pair_i : sdxl_lora_name_lookup) {
|
||||
if (tensor_name.compare(0, pair_i.first.length(), pair_i.first) == 0) {
|
||||
tensor_name = std::regex_replace(tensor_name, std::regex(pair_i.first), pair_i.second);
|
||||
break;
|
||||
}
|
||||
}
|
||||
return tensor_name;
|
||||
}
|
||||
|
||||
std::unordered_map<std::string, std::unordered_map<std::string, std::string>> suffix_conversion_underline = {
|
||||
{
|
||||
"attentions",
|
||||
{
|
||||
{"to_k", "k"},
|
||||
{"to_q", "q"},
|
||||
{"to_v", "v"},
|
||||
{"to_out_0", "proj_out"},
|
||||
{"group_norm", "norm"},
|
||||
{"key", "k"},
|
||||
{"query", "q"},
|
||||
{"value", "v"},
|
||||
{"proj_attn", "proj_out"},
|
||||
},
|
||||
},
|
||||
{
|
||||
"resnets",
|
||||
{
|
||||
{"conv1", "in_layers_2"},
|
||||
{"conv2", "out_layers_3"},
|
||||
{"norm1", "in_layers_0"},
|
||||
{"norm2", "out_layers_0"},
|
||||
{"time_emb_proj", "emb_layers_1"},
|
||||
{"conv_shortcut", "skip_connection"},
|
||||
},
|
||||
},
|
||||
};
|
||||
|
||||
std::unordered_map<std::string, std::unordered_map<std::string, std::string>> suffix_conversion_dot = {
|
||||
{
|
||||
"attentions",
|
||||
{
|
||||
{"to_k", "k"},
|
||||
{"to_q", "q"},
|
||||
{"to_v", "v"},
|
||||
{"to_out.0", "proj_out"},
|
||||
{"group_norm", "norm"},
|
||||
{"key", "k"},
|
||||
{"query", "q"},
|
||||
{"value", "v"},
|
||||
{"proj_attn", "proj_out"},
|
||||
},
|
||||
},
|
||||
{
|
||||
"resnets",
|
||||
{
|
||||
{"conv1", "in_layers.2"},
|
||||
{"conv2", "out_layers.3"},
|
||||
{"norm1", "in_layers.0"},
|
||||
{"norm2", "out_layers.0"},
|
||||
{"time_emb_proj", "emb_layers.1"},
|
||||
{"conv_shortcut", "skip_connection"},
|
||||
},
|
||||
},
|
||||
};
|
||||
|
||||
std::string convert_diffusers_name_to_compvis(std::string key, char seq) {
|
||||
std::vector<std::string> m;
|
||||
|
||||
auto match = [](std::vector<std::string>& match_list, const std::regex& regex, const std::string& key) {
|
||||
auto r = std::smatch{};
|
||||
if (!std::regex_match(key, r, regex)) {
|
||||
return false;
|
||||
}
|
||||
|
||||
match_list.clear();
|
||||
for (size_t i = 1; i < r.size(); ++i) {
|
||||
match_list.push_back(r.str(i));
|
||||
}
|
||||
return true;
|
||||
};
|
||||
|
||||
std::unordered_map<std::string, std::unordered_map<std::string, std::string>> suffix_conversion;
|
||||
if (seq == '_') {
|
||||
suffix_conversion = suffix_conversion_underline;
|
||||
} else {
|
||||
suffix_conversion = suffix_conversion_dot;
|
||||
}
|
||||
|
||||
auto get_converted_suffix = [&suffix_conversion](const std::string& outer_key, const std::string& inner_key) {
|
||||
auto outer_iter = suffix_conversion.find(outer_key);
|
||||
if (outer_iter != suffix_conversion.end()) {
|
||||
auto inner_iter = outer_iter->second.find(inner_key);
|
||||
if (inner_iter != outer_iter->second.end()) {
|
||||
return inner_iter->second;
|
||||
}
|
||||
}
|
||||
return inner_key;
|
||||
};
|
||||
|
||||
// convert attn to out
|
||||
if (ends_with(key, "to_out")) {
|
||||
key += format("%c0", seq);
|
||||
}
|
||||
|
||||
// unet
|
||||
if (match(m, std::regex(format("unet%cconv_in(.*)", seq)), key)) {
|
||||
return format("model%cdiffusion_model%cinput_blocks%c0%c0", seq, seq, seq, seq) + m[0];
|
||||
}
|
||||
|
||||
if (match(m, std::regex(format("unet%cconv%cout(.*)", seq, seq)), key)) {
|
||||
return format("model%cdiffusion_model%cout%c2", seq, seq, seq) + m[0];
|
||||
}
|
||||
|
||||
if (match(m, std::regex(format("unet%cconv_norm_out(.*)", seq)), key)) {
|
||||
return format("model%cdiffusion_model%cout%c0", seq, seq, seq) + m[0];
|
||||
}
|
||||
|
||||
if (match(m, std::regex(format("unet%ctime_embedding%clinear_(\\d+)(.*)", seq, seq)), key)) {
|
||||
return format("model%cdiffusion_model%ctime_embed%c", seq, seq, seq) + std::to_string(std::stoi(m[0]) * 2 - 2) + m[1];
|
||||
}
|
||||
|
||||
if (match(m, std::regex(format("unet%cadd_embedding%clinear_(\\d+)(.*)", seq, seq)), key)) {
|
||||
return format("model%cdiffusion_model%clabel_emb%c0%c", seq, seq, seq, seq) + std::to_string(std::stoi(m[0]) * 2 - 2) + m[1];
|
||||
}
|
||||
|
||||
if (match(m, std::regex(format("unet%cdown_blocks%c(\\d+)%c(attentions|resnets)%c(\\d+)%c(.+)", seq, seq, seq, seq, seq)), key)) {
|
||||
std::string suffix = get_converted_suffix(m[1], m[3]);
|
||||
// LOG_DEBUG("%s %s %s %s", m[0].c_str(), m[1].c_str(), m[2].c_str(), m[3].c_str());
|
||||
return format("model%cdiffusion_model%cinput_blocks%c", seq, seq, seq) + std::to_string(1 + std::stoi(m[0]) * 3 + std::stoi(m[2])) + seq +
|
||||
(m[1] == "attentions" ? "1" : "0") + seq + suffix;
|
||||
}
|
||||
|
||||
if (match(m, std::regex(format("unet%cmid_block%c(attentions|resnets)%c(\\d+)%c(.+)", seq, seq, seq, seq)), key)) {
|
||||
std::string suffix = get_converted_suffix(m[0], m[2]);
|
||||
return format("model%cdiffusion_model%cmiddle_block%c", seq, seq, seq) + (m[0] == "attentions" ? "1" : std::to_string(std::stoi(m[1]) * 2)) +
|
||||
seq + suffix;
|
||||
}
|
||||
|
||||
if (match(m, std::regex(format("unet%cup_blocks%c(\\d+)%c(attentions|resnets)%c(\\d+)%c(.+)", seq, seq, seq, seq, seq)), key)) {
|
||||
std::string suffix = get_converted_suffix(m[1], m[3]);
|
||||
return format("model%cdiffusion_model%coutput_blocks%c", seq, seq, seq) + std::to_string(std::stoi(m[0]) * 3 + std::stoi(m[2])) + seq +
|
||||
(m[1] == "attentions" ? "1" : "0") + seq + suffix;
|
||||
}
|
||||
|
||||
if (match(m, std::regex(format("unet%cdown_blocks%c(\\d+)%cdownsamplers%c0%cconv", seq, seq, seq, seq, seq)), key)) {
|
||||
return format("model%cdiffusion_model%cinput_blocks%c", seq, seq, seq) + std::to_string(3 + std::stoi(m[0]) * 3) + seq + "0" + seq + "op";
|
||||
}
|
||||
|
||||
if (match(m, std::regex(format("unet%cup_blocks%c(\\d+)%cupsamplers%c0%cconv", seq, seq, seq, seq, seq)), key)) {
|
||||
return format("model%cdiffusion_model%coutput_blocks%c", seq, seq, seq) + std::to_string(2 + std::stoi(m[0]) * 3) + seq +
|
||||
(std::stoi(m[0]) > 0 ? "2" : "1") + seq + "conv";
|
||||
}
|
||||
|
||||
// clip
|
||||
if (match(m, std::regex(format("te%ctext_model%cencoder%clayers%c(\\d+)%c(.+)", seq, seq, seq, seq, seq)), key)) {
|
||||
return format("cond_stage_model%ctransformer%ctext_model%cencoder%clayers%c", seq, seq, seq, seq, seq) + m[0] + seq + m[1];
|
||||
}
|
||||
|
||||
if (match(m, std::regex(format("te%ctext_model(.*)", seq)), key)) {
|
||||
return format("cond_stage_model%ctransformer%ctext_model", seq, seq) + m[0];
|
||||
}
|
||||
|
||||
// clip-g
|
||||
if (match(m, std::regex(format("te%c1%ctext_model%cencoder%clayers%c(\\d+)%c(.+)", seq, seq, seq, seq, seq, seq)), key)) {
|
||||
return format("cond_stage_model%c1%ctransformer%ctext_model%cencoder%clayers%c", seq, seq, seq, seq, seq, seq) + m[0] + seq + m[1];
|
||||
}
|
||||
|
||||
if (match(m, std::regex(format("te%c1%ctext_model(.*)", seq, seq)), key)) {
|
||||
return format("cond_stage_model%c1%ctransformer%ctext_model", seq, seq, seq) + m[0];
|
||||
}
|
||||
|
||||
if (match(m, std::regex(format("te%c1%ctext_projection", seq, seq)), key)) {
|
||||
return format("cond_stage_model%c1%ctransformer%ctext_model%ctext_projection", seq, seq, seq, seq);
|
||||
}
|
||||
|
||||
// vae
|
||||
if (match(m, std::regex(format("vae%c(.*)%cconv_norm_out(.*)", seq, seq)), key)) {
|
||||
return format("first_stage_model%c%s%cnorm_out%s", seq, m[0].c_str(), seq, m[1].c_str());
|
||||
}
|
||||
|
||||
if (match(m, std::regex(format("vae%c(.*)%cmid_block%c(attentions|resnets)%c(\\d+)%c(.+)", seq, seq, seq, seq, seq)), key)) {
|
||||
std::string suffix;
|
||||
std::string block_name;
|
||||
if (m[1] == "attentions") {
|
||||
block_name = "attn";
|
||||
suffix = get_converted_suffix(m[1], m[3]);
|
||||
} else {
|
||||
block_name = "block";
|
||||
suffix = m[3];
|
||||
}
|
||||
return format("first_stage_model%c%s%cmid%c%s_%d%c%s",
|
||||
seq, m[0].c_str(), seq, seq, block_name.c_str(), std::stoi(m[2]) + 1, seq, suffix.c_str());
|
||||
}
|
||||
|
||||
if (match(m, std::regex(format("vae%c(.*)%cup_blocks%c(\\d+)%cresnets%c(\\d+)%c(.+)", seq, seq, seq, seq, seq, seq)), key)) {
|
||||
std::string suffix = m[3];
|
||||
if (suffix == "conv_shortcut") {
|
||||
suffix = "nin_shortcut";
|
||||
}
|
||||
return format("first_stage_model%c%s%cup%c%d%cblock%c%s%c%s",
|
||||
seq, m[0].c_str(), seq, seq, 3 - std::stoi(m[1]), seq, seq, m[2].c_str(), seq, suffix.c_str());
|
||||
}
|
||||
|
||||
if (match(m, std::regex(format("vae%c(.*)%cdown_blocks%c(\\d+)%cdownsamplers%c0%cconv", seq, seq, seq, seq, seq, seq)), key)) {
|
||||
return format("first_stage_model%c%s%cdown%c%d%cdownsample%cconv",
|
||||
seq, m[0].c_str(), seq, seq, std::stoi(m[1]), seq, seq);
|
||||
}
|
||||
|
||||
if (match(m, std::regex(format("vae%c(.*)%cdown_blocks%c(\\d+)%cresnets%c(\\d+)%c(.+)", seq, seq, seq, seq, seq, seq)), key)) {
|
||||
std::string suffix = m[3];
|
||||
if (suffix == "conv_shortcut") {
|
||||
suffix = "nin_shortcut";
|
||||
}
|
||||
return format("first_stage_model%c%s%cdown%c%d%cblock%c%s%c%s",
|
||||
seq, m[0].c_str(), seq, seq, std::stoi(m[1]), seq, seq, m[2].c_str(), seq, suffix.c_str());
|
||||
}
|
||||
|
||||
if (match(m, std::regex(format("vae%c(.*)%cup_blocks%c(\\d+)%cupsamplers%c0%cconv", seq, seq, seq, seq, seq, seq)), key)) {
|
||||
return format("first_stage_model%c%s%cup%c%d%cupsample%cconv",
|
||||
seq, m[0].c_str(), seq, seq, 3 - std::stoi(m[1]), seq, seq);
|
||||
}
|
||||
|
||||
if (match(m, std::regex(format("vae%c(.*)", seq)), key)) {
|
||||
return format("first_stage_model%c", seq) + m[0];
|
||||
}
|
||||
|
||||
return key;
|
||||
}
|
||||
|
||||
std::string convert_tensor_name(std::string name) {
|
||||
if (starts_with(name, "diffusion_model")) {
|
||||
name = "model." + name;
|
||||
}
|
||||
if (starts_with(name, "model.diffusion_model.up_blocks.0.attentions.0.")) {
|
||||
name.replace(0, sizeof("model.diffusion_model.up_blocks.0.attentions.0.") - 1,
|
||||
"model.diffusion_model.output_blocks.0.1.");
|
||||
}
|
||||
if (starts_with(name, "model.diffusion_model.up_blocks.0.attentions.1.")) {
|
||||
name.replace(0, sizeof("model.diffusion_model.up_blocks.0.attentions.1.") - 1,
|
||||
"model.diffusion_model.output_blocks.1.1.");
|
||||
}
|
||||
// size_t pos = name.find("lora_A");
|
||||
// if (pos != std::string::npos) {
|
||||
// name.replace(pos, strlen("lora_A"), "lora_up");
|
||||
// }
|
||||
// pos = name.find("lora_B");
|
||||
// if (pos != std::string::npos) {
|
||||
// name.replace(pos, strlen("lora_B"), "lora_down");
|
||||
// }
|
||||
std::string new_name = name;
|
||||
if (starts_with(name, "cond_stage_model.") ||
|
||||
starts_with(name, "conditioner.embedders.") ||
|
||||
starts_with(name, "text_encoders.") ||
|
||||
ends_with(name, ".vision_model.visual_projection.weight") ||
|
||||
starts_with(name, "qwen2vl")) {
|
||||
new_name = convert_cond_model_name(name);
|
||||
} else if (starts_with(name, "first_stage_model.decoder")) {
|
||||
new_name = convert_vae_decoder_name(name);
|
||||
} else if (starts_with(name, "pmid.qformer_perceiver")) {
|
||||
new_name = convert_pmid_v2_name(name);
|
||||
} else if (starts_with(name, "control_model.")) { // for controlnet pth models
|
||||
size_t pos = name.find('.');
|
||||
if (pos != std::string::npos) {
|
||||
new_name = name.substr(pos + 1);
|
||||
}
|
||||
} else if (starts_with(name, "lora_")) { // for lora
|
||||
size_t pos = name.find('.');
|
||||
if (pos != std::string::npos) {
|
||||
std::string name_without_network_parts = name.substr(5, pos - 5);
|
||||
std::string network_part = name.substr(pos + 1);
|
||||
|
||||
// LOG_DEBUG("%s %s", name_without_network_parts.c_str(), network_part.c_str());
|
||||
std::string new_key = convert_diffusers_name_to_compvis(name_without_network_parts, '_');
|
||||
/* For dealing with the new SDXL LoRA tensor naming convention */
|
||||
new_key = convert_sdxl_lora_name(new_key);
|
||||
|
||||
if (new_key.empty()) {
|
||||
new_name = name;
|
||||
} else {
|
||||
new_name = "lora." + new_key + "." + network_part;
|
||||
}
|
||||
} else {
|
||||
new_name = name;
|
||||
}
|
||||
} else if (ends_with(name, ".diff") || ends_with(name, ".diff_b")) {
|
||||
new_name = "lora." + name;
|
||||
} else if (contains(name, "lora_up") || contains(name, "lora_down") ||
|
||||
contains(name, "lora.up") || contains(name, "lora.down") ||
|
||||
contains(name, "lora_linear") || ends_with(name, ".alpha")) {
|
||||
size_t pos = new_name.find(".processor");
|
||||
if (pos != std::string::npos) {
|
||||
new_name.replace(pos, strlen(".processor"), "");
|
||||
}
|
||||
// if (starts_with(new_name, "transformer.transformer_blocks") || starts_with(new_name, "transformer.single_transformer_blocks")) {
|
||||
// new_name = "model.diffusion_model." + new_name;
|
||||
// }
|
||||
if (ends_with(name, ".alpha")) {
|
||||
pos = new_name.rfind("alpha");
|
||||
} else {
|
||||
pos = new_name.rfind("lora");
|
||||
}
|
||||
if (pos != std::string::npos) {
|
||||
std::string name_without_network_parts = new_name.substr(0, pos - 1);
|
||||
std::string network_part = new_name.substr(pos);
|
||||
// LOG_DEBUG("%s %s", name_without_network_parts.c_str(), network_part.c_str());
|
||||
std::string new_key = convert_diffusers_name_to_compvis(name_without_network_parts, '.');
|
||||
new_key = convert_sdxl_lora_name(new_key);
|
||||
replace_all_chars(new_key, '.', '_');
|
||||
size_t npos = network_part.rfind("_linear_layer");
|
||||
if (npos != std::string::npos) {
|
||||
network_part.replace(npos, strlen("_linear_layer"), "");
|
||||
}
|
||||
if (starts_with(network_part, "lora.")) {
|
||||
network_part = "lora_" + network_part.substr(5);
|
||||
}
|
||||
if (new_key.size() > 0) {
|
||||
new_name = "lora." + new_key + "." + network_part;
|
||||
}
|
||||
// LOG_DEBUG("new name: %s", new_name.c_str());
|
||||
}
|
||||
} else if (starts_with(name, "unet") || starts_with(name, "vae") || starts_with(name, "te")) { // for diffuser
|
||||
size_t pos = name.find_last_of('.');
|
||||
if (pos != std::string::npos) {
|
||||
std::string name_without_network_parts = name.substr(0, pos);
|
||||
std::string network_part = name.substr(pos + 1);
|
||||
// LOG_DEBUG("%s %s", name_without_network_parts.c_str(), network_part.c_str());
|
||||
std::string new_key = convert_diffusers_name_to_compvis(name_without_network_parts, '.');
|
||||
if (new_key.empty()) {
|
||||
new_name = name;
|
||||
} else if (new_key == "cond_stage_model.1.transformer.text_model.text_projection") {
|
||||
new_name = new_key;
|
||||
} else {
|
||||
new_name = new_key + "." + network_part;
|
||||
}
|
||||
} else {
|
||||
new_name = name;
|
||||
}
|
||||
} else {
|
||||
new_name = name;
|
||||
}
|
||||
// if (new_name != name) {
|
||||
// LOG_DEBUG("%s => %s", name.c_str(), new_name.c_str());
|
||||
// }
|
||||
return new_name;
|
||||
}
|
||||
|
||||
float bf16_to_f32(uint16_t bfloat16) {
|
||||
uint32_t val_bits = (static_cast<uint32_t>(bfloat16) << 16);
|
||||
return *reinterpret_cast<float*>(&val_bits);
|
||||
@@ -916,9 +293,7 @@ void convert_tensor(void* src,
|
||||
/*================================================= ModelLoader ==================================================*/
|
||||
|
||||
void ModelLoader::add_tensor_storage(const TensorStorage& tensor_storage) {
|
||||
TensorStorage copy = tensor_storage;
|
||||
copy.name = convert_tensor_name(copy.name);
|
||||
tensor_storage_map[copy.name] = std::move(copy);
|
||||
tensor_storage_map[tensor_storage.name] = tensor_storage;
|
||||
}
|
||||
|
||||
bool is_zip_file(const std::string& file_path) {
|
||||
@@ -1012,6 +387,31 @@ bool ModelLoader::init_from_file(const std::string& file_path, const std::string
|
||||
}
|
||||
}
|
||||
|
||||
void ModelLoader::convert_tensors_name() {
|
||||
SDVersion version = (version_ == VERSION_COUNT) ? get_sd_version() : version_;
|
||||
String2TensorStorage new_map;
|
||||
|
||||
for (auto& [_, tensor_storage] : tensor_storage_map) {
|
||||
auto new_name = convert_tensor_name(tensor_storage.name, version);
|
||||
// LOG_DEBUG("%s -> %s", tensor_storage.name.c_str(), new_name.c_str());
|
||||
tensor_storage.name = new_name;
|
||||
new_map[new_name] = std::move(tensor_storage);
|
||||
}
|
||||
|
||||
tensor_storage_map.swap(new_map);
|
||||
}
|
||||
|
||||
bool ModelLoader::init_from_file_and_convert_name(const std::string& file_path, const std::string& prefix, SDVersion version) {
|
||||
if (version_ == VERSION_COUNT && version != VERSION_COUNT) {
|
||||
version_ = version;
|
||||
}
|
||||
if (!init_from_file(file_path, prefix)) {
|
||||
return false;
|
||||
}
|
||||
convert_tensors_name();
|
||||
return true;
|
||||
}
|
||||
|
||||
/*================================================= GGUFModelLoader ==================================================*/
|
||||
|
||||
bool ModelLoader::init_from_gguf_file(const std::string& file_path, const std::string& prefix) {
|
||||
@@ -1259,32 +659,6 @@ bool ModelLoader::init_from_diffusers_file(const std::string& file_path, const s
|
||||
if (!init_from_safetensors_file(unet_path, "unet.")) {
|
||||
return false;
|
||||
}
|
||||
for (auto& [name, tensor_storage] : tensor_storage_map) {
|
||||
if (name.find("add_embedding") != std::string::npos || name.find("label_emb") != std::string::npos) {
|
||||
// probably SDXL
|
||||
LOG_DEBUG("Fixing name for SDXL output blocks.2.2");
|
||||
String2TensorStorage new_tensor_storage_map;
|
||||
|
||||
for (auto& [name, tensor_storage] : tensor_storage_map) {
|
||||
int len = 34;
|
||||
auto pos = tensor_storage.name.find("unet.up_blocks.0.upsamplers.0.conv");
|
||||
if (pos == std::string::npos) {
|
||||
len = 44;
|
||||
pos = tensor_storage.name.find("model.diffusion_model.output_blocks.2.1.conv");
|
||||
}
|
||||
if (pos != std::string::npos) {
|
||||
std::string new_name = "model.diffusion_model.output_blocks.2.2.conv" + name.substr(len);
|
||||
LOG_DEBUG("NEW NAME: %s", new_name.c_str());
|
||||
tensor_storage.name = new_name;
|
||||
new_tensor_storage_map[new_name] = tensor_storage;
|
||||
} else {
|
||||
new_tensor_storage_map[name] = tensor_storage;
|
||||
}
|
||||
}
|
||||
tensor_storage_map = new_tensor_storage_map;
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
if (!init_from_safetensors_file(vae_path, "vae.")) {
|
||||
LOG_WARN("Couldn't find working VAE in %s", file_path.c_str());
|
||||
@@ -1925,7 +1299,7 @@ bool ModelLoader::load_tensors(on_new_tensor_cb_t on_new_tensor_cb, int n_thread
|
||||
int64_t start_time = ggml_time_ms();
|
||||
|
||||
std::vector<TensorStorage> processed_tensor_storages;
|
||||
for (auto& [name, tensor_storage] : tensor_storage_map) {
|
||||
for (const auto& [name, tensor_storage] : tensor_storage_map) {
|
||||
if (is_unused_tensor(tensor_storage.name)) {
|
||||
continue;
|
||||
}
|
||||
@@ -2394,6 +1768,7 @@ bool convert(const char* input_path, const char* vae_path, const char* output_pa
|
||||
return false;
|
||||
}
|
||||
}
|
||||
model_loader.convert_tensors_name();
|
||||
bool success = model_loader.save_to_gguf_file(output_path, (ggml_type)output_type, tensor_type_rules);
|
||||
return success;
|
||||
}
|
||||
|
||||
@@ -15,6 +15,7 @@
|
||||
#include "ggml.h"
|
||||
#include "gguf.h"
|
||||
#include "json.hpp"
|
||||
#include "ordered_map.hpp"
|
||||
#include "zip.h"
|
||||
|
||||
#define SD_MAX_DIMS 5
|
||||
@@ -108,7 +109,11 @@ static inline bool sd_version_is_qwen_image(SDVersion version) {
|
||||
}
|
||||
|
||||
static inline bool sd_version_is_inpaint(SDVersion version) {
|
||||
if (version == VERSION_SD1_INPAINT || version == VERSION_SD2_INPAINT || version == VERSION_SDXL_INPAINT || version == VERSION_FLUX_FILL || version == VERSION_FLEX_2) {
|
||||
if (version == VERSION_SD1_INPAINT ||
|
||||
version == VERSION_SD2_INPAINT ||
|
||||
version == VERSION_SDXL_INPAINT ||
|
||||
version == VERSION_FLUX_FILL ||
|
||||
version == VERSION_FLEX_2) {
|
||||
return true;
|
||||
}
|
||||
return false;
|
||||
@@ -253,10 +258,11 @@ struct TensorStorage {
|
||||
|
||||
typedef std::function<bool(const TensorStorage&, ggml_tensor**)> on_new_tensor_cb_t;
|
||||
|
||||
typedef std::map<std::string, TensorStorage> String2TensorStorage;
|
||||
typedef OrderedMap<std::string, TensorStorage> String2TensorStorage;
|
||||
|
||||
class ModelLoader {
|
||||
protected:
|
||||
SDVersion version_ = VERSION_COUNT;
|
||||
std::vector<std::string> file_paths_;
|
||||
String2TensorStorage tensor_storage_map;
|
||||
|
||||
@@ -276,6 +282,10 @@ protected:
|
||||
|
||||
public:
|
||||
bool init_from_file(const std::string& file_path, const std::string& prefix = "");
|
||||
void convert_tensors_name();
|
||||
bool init_from_file_and_convert_name(const std::string& file_path,
|
||||
const std::string& prefix = "",
|
||||
SDVersion version = VERSION_COUNT);
|
||||
SDVersion get_sd_version();
|
||||
std::map<ggml_type, uint32_t> get_wtype_stat();
|
||||
std::map<ggml_type, uint32_t> get_conditioner_wtype_stat();
|
||||
|
||||
+1058
File diff suppressed because it is too large
Load Diff
@@ -0,0 +1,14 @@
|
||||
#ifndef __NAME_CONVERSTION_H__
|
||||
#define __NAME_CONVERSTION_H__
|
||||
|
||||
#include <string>
|
||||
|
||||
#include "model.h"
|
||||
|
||||
bool is_cond_stage_model_name(const std::string& name);
|
||||
bool is_diffusion_model_name(const std::string& name);
|
||||
bool is_first_stage_model_name(const std::string& name);
|
||||
|
||||
std::string convert_tensor_name(std::string name, SDVersion version);
|
||||
|
||||
#endif // __NAME_CONVERSTION_H__
|
||||
+177
@@ -0,0 +1,177 @@
|
||||
#ifndef __ORDERED_MAP_HPP__
|
||||
#define __ORDERED_MAP_HPP__
|
||||
|
||||
#include <iostream>
|
||||
#include <list>
|
||||
#include <string>
|
||||
#include <unordered_map>
|
||||
|
||||
#include <initializer_list>
|
||||
#include <iterator>
|
||||
#include <list>
|
||||
#include <stdexcept>
|
||||
#include <unordered_map>
|
||||
#include <utility>
|
||||
|
||||
template <typename Key, typename T>
|
||||
class OrderedMap {
|
||||
public:
|
||||
using key_type = Key;
|
||||
using mapped_type = T;
|
||||
using value_type = std::pair<const Key, T>;
|
||||
using list_type = std::list<value_type>;
|
||||
using size_type = typename list_type::size_type;
|
||||
using difference_type = typename list_type::difference_type;
|
||||
using iterator = typename list_type::iterator;
|
||||
using const_iterator = typename list_type::const_iterator;
|
||||
|
||||
private:
|
||||
list_type data_;
|
||||
std::unordered_map<Key, iterator> index_;
|
||||
|
||||
public:
|
||||
// --- constructors ---
|
||||
OrderedMap() = default;
|
||||
|
||||
OrderedMap(std::initializer_list<value_type> init) {
|
||||
for (const auto& kv : init)
|
||||
insert(kv);
|
||||
}
|
||||
|
||||
OrderedMap(const OrderedMap&) = default;
|
||||
OrderedMap(OrderedMap&&) noexcept = default;
|
||||
OrderedMap& operator=(const OrderedMap&) = default;
|
||||
OrderedMap& operator=(OrderedMap&&) noexcept = default;
|
||||
|
||||
// --- element access ---
|
||||
T& at(const Key& key) {
|
||||
auto it = index_.find(key);
|
||||
if (it == index_.end())
|
||||
throw std::out_of_range("OrderedMap::at: key not found");
|
||||
return it->second->second;
|
||||
}
|
||||
|
||||
const T& at(const Key& key) const {
|
||||
auto it = index_.find(key);
|
||||
if (it == index_.end())
|
||||
throw std::out_of_range("OrderedMap::at: key not found");
|
||||
return it->second->second;
|
||||
}
|
||||
|
||||
T& operator[](const Key& key) {
|
||||
auto it = index_.find(key);
|
||||
if (it == index_.end()) {
|
||||
data_.emplace_back(key, T{});
|
||||
auto iter = std::prev(data_.end());
|
||||
index_[key] = iter;
|
||||
return iter->second;
|
||||
}
|
||||
return it->second->second;
|
||||
}
|
||||
|
||||
// --- iterators ---
|
||||
iterator begin() noexcept { return data_.begin(); }
|
||||
const_iterator begin() const noexcept { return data_.begin(); }
|
||||
const_iterator cbegin() const noexcept { return data_.cbegin(); }
|
||||
|
||||
iterator end() noexcept { return data_.end(); }
|
||||
const_iterator end() const noexcept { return data_.end(); }
|
||||
const_iterator cend() const noexcept { return data_.cend(); }
|
||||
|
||||
// --- capacity ---
|
||||
bool empty() const noexcept { return data_.empty(); }
|
||||
size_type size() const noexcept { return data_.size(); }
|
||||
|
||||
// --- modifiers ---
|
||||
void clear() noexcept {
|
||||
data_.clear();
|
||||
index_.clear();
|
||||
}
|
||||
|
||||
std::pair<iterator, bool> insert(const value_type& value) {
|
||||
auto it = index_.find(value.first);
|
||||
if (it != index_.end()) {
|
||||
return {it->second, false};
|
||||
}
|
||||
data_.push_back(value);
|
||||
auto iter = std::prev(data_.end());
|
||||
index_[value.first] = iter;
|
||||
return {iter, true};
|
||||
}
|
||||
|
||||
std::pair<iterator, bool> insert(value_type&& value) {
|
||||
auto it = index_.find(value.first);
|
||||
if (it != index_.end()) {
|
||||
return {it->second, false};
|
||||
}
|
||||
data_.push_back(std::move(value));
|
||||
auto iter = std::prev(data_.end());
|
||||
index_[iter->first] = iter;
|
||||
return {iter, true};
|
||||
}
|
||||
|
||||
void erase(const Key& key) {
|
||||
auto it = index_.find(key);
|
||||
if (it != index_.end()) {
|
||||
data_.erase(it->second);
|
||||
index_.erase(it);
|
||||
}
|
||||
}
|
||||
|
||||
iterator erase(iterator pos) {
|
||||
index_.erase(pos->first);
|
||||
return data_.erase(pos);
|
||||
}
|
||||
|
||||
// --- lookup ---
|
||||
size_type count(const Key& key) const {
|
||||
return index_.count(key);
|
||||
}
|
||||
|
||||
iterator find(const Key& key) {
|
||||
auto it = index_.find(key);
|
||||
if (it == index_.end())
|
||||
return data_.end();
|
||||
return it->second;
|
||||
}
|
||||
|
||||
const_iterator find(const Key& key) const {
|
||||
auto it = index_.find(key);
|
||||
if (it == index_.end())
|
||||
return data_.end();
|
||||
return it->second;
|
||||
}
|
||||
|
||||
bool contains(const Key& key) const {
|
||||
return index_.find(key) != index_.end();
|
||||
}
|
||||
|
||||
// --- comparison ---
|
||||
bool operator==(const OrderedMap& other) const {
|
||||
return data_ == other.data_;
|
||||
}
|
||||
|
||||
bool operator!=(const OrderedMap& other) const {
|
||||
return !(*this == other);
|
||||
}
|
||||
|
||||
template <typename... Args>
|
||||
std::pair<iterator, bool> emplace(Args&&... args) {
|
||||
value_type value(std::forward<Args>(args)...);
|
||||
auto it = index_.find(value.first);
|
||||
if (it != index_.end()) {
|
||||
return {it->second, false};
|
||||
}
|
||||
data_.push_back(std::move(value));
|
||||
auto iter = std::prev(data_.end());
|
||||
index_[iter->first] = iter;
|
||||
return {iter, true};
|
||||
}
|
||||
|
||||
void swap(OrderedMap& other) noexcept {
|
||||
data_.swap(other.data_);
|
||||
index_.swap(other.index_);
|
||||
}
|
||||
};
|
||||
|
||||
#endif // __ORDERED_MAP_HPP__
|
||||
@@ -578,7 +578,7 @@ struct PhotoMakerIDEmbed : public GGMLRunner {
|
||||
const std::string& file_path = "",
|
||||
const std::string& prefix = "")
|
||||
: file_path(file_path), GGMLRunner(backend, offload_params_to_cpu), model_loader(ml) {
|
||||
if (!model_loader->init_from_file(file_path, prefix)) {
|
||||
if (!model_loader->init_from_file_and_convert_name(file_path, prefix)) {
|
||||
load_failed = true;
|
||||
}
|
||||
}
|
||||
|
||||
+2
-2
@@ -543,7 +543,7 @@ namespace Qwen {
|
||||
std::vector<ggml_tensor*> ref_latents = {},
|
||||
bool increase_ref_index = false) {
|
||||
GGML_ASSERT(x->ne[3] == 1);
|
||||
struct ggml_cgraph* gf = ggml_new_graph_custom(compute_ctx, QWEN_IMAGE_GRAPH_SIZE, false);
|
||||
struct ggml_cgraph* gf = new_graph_custom(QWEN_IMAGE_GRAPH_SIZE);
|
||||
|
||||
x = to_backend(x);
|
||||
context = to_backend(context);
|
||||
@@ -644,7 +644,7 @@ namespace Qwen {
|
||||
ggml_type model_data_type = GGML_TYPE_Q8_0;
|
||||
|
||||
ModelLoader model_loader;
|
||||
if (!model_loader.init_from_file(file_path, "model.diffusion_model.")) {
|
||||
if (!model_loader.init_from_file_and_convert_name(file_path, "model.diffusion_model.")) {
|
||||
LOG_ERROR("init model loader from file failed: '%s'", file_path.c_str());
|
||||
return;
|
||||
}
|
||||
|
||||
+2
-2
@@ -1049,7 +1049,7 @@ namespace Qwen {
|
||||
}
|
||||
|
||||
struct ggml_cgraph* build_encode_image_graph(struct ggml_tensor* image) {
|
||||
struct ggml_cgraph* gf = ggml_new_graph_custom(compute_ctx, QWENVL_GRAPH_SIZE, false);
|
||||
struct ggml_cgraph* gf = new_graph_custom(QWENVL_GRAPH_SIZE);
|
||||
|
||||
GGML_ASSERT(image->ne[1] % (params.vision.patch_size * params.vision.spatial_merge_size) == 0);
|
||||
GGML_ASSERT(image->ne[0] % (params.vision.patch_size * params.vision.spatial_merge_size) == 0);
|
||||
@@ -1342,7 +1342,7 @@ namespace Qwen {
|
||||
ggml_type model_data_type = GGML_TYPE_F16;
|
||||
|
||||
ModelLoader model_loader;
|
||||
if (!model_loader.init_from_file(file_path, "qwen2vl.")) {
|
||||
if (!model_loader.init_from_file_and_convert_name(file_path, "qwen2vl.")) {
|
||||
LOG_ERROR("init model loader from file failed: '%s'", file_path.c_str());
|
||||
return;
|
||||
}
|
||||
|
||||
+230
-24
@@ -17,6 +17,7 @@
|
||||
#include "vae.hpp"
|
||||
|
||||
#include "latent-preview.h"
|
||||
#include "name_conversion.h"
|
||||
|
||||
const char* model_version_to_str[] = {
|
||||
"SD 1.x",
|
||||
@@ -108,10 +109,14 @@ public:
|
||||
std::shared_ptr<DiffusionModel> high_noise_diffusion_model;
|
||||
std::shared_ptr<VAE> first_stage_model;
|
||||
std::shared_ptr<TinyAutoEncoder> tae_first_stage;
|
||||
std::shared_ptr<ControlNet> control_net = nullptr;
|
||||
std::shared_ptr<ControlNet> control_net;
|
||||
std::shared_ptr<PhotoMakerIDEncoder> pmid_model;
|
||||
std::shared_ptr<LoraModel> pmid_lora;
|
||||
std::shared_ptr<PhotoMakerIDEmbed> pmid_id_embeds;
|
||||
std::vector<std::shared_ptr<LoraModel>> cond_stage_lora_models;
|
||||
std::vector<std::shared_ptr<LoraModel>> diffusion_lora_models;
|
||||
std::vector<std::shared_ptr<LoraModel>> first_stage_lora_models;
|
||||
bool apply_lora_immediately = false;
|
||||
|
||||
std::string taesd_path;
|
||||
bool use_tiny_autoencoder = false;
|
||||
@@ -278,6 +283,8 @@ public:
|
||||
}
|
||||
}
|
||||
|
||||
model_loader.convert_tensors_name();
|
||||
|
||||
version = model_loader.get_sd_version();
|
||||
if (version == VERSION_COUNT) {
|
||||
LOG_ERROR("get sd version from file failed: '%s'", SAFE_STR(sd_ctx_params->model_path));
|
||||
@@ -327,6 +334,29 @@ public:
|
||||
|
||||
LOG_DEBUG("ggml tensor size = %d bytes", (int)sizeof(ggml_tensor));
|
||||
|
||||
if (sd_ctx_params->lora_apply_mode == LORA_APPLY_AUTO) {
|
||||
bool have_quantized_weight = false;
|
||||
if (wtype != GGML_TYPE_COUNT && ggml_is_quantized(wtype)) {
|
||||
have_quantized_weight = true;
|
||||
} else {
|
||||
for (const auto& [type, _] : wtype_stat) {
|
||||
if (ggml_is_quantized(type)) {
|
||||
have_quantized_weight = true;
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
if (have_quantized_weight) {
|
||||
apply_lora_immediately = false;
|
||||
} else {
|
||||
apply_lora_immediately = true;
|
||||
}
|
||||
} else if (sd_ctx_params->lora_apply_mode == LORA_APPLY_IMMEDIATELY) {
|
||||
apply_lora_immediately = true;
|
||||
} else {
|
||||
apply_lora_immediately = false;
|
||||
}
|
||||
|
||||
if (sd_version_is_sdxl(version)) {
|
||||
scale_factor = 0.13025f;
|
||||
} else if (sd_version_is_sd3(version)) {
|
||||
@@ -569,13 +599,19 @@ public:
|
||||
version);
|
||||
}
|
||||
if (strlen(SAFE_STR(sd_ctx_params->photo_maker_path)) > 0) {
|
||||
pmid_lora = std::make_shared<LoraModel>(backend, sd_ctx_params->photo_maker_path, "");
|
||||
if (!pmid_lora->load_from_file(true, n_threads)) {
|
||||
pmid_lora = std::make_shared<LoraModel>("pmid", backend, sd_ctx_params->photo_maker_path, "", version);
|
||||
auto lora_tensor_filter = [&](const std::string& tensor_name) {
|
||||
if (starts_with(tensor_name, "lora.model")) {
|
||||
return true;
|
||||
}
|
||||
return false;
|
||||
};
|
||||
if (!pmid_lora->load_from_file(n_threads, lora_tensor_filter)) {
|
||||
LOG_WARN("load photomaker lora tensors from %s failed", sd_ctx_params->photo_maker_path);
|
||||
return false;
|
||||
}
|
||||
LOG_INFO("loading stacked ID embedding (PHOTOMAKER) model file from '%s'", sd_ctx_params->photo_maker_path);
|
||||
if (!model_loader.init_from_file(sd_ctx_params->photo_maker_path, "pmid.")) {
|
||||
if (!model_loader.init_from_file_and_convert_name(sd_ctx_params->photo_maker_path, "pmid.")) {
|
||||
LOG_WARN("loading stacked ID embedding from '%s' failed", sd_ctx_params->photo_maker_path);
|
||||
} else {
|
||||
stacked_id = true;
|
||||
@@ -609,7 +645,7 @@ public:
|
||||
ignore_tensors.insert("first_stage_model.");
|
||||
}
|
||||
if (stacked_id) {
|
||||
ignore_tensors.insert("lora.");
|
||||
ignore_tensors.insert("pmid.unet.");
|
||||
}
|
||||
|
||||
if (vae_decode_only) {
|
||||
@@ -905,8 +941,11 @@ public:
|
||||
return result < -1;
|
||||
}
|
||||
|
||||
void apply_lora(std::string lora_name, float multiplier) {
|
||||
int64_t t0 = ggml_time_ms();
|
||||
std::shared_ptr<LoraModel> load_lora_model_from_file(const std::string& lora_id,
|
||||
float multiplier,
|
||||
ggml_backend_t backend,
|
||||
LoraModel::filter_t lora_tensor_filter = nullptr) {
|
||||
std::string lora_name = lora_id;
|
||||
std::string high_noise_tag = "|high_noise|";
|
||||
bool is_high_noise = false;
|
||||
if (starts_with(lora_name, high_noise_tag)) {
|
||||
@@ -923,25 +962,19 @@ public:
|
||||
file_path = ckpt_file_path;
|
||||
} else {
|
||||
LOG_WARN("can not find %s or %s for lora %s", st_file_path.c_str(), ckpt_file_path.c_str(), lora_name.c_str());
|
||||
return;
|
||||
return nullptr;
|
||||
}
|
||||
LoraModel lora(backend, file_path, is_high_noise ? "model.high_noise_" : "");
|
||||
if (!lora.load_from_file(false, n_threads)) {
|
||||
auto lora = std::make_shared<LoraModel>(lora_id, backend, file_path, is_high_noise ? "model.high_noise_" : "", version);
|
||||
if (!lora->load_from_file(n_threads, lora_tensor_filter)) {
|
||||
LOG_WARN("load lora tensors from %s failed", file_path.c_str());
|
||||
return;
|
||||
return nullptr;
|
||||
}
|
||||
|
||||
lora.multiplier = multiplier;
|
||||
// TODO: send version?
|
||||
lora.apply(tensors, version, n_threads);
|
||||
lora.free_params_buffer();
|
||||
|
||||
int64_t t1 = ggml_time_ms();
|
||||
|
||||
LOG_INFO("lora '%s' applied, taking %.2fs", lora_name.c_str(), (t1 - t0) * 1.0f / 1000);
|
||||
lora->multiplier = multiplier;
|
||||
return lora;
|
||||
}
|
||||
|
||||
void apply_loras(const std::unordered_map<std::string, float>& lora_state) {
|
||||
void apply_loras_immediately(const std::unordered_map<std::string, float>& lora_state) {
|
||||
std::unordered_map<std::string, float> lora_state_diff;
|
||||
for (auto& kv : lora_state) {
|
||||
const std::string& lora_name = kv.first;
|
||||
@@ -962,12 +995,149 @@ public:
|
||||
}
|
||||
|
||||
for (auto& kv : lora_state_diff) {
|
||||
apply_lora(kv.first, kv.second);
|
||||
int64_t t0 = ggml_time_ms();
|
||||
|
||||
auto lora = load_lora_model_from_file(kv.first, kv.second, backend);
|
||||
lora->apply(tensors, version, n_threads);
|
||||
lora->free_params_buffer();
|
||||
|
||||
int64_t t1 = ggml_time_ms();
|
||||
|
||||
LOG_INFO("lora '%s' applied, taking %.2fs", kv.first.c_str(), (t1 - t0) * 1.0f / 1000);
|
||||
}
|
||||
|
||||
curr_lora_state = lora_state;
|
||||
}
|
||||
|
||||
void apply_loras_at_runtime(const std::unordered_map<std::string, float>& lora_state) {
|
||||
cond_stage_lora_models.clear();
|
||||
diffusion_lora_models.clear();
|
||||
first_stage_lora_models.clear();
|
||||
if (cond_stage_model) {
|
||||
std::vector<std::shared_ptr<LoraModel>> lora_models;
|
||||
auto lora_state_diff = lora_state;
|
||||
for (auto& lora_model : cond_stage_lora_models) {
|
||||
auto iter = lora_state_diff.find(lora_model->lora_id);
|
||||
|
||||
if (iter != lora_state_diff.end()) {
|
||||
lora_model->multiplier = iter->second;
|
||||
lora_models.push_back(lora_model);
|
||||
lora_state_diff.erase(iter);
|
||||
}
|
||||
}
|
||||
cond_stage_lora_models = lora_models;
|
||||
auto lora_tensor_filter = [&](const std::string& tensor_name) {
|
||||
if (is_cond_stage_model_name(tensor_name)) {
|
||||
return true;
|
||||
}
|
||||
return false;
|
||||
};
|
||||
for (auto& kv : lora_state_diff) {
|
||||
const std::string& lora_id = kv.first;
|
||||
float multiplier = kv.second;
|
||||
|
||||
auto lora = load_lora_model_from_file(lora_id, multiplier, clip_backend, lora_tensor_filter);
|
||||
if (lora && !lora->lora_tensors.empty()) {
|
||||
lora->preprocess_lora_tensors(tensors);
|
||||
cond_stage_lora_models.push_back(lora);
|
||||
}
|
||||
}
|
||||
auto multi_lora_adapter = std::make_shared<MultiLoraAdapter>(cond_stage_lora_models);
|
||||
cond_stage_model->set_weight_adapter(multi_lora_adapter);
|
||||
}
|
||||
if (diffusion_model) {
|
||||
std::vector<std::shared_ptr<LoraModel>> lora_models;
|
||||
auto lora_state_diff = lora_state;
|
||||
for (auto& lora_model : diffusion_lora_models) {
|
||||
auto iter = lora_state_diff.find(lora_model->lora_id);
|
||||
|
||||
if (iter != lora_state_diff.end()) {
|
||||
lora_model->multiplier = iter->second;
|
||||
lora_models.push_back(lora_model);
|
||||
lora_state_diff.erase(iter);
|
||||
}
|
||||
}
|
||||
diffusion_lora_models = lora_models;
|
||||
auto lora_tensor_filter = [&](const std::string& tensor_name) {
|
||||
if (is_diffusion_model_name(tensor_name)) {
|
||||
return true;
|
||||
}
|
||||
return false;
|
||||
};
|
||||
for (auto& kv : lora_state_diff) {
|
||||
const std::string& lora_name = kv.first;
|
||||
float multiplier = kv.second;
|
||||
|
||||
auto lora = load_lora_model_from_file(lora_name, multiplier, backend, lora_tensor_filter);
|
||||
if (lora && !lora->lora_tensors.empty()) {
|
||||
lora->preprocess_lora_tensors(tensors);
|
||||
diffusion_lora_models.push_back(lora);
|
||||
}
|
||||
}
|
||||
auto multi_lora_adapter = std::make_shared<MultiLoraAdapter>(diffusion_lora_models);
|
||||
diffusion_model->set_weight_adapter(multi_lora_adapter);
|
||||
if (high_noise_diffusion_model) {
|
||||
high_noise_diffusion_model->set_weight_adapter(multi_lora_adapter);
|
||||
}
|
||||
}
|
||||
|
||||
if (first_stage_model) {
|
||||
std::vector<std::shared_ptr<LoraModel>> lora_models;
|
||||
auto lora_state_diff = lora_state;
|
||||
for (auto& lora_model : first_stage_lora_models) {
|
||||
auto iter = lora_state_diff.find(lora_model->lora_id);
|
||||
|
||||
if (iter != lora_state_diff.end()) {
|
||||
lora_model->multiplier = iter->second;
|
||||
lora_models.push_back(lora_model);
|
||||
lora_state_diff.erase(iter);
|
||||
}
|
||||
}
|
||||
first_stage_lora_models = lora_models;
|
||||
auto lora_tensor_filter = [&](const std::string& tensor_name) {
|
||||
if (is_first_stage_model_name(tensor_name)) {
|
||||
return true;
|
||||
}
|
||||
return false;
|
||||
};
|
||||
for (auto& kv : lora_state_diff) {
|
||||
const std::string& lora_name = kv.first;
|
||||
float multiplier = kv.second;
|
||||
|
||||
auto lora = load_lora_model_from_file(lora_name, multiplier, vae_backend, lora_tensor_filter);
|
||||
if (lora && !lora->lora_tensors.empty()) {
|
||||
lora->preprocess_lora_tensors(tensors);
|
||||
first_stage_lora_models.push_back(lora);
|
||||
}
|
||||
}
|
||||
auto multi_lora_adapter = std::make_shared<MultiLoraAdapter>(first_stage_lora_models);
|
||||
first_stage_model->set_weight_adapter(multi_lora_adapter);
|
||||
}
|
||||
}
|
||||
|
||||
void lora_stat() {
|
||||
if (!cond_stage_lora_models.empty()) {
|
||||
LOG_INFO("cond_stage_lora_models:");
|
||||
for (auto& lora_model : cond_stage_lora_models) {
|
||||
lora_model->stat();
|
||||
}
|
||||
}
|
||||
|
||||
if (!diffusion_lora_models.empty()) {
|
||||
LOG_INFO("diffusion_lora_models:");
|
||||
for (auto& lora_model : diffusion_lora_models) {
|
||||
lora_model->stat();
|
||||
}
|
||||
}
|
||||
|
||||
if (!first_stage_lora_models.empty()) {
|
||||
LOG_INFO("first_stage_lora_models:");
|
||||
for (auto& lora_model : first_stage_lora_models) {
|
||||
lora_model->stat();
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
std::string apply_loras_from_prompt(const std::string& prompt) {
|
||||
auto result_pair = extract_and_remove_lora(prompt);
|
||||
std::unordered_map<std::string, float> lora_f2m = result_pair.first; // lora_name -> multiplier
|
||||
@@ -976,10 +1146,18 @@ public:
|
||||
LOG_DEBUG("lora %s:%.2f", kv.first.c_str(), kv.second);
|
||||
}
|
||||
int64_t t0 = ggml_time_ms();
|
||||
apply_loras(lora_f2m);
|
||||
if (apply_lora_immediately) {
|
||||
LOG_INFO("apply lora immediately");
|
||||
apply_loras_immediately(lora_f2m);
|
||||
} else {
|
||||
LOG_INFO("apply at runtime");
|
||||
apply_loras_at_runtime(lora_f2m);
|
||||
}
|
||||
int64_t t1 = ggml_time_ms();
|
||||
LOG_INFO("apply_loras completed, taking %.2fs", (t1 - t0) * 1.0f / 1000);
|
||||
LOG_DEBUG("prompt after extract and remove lora: \"%s\"", result_pair.second.c_str());
|
||||
if (!lora_f2m.empty()) {
|
||||
LOG_INFO("apply_loras completed, taking %.2fs", (t1 - t0) * 1.0f / 1000);
|
||||
LOG_DEBUG("prompt after extract and remove lora: \"%s\"", result_pair.second.c_str());
|
||||
}
|
||||
return result_pair.second;
|
||||
}
|
||||
|
||||
@@ -2079,6 +2257,28 @@ enum preview_t str_to_preview(const char* str) {
|
||||
return PREVIEW_COUNT;
|
||||
}
|
||||
|
||||
const char* lora_apply_mode_to_str[] = {
|
||||
"auto",
|
||||
"immediately",
|
||||
"at_runtime",
|
||||
};
|
||||
|
||||
const char* sd_lora_apply_mode_name(enum lora_apply_mode_t mode) {
|
||||
if (mode < LORA_APPLY_MODE_COUNT) {
|
||||
return lora_apply_mode_to_str[mode];
|
||||
}
|
||||
return NONE_STR;
|
||||
}
|
||||
|
||||
enum lora_apply_mode_t str_to_lora_apply_mode(const char* str) {
|
||||
for (int i = 0; i < LORA_APPLY_MODE_COUNT; i++) {
|
||||
if (!strcmp(str, lora_apply_mode_to_str[i])) {
|
||||
return (enum lora_apply_mode_t)i;
|
||||
}
|
||||
}
|
||||
return LORA_APPLY_MODE_COUNT;
|
||||
}
|
||||
|
||||
void sd_ctx_params_init(sd_ctx_params_t* sd_ctx_params) {
|
||||
*sd_ctx_params = {};
|
||||
sd_ctx_params->vae_decode_only = true;
|
||||
@@ -2087,6 +2287,7 @@ void sd_ctx_params_init(sd_ctx_params_t* sd_ctx_params) {
|
||||
sd_ctx_params->wtype = SD_TYPE_COUNT;
|
||||
sd_ctx_params->rng_type = CUDA_RNG;
|
||||
sd_ctx_params->prediction = DEFAULT_PRED;
|
||||
sd_ctx_params->lora_apply_mode = LORA_APPLY_AUTO;
|
||||
sd_ctx_params->offload_params_to_cpu = false;
|
||||
sd_ctx_params->keep_clip_on_cpu = false;
|
||||
sd_ctx_params->keep_control_net_on_cpu = false;
|
||||
@@ -2672,6 +2873,9 @@ sd_image_t* generate_image_internal(sd_ctx_t* sd_ctx,
|
||||
if (sd_ctx->sd->free_params_immediately && !sd_ctx->sd->use_tiny_autoencoder) {
|
||||
sd_ctx->sd->first_stage_model->free_params_buffer();
|
||||
}
|
||||
|
||||
sd_ctx->sd->lora_stat();
|
||||
|
||||
sd_image_t* result_images = (sd_image_t*)calloc(batch_count, sizeof(sd_image_t));
|
||||
if (result_images == nullptr) {
|
||||
ggml_free(work_ctx);
|
||||
@@ -3341,6 +3545,8 @@ SD_API sd_image_t* generate_video(sd_ctx_t* sd_ctx, const sd_vid_gen_params_t* s
|
||||
sd_ctx->sd->first_stage_model->free_params_buffer();
|
||||
}
|
||||
|
||||
sd_ctx->sd->lora_stat();
|
||||
|
||||
sd_image_t* result_images = (sd_image_t*)calloc(vid->ne[2], sizeof(sd_image_t));
|
||||
if (result_images == nullptr) {
|
||||
ggml_free(work_ctx);
|
||||
|
||||
+11
-1
@@ -134,6 +134,13 @@ enum preview_t {
|
||||
PREVIEW_COUNT
|
||||
};
|
||||
|
||||
enum lora_apply_mode_t {
|
||||
LORA_APPLY_AUTO,
|
||||
LORA_APPLY_IMMEDIATELY,
|
||||
LORA_APPLY_AT_RUNTIME,
|
||||
LORA_APPLY_MODE_COUNT,
|
||||
};
|
||||
|
||||
typedef struct {
|
||||
bool enabled;
|
||||
int tile_size_x;
|
||||
@@ -165,6 +172,7 @@ typedef struct {
|
||||
enum sd_type_t wtype;
|
||||
enum rng_type_t rng_type;
|
||||
enum prediction_t prediction;
|
||||
enum lora_apply_mode_t lora_apply_mode;
|
||||
bool offload_params_to_cpu;
|
||||
bool keep_clip_on_cpu;
|
||||
bool keep_control_net_on_cpu;
|
||||
@@ -267,7 +275,7 @@ typedef void (*sd_preview_cb_t)(int step, int frame_count, sd_image_t* frames, b
|
||||
|
||||
SD_API void sd_set_log_callback(sd_log_cb_t sd_log_cb, void* data);
|
||||
SD_API void sd_set_progress_callback(sd_progress_cb_t cb, void* data);
|
||||
SD_API void sd_set_preview_callback(sd_preview_cb_t cb, preview_t mode, int interval, bool denoised, bool noisy);
|
||||
SD_API void sd_set_preview_callback(sd_preview_cb_t cb, enum preview_t mode, int interval, bool denoised, bool noisy);
|
||||
SD_API int32_t get_num_physical_cores();
|
||||
SD_API const char* sd_get_system_info();
|
||||
|
||||
@@ -283,6 +291,8 @@ SD_API const char* sd_prediction_name(enum prediction_t prediction);
|
||||
SD_API enum prediction_t str_to_prediction(const char* str);
|
||||
SD_API const char* sd_preview_name(enum preview_t preview);
|
||||
SD_API enum preview_t str_to_preview(const char* str);
|
||||
SD_API const char* sd_lora_apply_mode_name(enum lora_apply_mode_t mode);
|
||||
SD_API enum lora_apply_mode_t str_to_lora_apply_mode(const char* str);
|
||||
|
||||
SD_API void sd_ctx_params_init(sd_ctx_params_t* sd_ctx_params);
|
||||
SD_API char* sd_ctx_params_to_str(const sd_ctx_params_t* sd_ctx_params);
|
||||
|
||||
@@ -1004,7 +1004,7 @@ struct T5Embedder {
|
||||
ggml_type model_data_type = GGML_TYPE_F16;
|
||||
|
||||
ModelLoader model_loader;
|
||||
if (!model_loader.init_from_file(file_path)) {
|
||||
if (!model_loader.init_from_file_and_convert_name(file_path)) {
|
||||
LOG_ERROR("init model loader from file failed: '%s'", file_path.c_str());
|
||||
return;
|
||||
}
|
||||
|
||||
@@ -222,7 +222,7 @@ struct TinyAutoEncoder : public GGMLRunner {
|
||||
}
|
||||
|
||||
ModelLoader model_loader;
|
||||
if (!model_loader.init_from_file(file_path)) {
|
||||
if (!model_loader.init_from_file_and_convert_name(file_path)) {
|
||||
LOG_ERROR("init taesd model loader from file failed: '%s'", file_path.c_str());
|
||||
return false;
|
||||
}
|
||||
|
||||
@@ -7,7 +7,7 @@
|
||||
|
||||
/*==================================================== UnetModel =====================================================*/
|
||||
|
||||
#define UNET_GRAPH_SIZE 10240
|
||||
#define UNET_GRAPH_SIZE 102400
|
||||
|
||||
class SpatialVideoTransformer : public SpatialTransformer {
|
||||
protected:
|
||||
@@ -612,7 +612,7 @@ struct UNetModelRunner : public GGMLRunner {
|
||||
int num_video_frames = -1,
|
||||
std::vector<struct ggml_tensor*> controls = {},
|
||||
float control_strength = 0.f) {
|
||||
struct ggml_cgraph* gf = ggml_new_graph_custom(compute_ctx, UNET_GRAPH_SIZE, false);
|
||||
struct ggml_cgraph* gf = new_graph_custom(UNET_GRAPH_SIZE);
|
||||
|
||||
if (num_video_frames == -1) {
|
||||
num_video_frames = x->ne[3];
|
||||
|
||||
+1
-1
@@ -42,7 +42,7 @@ struct UpscalerGGML {
|
||||
backend = ggml_backend_sycl_init(0);
|
||||
#endif
|
||||
ModelLoader model_loader;
|
||||
if (!model_loader.init_from_file(esrgan_path)) {
|
||||
if (!model_loader.init_from_file_and_convert_name(esrgan_path)) {
|
||||
LOG_ERROR("init model loader from file failed: '%s'", esrgan_path.c_str());
|
||||
}
|
||||
model_loader.set_wtype_override(model_data_type);
|
||||
|
||||
@@ -5,6 +5,7 @@
|
||||
#include <cstdarg>
|
||||
#include <fstream>
|
||||
#include <locale>
|
||||
#include <regex>
|
||||
#include <sstream>
|
||||
#include <string>
|
||||
#include <thread>
|
||||
@@ -547,6 +548,8 @@ sd_image_f32_t clip_preprocess(sd_image_f32_t image, int target_width, int targe
|
||||
// (abc) - increases attention to abc by a multiplier of 1.1
|
||||
// (abc:3.12) - increases attention to abc by a multiplier of 3.12
|
||||
// [abc] - decreases attention to abc by a multiplier of 1.1
|
||||
// BREAK - separates the prompt into conceptually distinct parts for sequential processing
|
||||
// B - internal helper pattern; prevents 'B' in 'BREAK' from being consumed as normal text
|
||||
// \( - literal character '('
|
||||
// \[ - literal character '['
|
||||
// \) - literal character ')'
|
||||
@@ -582,7 +585,7 @@ std::vector<std::pair<std::string, float>> parse_prompt_attention(const std::str
|
||||
float round_bracket_multiplier = 1.1f;
|
||||
float square_bracket_multiplier = 1 / 1.1f;
|
||||
|
||||
std::regex re_attention(R"(\\\(|\\\)|\\\[|\\\]|\\\\|\\|\(|\[|:([+-]?[.\d]+)\)|\)|\]|[^\\()\[\]:]+|:)");
|
||||
std::regex re_attention(R"(\\\(|\\\)|\\\[|\\\]|\\\\|\\|\(|\[|:([+-]?[.\d]+)\)|\)|\]|\bBREAK\b|[^\\()\[\]:B]+|:|\bB)");
|
||||
std::regex re_break(R"(\s*\bBREAK\b\s*)");
|
||||
|
||||
auto multiply_range = [&](int start_position, float multiplier) {
|
||||
@@ -591,7 +594,7 @@ std::vector<std::pair<std::string, float>> parse_prompt_attention(const std::str
|
||||
}
|
||||
};
|
||||
|
||||
std::smatch m;
|
||||
std::smatch m, m2;
|
||||
std::string remaining_text = text;
|
||||
|
||||
while (std::regex_search(remaining_text, m, re_attention)) {
|
||||
@@ -615,6 +618,8 @@ std::vector<std::pair<std::string, float>> parse_prompt_attention(const std::str
|
||||
square_brackets.pop_back();
|
||||
} else if (text == "\\(") {
|
||||
res.push_back({text.substr(1), 1.0f});
|
||||
} else if (std::regex_search(text, m2, re_break)) {
|
||||
res.push_back({"BREAK", -1.0f});
|
||||
} else {
|
||||
res.push_back({text, 1.0f});
|
||||
}
|
||||
@@ -645,4 +650,4 @@ std::vector<std::pair<std::string, float>> parse_prompt_attention(const std::str
|
||||
}
|
||||
|
||||
return res;
|
||||
}
|
||||
}
|
||||
|
||||
@@ -1133,7 +1133,7 @@ namespace WAN {
|
||||
}
|
||||
|
||||
struct ggml_cgraph* build_graph(struct ggml_tensor* z, bool decode_graph) {
|
||||
struct ggml_cgraph* gf = ggml_new_graph_custom(compute_ctx, 10240 * z->ne[2], false);
|
||||
struct ggml_cgraph* gf = new_graph_custom(10240 * z->ne[2]);
|
||||
|
||||
z = to_backend(z);
|
||||
|
||||
@@ -1147,7 +1147,7 @@ namespace WAN {
|
||||
}
|
||||
|
||||
struct ggml_cgraph* build_graph_partial(struct ggml_tensor* z, bool decode_graph, int64_t i) {
|
||||
struct ggml_cgraph* gf = ggml_new_graph_custom(compute_ctx, 20480, false);
|
||||
struct ggml_cgraph* gf = new_graph_custom(20480);
|
||||
|
||||
ae.clear_cache();
|
||||
|
||||
@@ -1271,7 +1271,7 @@ namespace WAN {
|
||||
vae->get_param_tensors(tensors, "first_stage_model");
|
||||
|
||||
ModelLoader model_loader;
|
||||
if (!model_loader.init_from_file(file_path, "vae.")) {
|
||||
if (!model_loader.init_from_file_and_convert_name(file_path, "vae.")) {
|
||||
LOG_ERROR("init model loader from file failed: '%s'", file_path.c_str());
|
||||
return;
|
||||
}
|
||||
@@ -2142,7 +2142,7 @@ namespace WAN {
|
||||
struct ggml_tensor* time_dim_concat = nullptr,
|
||||
struct ggml_tensor* vace_context = nullptr,
|
||||
float vace_strength = 1.f) {
|
||||
struct ggml_cgraph* gf = ggml_new_graph_custom(compute_ctx, WAN_GRAPH_SIZE, false);
|
||||
struct ggml_cgraph* gf = new_graph_custom(WAN_GRAPH_SIZE);
|
||||
|
||||
x = to_backend(x);
|
||||
timesteps = to_backend(timesteps);
|
||||
@@ -2255,7 +2255,7 @@ namespace WAN {
|
||||
LOG_INFO("loading from '%s'", file_path.c_str());
|
||||
|
||||
ModelLoader model_loader;
|
||||
if (!model_loader.init_from_file(file_path, "model.diffusion_model.")) {
|
||||
if (!model_loader.init_from_file_and_convert_name(file_path, "model.diffusion_model.")) {
|
||||
LOG_ERROR("init model loader from file failed: '%s'", file_path.c_str());
|
||||
return;
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user