ronantakizawa/codereview-bench huggingface dataset:
Repository: ggerganov/whisper.cpp
File: examples/addon.node/__test__/whisper.spec.js (JavaScript)

Code before:
const path = require('path');
const { whisper } = require(path.join(__dirname, '../../../build/Release/whisper-addon'));

const whisperParamsMock = {
    language: 'en',
    model: path.join(__dirname, '../../../models/ggml-base.en.bin'),
    fname_inp: path.join(__dirname, './samples_jfk.wav'),
};

describe("Run whisper.node", () => {

    test("it should receive a non-empty value", () => {
        expect(whisper(whisperParamsMock).length).toBeGreaterThan(0);
    });
});


Review comment (suggestion):
Maybe better to reuse the `jfk.wav` from the `samples` folder, instead of having a copy here:

```suggestion
    fname_inp: path.join(__dirname, '../../../samples/jfk.wav'),
```

Code after:
const path = require('path');
const { whisper } = require(path.join(__dirname, '../../../build/Release/whisper-addon'));

const whisperParamsMock = {
    language: 'en',
    model: path.join(__dirname, '../../../models/ggml-base.en.bin'),
    fname_inp: path.join(__dirname, '../../../samples/jfk.wav'),
};

describe("Run whisper.node", () => {

    test("it should receive a non-empty value", () => {
        expect(whisper(whisperParamsMock).length).toBeGreaterThan(0);
    });
});
Repository: ggerganov/whisper.cpp
File: whisper.cpp (C++)

Code before:

    path_bin += "-encoder.mlmodelc";

    return path_bin;
}
#endif

#ifdef WHISPER_USE_OPENVINO
// replace .bin with-encoder-openvino.xml
static std::string whisper_get_openvino_path_encoder(std::string path_bin) {
    auto pos = path_bin.rfind('.');
    if (pos != std::string::npos) {
        path_bin = path_bin.substr(0, pos);
    }

    path_bin += "-encoder-openvino.xml";

    return path_bin;
}

static std::string whisper_get_openvino_path_cache(std::string path_bin) {
    auto pos = path_bin.rfind('.');
    if (pos != std::string::npos) {
        path_bin = path_bin.substr(0, pos);
    }

    path_bin += "-encoder-openvino-cache";

    return path_bin;
}
#endif

struct whisper_state * whisper_init_state(whisper_context * ctx) {
    whisper_state * state = new whisper_state;

    const size_t scale = ctx->model.hparams.ftype ? 1 : 2;

    if (!kv_cache_init(ctx->model.hparams, scale * MEM_REQ_KV_SELF.at(ctx->model.type), state->decoders[0].kv_self, ctx->itype, ctx->model.hparams.n_text_ctx)) {
        fprintf(stderr, "%s: kv_cache_init() failed for self-attention cache\n", __func__);
        delete state;
        return nullptr;
    }

    {
        const size_t memory_size = ggml_nbytes(state->decoders[0].kv_self.k) + ggml_nbytes(state->decoders[0].kv_self.v);
        fprintf(stderr, "%s: kv self size  = %7.2f MB\n", __func__, memory_size / 1024.0 / 1024.0);
    }

