Using GGUF as the file format, for greater extensibility
| 714 | |
| 715 | // Using GGUF as the file format, for greater extensibility |
| 716 | bool IMatrixCollector::load_imatrix(const char * file_name) { |
| 717 | struct ggml_context * ctx = nullptr; |
| 718 | struct gguf_init_params meta_gguf_params = { |
| 719 | /* .no_alloc = */ false, // the data is needed |
| 720 | /* .ctx = */ &ctx, |
| 721 | }; |
| 722 | struct gguf_context * ctx_gguf = gguf_init_from_file(file_name, meta_gguf_params); |
| 723 | if (!ctx_gguf) { |
| 724 | return this->load_imatrix_legacy(file_name); |
| 725 | } |
| 726 | const int32_t n_entries = gguf_get_n_tensors(ctx_gguf); |
| 727 | if (n_entries < 1) { |
| 728 | LOG_ERR("%s: no data in file %s\n", __func__, file_name); |
| 729 | gguf_free(ctx_gguf); |
| 730 | ggml_free(ctx); |
| 731 | return false; |
| 732 | } |
| 733 | |
| 734 | const int64_t datasets_key = gguf_find_key(ctx_gguf, LLM_KV_IMATRIX_DATASETS); |
| 735 | if (datasets_key != -1 && gguf_get_arr_type(ctx_gguf, datasets_key) == GGUF_TYPE_STRING) { |
| 736 | const int64_t n = gguf_get_arr_n(ctx_gguf, datasets_key); |
| 737 | m_datasets.reserve(m_datasets.size() + n); |
| 738 | for (int64_t i = 0; i < n; ++i) { |
| 739 | m_datasets.push_back(gguf_get_arr_str(ctx_gguf, datasets_key, i)); |
| 740 | } |
| 741 | } |
| 742 | |
| 743 | const std::string in_sum2_suffix{ ".in_sum2" }; |
| 744 | const std::string counts_suffix{ ".counts" }; |
| 745 | |
| 746 | // Could re-use m_stats instead, but this allows |
| 747 | // checking for completeness of *each* loaded imatrix file |
| 748 | // and also makes it easier to re-use a similar implementation in quantize.cpp |
| 749 | // Using an ordered map to get a deterministic iteration order. |
| 750 | std::map<std::string, std::pair<struct ggml_tensor *, struct ggml_tensor *>> sums_counts_for; |
| 751 | |
| 752 | for (struct ggml_tensor * cur = ggml_get_first_tensor(ctx); cur; cur = ggml_get_next_tensor(ctx, cur)) { |
| 753 | std::string name = cur->name; |
| 754 | |
| 755 | if (name.empty()) { continue; } |
| 756 | |
| 757 | if (string_remove_suffix(name, in_sum2_suffix)) { |
| 758 | // in_sum2 |
| 759 | sums_counts_for[std::move(name)].first = cur; |
| 760 | } else if (string_remove_suffix(name, counts_suffix)) { |
| 761 | // counts |
| 762 | sums_counts_for[std::move(name)].second = cur; |
| 763 | } else { |
| 764 | // ignore other tensors |
| 765 | } |
| 766 | } |
| 767 | |
| 768 | for (const auto & sc : sums_counts_for) { |
| 769 | const std::string & name = sc.first; |
| 770 | const struct ggml_tensor * in_sum2 = sc.second.first; |
| 771 | const struct ggml_tensor * counts = sc.second.second; |
| 772 | |
| 773 | if (!in_sum2 || !counts) { |
no test coverage detected