Skip to content

npu: load Ryzen AI OGA NPU model packs on Linux through the engine (pack import -> Q4NX -> our kernels) #671

Open

Description

@bong-water-water-bong

Goal (owner, 2026-10-30): a Ryzen AI OGA NPU model pack (*_rai_*_npu_*: model.onnx + external data, genai_config.json, descriptors) dropped on a Linux box runs on the NPU through 1bit serve with the engine's own runtime and kernels. The pack supplies the weights, tokenizer and config; the engine supplies everything else. No vendor wheel or shared object is linked, shipped or required, and no vendor-compiled NPU program is executed.

Plan:

  1. 1bit npu-pack import <pack-dir> -o <dir>: parse the pack's quantized weights (MatMulNBits tensors, documented com.microsoft contrib op) into the Q4NX container with a layout-version field; self-check dequantises sampled tensors against the reference values bit for bit.
  2. Per-shape full ELFs for the pack model's geometry from our generator (decode M=16 twins, prefill M=128), bit-exact against the CPU reference.
  3. Gates on the first pack (Qwen2.5-0.5B-Instruct npu_4K): greedy output identical to the vendor stack on three prompts, 12-chunk KLD of our logits vs the vendor stack, decode tok/s at ctx 128/512/2048 and prefill at 128/2048 side by side with the vendor stack measured the same hour, medians of 3.
  4. A second pack of a different family from the public collection; unsupported pack features filed as issues.
  5. Later: the ORT execution provider (onnx: ONNX Runtime in-process behind -DONEBIT_ORT, with our plugin EP #647) claims the pack graph; out of scope here.

Related: #647 (ORT EP), #640 (two NPU engines), #650-#653 (NPU feature gaps).

🤖 Generated with Claude Code

Activity

  1. bong-water-water-bong commented on Oct 31, 2026

    @bong-water-water-bong
    CollaboratorAuthor

    Triage: enhancement. Item 1 is genuinely not started at origin/main 31d52e1:

    $ git grep -ln 'genai_config\|MatMulNBits\|npu-pack' origin/main -- app/ npu/ tools/ docs/   -> no file
    

    Lane: pi-ogaload. Two facts that bound the first PR:

    1. Items 1 and 2 are separable, and item 1 is the one that can land from this box. The importer reads the
      pack's model.onnx initializers plus genai_config.json and writes Q4NX with a layout-version field; the
      self-check (sample tensors dequantised against the documented com.microsoft MatMulNBits formula,
      bit-exact) is the test, and it needs no device. Item 2's per-shape full ELFs (decode M=16 twins, prefill
      M=128) are device work and follow.
    2. onnx: ONNX Runtime in-process behind -DONEBIT_ORT, with our plugin EP #647 is not a substitute for this. 8b6895e lands ONNX Runtime in-process behind -DONEBIT_ORT with
      our plugin EP — that claims the pack graph. This issue claims the weights by re-packing them into our
      container, which is what makes a pack runnable on the engine's own kernels today, with no vendor wheel,
      shared object or vendor-compiled program anywhere in the path. Keeping them separate is what keeps that
      constraint checkable.

    One thing I would add to the plan while it is still cheap: a pack that the importer cannot represent
    (supported pack features are a moving target) should exit with a named refusal listing the unsupported
    attribute, not a partial conversion — item 4 says unsupported features become issues, and that only works if
    the importer names them.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Metadata

Metadata

Assignees

No one assigned

    Labels

    enhancementNew feature or request

    Type

    No type

    Projects

    No projects

      Milestone

      No milestone

      Relationships

      None yet

      Development

      No branches or pull requests

      Issue actions