fix(ik-llama): port multimodal path to mtmd API and bump to f96eaddb (#10534)#10568
Merged
Conversation
…10534) The IK_LLAMA_VERSION bump to f96eaddba8bed6a9a5e628bbf6a566775c70b49c pulls in upstream commit "Prune examples/llava", which deletes examples/llava (clip.* / llava.*). The ik-llama backend's grpc-server.cpp built a local `myclip` library from those files and called the removed clip/llava C API, so the bump no longer builds. ik_llama keeps its multimodal stack in the surviving `mtmd` library (examples/mtmd/, public headers mtmd.h + mtmd-helper.h). This ports the backend's multimodal path onto the high-level mtmd_* / mtmd_helper_* API in place, leaving the text path (which still uses ik_llama's retained old common API) untouched: - Makefile: bump IK_LLAMA_VERSION to f96eaddb. - prepare.sh: drop the clip/llava source copy + sed block; mtmd is a library target, no source copy needed. - CMakeLists.txt: remove the `myclip` target; link `mtmd` and add its include dir; build grpc-server as C++17 (mtmd headers require it). - patches: drop 0002 (targeted the deleted examples/llava/clip.cpp; the mtmd clip.cpp never calls ggml_quantize_chunk, so the fix is unneeded). Keep 0001 (verified still applies). - grpc-server.cpp / utils.hpp: replace clip_model_load + clip_image_load_from_bytes + llava_image_embed_make_with_clip_img + the manual [img-N] prefix splitting and per-image llava_embd_batch decode loop with mtmd_init_from_file (moved after the model load, which it requires), mtmd_helper_bitmap_init_from_buf, mtmd_tokenize and mtmd_helper_eval_chunks. Legacy [img-N] tags are translated, in order, into mtmd media markers (mtmd_default_marker()); the post-image suffix text stays on the normal token path so the sampling loop is unchanged. Supersedes #10534. Signed-off-by: Ettore Di Giacinto <mudler@localai.io> Assisted-by: Claude:claude-opus-4-8 [Claude Code]
…flict (#10534) mtmd.h declares `using json = nlohmann::ordered_json` at global scope (and its mtmd.cpp depends on it), while ik_llama's whole server/common stack also uses ordered_json. Our grpc-server.cpp/utils.hpp kept a plain `nlohmann::json` alias, which now collides with mtmd.h once it is included for the multimodal port: "conflicting declaration 'using json = ...'". Switch our two aliases to ordered_json to match; it is API-compatible (utils.hpp already used ordered_json for its log helper) and our json never crosses into an unordered-json API. Signed-off-by: Ettore Di Giacinto <mudler@localai.io> Assisted-by: Claude:claude-opus-4-8 [Claude Code]
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.
Description
PR #10534 bumps
IK_LLAMA_VERSIONtof96eaddba8bed6a9a5e628bbf6a566775c70b49c(repoikawrakow/ik_llama.cpp). Between the old pin and that commit, ik_llama landed an upstream change that prunesexamples/llava(clip.h/.cpp,llava.h/.cpp). The ik-llama backend'sgrpc-server.cppis a hand-rolled, old-style llava server: it built a localmycliplibrary from those now-deleted files and called the removed clip/llava C API (clip_model_load,clip_image_load_from_bytes,llava_image_embed_make_with_clip_img). The bump therefore does not build until the multimodal path is ported.This PR is the surgical in-place port of that path onto ik_llama's surviving multimodal stack, the
mtmdlibrary (examples/mtmd/, public headersmtmd.h+mtmd-helper.h). ik_llama is a fork that keeps the old common API, so the text path is unaffected; only the clip/llava multimodal path needed changing. The backend keeps its own self-containedexamples/grpc-server/(it is not rewritten onto the siblingllama-cppbackend's modular-server architecture, which is at a different refactor point and uses a differentmctxaccess pattern).Changes
IK_LLAMA_VERSIONtof96eaddb.sedblock.mtmdis a library target that builds transitively; no source copy is needed.mycliptarget; linkmtmdand add its include dir; buildgrpc-serveras C++17 (mtmd headers require it).0002-clip-ggml-quantize-chunk-user-data.patch(it targeted the now-deletedexamples/llava/clip.cpp; the replacementexamples/mtmd/clip.cppnever callsggml_quantize_chunk, so the fix is needed nowhere). Keep0001-fix-missing-cstdint-include.patch(verified still applies cleanly).Old → new mtmd call-site mapping (verified against the fork @
f96eaddb)examples/mtmd/)clip_ctx *clp_ctxmembermtmd_context *mctxclip_model_load(mmproj, 1)(before model load)mtmd_init_from_file(mmproj, model, mtmd_context_params)moved afterllama_init_from_gpt_params(it requires the loadedllama_model*)clip_n_mmproj_embddim guardnullptron mismatch)clip_image_u8_init+clip_image_load_from_bytes(buf,len,..)mtmd_helper_bitmap_init_from_buf(mctx, buf, len)[img-N]prefix-splitting into per-imageprefix_prompt[img-N], in order, intomtmd_default_marker(); collect bitmaps in marker order; trailing suffix kept on the normal token pathllava_image_embed_make_with_clip_img(...)eager encodestruct llava_embd_batch+ manual per-imagellama_decodeloopmtmd_tokenize(mctx, chunks, &input_text, bitmaps, n)thenmtmd_helper_eval_chunks(mctx, ctx, chunks, n_past, seq_id, n_batch, /*logits_last=*/false, &new_n_past)clip_image_u8_free/free(image_embedding)cleanupmtmd_bitmap_freeslot_imagenow holds a singlemtmd_bitmap *(owned by the slot, freed on reset) instead of the clip image + embedding + token-count + per-image prefix fields.Notes for Reviewers
The text (non-multimodal) path is unchanged - it still compiles against ik_llama's retained old common API; the only shared-flow edit makes the per-image prefix-token queue empty for the multimodal case.
Multimodal (VLM) inference is NOT yet verified end-to-end. It needs a full docker build of the backend plus an image-model e2e run, which I could not perform here.
What was statically verified (against a clone of
ikawrakow/ik_llama.cpp@f96eaddb):mtmd_default_marker,mtmd_context_params_default,mtmd_init_from_file,mtmd_helper_bitmap_init_from_buf,mtmd_tokenize,mtmd_helper_eval_chunks,mtmd_bitmap_free,mtmd_input_chunks_init, and themtmd::input_chunksC++ wrapper.mtmdlibrary target exists and is wired viaadd_subdirectory(mtmd); its PUBLIC include dir (examples/mtmd) and thenlohmann/json.hppit pulls (viacommon's vendor include) resolve for the grpc-server target.mtmd.h/mtmd-helper.hcarry include guards (included both directly and viautils.hpp).gpt_paramsfields referenced for the mtmd context (mmproj_use_gpu,n_threads_mtmd,flash_attn,image_min_tokens,image_max_tokens) and theLLAMA_FLASH_ATTN_TYPE_*enum exist in the fork.0001still applies cleanly; patch0002's target is gone and its fix is unneeded in the mtmd path.myclip,clip_*,llava_*, or the removed slot fields remain.What still needs the build / runtime:
mtmdunder the static-gRPC (BUILD_SHARED_LIBS=OFF) build, and each per-microarch variant.[img-N]→<__media__>marker translation and themtmd_helper_eval_chunksn_past/seq_idbookkeeping vs. the surrounding slot state. This is behavioral, not mechanical, and is unverified until an image-model e2e run.Fixes #10534
Signed commits