Repository navigation
feat(core): ryzenai-corelib 0.53.0, Qwen3.8-27B, Q4 Qwen3.6, paged context to each model's maximum - #859
Merged
Conversation
- Add a llama3 core backend over corelib's built-in llama model, catalogued as llama3.2-core:1b/3b and llama3.1-core:8b on dev04. - Align the Llama3 frontend's capacity check, poison guard and failure handling with Phi-4/Qwen3. - _shared_generate: leave a token cut off by the budget, the decode window or a cancel out of token_history, so the next turn prefills it. - Tests: test/llama_core frontend suite, test_llama_core_backend, and cut-off-token cases for the core and flm backends.
…hat library and prefix cache automodel.cpp now calls PrefixSlotCache and the chat library, and Sampler::sample takes an allowed-token mask and a logprobs out-parameter. The llama, phi4 and gemma4 frontend harnesses compile prefix_slot_cache.cpp; the llama harness also links flm_xgrammar and stubs the new sample signature. Co-authored-by: Cursor <cursoragent@cursor.com>
… tables in the frontend harnesses modeling_llama3.cpp and modeling_phi4.cpp now attach the prefix cache through llama_npu_state_api / phi4_npu_state_api, which only the engine libraries export; the harnesses return a null table, which leaves the cache off. The llama harness also gets the Sampler::set_seed and set_repeat_last_n stubs the phi4 and gemma4 ones already have. Co-authored-by: Cursor <cursoragent@cursor.com>
corelib splits a model from its sessions (0.48.0): create_model_from_path replaces model_weights_create_path, model_create_session replaces model_create, and forward, reset, get_info, state_save and state_restore take the session. CorelibModel keeps one model for the engine's life and opens a new session of it when the capacity grows, so a larger context no longer re-reads the weights. model_session_options is model_create_options renamed, with lora and enabled_backends appended; zero leaves both at their defaults. model_info_get is model_get_info (0.53.0). flat_mha_bf16, its enum_kernels and paged_mha_bf16_enum_kernels become one mha_bf16 (0.37.0). Nothing here called them, but the function table resolves every symbol at load, so they leave it. ryzenai_corelib_get_hardware_context goes (0.53.0): each stream opens its own hardware context on a device corelib keeps to itself. The process no longer takes corelib's xrt::device; it opens its own for every other family, and a core model shares no buffer with those engines. corelib_device.hpp goes, and main.cpp keeps its XRT-only #error. The runtime is ready only where ryzenai_corelib_npu_usable says so: on a refused NPU stack corelib now runs a session on the GPU or the host instead of failing. The fake corelib follows every signature and tells a model from a session, both an object_ptr to the compiler, refusing one passed for the other as corelib would. The docs name 0.53.0; core-setup-linux.md adds RYZENAI_CORELIB_DISABLE_GPU and RYZENAI_CORELIB_PROFILE and drops RYZENAI_CORELIB_NO_RUN_POOL and RYZENAI_CORELIB_MAX_RUNS_IN_FLIGHT, which corelib no longer reads. Co-authored-by: Cursor <cursoragent@cursor.com>
…aximum Qwen3.8-27B runs on corelib's qwen38 under the qwen3.8-mtp family, so it takes the Qwen3_8MTP frontend; insert() reached the engine's restore() and checkpoint() through a cast to the FastFlowLM engine, which is null for a core engine, and now calls them on the causal_lm, and the MTP loop speculates only where the engine says it can. Its catalog entry, qwen3.8-core:27b, prefers amd/Qwen3.8-27B-Q4_G128-GGUF, the Q4_G128 corelib runs on the NPU, converted from amd/Qwen3.8-27B_gpuep_1.0_gpu_128 at 9b37cf56 (15,964,921,824 bytes, the sha256 corelib's qwen38.md records), and falls back to unsloth's public Q4_0, which corelib runs on the GPU. Qwen3.6 prefers amd/Qwen3.6-35B-A3B-Q4_G32-GGUF over its public Q8_0. Both repositories are pinned to main until they are published; model_info.json carries every file's size and sha256. corelib 0.53 pages every model's KV cache a page at a time, so each backend takes the most corelib runs it at: Qwen3 32768, Llama, Phi-4-mini and Gemma 4 131072, Qwen3.5, Qwen3.6 and Qwen3.8 262144. Gemma 4's rule of whole pages past 4096 goes, corelib rounding any capacity up. Llama, Qwen3, Phi-4-mini and Gemma 4 continue from the page a later prompt starts in rather than from 0: corelib steps a pass off a page boundary one row at a time, and a whole page from a boundary runs as one. Qwen3.5 now restores a snapshot at its checkpoint instead of replaying. The catalog defaults to the longest context corelib records no accuracy problem at: Llama and Phi-4-mini 131072, Qwen3 32768, Gemma 4 65536 (PAGED_ATTENTION_POSITION_WRAP past 65535), and 32768 for Qwen3.5, Qwen3.6 and Qwen3.8, whose paged decode drifts the more pages it attends (PAGED_DECODE_PAGE_DRIFT); a longer one up to the limit is asked for. Co-authored-by: Cursor <cursoragent@cursor.com>
…3.6's 32768 corelib fails only the call that failed, and a 4096-row paged prefill can intermittently fail to complete (PAGED_PREFILL_PREEMPTION_TIMEOUT): on an AIE4 test machine, with another user's process on the NPU, Qwen3.8 and Qwen3-4B lost a 19k-token prompt that ran clean on the next try, and corelib's own runner failed the same way. The engine was poisoned on the first failure, so every later request failed until a reload. CorelibModel now resets the session and runs everything it held plus the new tokens again from position 0, once, and poisons the engine only when that fails too or the failure is not corelib's. Qwen3.6's paged attention past 32768 can return garbage (a passkey at 48k tokens came back as "!" repeated, on an AIE4 test machine), so a context past 32768 still loads but says so: BackendSpec gains reliable_context and the reason given when a context exceeds it. Co-authored-by: Cursor <cursoragent@cursor.com>
qwen.md lists every -core tag with the file it pulls by default, its public fallback, its context limit and its default, how a later turn continues, and the limits corelib and an AIE4 test machine found: Qwen3.6 past 32768, Qwen3.8 on long prompts, the paged decode drift, Gemma 4 past 65535, Llama on a very long repetitive prompt, and the retried prefill timeout. phi.md drops the 4096 ceiling: corelib runs Phi-4-mini to 131072 with LongRoPE's long factors past one page. Co-authored-by: Cursor <cursoragent@cursor.com>
modeling_gemma4e.cpp attaches the prefix cache through gemma4e_npu_state_api since upstream's prefix slots for Gemma 4; only the engine exports it, so the harness returns a null table, which leaves the cache off, as the llama and phi4 harnesses do. Co-authored-by: Cursor <cursoragent@cursor.com>
…d commits amd/Qwen3.8-27B-Q4_G128-GGUF at deab6eaf and amd/Qwen3.6-35B-A3B-Q4_G32-GGUF at 53a2155b, in place of main: every file there matches model_info.json's size and sha256. Co-authored-by: Cursor <cursoragent@cursor.com>
chizamd
marked this pull request as ready for review
October 28, 2026 06:51
flm list offered whatever default_npu_platform() was compiled to: dev04 in every corelib build, aie2p in every other, whatever the silicon. A corelib build now asks corelib, once per process, which NPU it has: AIEM is dev04, and AIE2P, none, or a corelib that cannot be loaded is aie2p. corelib reads the device itself, so FastFlowLM keeps no table of devices, IDs or geometry; a build without corelib answers aie2p, as every dev04 model is a corelib one. The question goes through ryzenai_corelib_testing_npu_arch, the one entry point that names the architecture whatever the NPU stack's version, until corelib's public header has one; the header is included after the version pin, which a testing hook makes the more necessary. CorelibRuntime::NpuArch loads the API without the readiness check, which refuses an AIE2P, and GetOrCreate reuses that load. On aie2p, main() no longer reports corelib as unavailable for every run: there it has nothing to run. On this AIE2P machine a corelib build lists the FastFlowLM models and none of the -core ones. Co-authored-by: Cursor <cursoragent@cursor.com>
Co-authored-by: Cursor <cursoragent@cursor.com> # Conflicts: # src/common/AutoModel/modeling_qwen3_8mtp.cpp # src/model_info.json
Co-authored-by: Cursor <cursoragent@cursor.com> # Conflicts: # src/common/AutoModel/automodel.cpp
…shared_generate now does ROCm#870 counts the token insert() sampled toward generated_tokens and the length limit. A 4093-token prompt in a 4095-token window now reports 3 generated tokens, the engine still running 11 and 12; and a budget of 2 is what leaves 12 sampled but never run, as a budget of 1 did. Co-authored-by: Cursor <cursoragent@cursor.com>
flm validate in a corelib build skipped every check and answered checks_skipped / ready, on any NPU: the skip was decided at compile time, when every corelib build was taken for dev04. Lemonade gates FastFlowLM's install on validate, so on XDNA2 it no longer checked the driver, the firmware or memlock. The skip is now the machine's: only a dev04 NPU, where corelib owns device setup, skips (and says npu_platform), and an aie2p one runs the same checks as a build without corelib. validate also runs before the device is opened, as it does in that build, since on Linux it probes /dev/accel itself and amdxdna refuses a second open. On an XDNA2 machine with driver 32.0.203.281, below the 32.0.203.304 minimum, a corelib build now reports npu_driver_ok false and ready false where it reported the checks skipped. Co-authored-by: Cursor <cursoragent@cursor.com>
On dev04, flm validate skipped every check and answered ready, so a caller gating on it, Lemonade among them, learned nothing about the NPU stack. The stock checks do not apply there -- they hold an XDNA2 device ID, driver line, firmware and column count against FastFlowLM's own kernels -- but corelib's own gate does: validate now brings corelib up as the core backend does, which loads XRT and asks whether this is an NPU whose stack corelib supports (on Windows, XRT and the NPU driver at corelib's minimums), opening no context. ready is that answer, and on Linux the memlock limit too, shared with the aie2p checks. The JSON reports corelib_npu_ok, and corelib_error when it is false, in place of checks_skipped. Co-authored-by: Cursor <cursoragent@cursor.com>
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.
Moves the
corebackend to ryzenai-corelib 0.53.0, adds Qwen3.8-27B, takes Qwen3.6-35B-A3B to its Q4_G32 file, and runs every core model on paged attention up to the most corelib runs it at, AMD's 4-bit GGUFs by default. Thirteen commits, andmainmerged in atf37cdd29.Model repositories:
preferred_sourcepinsamd/Qwen3.8-27B-Q4_G128-GGUFatdeab6eafandamd/Qwen3.6-35B-A3B-Q4_G32-GGUFat53a2155b(private, like the otheramd/*-Q4_*-GGUF); every file there matchesmodel_info.json's size and sha256.Commits
main; the commits below build on it.gemma4e_npu_state_api— the core frontend test harnesses link again againstmain's prefix slots and sampler.create_model_from_pathandmodel_create_sessionreplacemodel_weights_create_pathandmodel_create, and forward, reset,model_get_infoand the state calls take the session; a larger context opens a new session of the same model rather than re-reading the weights.get_hardware_contextis gone (0.53.0): each stream opens its own context on a device corelib keeps, soflmopens its own device for the other families andcorelib_device.hppgoes; the core backend comes up only whereryzenai_corelib_npu_usable()says so, since corelib now runs a session on the GPU or the host on a refused NPU stack.flat_mha_bf16andpaged_mha_bf16_enum_kernelsleave the function table (0.37.0).qwen3.8-core:27bruns on corelib'sqwen38under theqwen3.8-mtpfamily'sQwen3_8MTPfrontend, which reachedrestore()/checkpoint()through a cast to the FastFlowLM engine (null for a core engine) and now goes through thecausal_lm. It prefers the Q4_G128 corelib runs on the NPU, converted fromamd/Qwen3.8-27B_gpuep_1.0_gpu_128at9b37cf56(sha256 as corelib'sqwen38.mdrecords), falling back to unsloth's public Q4_0, which corelib runs on the GPU.qwen3.6-moe-core:35b-a3bprefers its Q4_G32, fromamd/Qwen3.6-35B-A3B_gpuep_1.0_gpu_128atc2fdd896, over the public Q8_0.PAGED_PREFILL_PREEMPTION_TIMEOUT); the engine was poisoned on the first failure. It now resets the session and runs everything again from position 0, once. A Qwen3.6 context past 32768 loads with a warning.qwen.mdlists every-coretag's file, fallback, limit, default and known limits;phi.mddrops the 4096 ceiling.PAGED_ATTENTION_POSITION_WRAPpast 65535)PAGED_DECODE_PAGE_DRIFT)With an HF token that reads AMD's repositories every tag but Qwen3-0.6B and the Llama tags pulls a 4-bit GGUF; those have only a Q8_0 (corelib's
llamareads Q8_0 only), refit to 4-bit groups on load.flm listoffered whateverdefault_npu_platform()was compiled to: dev04 in every corelib build, aie2p in every other. A corelib build now asks corelib once per process: itsAIEMis dev04, andAIE2P, none, or a corelib that cannot be loaded is aie2p; a build without corelib answers aie2p, as every dev04 model is a corelib one. corelib reads the device itself, so FastFlowLM holds no table of devices, IDs or geometry. The question goes throughryzenai_corelib_testing_npu_arch(included after the version pin) until corelib's public header names the architecture. On aie2p,flmno longer reports corelib unavailable on every run.#870's_shared_generatecounts the token the prefill samples towardgenerated_tokensand the length limit, so twophi4_coreexpectations move by one (mainfails the same two).flm validatein a corelib build answeredchecks_skippedandreadyon any NPU, the skip decided at compile time; Lemonade gates FastFlowLM onvalidate, so on XDNA2 it no longer checked the driver, the firmware or memlock. aie2p now runs the same checks as a build without corelib, before the device is opened, as there.validatebrings corelib up as the core backend does: XRT loads, and the NPU stack is one corelib supports (on Windows, XRT and the NPU driver at corelib's minimums), opening no context.readyis that, and memlock on Linux; the JSON reportscorelib_npu_ok, andcorelib_errorwhen false, in place ofchecks_skipped.The merges of
mainkeep#863's prefix slots inQwen3_8MTP::insertand callsrestore()/checkpoint()there through thecausal_lm, as commit 5 does;model_info.jsontakesmain's and adds this branch's six keys;automodel.cpptakes#870's_shared_generate, whose singlepop_backon every stop but EOT replaces the two this branch had.Testing
On this branch after the merge:
core_model4/4,phi4_core5/5,model_backend1/1,gemma4_core3/3,llama_core1/1,model_list_platform1/1,chat_continue1/1, against the 0.53.0 headers;flm.exebuilds with-DFLM_ENABLE_CORE=ON. Platform detection: on an AIE2P (Strix) machine a corelib build lists the 51 FastFlowLM models and no-coreone; on an AIE4 machine it lists the 14-coremodels only.flm validate --jsonon that AIE2P machine, whose NPU driver 32.0.203.281 is below the 32.0.203.304 minimum, now reportsnpu_driver_ok: false,ready: falseinstead of skipping; on the AIE4 machine it reportsnpu_platform: dev04,corelib_npu_ok: true,ready: true.On an AIE4 (Medusa) test machine (XRT 2.27.0, NPU driver 10.1.0.3575), the same commits on an internal branch, with another user's processes on the NPU for most runs:
test_real_corelibpasses; every-coretag at its default context answers three greedy prompts correctly (Qwen3.8 at 5.5 tok/s decode, Qwen3.6 at 32.8); two-turn passkey recall across pages is right for Qwen3-4B, Qwen3.5-9B, Qwen3.6, Gemma 4 E2B, Llama 3.2 3B and Phi-4-mini; Phi-4-mini recalls a passkey after ~96k tokens.Known limits, each reproduced through corelib's own runner too, so corelib's: Qwen3.6 past 32768 and Qwen3.8 on long prompts can return
!repeated (Qwen3.8 intermittently, from about 10k tokens), and so did Llama 3.2 3B on a ~96k-token prompt of one repeated sentence.qwen.mdlists them.