Skip to content
Draft
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
15 changes: 15 additions & 0 deletions .claude/skills/ov-gguf-add-architecture/SKILL.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,15 @@
---
name: ov-gguf-add-architecture
description: >
Enable a new model architecture/family in the OpenVINO GGUF frontend's native .gguf builder,
or check whether a GGUF model is supported. Use when the user asks to enable, support or bring
up a GGUF/llama.cpp model (llama, qwen, phi, gemma, MoE and similar decoder-only families),
when a .gguf file is rejected as an unsupported architecture, or when working on
supported_archs / TransformerBuilder in src/frontends/gguf/src/builder/. Do NOT use for adding
a single ggml op translator or for debugging wrong output from an already-supported model.
---

1. Read [src/frontends/gguf/docs/adding_an_architecture.md](../../../src/frontends/gguf/docs/adding_an_architecture.md) — most architectures in the transformer family need **no code**, only a `general.architecture` string added to `supported_archs()` plus the correct RoPE type. It also lists exactly which structural features are auto-detected from the tensor table and metadata, and how to verify a new arch.
2. Check [src/frontends/gguf/docs/supported_models.md](../../../src/frontends/gguf/docs/supported_models.md) first to see whether the architecture is already accepted and how support was verified.
3. Only if the family is structurally novel, consult the "10% case" section and [frontend_design.md](../../../src/frontends/gguf/docs/frontend_design.md) before adding builder code.
4. Verify as that document prescribes, including the graph-fingerprint check, and re-run the other supported architectures after any change to shared builder logic.
15 changes: 15 additions & 0 deletions .claude/skills/ov-gguf-debug-accuracy/SKILL.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,15 @@
---
name: ov-gguf-debug-accuracy
description: >
Debug wrong or degraded output from a GGUF model running through the OpenVINO GGUF frontend or
the ggml-openvino backend. Use when a GGUF model converts but produces garbage, repeated or
drifting tokens, a cosine-similarity cliff between layers, output that diverges from llama.cpp
CPU, or a broadcast/shape crash that appears only at decode or only for one architecture. Do
NOT use for ops that fail to convert at all ("Translation for operation type ... is not
implemented"), or for build and CMake failures.
---

1. Read [src/frontends/gguf/docs/debugging_accuracy.md](../../../src/frontends/gguf/docs/debugging_accuracy.md) — the coarse-to-fine bisection strategy, the ggml-CPU oracle technique, the catalogue of bug archetypes with their generalizable lessons, the debug env vars, and the checklist.
2. Apply its one governing rule before anything else: every accuracy claim is a comparison against the **real llama.cpp CPU implementation**, never a hand-derived reference. If you are about to write out an op's math to form an expectation, generate it from ggml instead.
3. Work the bisection steps in order and do not open a debugger until they have cornered the bug. Check the bug archetypes first when a cosine cliff or dynamic-shape crash points near one.
4. After any fix to a shared path — especially a VIEW or `op_case` predicate — re-run the other supported architectures and confirm their classification and output are unchanged.
15 changes: 15 additions & 0 deletions .claude/skills/ov-gguf-enable-op/SKILL.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,15 @@
---
name: ov-gguf-enable-op
description: >
Enable a ggml operation in the OpenVINO GGUF frontend by adding or fixing an op translator.
Use when conversion fails with "Translation for operation type GGML_OP_* is not implemented",
when the user asks to add/implement/fix a GGUF or ggml op translator or an op_case, or when
working on src/frontends/gguf/src/op/. Do NOT use for enabling a new model architecture
(that is usually just a name in supported_archs), for wrong numerical output from an op that
already converts, or for GGUF quantization format work.
---

1. Read [src/frontends/gguf/docs/how_to_add_op.md](../../../src/frontends/gguf/docs/how_to_add_op.md) — the five-file checklist (including the test CMake source list, which is not globbed), the `NodeContext` API, the mandatory op-coverage gate, where reference values must come from, and the build/test commands (`-DENABLE_OV_GGUF_FRONTEND=ON`).
2. Confirm a translator is really what is missing: a new architecture usually needs only a name in `supported_archs()`, and a structurally different use of an existing op is an `op_case`. Both are covered in that document.
3. Find the closest existing op with `grep -n "GGML_" src/frontends/gguf/src/op_table.cpp` and the closest test with `grep -n "^TEST(" src/frontends/gguf/tests/test_ops.cpp`, then read only those ranges — do not read `test_ops.cpp` in full.
4. Implement, then build and run `ov_gguf_frontend_tests` — filtered while iterating, unfiltered before finishing so the coverage gate runs.
6 changes: 6 additions & 0 deletions .github/components.yml
Original file line number Diff line number Diff line change
Expand Up @@ -107,6 +107,12 @@ PROXY:
- GPU
build: []

GGUF_FE:
revalidate:
- CPU # the per-op tests compile and infer their converted graphs on the CPU plugin
build:
- CPU

IR_FE:
revalidate:
- C_API
Expand Down
5 changes: 5 additions & 0 deletions .github/coverage/tests_cpp.yml
Original file line number Diff line number Diff line change
Expand Up @@ -98,6 +98,11 @@ tests:
mode: gtest_single
profiles: [cpu]

- name: ov_gguf_frontend_tests
binary: ov_gguf_frontend_tests
mode: gtest_single
profiles: [cpu]

- name: ov_inference_functional_tests
binary: ov_inference_functional_tests
mode: gtest_single
Expand Down
14 changes: 11 additions & 3 deletions .github/labeler.yml
Original file line number Diff line number Diff line change
Expand Up @@ -71,6 +71,11 @@
- 'src/frontends/common/include/openvino/frontend/extension.hpp'
- 'src/frontends/common/include/openvino/frontend/extension/**/*'

'category: GGUF FE':
- 'src/frontends/gguf/**/*'
- 'tests/model_hub_tests/gguf/**/*'
- 'tests/requirements_gguf'

'category: GPU':
- 'src/plugins/intel_gpu/**/*'
- 'thirdparty/ocl/**/*'
Expand Down Expand Up @@ -154,7 +159,8 @@
- 'tests/requirements_tensorflow'
- any: ['tests/model_hub_tests/**',
'!tests/model_hub_tests/pytorch/**/*',
'!tests/model_hub_tests/jax/**/*']
'!tests/model_hub_tests/jax/**/*',
'!tests/model_hub_tests/gguf/**/*']

