Repository navigation
feat(core): move to ryzenai-corelib 0.33.1, run every corelib model behind one engine, prefer AMD Q4 GGUFs, rename rai to core - #774
Merged
Conversation
chizamd
force-pushed
the
feature/dev01-update
branch
from
October 14, 2026 10:38
047076b to
bb5fcc2
Compare
chizamd
marked this pull request as ready for review
October 14, 2026 11:12
aaronn-xilinx
approved these changes
Oct 15, 2026
chizamd
force-pushed
the
feature/dev01-update
branch
from
October 16, 2026 04:11
bb5fcc2 to
b7d3829
Compare
…ma 4 at 16k Moves the `--rai` backend from ryzenai-corelib 0.11 to 0.26 and builds on what the new corelib offers. corelib 0.26 (pinned exactly): - Follow the ABI changes: `create_tensor_window` takes strides, `linear_attention_bf16` takes rows, and models are built with `model_weights_create_path` + `model_create`. - A 3-D matmul output that writes the KV cache is a strided window `[max_seq*head, head, 1]` (Phi-4, Qwen3, Qwen3.5 V writes; Gemma 4 E4B staging window). - Per-op engines open their stream through `corelib::OpenModelStream`, which enables the model's kernel bundle before any kernel query. - corelib's per-model libraries are copied beside `flm.exe` on Windows and beside corelib by `home_install.sh` on Linux. Nothing needs `RYZENAI_CORELIB_DD_ROOT` or `RYZENAI_CORELIB_KERNELS_ROOT` any more. Qwen3.6-35B-A3B (new `qwen3.6-moe-rai:35b-a3b`, text only): - Runs on corelib's model API; context up to 262144 in 4096-row pages, a prompt is a single `model_forward`, and checkpoint/restore use corelib state snapshots. - Fetch logits only for the row that gets sampled. Gemma 4: - Context of 1..4096 on flat attention, or a multiple of 4096 up to 16384 on corelib paged attention; the aie_next catalog entries default to 16384. A paged continuation starts from its own page. - `gemma4-it-rai:e4b` is offered again. Shared: - `Sampler::sampler_topk_apply` selects top-k with a k-entry heap in one pass (same ranking and tie rule). Tests: new `src/test/qwen36_rai`, and the Gemma 4, Phi-4 and Qwen3 rai tests and fake corelib follow the 0.26 ABI and the 16k paged context. Co-authored-by: Cursor <cursoragent@cursor.com>
Qwen3, Qwen3.5 and Gemma 4 on the `rai` backend stop driving corelib op by op and run as corelib's own models (`ryzenai_corelib_model_*`), the way Qwen3.6 already does. All four share one engine and one backend; each model is a short spec. Phi-4 is unchanged (corelib's `phi4mini` takes ONNX only, and FastFlowLM ships a GGUF). - `flm::rai::CorelibModel` (`rai/corelib_model`): a `causal_lm` over a corelib model, generalized from the Qwen3.6 engine. `ModelSpec` states where a multi-row pass may start (`Continuation`: anywhere, only at 0, or at 0 / a 4096-row page boundary) and how to rewind (`Rewind`: seek, state snapshot, or reset and replay). Token ids and the context limit are checked before corelib is called; a failed forward, restore or reset poisons the engine. - `flm::rai::Factory(BackendSpec)` (`rai/corelib_model_backend`): refuses preemption and a context outside the model's rule, reads the package's BOS/EOS ids, and resolves the GGUF before the runtime or weights are touched. - Removed: the per-op engines, GGUF readers, shape plans and host math of Qwen3, Qwen3.5 and Gemma 4; `rai/gguf_file`, `rai/weight_cache`, the Q8/RMSNorm parts of `rai/host_ops`, and 14 unused corelib entry points. corelib packs the weights on every load; old `<gguf stem>.rai-weights.bin/.json` files can be deleted. - Tests: new `src/test/rai_model` (engine and backend against the fake corelib; the Qwen3.6 tests move here). Gemma 4's registry, catalog and server-gate tests move to `test_gemma4_registry.cpp`; the op-level Gemma 4 and Qwen3 suites are gone. Gemma 4 is slower on corelib 0.26's built-in model than on the per-op engine (prefill ~1.5-2x, decode 24-29% slower, slower loads). The cause is in corelib's host per-layer-embedding projection and serial weight packing; FastFlowLM picks up the fix with a corelib version bump. Co-authored-by: Cursor <cursoragent@cursor.com>
…efill chunks to pages corelib 0.28 pages Qwen3.5's KV cache up to 32768 and runs Qwen3.6's prefill past page 0 in whole-page passes. A later turn's prompt is now chunked on multiples of 4096 counted from position 0, so its chunks start on page boundaries. Co-authored-by: Cursor <cursoragent@cursor.com>
No ABI change FastFlowLM meets. 0.29 speeds up Gemma 4's per-layer-embedding projection and runs Qwen3.6's prefill chunks inside a page on the NPU. Co-authored-by: Cursor <cursoragent@cursor.com>
No ABI change. corelib now refuses a Qwen3.6 capacity past 131072 at model_create, the most it has verified on the NPU, so kRaiContextLimit drops from 262144 to 131072 and qwen.md's memory figures follow. Qwen3.5 and 3.6 refusing an explicit position other than 0 or their own does not reach FastFlowLM, which passes POSITION_CONTINUE to both and resets before a replay; nor does a model that refuses to continue after a failed forward, since the engine is poisoned there. Co-authored-by: Cursor <cursoragent@cursor.com>
The backend id, the "-rai" tag suffix, the FLM_ENABLE_RAI option, the presets, the FLM_RAI_* environment variables and home_install.sh's --rai flag all move to "core"; the platform id and enum value move to "dev04". The directories and files carrying either name move with them. No old name is kept as an alias. ryzenai-corelib and RYZENAI_CORELIB_* name the external library and stay. llama3_results.md's "NPU (RAI)" is the Ryzen AI software baseline, not this backend, and stays. Co-authored-by: Cursor <cursoragent@cursor.com>
No ABI change: corelib.def is untouched and corelib.h only changes its version and comments. The version pin and the four docs that name it move to 0.29.7. 0.29.5 to 0.29.7 let Gemma 4 and Qwen3.6 also read Q4_G32 GGUFs; the unsloth Q8_0 files model_list.json names give the same logits as on 0.29.4. src/test/phi4_core's version-pin probe can fail again. Its include paths went through CMAKE_CXX_FLAGS, which try_compile does not pass on, so the probe failed on the missing header and that passed as a rejection; and it only rewrote a patch version of 0. It now passes INCLUDE_DIRECTORIES, compiles only, must first compile against the real header, and must then fail on the pin's own #error against a header rewritten to patch 9999. Co-authored-by: Cursor <cursoragent@cursor.com>
…ic Q8_0 `flm pull` tries the AMD Q4 GGUFs first for the core (dev04) models and falls back to the existing public Q8_0 source when the AMD repo can't be reached. - phi4-mini-it-core:4b: amd/Phi-4-mini-instruct-Q4_G128-GGUF - qwen3-core:1.7b / 4b / 8b: amd/Qwen3-*-Q4_G128-GGUF - qwen3.5-core:4b (new, falls back to unsloth/Qwen3.5-4B-GGUF Q8_0) and qwen3.5-core:9b: amd/Qwen3.5-*-Q4_G128-GGUF - gemma4-it-core:e2b / e4b: amd/gemma-4-E*-it-Q4_G32-GGUF Each AMD source is pinned to a commit, and its GGUF to a sha256 in model_info.json (keyed `<tag>@amd`). Only the GGUF comes from AMD; the tokenizer and config files keep their pinned file_sources. - Catalog: an entry may carry `preferred_source`, a JSON merge patch over the entry that sets its own url, files, size, quantization level and model_info_key. - Pull: ModelDownloader::choose_pull_source sends a HEAD request for the preferred GGUF and uses the AMD source on 2xx/3xx; otherwise it prints `Falling back to: <url>` and uses the entry's own source. AMD files already on disk are kept without probing. - Outside a pull: model_list::get_model_info resolves an entry to its preferred source exactly when every file only that source has is on disk, so run, serve, list and check follow whatever was pulled. - Auth: the AMD repos currently need a Hugging Face token, read from HF_TOKEN, HUGGING_FACE_HUB_TOKEN, HF_TOKEN_PATH, HF_HOME/token or ~/.cache/huggingface/token. It is sent only for a `"use_hf_token": true` source, only to https://huggingface.co/, with TLS verification on. Public sources never get it, because the Hub answers 401 to an expired token even on a public repo. A bare `qwen3.5-core` now resolves to 4b, the first key in sorted order. Footprints for the AMD sources are scaled from each base entry by file size, not measured. test_model_downloader gains offline file:// tests for resolving by what is on disk, keeping a pulled preferred source, and falling back when it is unreachable.
…4_G128
phi4-mini-it-core:4b now runs on corelib's own phi4mini model through the
shared core backend, like Qwen3, Qwen3.5, Qwen3.6 and Gemma 4. corelib's
phi4mini reads a phi3 GGUF in Q8_0 or Q4_G128, so the AMD Q4_G128 GGUF
that `flm pull` prefers now loads and runs; the per-op engine it replaces
took only Q8_0, under a fixed filename.
- phi4_core_backend.cpp is a spec for core::Factory: corelib model
phi4mini, context 4096, multi-row passes only from position 0 (a later
turn re-runs the conversation, as before), Rewind::kSeek, and stop
tokens {200020, 199999} (`<|end|>` and `<|endoftext|>`; the package
names only the second). The GGUF is the one the catalog resolves to.
- Removed: the per-op engine (its GGUF reader and contract check, host
ops, shape plan and packed-weight cache), its tests, and
core/kernel_grid.hpp and core/weight_source.hpp, which only it used.
- Added test/core_model/test_phi4_core_backend.cpp, which runs the real
factory against the fake corelib.
- Docs: phi.md covers the AMD and unsloth sources and the absence of a
weight cache; qwen.md lists Phi-4 among the models corelib runs whole;
the contributor guide points to the last per-op engine in history.
fix(automodel): keep an EOS the engine never ran out of the token history
_shared_generate appended every sampled token to token_history, including
an EOS the engine never ran: one sampled straight from the prefill, and,
on a backend that declines the post-EOS forward (every core backend), the
EOS that ends a decode. The next turn's prefix match then treated it as
already held, so the engine never saw the end-of-turn token between the
reply and the next user message. That token is now left out of the
history and prefilled with the next turn. A new frontend test covers both
cases on core and the unchanged flm behaviour.
- The version pin moves to 0.33.1 (include/core/corelib_api.hpp), and the four docs that name it. - model_forward takes images, options, out_token and the logits as arguments (corelib 0.31.0), and forward_options gains a leading `size` that corelib refuses when short (0.33.0). CorelibModel, which now runs every core model, sets `size` and passes its logits buffer only when it wants logits. - create_stream takes a priority list of PDIs per phase (0.30.0). OpenModelStream, which nothing calls any more but which stays in the header, passes its two PDIs as one-element lists. - The fake corelib follows both signatures, records a stream's PDI lists, and refuses short forward options as corelib does. - core-setup-linux.md: RYZENAI_CORELIB_FALLBACK_PROFILE is now RYZENAI_CORELIB_REPORT_FALLBACKS, and RYZENAI_CORELIB_TRACE_XRT is gone in favour of RYZENAI_CORELIB_TRACE=xrt. Every other function and struct FastFlowLM binds is unchanged, and corelib.def only adds exports. corelib 0.31-0.33 also add Qwen3.6 image input and rope_positions, which FastFlowLM does not pass (it runs Qwen3.6 text only; corelib reports text-only logits unchanged).
chizamd
force-pushed
the
feature/dev01-update
branch
from
October 16, 2026 04:15
b7d3829 to
bb91d58
Compare
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
Add this suggestion to a batch that can be applied as a single commit.This suggestion is invalid because no changes were made to the code.Suggestions cannot be applied while the pull request is closed.Suggestions cannot be applied while viewing a subset of changes.Only one suggestion per line can be applied in a batch.Add this suggestion to a batch that can be applied as a single commit.Applying suggestions on deleted lines is not supported.You must change the existing code in this line in order to create a valid suggestion.Outdated suggestions cannot be applied.This suggestion has been applied or marked resolved.Suggestions cannot be applied from pending reviews.Suggestions cannot be applied on multi-line comments.Suggestions cannot be applied while the pull request is queued to merge.Suggestion cannot be applied right now. Please check back later.
Follow-up to #748. Moves the corelib backend from ryzenai-corelib 0.11 to 0.33.1, adds Qwen3.6-35B-A3B and Qwen3.5-4B, runs Gemma 4 at 16k and Qwen3.5 at 32k, has every corelib model (Phi-4, Qwen3, Qwen3.5, Qwen3.6, Gemma 4) run as corelib's own model behind one shared engine, makes
flm pullprefer AMD's Q4 GGUFs with a public Q8_0 fallback, and renames the backend fromraitocore.Commits:
ryzenai_corelib_model_*, like Qwen3.6.rai→coreandaie_next→dev04, as above. Directories and files carrying either name move with them; no behaviour change.src/test/phi4_core's version-pin probe can fail again (it used to pass by failing on a missing include path).flm pullprefers AMD Q4 GGUFs for the core models and falls back to the public Q8_0 source. Addsqwen3.5-core:4b.phi4minimodel, Q8_0 or Q4_G128; the last per-op engine is removed. Also fixes the token history keeping an EOS the engine never ran.model_forward,forward_optionsandcreate_streamchange shape.Models
Every tag below runs as a corelib model through the shared engine.
qwen3.6-moe-core:35b-a3bgemma4-it-core:e2bgemma4-it-core:e4bqwen3-core:0.6bqwen3-core:1.7b4b8bqwen3.5-core:9bqwen3.5-core:4bqwen3.5-corenow resolves to4bphi4-mini-it-core:4bWhat changes
corelib 0.33.1 (version pinned exactly)
create_tensor_windowtakesstrides,linear_attention_bf16takesrows, and models are built withmodel_weights_create_path+model_create(name, weights, options).create_streamtakes a priority list of PDIs per phase.OpenModelStream, which nothing calls any more, passes its two PDIs as one-element lists.model_forwardtakes images, options,out_tokenand the logits as arguments, andforward_optionsgains a leadingsizethat corelib refuses when short.CorelibModelsetssizeand passes its logits buffer only when it wants logits.docs/core-setup-linux.md:RYZENAI_CORELIB_FALLBACK_PROFILEis nowRYZENAI_CORELIB_REPORT_FALLBACKS, andRYZENAI_CORELIB_TRACE_XRTis nowRYZENAI_CORELIB_TRACE=xrt.Packaging
ryzenai_corelibplus oneryzenai_corelib_model_<name>library per model and loads them only from its own directory. A Windows core build copies them besideflm.exe;home_install.shcopies them beside corelib on Linux.RYZENAI_CORELIB_DD_ROOT/RYZENAI_CORELIB_KERNELS_ROOTare no longer needed, and the installer stops staging DynamicDispatch.One engine:
flm::core::CorelibModel(include/core/corelib_model.hpp,common/core/corelib_model.cpp)causal_lmover a corelib model. Each model is a shortModelSpecnaming what differs:Continuation: where a multi-row pass may start past position 0 — anywhere (Qwen3.5, Qwen3.6), only at 0 (Qwen3 and Phi-4, so a later prompt re-runs the conversation), or at 0 / a 4096-row page boundary (Gemma 4).Rewind:kSeekfor attention-only models (every pass states its position; rewind just moves it),kSnapshotfor Qwen3.6 (model_state_save/restore, reused only if its history is a prefix of the current one),kReplayfor Qwen3.5 (reset and replay).One backend:
flm::core::Factory(BackendSpec)(include/core/corelib_model_backend.hpp)tokenizer_config.json+config.json, e.g. Gemma 4 → {1, 106}; Phi-4 adds<|end|>, which the package does not name), and resolves the GGUF the catalog points at before the runtime or weights are touched. Image requests on core return HTTP 400.Preferred AMD sources in
flm pull(model_list.hpp,pull/)preferred_source, a JSON merge patch over the entry that sets its ownurl,files,size, quantization level andmodel_info_key. Each AMD source is pinned to a commit, and its GGUF to a sha256 inmodel_info.json(keyed<tag>@amd); the tokenizer and config files keep their existing pinned sources.flm pullsends a HEAD request for the preferred GGUF and uses it on 2xx/3xx; otherwise it printsFalling back to: <url>and pulls the entry's own source. Files already on disk are kept without probing.run,serve,listandcheckfollow whatever was pulled.HF_TOKEN,HUGGING_FACE_HUB_TOKEN,HF_TOKEN_PATH,HF_HOME/tokenor~/.cache/huggingface/token). It is sent only for a"use_hf_token": truesource, only tohttps://huggingface.co/, with TLS verification on; public sources never get it. Without access, a pull falls back to the public Q8_0.Page-aligned prefill chunks (
AutoModel::_chunked_insert,model_backend.hpp)ModelBackend::aligns_prefill_chunks(), defaultfalse, so FastFlowLM's own engines are unaffected. The corelib-model backend returnstrue: a later turn's prompt is chunked on multiples of 4096 counted from position 0 instead of from the turn's start, so every chunk after the first starts on a page boundary and corelib runs it as whole pages on the NPU. Prompts carrying a multimodal payload keep the old chunking.EOS in the token history (
AutoModel::_shared_generate)Removed
rai/gguf_file,rai/weight_cache,core/kernel_grid.hpp,core/weight_source.hpp, the Q8/RMSNorm parts of the host ops, and the corelib entry points nothing calls.*.rai-weights.bin/.jsonandphi4-*-weights.*files can be deleted.Shared
Sampler::sampler_topk_applyselects top-k with a k-entry heap in one pass instead ofpartial_sorting a vocab-sized array each token. Same ranking and lowest-id tie rule; checked against the old code on 63 inputs (vocab 1..248320, k = 1/2/20/40, heavy ties).Docs:
src/common/models/README.mdgains a section on models corelib runs whole;docs/core-setup-linux.mdand the model pages cover the version, the AMD and public sources, and the dropped weight cache.Results
All on a
dev04NPU, Windows.Unit tests (fake corelib, 0.33.1 headers):
core_model,phi4_core,gemma4_coreandmodel_backendpass;test_model_downloaderincludes offlinefile://tests for the preferred-source logic.test_real_corelibagainst the 0.33.1 library loads it, matches the version and resolves every entry point.flm.exebuilds withFLM_ENABLE_CORE=ONagainst 0.33.1.Shared engine vs the per-op engines (measured at commit 4, corelib 0.29.2) — "before" is the first commit's build on corelib 0.26: the per-op engines for Phi-4, Qwen3, Qwen3.5 and Gemma 4, and Qwen3.6 on corelib's model API. Both builds run interleaved, Gemma 4 twice each, with the NPU checked idle before and after every run. Long-prompt TTFT is the median of three ~1.1k-token prompts; decode is the median over three short prompts, 64 greedy tokens each.
gemma4-it-core:e2bgemma4-it-core:e4bqwen3.6-moe-core:35b-a3bqwen3.5-core:9bqwen3-core:0.6bLoads are slower because corelib packs the weights on every load and this path has no packed-weight cache.
Phi-4 on corelib's
phi4minivs its per-op engine (commit 9, corelib 0.29.7):phi4mini, Q8_0phi4mini, AMD Q4_G128Q8_0 gives the same greedy text on both engines. A second turn, which the per-op engine refused (
Phi-4 prefill must start at logical position zero), now works, and a two-turn passkey is recalled on Q8_0 and Q4_G128.corelib 0.33.1 vs 0.29.7, and 0.29.7 vs 0.29.4 (each pair run interleaved): greedy text and TTFTs match on every model, Phi-4 on both its Q8_0 and Q4_G128 files. Decode and load differences followed run order rather than the build: rerun with the order swapped, the two builds match.
Two-turn continuation at
--ctx-len 16384: turn 1 is ~6.8k tokens carrying a passkey; turn 2 resends it with the reply and adds ~6.9k tokens, chunked on page boundaries (1395 / 4096 / 1414).qwen3.6-moe-core:35b-a3bgemma4-it-core:e2bThe same chunks and TTFTs within 0.1 s on 0.29.7 and 0.33.1.
Qwen3.6 at
--ctx-len 131072(corelib 0.29.4, 0.29.7 and 0.33.1): turn 1 is 49,917 tokens with a passkey, turn 2 ends at 75,442 tokens; every build recalls the passkey with the same seven turn-2 chunks, turn-2 TTFT 60–65 s.Measured on the second commit (corelib 0.26):
flm serveprocess: every answer matches a fresh run, no errors.Long-context passkey recall (passkey at 45% depth, measured on the first commit):
gemma4-it-core:e2bgemma4-it-core:e4bqwen3.6-moe-core:35b-a3bGemma 4 on corelib's built-in model. On corelib 0.26 it was slower than the per-op engine (prefill ~1.5–2×, decode 24–29% slower), because of corelib's host per-layer-embedding projection. corelib 0.29 fixes that projection: prefill is now faster than the per-op engine, and decode is equal on E4B and ~5–8% lower on E2B. Loads stay slower, as above.
Not done yet
main(merge was clean; the merged tree has not been built)flm_coreand thehome_install.sh --coresmoke test