    if (!kv_cache_init(ctx->model.hparams, scale * MEM_REQ_KV_CROSS.at(ctx->model.type), state->kv_cross, ctx->itype, ctx->model.hparams.n_audio_ctx)) {
        fprintf(stderr, "%s: kv_cache_init() failed for cross-attention cache\n", __func__);
        delete state;

Review comment (suggestion):
```suggestion
static std::string whisper_get_openvino_path_encoder(const std::string & path_bin) {
```

Code after:
#ifdef WHISPER_USE_COREML
// replace .bin with -encoder.mlmodelc
static std::string whisper_get_coreml_path_encoder(std::string path_bin) {
    auto pos = path_bin.rfind('.');
    if (pos != std::string::npos) {
        path_bin = path_bin.substr(0, pos);
    }

    // match "-qx_x"
    pos = path_bin.rfind('-');
    if (pos != std::string::npos) {
        auto sub = path_bin.substr(pos);
        if (sub.size() == 5 && sub[1] == 'q' && sub[3] == '_') {
            path_bin = path_bin.substr(0, pos);
        }
    }

    path_bin += "-encoder.mlmodelc";

    return path_bin;
}
#endif

#ifdef WHISPER_USE_OPENVINO
// replace .bin with-encoder-openvino.xml
static std::string whisper_get_openvino_path_encoder(std::string path_bin) {
    auto pos = path_bin.rfind('.');
    if (pos != std::string::npos) {
        path_bin = path_bin.substr(0, pos);
    }

    path_bin += "-encoder-openvino.xml";

    return path_bin;
}

static std::string whisper_get_openvino_path_cache(std::string path_bin) {
    auto pos = path_bin.rfind('.');
    if (pos != std::string::npos) {
        path_bin = path_bin.substr(0, pos);
    }

    path_bin += "-encoder-openvino-cache";

    return path_bin;
}
#endif

struct whisper_state * whisper_init_state(whisper_context * ctx) {
    whisper_state * state = new whisper_state;
Repository: ggerganov/whisper.cpp
File: whisper.cpp (C++)

Code before:
struct whisper_filters {
    int32_t n_mel;
    int32_t n_fft;

    std::vector<float> data;
};

struct whisper_vocab {
    using id    = int32_t;
    using token = std::string;

    int n_vocab = 51864;

    std::map<token, id> token_to_id;
    std::map<id, token> id_to_token;

    // reference: https://github.com/openai/whisper/blob/248b6cb124225dd263bb9bd32d060b6517e067f8/whisper/tokenizer.py#L334-L349
    id token_eot        = 50256;
    id token_sot        = 50257;
    // task tokens (used only for multilingual models)
    id token_translate  = 50357;
    id token_transcribe = 50358;
    // other special tokens
    id token_tdrz       = 50359; // [TDRZ] used by tinydiarize models to indicate speaker turn
    id token_prev       = 50360;
    id token_solm       = 50361; // start of lm ?
    id token_not        = 50362; // no timestamps
    id token_beg        = 50363; // begin timestamps

    bool is_multilingual() const {
        return n_vocab == 51865;
    }
};

struct whisper_segment {
    int64_t t0;
    int64_t t1;

    std::string text;

    std::vector<whisper_token_data> tokens;

    bool speaker_turn_next;
};

// medium
// hparams: {
// 'n_mels': 80,
// 'n_vocab': 51864,
// 'n_audio_ctx': 1500,
// 'n_audio_state': 1024,

Review comment (bug):
Hi @ggerganov - so actually id 50361 corresponds to the `nospeech` token.

https://github.com/openai/whisper/blob/248b6cb124225dd263bb9bd32d060b6517e067f8/whisper/tokenizer.py#L334-L349

Both variables `token_solm` and `token_tdrz` should have the same value. I basically repurposed an unused token ID in the released whisper models https://github.com/openai/whisper/discussions/414.

FYI - there was actually also a bug in whisper.cpp with some incorrect token IDs, which I fixed in this commit - https://github.com/akashmjn/whisper.cpp/commit/c8e1ed6f8281e83abc8cbd54483c24c767bcde66 




Code after:
struct whisper_filters {
    int32_t n_mel;
    int32_t n_fft;

    std::vector<float> data;
};

struct whisper_vocab {
    using id    = int32_t;
    using token = std::string;

    int n_vocab = 51864;

    std::map<token, id> token_to_id;
    std::map<id, token> id_to_token;

    // reference: https://github.com/openai/whisper/blob/248b6cb124225dd263bb9bd32d060b6517e067f8/whisper/tokenizer.py#L334-L349
    id token_eot        = 50256;
    id token_sot        = 50257;
    // task tokens (used only for multilingual models)
    id token_translate  = 50357;
    id token_transcribe = 50358;
    // other special tokens
    id token_solm       = 50359; // [TDRZ] used by tinydiarize models to indicate speaker turn
    id token_prev       = 50360;
    id token_nosp       = 50361;
    id token_not        = 50362; // no timestamps
    id token_beg        = 50363; // begin timestamps

    bool is_multilingual() const {
        return n_vocab == 51865;
    }
};

struct whisper_segment {
    int64_t t0;
    int64_t t1;

    std::string text;

    std::vector<whisper_token_data> tokens;

    bool speaker_turn_next;
};

// medium
// hparams: {
// 'n_mels': 80,
// 'n_vocab': 51864,
// 'n_audio_ctx': 1500,
// 'n_audio_state': 1024,
Repository: ggerganov/whisper.cpp
File: whisper.cpp (C++)

Code before:
    size_t get_buf_max_mem(int i) const {
#if defined(WHISPER_USE_SCRATCH)
        return buf_max_size[i];
#else
        (void) i;
        return 0;
#endif
    }
};

struct whisper_context {
    int64_t t_load_us  = 0;
    int64_t t_start_us = 0;

    ggml_type wtype = ggml_type::GGML_TYPE_F16; // weight type (FP32 / FP16 / QX)
    ggml_type itype = ggml_type::GGML_TYPE_F16; // intermediate type (FP32 or FP16)

    whisper_model model;
    whisper_vocab vocab;
    whisper_state * state = nullptr;

    std::string path_model; // populated by whisper_init_from_file()
};

static void whisper_default_log(const char * text) {
    fprintf(stderr, "%s\n", text);
}

static whisper_log_callback whisper_log = whisper_default_log;

static void log(const char * fmt, ...) {
    char buf[256];
    va_list args;
    va_start(args, fmt);
    vsnprintf(buf, sizeof(buf), fmt, args);
    whisper_log(buf);
}

template<typename T>
static void read_safe(whisper_model_loader * loader, T & dest) {
    loader->read(loader->context, &dest, sizeof(T));
    BYTESWAP_VALUE(dest);
}

static bool kv_cache_init(
        const struct whisper_hparams & hparams,
                        const size_t   mem_bytes,
             struct whisper_kv_cache & cache,
                           ggml_type   wtype,
                                 int   n_ctx) {
    cache.buf.resize(mem_bytes);

Review comment (suggestion):
New lines must be explicitly logged

```suggestion
    fprintf(stderr, "%s", text);
```

Code after:
        }

        if (buf_last >= 0) {
            buf_max_size[buf_last] = std::max(buf_max_size[buf_last], last_size);
        }

        buf_last = i;
#else
        (void) i;
        (void) ctx;
#endif
    }