'category: TFL FE':
- 'src/frontends/tensorflow_lite/**/*'
Expand All @@ -170,15 +176,17 @@
- 'tests/requirements_pytorch'
- any: ['tests/model_hub_tests/**',
'!tests/model_hub_tests/tensorflow/**/*',
'!tests/model_hub_tests/jax/**/*']
'!tests/model_hub_tests/jax/**/*',
'!tests/model_hub_tests/gguf/**/*']

'category: JAX FE':
- 'src/frontends/jax/**/*'
- 'src/bindings/python/src/openvino/frontend/jax/**/*'
- 'tests/layer_tests/jax_tests/**/*'
- any: ['tests/model_hub_tests/**',
'!tests/model_hub_tests/tensorflow/**/*',
'!tests/model_hub_tests/pytorch/**/*']
'!tests/model_hub_tests/pytorch/**/*',
'!tests/model_hub_tests/gguf/**/*']

'category: tools':
- any: ['tools/**',
Expand Down
24 changes: 24 additions & 0 deletions .github/workflows/job_build_linux.yml
Original file line number Diff line number Diff line change
Expand Up @@ -85,6 +85,11 @@ on:
type: boolean
required: false
default: true
generate-gguf-fixtures:
description: 'Whether to generate the GGUF per-architecture test fixtures from llama.cpp into the tests artifact. Off by default: only useful where this build feeds job_cxx_unit_tests.yml'
type: boolean
required: false
default: false

permissions: read-all

Expand Down Expand Up @@ -249,6 +254,25 @@ jobs:
cmake --install ${BUILD_DIR} --config ${{ env.CMAKE_BUILD_TYPE }} --prefix ${INSTALL_TEST_DIR} --component tests
cmake --install ${BUILD_DIR} --config ${{ env.CMAKE_BUILD_TYPE }} --prefix ${DEVELOPER_PACKAGE_DIR} --component developer_package

# The GGUF per-architecture fixtures are GGUF headers emitted by llama.cpp's test-llama-archs.
# They are generated here rather than committed, and land in the tests artifact so the test job
# (which has neither a source checkout nor cmake) can consume them like any other test data.
# Where they are absent the arch test suite skips itself, so this is test data, not a build
# dependency -- which is what keeps llama.cpp out of OpenVINO's dependency graph.
#
# llama.cpp is pinned inside gen_arch_fixtures.py and only moves when the fixtures are
# deliberately refreshed: the generator writes whatever KVs llama.cpp currently defines, so
# following upstream would change every fixture's bytes -- and break the pinned graph
# fingerprints -- on an unrelated llama.cpp commit.
- name: Generate GGUF arch fixtures
if: ${{ inputs.generate-gguf-fixtures && fromJSON(inputs.affected-components).GGUF_FE.test }}
run: |
python3 -m pip install --no-cache-dir gguf
python3 ${OPENVINO_REPO}/src/frontends/gguf/tests/gen_arch_fixtures.py \
--fetch \
--out-dir ${INSTALL_TEST_DIR}/tests/test_data/arch_fixtures \
-j $(nproc)

- name: Install Python wheels for the main Python
if: ${{ ! inputs.build-additional-python-packages }}
run: cmake --install ${BUILD_DIR} --config ${{ env.CMAKE_BUILD_TYPE }} --prefix ${INSTALL_WHEELS_DIR} --component python_wheels
Expand Down
1 change: 1 addition & 0 deletions .github/workflows/job_cxx_unit_tests.yml
Original file line number Diff line number Diff line change
Expand Up @@ -129,6 +129,7 @@ jobs:
${{ env.INSTALL_TEST_DIR }}/ov_ir_frontend_tests --gtest_print_time=1 --gtest_output=xml:${{ env.INSTALL_TEST_DIR }}/TEST-IRFrontend.xml

- name: GGUF frontend tests
if: fromJSON(inputs.affected-components).GGUF_FE.test
run: |
${{ env.SOURCE_COMMAND }} ${{ env.SETUPVARS }}
${{ env.INSTALL_TEST_DIR }}/ov_gguf_frontend_tests --gtest_print_time=1 --gtest_output=xml:${{ env.INSTALL_TEST_DIR }}/TEST-GGUFFrontend.xml
Expand Down
116 changes: 116 additions & 0 deletions .github/workflows/job_gguf_models_tests.yml
Original file line number Diff line number Diff line change
@@ -0,0 +1,116 @@
name: GGUF Models tests

on:
workflow_call:
inputs:
runner:
description: 'Machine on which the tests would run'
type: string
required: true
image:
description: 'Docker image to use for the job'
type: string
required: false
default: null
model_scope:
description: 'Scope of models for testing.'
type: string
required: true

permissions: read-all

env:
HF_HUB_CACHE_LIN: /mount/caches/huggingface
HF_HUB_CACHE_WIN: "C:\\mount\\caches\\huggingface"
HF_TOKEN_PATH_LIN: /secrets/huggingface/token-secondary
HF_TOKEN_PATH_WIN: "C:\\mount\\secrets\\huggingface\\token-secondary"

jobs:
GGUF_Models_Tests:
name: GGUF Models tests
# The nightly scope downloads several 7B-30B checkpoints, so it needs far more time
# than the precommit scope (18 models of <=~4B).
timeout-minutes: ${{ inputs.model_scope == 'precommit' && 60 || 240 }}
runs-on: ${{ inputs.runner }}
container:
image: ${{ inputs.image }}
volumes:
- /mount:/mount
- /home/runner/secrets/:/secrets:ro
- ${{ github.workspace }}:${{ github.workspace }} # Needed as ${{ github.workspace }} is not working correctly when using Docker
defaults:
run:
shell: bash
env:
DEBIAN_FRONTEND: noninteractive # to prevent apt-get from waiting user input
INSTALL_DIR: ${{ github.workspace }}/install
INSTALL_TEST_DIR: ${{ github.workspace }}/install/tests
MODEL_HUB_TESTS_INSTALL_DIR: ${{ github.workspace }}/install/tests/model_hub_tests
USE_SYSTEM_CACHE: False # Using remote HuggingFace cache
HF_HUB_VERBOSITY: debug
steps:
# checkout action cleans up the workspace and have to be the first step
- name: Fetch custom actions
uses: ababushk/checkout@dd591a6a2ac25618db4eda86e7e0d938f88cf01b # cherry_pick_retries
timeout-minutes: 15
with:
sparse-checkout: |
.github/actions
sparse-checkout-cone-mode: false
submodules: 'false'

- name: Download OpenVINO artifacts (wheels)
uses: akashchi/download-artifact@d59a9c15fec3fdb7c9adf09464124d00f9c11415 # main
with:
name: openvino_wheels
path: ${{ env.INSTALL_DIR }}

- name: Download OpenVINO artifacts (tests)
uses: akashchi/download-artifact@d59a9c15fec3fdb7c9adf09464124d00f9c11415 # main
with:
name: openvino_tests
path: ${{ env.INSTALL_DIR }}

- name: Setup Variables
run: |
echo "HF_HUB_CACHE=${{ runner.os == 'Linux' && env.HF_HUB_CACHE_LIN || env.HF_HUB_CACHE_WIN }}" >> "$GITHUB_ENV"
echo "HUGGINGFACE_HUB_CACHE=${{ runner.os == 'Linux' && env.HF_HUB_CACHE_LIN || env.HF_HUB_CACHE_WIN }}" >> "$GITHUB_ENV"
echo "HF_TOKEN_PATH=${{ runner.os == 'Linux' && env.HF_TOKEN_PATH_LIN || env.HF_TOKEN_PATH_WIN }}" >> "$GITHUB_ENV"

- name: Extract OpenVINO packages and tests
run: pigz -dc openvino_tests.tar.gz | tar -xf - -v
working-directory: ${{ env.INSTALL_DIR }}

- name: Setup Python 3.11
uses: ./.github/actions/setup_python
with:
version: '3.11'
set-pip-install-path: 'false'
self-hosted-runner: ${{ contains(inputs.runner, 'aks') }}
use-pip-proxy: ${{ contains(inputs.runner, 'aks') }}

- name: Install OpenVINO Python wheels
uses: ./.github/actions/install_ov_wheels
with:
wheels-dir-path: ${{ env.INSTALL_DIR }}
wheels-to-install: 'openvino'

- name: Install GGUF Models tests requirements
run: python3 -m pip install -r ${INSTALL_TEST_DIR}/requirements_gguf

- name: GGUF Models Tests from Hugging Face
run: |
export PYTHONPATH=${MODEL_HUB_TESTS_INSTALL_DIR}:$PYTHONPATH
python3 -m pytest ${MODEL_HUB_TESTS_INSTALL_DIR}/gguf/ -m ${TYPE} --html=${INSTALL_TEST_DIR}/TEST-gguf_model_"${TYPE}"_tests.html --self-contained-html -v
env:
TYPE: ${{ inputs.model_scope == 'precommit' && 'precommit' || 'nightly' }}
TEST_DEVICE: CPU

- name: Upload Test Results
uses: ababushk/upload-artifact@ebc7d74ace101c08868aed05dba2aaf274b9a2c7 # main
if: ${{ !cancelled() }}
with:
name: test-results-gguf-models-${{ inputs.model_scope }}
path: |
${{ env.INSTALL_TEST_DIR }}/TEST*.html
if-no-files-found: 'error'
18 changes: 18 additions & 0 deletions .github/workflows/linux_sanitizers.yml
Original file line number Diff line number Diff line change
Expand Up @@ -220,6 +220,17 @@ jobs:
cmake -DCMAKE_INSTALL_PREFIX=${INSTALL_DIR} -P ${BUILD_DIR}/cmake_install.cmake --config ${{ env.CMAKE_BUILD_TYPE }}
cmake -DCMAKE_INSTALL_PREFIX=${INSTALL_TEST_DIR} -DCOMPONENT=tests -P ${BUILD_DIR}/cmake_install.cmake --config ${{ env.CMAKE_BUILD_TYPE }}

# Same generated test data as the regular Linux build (see job_build_linux.yml); running the 101
# per-architecture conversions under the sanitizers is the highest-value place for them. The
# generator's own llama.cpp build is not instrumented, which is fine -- only its output is used.
- name: Generate GGUF arch fixtures
run: |
python3 -m pip install --no-cache-dir gguf
python3 ${OPENVINO_REPO}/src/frontends/gguf/tests/gen_arch_fixtures.py \
--fetch \
--out-dir ${INSTALL_TEST_DIR}/tests/test_data/arch_fixtures \
-j $(nproc)

- name: Remove unused files to free space
run: rm -rf ${BUILD_DIR}/*

Expand Down Expand Up @@ -350,6 +361,13 @@ jobs:
${INSTALL_TEST_DIR}/ov_conditional_compilation_tests --gtest_print_time=1 \
--gtest_output=xml:${INSTALL_TEST_DIR}/TEST-ConditionalCompilation.xml

- name: GGUF frontend tests
if: ${{ !cancelled() }}
run: |
source ${INSTALL_DIR}/setupvars.sh
${INSTALL_TEST_DIR}/ov_gguf_frontend_tests --gtest_print_time=1 \
--gtest_output=xml:${INSTALL_TEST_DIR}/TEST-GGUFFrontend.xml

- name: IR frontend tests
if: ${{ !cancelled() }}
run: |
Expand Down
24 changes: 23 additions & 1 deletion .github/workflows/ubuntu_22.yml
Original file line number Diff line number Diff line change
Expand Up @@ -131,6 +131,7 @@ jobs:
build-debian-packages: true
build-rpm-packages: false
build-additional-python-packages: true
generate-gguf-fixtures: true
target-branch: ${{ inputs.target-branch }}
cmake-options: >-
-G 'Ninja Multi-Config'
Expand Down Expand Up @@ -493,6 +494,26 @@ jobs:
model_scope: 'precommit'
image: ${{ fromJSON(needs.docker.outputs.images).ov_test.ubuntu_22_04_x64 }}

GGUF_Models_Tests_Precommit:
name: GGUF Models tests
if: ${{ github.event_name != 'schedule' && fromJSON(needs.smart_ci.outputs.affected_components).GGUF_FE.test }}
needs: [ Docker, Build, Smart_CI ]
uses: ./.github/workflows/job_gguf_models_tests.yml
with:
runner: 'aks-linux-8-cores-32gb'
model_scope: 'precommit'
image: ${{ fromJSON(needs.docker.outputs.images).ov_test.ubuntu_22_04_x64 }}

GGUF_Models_Tests_Nightly:
name: GGUF Models Nightly tests
if: ${{ github.event_name == 'schedule' }}
needs: [ Docker, Build, Smart_CI ]
uses: ./.github/workflows/job_gguf_models_tests.yml
with:
runner: 'aks-linux-16-cores-64gb'
model_scope: 'nightly'
image: ${{ fromJSON(needs.docker.outputs.images).ov_test.ubuntu_22_04_x64 }}

NVIDIA_Plugin:
name: NVIDIA plugin
needs: [ Docker, Build, Smart_CI ]
Expand Down Expand Up @@ -660,7 +681,8 @@ jobs:
Overall_Status:
name: ci/gha_overall_status
needs: [Smart_CI, Build, Debian_Packages, Samples, Conformance, CXX_Unit_Tests, Python_Unit_Tests, TensorFlow_Layer_Tests, Pytorch_Layer_Tests,
CPU_Functional_Tests, TensorFlow_Models_Tests_Precommit, PyTorch_Models_Tests, JAX_Models_Tests_Precommit, NVIDIA_Plugin, Openvino_tokenizers, iGPU,
CPU_Functional_Tests, TensorFlow_Models_Tests_Precommit, PyTorch_Models_Tests, JAX_Models_Tests_Precommit, GGUF_Models_Tests_Precommit,
NVIDIA_Plugin, Openvino_tokenizers, iGPU,
Keras3_OpenVINO_Backend, iGPU_RoPE_Tests]
if: ${{ always() }}
runs-on: ubuntu-latest
Expand Down
1 change: 1 addition & 0 deletions .github/workflows/ubuntu_24.yml
Original file line number Diff line number Diff line change
Expand Up @@ -109,6 +109,7 @@ jobs:
build-debian-packages: true
build-contrib: true
build-additional-python-packages: true
generate-gguf-fixtures: true
target-branch: ${{ inputs.target-branch }}
cmake-options: >-
-G 'Ninja Multi-Config'
Expand Down
12 changes: 5 additions & 7 deletions src/frontends/common/src/manager.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -19,9 +19,10 @@ using namespace ov;
using namespace ov::frontend;

namespace {
// Frontends for direct linkage only: loadable, but never listed by available_front_ends() nor
// auto-selected by load_by_model / load_by_framework. A manager-side list (not a plugin-info flag)
// keeps the public FrontEndPluginInfo struct / ABI unchanged.
// Hidden frontends are absent from available_front_ends() and skipped by load_by_model, so they
// are never picked up implicitly (notably by core.read_model), but stay loadable on explicit
// request via load_by_framework(). Kept manager-side to leave FrontEndPluginInfo's ABI unchanged.
// "gguf" is listed because reading GGUF through core.read_model is not supported yet.
bool is_hidden_frontend(const std::string& name) {
static const std::set<std::string> hidden_frontends = {"gguf"};
return hidden_frontends.count(name) != 0;
Expand Down Expand Up @@ -71,10 +72,7 @@ class FrontEndManager::Impl {
// Load plugins until we found the right one
for (auto& plugin : m_plugins) {
OPENVINO_ASSERT(plugin.load(), "Cannot load frontend ", plugin.get_name_from_file());
// Hidden frontends are not selectable by name through the generic API.
if (is_hidden_frontend(plugin.get_creator().m_name)) {
continue;
}
// Not filtered by is_hidden_frontend: asking for a frontend by name is explicit.
if (plugin.get_creator().m_name == framework) {
return make_frontend(plugin);
}
Expand Down
3 changes: 3 additions & 0 deletions src/frontends/gguf/.gitignore
Original file line number Diff line number Diff line change
@@ -0,0 +1,3 @@
# The root .gitignore's "[Bb]uild*/" rule (meant for CMake build output dirs) also matches
# the src/builder/ source directory by name. Re-include it; this is tracked source code.
!src/builder
Loading
Loading