From 4b9d2ca4ada00e463d77e291c89acd845a3242cc Mon Sep 17 00:00:00 2001 From: peardox Date: Thu, 10 Apr 2025 09:14:14 +0100 Subject: [PATCH 1/3] Added whisper_get_system_info_json --- include/whisper.h | 1 + src/whisper.cpp | 42 ++++++++++++++++++++++++++++++++++++++++++ 2 files changed, 43 insertions(+) diff --git a/include/whisper.h b/include/whisper.h index 1e1375033ad..9948bb6442d 100644 --- a/include/whisper.h +++ b/include/whisper.h @@ -437,6 +437,7 @@ extern "C" { // Print system information WHISPER_API const char * whisper_print_system_info(void); + WHISPER_API const char * whisper_get_system_info_json(void); //////////////////////////////////////////////////////////////////////////// diff --git a/src/whisper.cpp b/src/whisper.cpp index 956d312dd3c..3874bcc9b9d 100644 --- a/src/whisper.cpp +++ b/src/whisper.cpp @@ -4346,6 +4346,48 @@ const char * whisper_print_system_info(void) { return s.c_str(); } +// whisper_get_system_info_json +// Returns system info as json, useful for ports +// NOTE : While testing features->value always returned a numeric so it is currently unquoted +// If strings are likely then something slightly more type-aware will be required +const char * whisper_get_system_info_json(void) { + static std::string s; + + whisper_load_backends(); + + s = "{"; + s += "\"WHISPER\":{"; + s += "\"COREML\":" + std::to_string(whisper_has_coreml()) + ","; + s += "\"OPENVINO\":" + std::to_string(whisper_has_openvino()) + "}"; + + for (size_t i = 0; i < ggml_backend_reg_count(); i++) { + auto * reg = ggml_backend_reg_get(i); + auto * get_features_fn = (ggml_backend_get_features_t) ggml_backend_reg_get_proc_address(reg, "ggml_backend_get_features"); + if (get_features_fn) { + ggml_backend_feature * features = get_features_fn(reg); + s += ",\""; + s += ggml_backend_reg_name(reg); + s += "\":{"; + auto first = true; + for (; features->name; features++) { + if(first) { + first = false; + } else { + s += ","; + } + s += "\""; + s += features->name; + s += "\":"; + s += features->value; + } + s += "}"; + } + } + s += "}"; + + return s.c_str(); +} + ////////////////////////////////// // Grammar - ported from llama.cpp ////////////////////////////////// From 0faa159b9bd3ed02d863f2a6f7efd41d6c4e4e23 Mon Sep 17 00:00:00 2001 From: peardox Date: Wed, 16 Apr 2025 03:00:07 +0100 Subject: [PATCH 2/3] Fix Tabs. Add two state-relted functions --- include/whisper.h | 12 ++- src/openvino/whisper-openvino-encoder.cpp | 2 +- src/whisper.cpp | 119 ++++++++++++++-------- 3 files changed, 89 insertions(+), 44 deletions(-) diff --git a/include/whisper.h b/include/whisper.h index 9948bb6442d..7d0fc6f15e8 100644 --- a/include/whisper.h +++ b/include/whisper.h @@ -437,7 +437,6 @@ extern "C" { // Print system information WHISPER_API const char * whisper_print_system_info(void); - WHISPER_API const char * whisper_get_system_info_json(void); //////////////////////////////////////////////////////////////////////////// @@ -669,6 +668,17 @@ extern "C" { // Get the no_speech probability for the specified segment WHISPER_API float whisper_full_get_segment_no_speech_prob (struct whisper_context * ctx, int i_segment); WHISPER_API float whisper_full_get_segment_no_speech_prob_from_state(struct whisper_state * state, int i_segment); + + // Return System Information formatted as a JSON string + WHISPER_API const char * whisper_get_system_info_json(void); + + // Returns whisper_state for a supplied whisper_context pointer + WHISPER_API struct whisper_state * whisper_get_state_from_context(struct whisper_context * ctx); + + // A version of whisper_get_timings that takes state as a parameter + WHISPER_API struct whisper_timings * whisper_get_timings_with_state(struct whisper_state * state); + + #ifdef __cplusplus } #endif diff --git a/src/openvino/whisper-openvino-encoder.cpp b/src/openvino/whisper-openvino-encoder.cpp index 4d9ce122858..12cfe1f5594 100644 --- a/src/openvino/whisper-openvino-encoder.cpp +++ b/src/openvino/whisper-openvino-encoder.cpp @@ -19,7 +19,7 @@ struct whisper_openvino_context * whisper_openvino_init(const char* path_model, fprintf(stderr, "%s: path_model = %s, device = %s, cache_dir = %s\n", __func__, path_model, device, cache_dir ? cache_dir : "(not set)"); - whisper_openvino_context *context = new whisper_openvino_context; + whisper_openvino_context *context = new whisper_openvino_context; try { ov::Core core; diff --git a/src/whisper.cpp b/src/whisper.cpp index 3874bcc9b9d..60c5e2a4962 100644 --- a/src/whisper.cpp +++ b/src/whisper.cpp @@ -4346,48 +4346,6 @@ const char * whisper_print_system_info(void) { return s.c_str(); } -// whisper_get_system_info_json -// Returns system info as json, useful for ports -// NOTE : While testing features->value always returned a numeric so it is currently unquoted -// If strings are likely then something slightly more type-aware will be required -const char * whisper_get_system_info_json(void) { - static std::string s; - - whisper_load_backends(); - - s = "{"; - s += "\"WHISPER\":{"; - s += "\"COREML\":" + std::to_string(whisper_has_coreml()) + ","; - s += "\"OPENVINO\":" + std::to_string(whisper_has_openvino()) + "}"; - - for (size_t i = 0; i < ggml_backend_reg_count(); i++) { - auto * reg = ggml_backend_reg_get(i); - auto * get_features_fn = (ggml_backend_get_features_t) ggml_backend_reg_get_proc_address(reg, "ggml_backend_get_features"); - if (get_features_fn) { - ggml_backend_feature * features = get_features_fn(reg); - s += ",\""; - s += ggml_backend_reg_name(reg); - s += "\":{"; - auto first = true; - for (; features->name; features++) { - if(first) { - first = false; - } else { - s += ","; - } - s += "\""; - s += features->name; - s += "\":"; - s += features->value; - } - s += "}"; - } - } - s += "}"; - - return s.c_str(); -} - ////////////////////////////////// // Grammar - ported from llama.cpp ////////////////////////////////// @@ -7590,3 +7548,80 @@ static void whisper_log_callback_default(ggml_log_level level, const char * text fputs(text, stderr); fflush(stderr); } + +// whisper_get_system_info_json +// Returns system info as json, useful for language bindings +// NOTE : While testing features->value always returned an int. +// Even though ints are invariably returned they may be +// some values that return other types. +// This function returns everything quoted (i.e. as a string) +// and leaves type-casting to the caller. +// This also removes the unlikely but plausible state of +// a string being returned unquoted (thus invalidating JSON) + +const char * whisper_get_system_info_json(void) { + static std::string s; + + whisper_load_backends(); + + s = "{"; + s += "\"WHISPER\":{"; + s += "\"COREML\":\"" + std::to_string(whisper_has_coreml()) + "\","; + s += "\"OPENVINO\":\"" + std::to_string(whisper_has_openvino()) + "\"}"; + + for (size_t i = 0; i < ggml_backend_reg_count(); i++) { + auto * reg = ggml_backend_reg_get(i); + auto * get_features_fn = (ggml_backend_get_features_t) ggml_backend_reg_get_proc_address(reg, "ggml_backend_get_features"); + if (get_features_fn) { + ggml_backend_feature * features = get_features_fn(reg); + s += ",\""; + s += ggml_backend_reg_name(reg); + s += "\":{"; + auto first = true; + for (; features->name; features++) { + if(first) { + first = false; + } else { + s += ","; + } + s += "\""; + s += features->name; + s += "\":\""; + s += features->value; + s += "\""; + } + s += "}"; + } + } + s += "}"; + + return s.c_str(); +} + +// whisper_get_state_from_context +// Returns state from supplied context pointer +// This is mainly a helper for non-C++ language bindings as whisper_context +// has embedded C++ specific types (e.g. maps and vectors) +struct whisper_state * whisper_get_state_from_context(struct whisper_context * ctx) { + if (!ctx->state) { + whisper_free(ctx); + return nullptr; + } + + return ctx->state; +} + +// whisper_get_timings_with_state +// Just a version of whisper_get_timings that takes state as a parameter +struct whisper_timings * whisper_get_timings_with_state(struct whisper_state * state) { + if (state == nullptr) { + return nullptr; + } + whisper_timings * timings = new whisper_timings; + timings->sample_ms = 1e-3f * state->t_sample_us / std::max(1, state->n_sample); + timings->encode_ms = 1e-3f * state->t_encode_us / std::max(1, state->n_encode); + timings->decode_ms = 1e-3f * state->t_decode_us / std::max(1, state->n_decode); + timings->batchd_ms = 1e-3f * state->t_batchd_us / std::max(1, state->n_batchd); + timings->prompt_ms = 1e-3f * state->t_prompt_us / std::max(1, state->n_prompt); + return timings; +} From 4d9a5a98d623602579a17b78648835e44e37811f Mon Sep 17 00:00:00 2001 From: peardox Date: Wed, 16 Apr 2025 09:43:21 +0100 Subject: [PATCH 3/3] Fix whisper_get_state_from_context freeing context --- src/whisper.cpp | 1 - 1 file changed, 1 deletion(-) diff --git a/src/whisper.cpp b/src/whisper.cpp index 60c5e2a4962..f2117de40e5 100644 --- a/src/whisper.cpp +++ b/src/whisper.cpp @@ -7604,7 +7604,6 @@ const char * whisper_get_system_info_json(void) { // has embedded C++ specific types (e.g. maps and vectors) struct whisper_state * whisper_get_state_from_context(struct whisper_context * ctx) { if (!ctx->state) { - whisper_free(ctx); return nullptr; }