    size_t get_buf_max_mem(int i) const {
#if defined(WHISPER_USE_SCRATCH)
        return buf_max_size[i];
#else
        (void) i;
        return 0;
#endif
    }
};

struct whisper_context {
    int64_t t_load_us  = 0;
    int64_t t_start_us = 0;

    ggml_type wtype = ggml_type::GGML_TYPE_F16; // weight type (FP32 / FP16 / QX)
    ggml_type itype = ggml_type::GGML_TYPE_F16; // intermediate type (FP32 or FP16)

    whisper_model model;
    whisper_vocab vocab;
    whisper_state * state = nullptr;

    std::string path_model; // populated by whisper_init_from_file()
};

static void whisper_default_log(const char * text) {
    fprintf(stderr, "%s", text);
}

static whisper_log_callback whisper_log = whisper_default_log;

static void log(const char * fmt, ...) {
    if (!whisper_log) return;
    char buf[1024];
    va_list args;
    va_start(args, fmt);
    vsnprintf(buf, sizeof(buf), fmt, args);
    whisper_log(buf);
}
Repository: ggerganov/whisper.cpp
File: whisper.cpp (C++)

Code before:
static void whisper_default_log(const char * text) {
    fprintf(stderr, "%s\n", text);
}

static whisper_log_callback whisper_log = whisper_default_log;

static void log(const char * fmt, ...) {
    char buf[256];
    va_list args;
    va_start(args, fmt);
    vsnprintf(buf, sizeof(buf), fmt, args);
    whisper_log(buf);
}

template<typename T>
static void read_safe(whisper_model_loader * loader, T & dest) {
    loader->read(loader->context, &dest, sizeof(T));
    BYTESWAP_VALUE(dest);
}

static bool kv_cache_init(
        const struct whisper_hparams & hparams,
                        const size_t   mem_bytes,
             struct whisper_kv_cache & cache,
                           ggml_type   wtype,
                                 int   n_ctx) {
    cache.buf.resize(mem_bytes);

    struct ggml_init_params params = {
        /*.mem_size   =*/ cache.buf.size(),
        /*.mem_buffer =*/ cache.buf.data(),
        /*.no_alloc   =*/ false,
    };

    cache.ctx = ggml_init(params);

    if (!cache.ctx) {
        log("%s: failed to allocate memory for kv cache", __func__);
        return false;
    }

    const int n_text_state = hparams.n_text_state;
    const int n_text_layer = hparams.n_text_layer;

    const int n_mem      = n_text_layer*n_ctx;
    const int n_elements = n_text_state*n_mem;

    cache.k = ggml_new_tensor_1d(cache.ctx, wtype, n_elements);
    cache.v = ggml_new_tensor_1d(cache.ctx, wtype, n_elements);

    return true;

Review comment (bug):
Check if `whisper_log` is `nullptr`. If it is - do nothing

Code after:
    int64_t t_load_us  = 0;
    int64_t t_start_us = 0;

    ggml_type wtype = ggml_type::GGML_TYPE_F16; // weight type (FP32 / FP16 / QX)
    ggml_type itype = ggml_type::GGML_TYPE_F16; // intermediate type (FP32 or FP16)

    whisper_model model;
    whisper_vocab vocab;
    whisper_state * state = nullptr;

    std::string path_model; // populated by whisper_init_from_file()
};

