-
Notifications
You must be signed in to change notification settings - Fork 3.3k
[GGUF FE] Support Q2_0 quantization and add missing op translators #37380
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
Changes from all commits
47d2f22
7dc2143
4c16171
b0dcd4e
d9464b3
File filter
Filter by extension
Conversations
Jump to
Diff view
Diff view
There are no files selected for viewing
| Original file line number | Diff line number | Diff line change |
|---|---|---|
| @@ -0,0 +1,38 @@ | ||
| // Copyright (C) 2018-2026 Intel Corporation | ||
| // SPDX-License-Identifier: Apache-2.0 | ||
| // | ||
|
|
||
| #include "node_context.hpp" | ||
| #include "op_table.hpp" | ||
| #include "openvino/core/node_output.hpp" | ||
| #include "openvino/op/constant.hpp" | ||
| #include "openvino/op/topk.hpp" | ||
| #include "utils.hpp" | ||
|
|
||
| namespace ov { | ||
| namespace frontend { | ||
| namespace gguf { | ||
| namespace op { | ||
|
|
||
| // ggml_top_k(a, k): the indices of the k largest values along ne[0] (the OV last axis), | ||
| // ordered by descending value, as i32. k is the extent of that axis on the output. | ||
| OutputVector translate_top_k(const NodeContext& context) { | ||
| num_inputs_check(context, 1, 1); | ||
|
|
||
| auto input = context.get_input(0); | ||
| const int64_t k = context.get_output_shape()[context.get_output_shape().size() - 1].get_length(); | ||
| auto k_node = ov::op::v0::Constant::create(ov::element::i64, ov::Shape{}, {k}); | ||
| auto topk = std::make_shared<ov::op::v11::TopK>(input, | ||
|
Contributor
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. [nitpick] Near-duplicate
Why it matters: the "indices come from Fix (optional): extract a small shared helper in and call it from both translators. Non-blocking — the two ops are distinct enough that |
||
| k_node, | ||
| -1, | ||
| ov::op::v11::TopK::Mode::MAX, | ||
| ov::op::v11::TopK::SortType::SORT_VALUES, | ||
| context.get_attribute<ov::element::Type>("output_type")); | ||
|
|
||
| return rename_outputs_with_suffix({topk->output(1)}, context.get_name()); | ||
| } | ||
|
|
||
| } // namespace op | ||
| } // namespace gguf | ||
| } // namespace frontend | ||
| } // namespace ov | ||
| Original file line number | Diff line number | Diff line change |
|---|---|---|
| @@ -0,0 +1,29 @@ | ||
| // Copyright (C) 2018-2026 Intel Corporation | ||
| // SPDX-License-Identifier: Apache-2.0 | ||
| // | ||
|
|
||
| #include "node_context.hpp" | ||
| #include "op_table.hpp" | ||
| #include "openvino/core/node_output.hpp" | ||
| #include "openvino/op/elu.hpp" | ||
| #include "utils.hpp" | ||
|
|
||
| namespace ov { | ||
| namespace frontend { | ||
| namespace gguf { | ||
| namespace op { | ||
|
|
||
| OutputVector translate_unary_elu(const NodeContext& context) { | ||
| num_inputs_check(context, 1, 1); | ||
|
|
||
| auto input = context.get_input(0); | ||
| // ggml's op_elu is `x > 0 ? x : expm1(x)`, i.e. ELU with alpha fixed at 1; it takes no param. | ||
| auto res = std::make_shared<ov::op::v0::Elu>(input, 1.0); | ||
|
|
||
| return rename_outputs_with_suffix({res}, context.get_name()); | ||
| } | ||
|
|
||
| } // namespace op | ||
| } // namespace gguf | ||
| } // namespace frontend | ||
| } // namespace ov |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
What: context.get_output_shape() is constructed twice on one line. More importantly, Dimension::get_length() throws if the output's last (k) dimension is dynamic. This differs from translate_argsort, which derives its length from the input shape at runtime via get_dimensions(...) and tolerates dynamic rank.
Why it matters: If a model ever produces a TOP_K whose extent is not statically known, conversion aborts with a hard throw rather than degrading. It's also a minor readability/efficiency nit.
Fix: Cache the shape in a local; if a dynamic k is reachable, derive it dynamically as ARGSORT does: