From ceb9ee1cf316685ba33f0e5ffd76b9cdc900b2ed Mon Sep 17 00:00:00 2001 From: ogad-tether Date: Tue, 7 Oct 2025 22:30:29 +0100 Subject: [PATCH] implement logging redirection --- tests/CMakeLists.txt | 1 + tools/mtmd/README.md | 31 +++++++++++++++++++++++++++++++ tools/mtmd/clip-impl.h | 23 +++++++++++++++++++++++ tools/mtmd/clip.cpp | 8 +++++++- tools/mtmd/mtmd.cpp | 4 ++++ tools/mtmd/mtmd.h | 8 ++++++++ tools/server/CMakeLists.txt | 1 + 7 files changed, 75 insertions(+), 1 deletion(-) diff --git a/tests/CMakeLists.txt b/tests/CMakeLists.txt index cb7ebae0a6bae..e3cd31720393f 100644 --- a/tests/CMakeLists.txt +++ b/tests/CMakeLists.txt @@ -214,6 +214,7 @@ endif() set(LLAMA_TEST_NAME test-mtmd-c-api) llama_build_and_test(test-mtmd-c-api.c) target_link_libraries(${LLAMA_TEST_NAME} PRIVATE mtmd) +target_include_directories(${LLAMA_TEST_NAME} PRIVATE ${CMAKE_SOURCE_DIR}/tools/mtmd) # dummy executable - not installed get_filename_component(TEST_TARGET test-c.c NAME_WE) diff --git a/tools/mtmd/README.md b/tools/mtmd/README.md index ef31d1957cdab..154d0c376ae8a 100644 --- a/tools/mtmd/README.md +++ b/tools/mtmd/README.md @@ -37,6 +37,37 @@ Built upon `clip.cpp` (similar to `llava.cpp`), `libmtmd` offers several advanta - **Improved UX/DX:** Features a more intuitive API, inspired by the `Processor` class in the Hugging Face `transformers` library. - **Flexibility:** Designed to support multiple input types (text, audio, images) while respecting the wide variety of chat templates used by different models. +## Logging Configuration + +By default, `libmtmd` logs messages directly to stderr. To integrate `libmtmd` logging with your application's logging system, you can use the `mtmd_log_set_llama_callback()` function to redirect all mtmd/clip logs through llama's logging callback. + +**Example usage:** + +```c +#include "llama.h" +#include "mtmd.h" + +// Your custom logging callback +void my_log_callback(ggml_log_level level, const char * text, void * user_data) { + // Your logging logic here + printf("[%d] %s", level, text); +} + +int main() { + // Set up llama's logging + llama_log_set(my_log_callback, NULL); + + // Redirect mtmd/clip logging to use the same callback + mtmd_log_set_llama_callback(my_log_callback, NULL); + + // Now all mtmd and clip logs will use your custom callback + mtmd_context * ctx = mtmd_init_from_file(...); + // ... +} +``` + +This ensures that all logging from `libmtmd`, including the underlying `clip.cpp` vision encoder, is routed through your application's logging system consistently. + ## How to obtain `mmproj` Multimodal projector (`mmproj`) files are specific to each model architecture. diff --git a/tools/mtmd/clip-impl.h b/tools/mtmd/clip-impl.h index 62c936ed00f77..efa5c088774fd 100644 --- a/tools/mtmd/clip-impl.h +++ b/tools/mtmd/clip-impl.h @@ -195,10 +195,33 @@ struct clip_logger_state { ggml_log_level verbosity_thold; ggml_log_callback log_callback; void * log_callback_user_data; + // Store the llama callback to forward logs to + ggml_log_callback llama_callback; + void * llama_callback_user_data; }; extern struct clip_logger_state g_logger_state; +// Callback that redirects to llama's logging system +static void clip_log_callback_llama(enum ggml_log_level level, const char * text, void * user_data) { + (void) user_data; + // Forward to the stored llama callback if available + if (g_logger_state.llama_callback != nullptr) { + g_logger_state.llama_callback(level, text, g_logger_state.llama_callback_user_data); + } else { + // Fallback to default if no llama callback is set + clip_log_callback_default(level, text, user_data); + } +} + +// Function to enable llama logging redirection +// This should be called after llama_log_set has been called to set up llama's logging +static inline void clip_log_use_llama_callback(ggml_log_callback llama_cb, void * llama_user_data) { + g_logger_state.llama_callback = llama_cb; + g_logger_state.llama_callback_user_data = llama_user_data; + g_logger_state.log_callback = clip_log_callback_llama; +} + static void clip_log_internal_v(enum ggml_log_level level, const char * format, va_list args) { if (format == NULL) { return; diff --git a/tools/mtmd/clip.cpp b/tools/mtmd/clip.cpp index 9146c9e9c4481..540ccc6250fc1 100644 --- a/tools/mtmd/clip.cpp +++ b/tools/mtmd/clip.cpp @@ -28,7 +28,13 @@ #include #include -struct clip_logger_state g_logger_state = {GGML_LOG_LEVEL_CONT, clip_log_callback_default, NULL}; +struct clip_logger_state g_logger_state = { + GGML_LOG_LEVEL_CONT, // verbosity_thold + clip_log_callback_default, // log_callback + NULL, // log_callback_user_data + nullptr, // llama_callback + nullptr // llama_callback_user_data +}; enum ffn_op_type { FFN_GELU, diff --git a/tools/mtmd/mtmd.cpp b/tools/mtmd/mtmd.cpp index e3829738338c3..c84c21afb669f 100644 --- a/tools/mtmd/mtmd.cpp +++ b/tools/mtmd/mtmd.cpp @@ -359,6 +359,10 @@ void mtmd_free(mtmd_context * ctx) { } } +void mtmd_log_set_llama_callback(ggml_log_callback llama_cb, void * llama_user_data) { + clip_log_use_llama_callback(llama_cb, llama_user_data); +} + struct mtmd_tokenizer { mtmd_context * ctx; std::vector bitmaps; diff --git a/tools/mtmd/mtmd.h b/tools/mtmd/mtmd.h index f4ea07d3ad521..d743e52f5a4e7 100644 --- a/tools/mtmd/mtmd.h +++ b/tools/mtmd/mtmd.h @@ -96,6 +96,14 @@ MTMD_API mtmd_context * mtmd_init_from_file(const char * mmproj_fname, MTMD_API void mtmd_free(mtmd_context * ctx); +// Set up logging to use llama's logging callback +// This redirects all mtmd/clip logging through llama's logging system +// Call this after llama_log_set to ensure mtmd uses the same logging callback +// Example: +// llama_log_set(my_log_callback, my_user_data); +// mtmd_log_set_llama_callback(my_log_callback, my_user_data); +MTMD_API void mtmd_log_set_llama_callback(ggml_log_callback llama_cb, void * llama_user_data); + // whether we need to set non-causal mask before llama_decode MTMD_API bool mtmd_decode_use_non_causal(mtmd_context * ctx); diff --git a/tools/server/CMakeLists.txt b/tools/server/CMakeLists.txt index c2a56aaa7f27b..27e950b2c684a 100644 --- a/tools/server/CMakeLists.txt +++ b/tools/server/CMakeLists.txt @@ -34,6 +34,7 @@ add_executable(${TARGET} ${TARGET_SRCS}) install(TARGETS ${TARGET} RUNTIME) target_include_directories(${TARGET} PRIVATE ../llava) +target_include_directories(${TARGET} PRIVATE ../mtmd) target_include_directories(${TARGET} PRIVATE ${CMAKE_SOURCE_DIR}) target_link_libraries(${TARGET} PRIVATE common mtmd ${CMAKE_THREAD_LIBS_INIT})