static void whisper_default_log(const char * text) {
    fprintf(stderr, "%s", text);
}

static whisper_log_callback whisper_log = whisper_default_log;

static void log(const char * fmt, ...) {
    if (!whisper_log) return;
    char buf[1024];
    va_list args;
    va_start(args, fmt);
    vsnprintf(buf, sizeof(buf), fmt, args);
    whisper_log(buf);
}

template<typename T>
static void read_safe(whisper_model_loader * loader, T & dest) {
    loader->read(loader->context, &dest, sizeof(T));
    BYTESWAP_VALUE(dest);
}

static bool kv_cache_init(
        const struct whisper_hparams & hparams,
                        const size_t   mem_bytes,
             struct whisper_kv_cache & cache,
                           ggml_type   wtype,
                                 int   n_ctx) {
    cache.buf.resize(mem_bytes);

    struct ggml_init_params params = {
        /*.mem_size   =*/ cache.buf.size(),
        /*.mem_buffer =*/ cache.buf.data(),
        /*.no_alloc   =*/ false,
    };

    cache.ctx = ggml_init(params);

    if (!cache.ctx) {
Repository: ggerganov/whisper.cpp
File: examples/stream/stream.cpp (C++)

Code before:
// Real-time speech recognition of input from a microphone
//
// A very quick-n-dirty implementation serving mainly as a proof of concept.
//

#include "common-sdl.h"
#include "common.h"
#include "whisper.h"

#include <cassert>
#include <cstdio>
#include <string>
#include <thread>
#include <vector>
#include <fstream>

//  500 -> 00:05.000
// 6000 -> 01:00.000
std::string to_timestamp(int64_t t) {
    int64_t sec = t/100;
    int64_t msec = t - sec*100;
    int64_t min = sec/60;
    sec = sec - min*60;

    char buf[32];
    snprintf(buf, sizeof(buf), "%02d:%02d.%03d", (int) min, (int) sec, (int) msec);

    return std::string(buf);
}

// command-line parameters
struct whisper_params {
    int32_t n_threads  = std::min(4, (int32_t) std::thread::hardware_concurrency());
    int32_t step_ms    = 3000;
    int32_t length_ms  = 10000;
    int32_t keep_ms    = 200;
    int32_t capture_id = -1;
    int32_t max_tokens = 32;
    int32_t audio_ctx  = 0;

    float vad_thold    = 0.6f;
    float freq_thold   = 100.0f;


Review comment (suggestion):
- The naming convention is to use snake case, so this should be `class wav_writer`
- Move to `common.h / common.cpp`
- API should be: `open()`, `write()`, `close()`
- Allocate on the stack instead of on the heap with `new` and forgetting to deallocate it
- If `params.save_audio` is true, call `init()`

Code after:
// Real-time speech recognition of input from a microphone
//
// A very quick-n-dirty implementation serving mainly as a proof of concept.
//
#include <fstream>
#include "common-sdl.h"
#include "common.h"
#include "whisper.h"

#include <cassert>
#include <cstdio>
#include <string>
#include <thread>
#include <vector>
#include <fstream>
#include <ctime>

class SimpleWavWriter {
private:
    std::ofstream file;
    int32_t dataSize = 0;

public:
    SimpleWavWriter(const std::string &filename, int sampleRate, int bitsPerSample, int channels) {
        file.open(filename, std::ios::binary);

        file.write("RIFF", 4);
        file.write("\0\0\0\0", 4);    // Placeholder for file size
        file.write("WAVE", 4);
        file.write("fmt ", 4);

        int32_t subChunkSize = 16;
        int16_t audioFormat = 1;      // PCM format
        int32_t byteRate = sampleRate * channels * bitsPerSample / 8;
        int16_t blockAlign = channels * bitsPerSample / 8;

        file.write(reinterpret_cast<char *>(&subChunkSize), 4);
        file.write(reinterpret_cast<char *>(&audioFormat), 2);
        file.write(reinterpret_cast<char *>(&channels), 2);
        file.write(reinterpret_cast<char *>(&sampleRate), 4);
        file.write(reinterpret_cast<char *>(&byteRate), 4);
        file.write(reinterpret_cast<char *>(&blockAlign), 2);
        file.write(reinterpret_cast<char *>(&bitsPerSample), 2);
Repository: ggerganov/whisper.cpp
File: models/download-ggml-model.sh (Shell)

Code before:
    "small.en"
    "small.en-tdrz"
    "small"
    "small-q5_1"
    "small.en-q5_1"
    "medium"
    "medium.en"
    "medium-q5_0"
    "medium.en-q5_0"
    "large-v1"
    "large-v2"
    "large-v3"
    "large-q5_0"
)

# list available models
function list_models {
    printf "\n"
    printf "  Available models:"
    for model in "${models[@]}"; do
        printf " $model"
    done
    printf "\n\n"
}

if [ "$#" -gt 2 ]; then
    printf "Usage: $0 <model> <models_path>\n"
    list_models

    exit 1
fi

model=$1

if [[ ! " ${models[@]} " =~ " ${model} " ]]; then
    printf "Invalid model: $model\n"
    list_models

    exit 1
fi

# check if model contains `tdrz` and update the src and pfx accordingly
if [[ $model == *"tdrz"* ]]; then
    src="https://huggingface.co/akashmjn/tinydiarize-whisper.cpp"
    pfx="resolve/main/ggml"
fi

# download ggml model

printf "Downloading ggml model $model from '$src' ...\n"


Review comment (suggestion):
```suggestion
if [ "$#" -lt 1 ] || [ "$#" -gt 2 ]; then
```

Code after:
    "small.en"
    "small.en-tdrz"
    "small"
    "small-q5_1"
    "small.en-q5_1"
    "medium"
    "medium.en"
    "medium-q5_0"
    "medium.en-q5_0"
    "large-v1"
    "large-v2"
    "large-v3"
    "large-q5_0"
)

# list available models
function list_models {
    printf "\n"
    printf "  Available models:"
    for model in "${models[@]}"; do
        printf " $model"
    done
    printf "\n\n"
}

if [ "$#" -lt 1 ] || [ "$#" -gt 2 ]; then
    printf "Usage: $0 <model> [models_path]\n"
    list_models

    exit 1
fi

model=$1

if [[ ! " ${models[@]} " =~ " ${model} " ]]; then
    printf "Invalid model: $model\n"
    list_models

    exit 1
fi

# check if model contains `tdrz` and update the src and pfx accordingly
if [[ $model == *"tdrz"* ]]; then
    src="https://huggingface.co/akashmjn/tinydiarize-whisper.cpp"
    pfx="resolve/main/ggml"
fi

# download ggml model

printf "Downloading ggml model $model from '$src' ...\n"
Repository: ggerganov/whisper.cpp
File: models/download-ggml-model.sh (Shell)

Code before:
    "small.en-tdrz"
    "small"
    "small-q5_1"
    "small.en-q5_1"
    "medium"
    "medium.en"
    "medium-q5_0"
    "medium.en-q5_0"
    "large-v1"
    "large-v2"
    "large-v3"
    "large-q5_0"
)

# list available models
function list_models {
    printf "\n"
    printf "  Available models:"
    for model in "${models[@]}"; do
        printf " $model"
    done
    printf "\n\n"
}

if [ "$#" -gt 2 ]; then
    printf "Usage: $0 <model> <models_path>\n"
    list_models

    exit 1
fi

model=$1

if [[ ! " ${models[@]} " =~ " ${model} " ]]; then
    printf "Invalid model: $model\n"
    list_models

    exit 1
fi

# check if model contains `tdrz` and update the src and pfx accordingly
if [[ $model == *"tdrz"* ]]; then
    src="https://huggingface.co/akashmjn/tinydiarize-whisper.cpp"
    pfx="resolve/main/ggml"
fi

# download ggml model

printf "Downloading ggml model $model from '$src' ...\n"

cd "$models_path"

Review comment (suggestion):
```suggestion
    printf "Usage: $0 <model> [<models_path>]\n"
```

Code after:
    "small.en-tdrz"
    "small"
    "small-q5_1"
    "small.en-q5_1"
    "medium"
    "medium.en"
    "medium-q5_0"
    "medium.en-q5_0"
    "large-v1"
    "large-v2"
    "large-v3"
    "large-q5_0"
)

# list available models
function list_models {
    printf "\n"
    printf "  Available models:"
    for model in "${models[@]}"; do
        printf " $model"
    done
    printf "\n\n"
}

if [ "$#" -lt 1 ] || [ "$#" -gt 2 ]; then
    printf "Usage: $0 <model> [models_path]\n"
    list_models

    exit 1
fi

model=$1

if [[ ! " ${models[@]} " =~ " ${model} " ]]; then
    printf "Invalid model: $model\n"
    list_models

    exit 1
fi

# check if model contains `tdrz` and update the src and pfx accordingly
if [[ $model == *"tdrz"* ]]; then
    src="https://huggingface.co/akashmjn/tinydiarize-whisper.cpp"
    pfx="resolve/main/ggml"
fi

# download ggml model

printf "Downloading ggml model $model from '$src' ...\n"

cd "$models_path"
Repository: ggerganov/whisper.cpp
File: whisper.cpp (C++)

Code before:
#ifdef GGML_USE_BLAS
    {
        WHISPER_LOG_INFO("%s: using BLAS backend\n", __func__);
        ggml_backend_t backend_blas = ggml_backend_blas_init();
        if (!backend_blas) {
            WHISPER_LOG_ERROR("%s: ggml_backend_blas_init() failed\n", __func__);
        } else {
            result.push_back(backend_blas);
        }
    }
#endif

    GGML_UNUSED(params);

    result.push_back(ggml_backend_cpu_init());

    return result;
}

