diff --git a/src/llama-quantize.cpp b/src/llama-quantize.cpp index 925fb4e9..2ed081d4 100644 --- a/src/llama-quantize.cpp +++ b/src/llama-quantize.cpp @@ -1448,19 +1448,33 @@ static void llama_model_quantize_internal(const std::string & fname_inp, const s if (imatrix_data) { auto it = imatrix_data->find(tensor->name); if (it == imatrix_data->end()) { - // MLA hack: most imatrix files floating around the Internet have been computed with standard attention. - // This means that the imatrix file does not contain data for the *.attn_k_b.weight and *.attn_v_b.weight - // required by MLA. But the *.attn_v_b.weight tensors "see" the exact same activations as the - // *.attn_kv_b.weight tensors used in standard attention. Hence, if we find imatrix data for - // *.attn_kv_b.weight we can use it for *.attn_v_b.weight and vice versa. - std::string name{tensor->name}; - static std::array alternatives{".attn_v_b.weight", ".attn_kv_b.weight"}; - for (int j = 0; j < int(alternatives.size()); ++j) { - if (auto pos = name.find(alternatives[j]); pos != std::string::npos) { - int j1 = (j + 1) % alternatives.size(); - auto alternative_name = name.substr(0, pos) + alternatives[j1]; - it = imatrix_data->find(alternative_name); - break; + if (auto pos1 = name.find("ffn_up_exps.weight"), pos2 = name.find("ffn_gate_exps.weight"); pos1 != std::string::npos || pos2 != std::string::npos) { + // Merged ffn_up/gate_exps hack + auto pos = pos1 != std::string::npos ? pos1 : pos2; + auto merged_name = name.substr(0, pos) + "ffn_gate_up_exps.weight"; + it = imatrix_data->find(merged_name); + if (it == imatrix_data->end()) { + auto up_name = name.substr(0, pos) + "ffn_up_exps.weight"; + it = imatrix_data->find(up_name); + } + } else if (auto pos = name.find("ffn_gate_up_exps.weight"); pos != std::string::npos) { + auto not_merged_name = name.substr(0, pos) + "ffn_up_exps.weight"; + it = imatrix_data->find(not_merged_name); + } else { + // MLA hack: most imatrix files floating around the Internet have been computed with standard attention. + // This means that the imatrix file does not contain data for the *.attn_k_b.weight and *.attn_v_b.weight + // required by MLA. But the *.attn_v_b.weight tensors "see" the exact same activations as the + // *.attn_kv_b.weight tensors used in standard attention. Hence, if we find imatrix data for + // *.attn_kv_b.weight we can use it for *.attn_v_b.weight and vice versa. + std::string name{tensor->name}; + static std::array alternatives{".attn_v_b.weight", ".attn_kv_b.weight"}; + for (int j = 0; j < int(alternatives.size()); ++j) { + if (auto pos = name.find(alternatives[j]); pos != std::string::npos) { + int j1 = (j + 1) % alternatives.size(); + auto alternative_name = name.substr(0, pos) + alternatives[j1]; + it = imatrix_data->find(alternative_name); + break; + } } } }