DEEPSEEK4 SLOP Explanation. (Tested and is working correctly after build)
fix mtmd: missing text_len in gpttype_adapter.cpp aggregate init
Commit 4114ba18b ("mtmd: fix silent prompt truncation on embedded NUL
(#25548)") added a `text_len` field to `mtmd_input_text`, changing the
struct layout from:
{ text, add_special, parse_special }
to:
{ text, text_len, add_special, parse_special }
The aggregate initialization in `gpttype_adapter.cpp` was never updated
to account for the new field. With C++ aggregate init, the positional
arguments shifted:
mtmd_input_text inp_txt = {
mtmd_default_marker(), // text = "<__media__>"
/* add_special */ false, // text_len = 0 <-- BUG
/* parse_special */ true, // add_special = true
};
// parse_special is zero-initialized
Because text_len was 0, `input_text.assign(text->text, text->text_len)`
in the mtmd_tokenizer constructor produced an empty string.
`split_text()` on an empty string returned an empty vector, yielding
zero media markers in the text -- but one bitmap was still provided,
triggering the error:
mtmd_tokenize: error: number of media markers in text (0) does not
match number of bitmaps (1)
Fix by explicitly capturing the marker pointer and passing its length.
* chat: fix DS4 template to explicitly follow reference behavior
* Support DeepSeekv4 flag (`drop_reasoning`).
* fix: hook DS3.2 parser for DS4 as well
* fix: add tool result reordering
* fix: post-merge
* ggml: enable PowerPC backend variants on AIX
Allow the PowerPC CPU backend variants to be built on AIX by extending the platform check in the CMake configuration. This reuses the existing PowerPC backend implementations without changing their behavior.
Also fix a missing semicolon in the PowerPC Q0 matmul implementation.
* Fix missing semicolon in sgemm.cpp
* webgpu : add CONV_2D_DW (depthwise conv2d) kernel
Implement GGML_OP_CONV_2D_DW for the WebGPU backend,
ported from the Vulkan backend's conv2d_dw.comp.
Assisted-by: Claude Opus-4.8
* Remove unnecessary comments in webgpu support
* update supported ops tables, triggered by adding webgpu CONV_2D_DW
* cuda: add k-quant support to GET_ROWS
Device-side embedding lookups require GET_ROWS to handle the k-quants
used by common GGUF recipes (Q4_K_M stores token_embd as q6_K). Without
it the backend rejects the op and the scheduler falls back to the host,
copying the full embedding matrix back on every token in single-device
graphs.
Factor the super-block dequantizers out of the dequantize_block kernels
in convert.cu into shared device functions in dequantize.cuh and reuse
them from a new k_get_rows_kq kernel : one thread block dequantizes one
(dst row, super-block) pair with the existing thread layouts, 32 threads
for q4_K and 64 for the other k-quants.
Covers q2_K to q6_K in get_rows_cuda and supports_op. i-quants are left
as a TODO.
* cuda: add i-quant support to GET_ROWS
Extends the shared super-block dequantizers to the nine i-quants and
reuses them from k_get_rows_kq with the 32-thread layout of the matching
convert.cu kernels. supports_op gates the k-quant and i-quant path on
ne0 being a multiple of QK_K, which iq4_nl does not guarantee on its
own (QK4_NL sub-blocks). mxfp4 is left as a TODO.
* cuda: add mxfp4 support to GET_ROWS
Moves the mxfp4 dequantizer into the shared super-block helpers and
reuses it from k_get_rows_kq with the 32-thread layout of the matching
convert.cu kernel. mxfp4 joins the ne0 % QK_K gate in supports_op since
its 32-value sub-blocks do not guarantee QK_K-aligned rows on their own.
This closes GET_ROWS type coverage on CUDA: every quantized GGML type
now takes the direct device path.
* cuda: gate the GET_ROWS row size only for 32-value sub-block types
Address review from @pwilkin: the i-quant commit replaced the return
shared by the whole supported type cascade, so f16/f32/bf16/i32 and the
legacy quants also inherited the ne0 % QK_K == 0 gate and any row size
that is not a multiple of 256 fell back to the scheduler. Split the
cascade: unconditional support is restored everywhere, the gate stays
only on iq4_nl and mxfp4 whose 32-value sub-blocks do not guarantee the
QK_K super-blocks the kernel iterates on.
The Qwen3-VL learned position embedding is interpolated to the runtime patch
grid with the default bilinear+antialias (align_corners=False) sampling, while
the transformers reference uses align_corners=True (torch.linspace(0, side-1, T)).
The mismatch scales grounding coordinates about the image center, growing with
image size and per-axis for non-square images (see #16880).
With -hfd pointing to a repo shipping speculative sidecars, the draft
resolved to the main model of that repo, since find_best_model()
excludes sidecar files, and the explicit draft plan suppressed the
sidecar discovery on the -hf repo.
The draft plan already discovers its sidecars, they were just never
consumed. Wire them as the draft, following the fallback pattern of
the main plan, so this now works as expected:
llama-server -hf repo -hfd repo --spec-type draft-dflash
* server: return 400 instead of 500 on validation error with X-Conversation-Id
set_req() attaches the spipe as soon as the header is present, before the request
body is parsed. When params validation throws, set_next() never runs and next_orig
stays empty, so on_complete() called it and crashed with std::bad_function_call,
turning the prepared 400 JSON into a generic 500.
on_complete() now treats an empty next_orig as "streaming never started" and evicts
the session installed by set_req(), so a failed request leaves nothing behind for
discovery or replay. This also covers valid requests that carry the header but do
not stream, which previously left an empty finalized session in the map until the
GC TTL.
* ui: do not send the backend_sampling placeholder
On a fresh profile the syncable settings hold the empty string placeholder meaning
"let the server decide". Every neighbor field goes through the hasValue() guard
that filters it, except backend_sampling, which sent the placeholder verbatim and
made every default settings completion fail validation.
Guard the field with hasValue() like its neighbors. hasValue(false) is true, so an
explicit false still reaches the server and the intent of #18781 (send both true
and false) is preserved. Only the placeholder is filtered.
* Refactor vk_queue to use per-instance mutexes and unique handles
* integrates VK_KHR_internally_synchronized_queues, abstracting the queue submission into a polymorphic interface that completely bypasses host-side mutex locking when driver-side synchronization is supported
* fix compilation error
* fix duplicate pNext chain for VkPhysicalDeviceInternallySynchronizedQueuesFeaturesKHR
* add fallback defines for VK_KHR_internally_synchronized_queues
* add null checks for queues in vk_device_struct destructor
* use unique_ptr for outer queues to enforce exclusive ownership and optimize lifetime
* use static constexpr for eInternallySynchronizedKHR
* add lock guard to ggml_vk_create_aliased_queue for thread safety
* initialize sync_query_features.internallySynchronizedQueues to VK_FALSE
* reuse sync_query_features for internallySynchronizedQueues and simplify chaining
* refactor internallySynchronizedQueues detection
* fix internallySynchronizedQueues query guard
* use eInternallySynchronizedKHR constant
* fix self-referential alias for eInternallySynchronizedKHR
* use macro for eInternallySynchronizedKHR fallback
* fix internallySynchronizedQueues query timing in ggml-vulkan.cpp to prevent device creation mismatch
* reset sync_query_features.pNext before reusing in device creation chain, also removed the redundant second probe call
* refactor internally synchronized queues detection to use chained feature query and avoid redundant API calls
* Update ggml/src/ggml-vulkan/ggml-vulkan.cpp
Co-authored-by: Jeff Bolz <jbolz@nvidia.com>
* Update ggml/src/ggml-vulkan/ggml-vulkan.cpp
Co-authored-by: Jeff Bolz <jbolz@nvidia.com>
* Update ggml/src/ggml-vulkan/ggml-vulkan.cpp
Co-authored-by: Jeff Bolz <jbolz@nvidia.com>
* Update ggml/src/ggml-vulkan/ggml-vulkan.cpp
Co-authored-by: Jeff Bolz <jbolz@nvidia.com>
* Update ggml/src/ggml-vulkan/ggml-vulkan.cpp
Co-authored-by: Jeff Bolz <jbolz@nvidia.com>
* Update ggml/src/ggml-vulkan/ggml-vulkan.cpp
Co-authored-by: Jeff Bolz <jbolz@nvidia.com>
* rename sync_enable_features to internally_synchronized_queues_features
* queue_flags is still computed before has_internally_synchronized_queues is set
* fix trailing whitespace
* replace eInternallySynchronizedKHR macro with static constexpr
* preserve source queue semantics in single-queue aliased transfer queue
* vulkan: fix cmd_pool access via pointer for compute_queue unique_ptr
* vulkan: lock queue during debug label emission when not internally synchronized
---------
Co-authored-by: Jeff Bolz <jbolz@nvidia.com>
k_get_rows_float did a scalar one-element-per-thread copy and recomputed the
row-invariant work (index load, fast_div_modulo, src/dst row pointers) for
every element. Hoist that out of the per-element loop, and add a vectorized
path (k_get_rows_float_vec) that copies one int4 (16 B) per thread for the
contiguous same-type (no-cast) case.
The vectorized path is gated at compile time (is_same<src0_t, dst_t>) and at
runtime on 16-byte alignment of the base pointers and all row strides and on
ne00 % VEC == 0. Vectorizing divides the block count by VEC, so a small
single-row gather can drop below the device CU count and regress; an
occupancy gate keeps those on the block-rich scalar path.
On Strix Halo (gfx1151) the DeltaNet recurrent-state gather (ne00=524288)
drops 18.6us -> 13.0us (rocprofv3 HW timestamps), faster than the Vulkan
backend, with no regression on the small conv-state gather; total get_rows
-27%. test-backend-ops GET_ROWS passes (47/47).
Assisted-by: Claude Opus 4.8
submit_generation_button() only performed normal generation when
voice_typing_mode==0. If a session saved voice_typing_mode>0 and is then
reopened without a Whisper model loaded, the option is greyed out and
cannot be reset, so onclick fell through and did nothing while the button
was still visually a submit button - Generate More (and Submit) stopped
working.
Guard the branch with is_using_kcpp_with_whisper(), matching the pattern
already used everywhere else voice_typing_mode is checked (init, submit
button rendering, ready_to_record). When Whisper is unavailable the button
now behaves as a normal generation button regardless of the stale saved
setting. Behaviour is unchanged when Whisper is loaded.
Fixes#2353
* feat: WIP
* feat: Replace conversation rename flow with unified AlertDialog component
* feat: Add radio group component and consolidate title generation settings
* refactor: Remove JS Sandbox global toggle and migrate legacy user state
* chore: Formatting
* refactor: Cleanup
Co-authored-by: Aleksander Grygier <aleksander.grygier@gmail.com>
* refactor: Cleanup
* refactor: Marquee selection hook
* feat: UI improvements
* refactor: Bulk db operations
* fix: optimize bulk conversation deletion to handle ancestor chains
* refactor: remove pairedKey mechanism from settings system
* fix: remove redundant onclick handler from dialog cancel button
* chore: pin @lucide/svelte to exact version
* feat: Run JavaScript tool disabled by default
* fix: correct active conversation deletion tracking in bulk delete
* feat: improve shift-key multi-selection support in sidebar via keyboard
* refactor: Retrieve JS Tool enabling via Developer Settings
* nits: sync, dialog wording, cycle guard, and lockfile follow-ups
- Restore titleGenerationUseLLM registry entry so it syncs across devices again
- Mention fork cascade in the bulk delete confirmation dialog
- Clear newParent on cycle guard break so children never point at a deleted conversation
- Align @lucide/svelte in package-lock.json with the exact pin in package.json
---------
Co-authored-by: Pascal <admin@serveurperso.com>
Edge paragraph margins are now zeroed at the source in
markdown-content.css, but the user bubble and the system message still
carried the -my-4 compensation for them. The uncompensated negative
margins shrank the wrapper 2rem below its content, collapsing
single-line user bubbles into a scrollable sliver and skewing the
system message expand threshold.
* ui: fix Show tool call in progress toggle ignored
The showToolCallInProgress setting was disconnected from the render
path during the agentic content rework: getDefaultExpanded() returns
a hardcoded false for tool call sections and an unconditional effect
auto-expands the currently executing tool call regardless of the
setting.
Drive default expansion of all tool call section types from the
setting and remove the now redundant auto-expand effect. Manual
toggling still takes precedence over the default in both directions.
* ui: rename Show tool call in progress to Always show tool call content
The previous name suggested symmetry with Show thought in progress,
which only applies while inference is running, but tool call content
stays expanded after completion. Rename the label, the settings key
and the syncable server key to alwaysShowToolCallContent. The synced
parameter never worked under its previous name so no migration is
needed.
The agentic gate counted MCP servers, builtin and custom tools but not
frontend tools, so with the JS sandbox as the only tool source the
agentic flow was skipped, no tools field reached the server and the
chat template rendered without the tool system prompt.
The sandbox is fully client-side: frontendTools derives from the
Developer settings toggle alone, counting it in the gate restores that
single source of truth.
Treat the presence of sdtiledvae separately from its truthiness so the documented zero value survives a launcher config reload. Fixes#2065.
Co-authored-by: LK-Customs <lolikun@sunpraise-mc.com>
DeepSeek-V4's ffn_gate_tid2eid tensor is an i32 token-id -> expert-id
index table, not weights. It was never added to the name-based
exclusion list alongside ffn_gate_inp.weight, so llama-quantize tries
to quantize it and fails since i32 cannot convert to a float type.
Fixesggml-org/llama.cpp#25754
Signed-off-by: Yash Raj Pandey <yashpn62@gmail.com>
* fix(api): don't iterate a string banned_tokens character by character (#2333)
banned_tokens/banned_strings are consumed as a list of substrings. When a
caller supplies a bare string instead, `banned_tokens[:ban_token_max]`
slices it and `for tok in banned_tokens` walks it one character at a time,
so every letter in the value becomes its own banned substring. Banning
common letters like "e" makes generation collapse into garbage, with no
error to point at the cause.
Coerce a string value into a single-element list, matching how the OpenAI
`stop` parameter is already normalized in transform_genparams.
* fix(api): parse a JSON-array string in banned_tokens instead of inerting it
Per review: coercing the string form to a single-element list left the
reported gendefaults case a seemingly-effective no-op. Parse a JSON array
supplied as a string so the reported config bans "exclude" as intended,
and keep the bare-string form ("exclude") working as a single substring ban.
---------
Co-authored-by: Anai-Guo <antai12232931@anaiguo.com>
The two websearch status messages in koboldcpp.py print with no leading
newline, so they run onto the end of the preceding generation-stats line
(which has no trailing newline), e.g.:
...Total:26.31sReturning cached websearch...
Give both the cached-result print and the new-search print a leading
newline so each starts on its own line, matching the approach already
taken elsewhere (adding the missing newline at the offending print
rather than changing the stats line). Fixes#2337.
Co-authored-by: Anai-Guo <antai12232931@anaiguo.com>