static ggml_backend_buffer_type_t whisper_default_buffer_type(const whisper_context_params & params) {
    if (!params.use_gpu) {
        return ggml_backend_cpu_buffer_type();
    }

#ifdef GGML_USE_CUDA
    return ggml_backend_cuda_buffer_type(params.gpu_device);
#endif

#ifdef GGML_USE_METAL
    return ggml_backend_metal_buffer_type();
#endif

#ifdef GGML_USE_SYCL
    return ggml_backend_sycl_buffer_type();
#endif

    return ggml_backend_cpu_buffer_type();
}

// load the model from a ggml file
//
// file format:
//
//   - hparams
//   - pre-computed mel filters
//   - vocab
//   - weights
//
// see the convert-pt-to-ggml.py script for details
//
static bool whisper_model_load(struct whisper_model_loader * loader, whisper_context & wctx) {

Review comment (suggestion):
This will return `NULL` if there are no CUDA devices. To allow it to continue and fallback to the CPU backend, it should check for that in a similar way the llama.cpp function does this.

Code after:
#ifdef GGML_USE_BLAS
    {
        WHISPER_LOG_INFO("%s: using BLAS backend\n", __func__);
        ggml_backend_t backend_blas = ggml_backend_blas_init();
        if (!backend_blas) {
            WHISPER_LOG_ERROR("%s: ggml_backend_blas_init() failed\n", __func__);
        } else {
            result.push_back(backend_blas);
        }
    }
#endif

    GGML_UNUSED(params);

    result.push_back(ggml_backend_cpu_init());

    return result;
}

static ggml_backend_buffer_type_t whisper_default_buffer_type(const whisper_context_params & params) {
    ggml_backend_buffer_type_t result = nullptr;

    params.use_gpu || (result = ggml_backend_cpu_buffer_type());

#ifdef GGML_USE_CUDA
    result || (result = ggml_backend_cuda_buffer_type(params.gpu_device));
#endif

#ifdef GGML_USE_METAL
    result || (result = ggml_backend_metal_buffer_type());
#endif

#ifdef GGML_USE_SYCL
    result || (result = ggml_backend_sycl_buffer_type(params.gpu_device));
#endif

    result || (result = ggml_backend_cpu_buffer_type());

    return result;
}

// load the model from a ggml file
//
// file format:
//
//   - hparams
//   - pre-computed mel filters
//   - vocab
//   - weights
//
// see the convert-pt-to-ggml.py script for details