Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
37 changes: 35 additions & 2 deletions src/whisper.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -602,6 +602,39 @@ struct whisper_hparams {
float eps = 1e-5f;
};

static bool whisper_is_valid_ftype(int32_t ftype) {
switch ((ggml_ftype) ftype) {
case GGML_FTYPE_ALL_F32:
case GGML_FTYPE_MOSTLY_F16:
case GGML_FTYPE_MOSTLY_BF16:
case GGML_FTYPE_MOSTLY_Q4_0:
case GGML_FTYPE_MOSTLY_Q4_1:
case GGML_FTYPE_MOSTLY_Q1_0:
case GGML_FTYPE_MOSTLY_Q5_0:
case GGML_FTYPE_MOSTLY_Q5_1:
case GGML_FTYPE_MOSTLY_Q8_0:
case GGML_FTYPE_MOSTLY_MXFP4:
case GGML_FTYPE_MOSTLY_NVFP4:
case GGML_FTYPE_MOSTLY_Q2_K:
case GGML_FTYPE_MOSTLY_Q3_K:
case GGML_FTYPE_MOSTLY_Q4_K:
case GGML_FTYPE_MOSTLY_Q5_K:
case GGML_FTYPE_MOSTLY_Q6_K:
case GGML_FTYPE_MOSTLY_IQ2_XXS:
case GGML_FTYPE_MOSTLY_IQ2_XS:
case GGML_FTYPE_MOSTLY_IQ3_XXS:
case GGML_FTYPE_MOSTLY_IQ1_S:
case GGML_FTYPE_MOSTLY_IQ1_M:
case GGML_FTYPE_MOSTLY_IQ4_NL:
case GGML_FTYPE_MOSTLY_IQ4_XS:
case GGML_FTYPE_MOSTLY_IQ3_S:
case GGML_FTYPE_MOSTLY_IQ2_S:
return true;
default:
return false;
}
}

// audio encoding layer
struct whisper_layer_encoder {
// encoder.blocks.*.attn_ln
Expand Down Expand Up @@ -1552,11 +1585,11 @@ static bool whisper_model_load(struct whisper_model_loader * loader, whisper_con

// for the big tensors, we have the option to store the data in 16-bit floats or quantized
// in order to save memory and also to speed up the computation
wctx.wtype = ggml_ftype_to_ggml_type((ggml_ftype) (model.hparams.ftype));
if (wctx.wtype == GGML_TYPE_COUNT) {
if (!whisper_is_valid_ftype(model.hparams.ftype)) {
WHISPER_LOG_ERROR("%s: invalid model (bad ftype value %d)\n", __func__, model.hparams.ftype);
return false;
}
wctx.wtype = ggml_ftype_to_ggml_type((ggml_ftype) (model.hparams.ftype));

WHISPER_LOG_INFO("%s: n_vocab = %d\n", __func__, hparams.n_vocab);
WHISPER_LOG_INFO("%s: n_audio_ctx = %d\n", __func__, hparams.n_audio_ctx);
Expand Down
8 changes: 8 additions & 0 deletions tests/CMakeLists.txt
Original file line number Diff line number Diff line change
Expand Up @@ -96,6 +96,14 @@ target_link_libraries(${UTF8_TEST} PRIVATE common)
add_test(NAME ${UTF8_TEST} COMMAND ${UTF8_TEST})
set_tests_properties(${UTF8_TEST} PROPERTIES LABELS "unit")

# Model loading unit test
set(MODEL_LOAD_TEST test-model-load)
add_executable(${MODEL_LOAD_TEST} ${MODEL_LOAD_TEST}.cpp)
target_include_directories(${MODEL_LOAD_TEST} PRIVATE ../include ../ggml/include)
target_link_libraries(${MODEL_LOAD_TEST} PRIVATE whisper)
add_test(NAME ${MODEL_LOAD_TEST} COMMAND ${MODEL_LOAD_TEST})
set_tests_properties(${MODEL_LOAD_TEST} PROPERTIES LABELS "unit")

# VAD test tests VAD in isolation
set(VAD_TEST test-vad)
add_executable(${VAD_TEST} ${VAD_TEST}.cpp)
Expand Down
53 changes: 53 additions & 0 deletions tests/test-model-load.cpp
Original file line number Diff line number Diff line change
@@ -0,0 +1,53 @@
#include "ggml.h"
#include "whisper.h"

#include <cstdint>
#include <cstdio>
#include <fstream>

static void write_u32(std::ofstream & fout, uint32_t value) {
fout.write(reinterpret_cast<const char *>(&value), sizeof(value));
}

static void write_i32(std::ofstream & fout, int32_t value) {
fout.write(reinterpret_cast<const char *>(&value), sizeof(value));
}

int main() {
const char * path = "invalid-ftype.ggml";

{
std::ofstream fout(path, std::ios::binary);
if (!fout) {
return 1;
}

write_u32(fout, GGML_FILE_MAGIC);
write_i32(fout, 1); // n_vocab
write_i32(fout, 1500); // n_audio_ctx
write_i32(fout, 384); // n_audio_state
write_i32(fout, 6); // n_audio_head
write_i32(fout, 4); // n_audio_layer
write_i32(fout, 448); // n_text_ctx
write_i32(fout, 384); // n_text_state
write_i32(fout, 6); // n_text_head
write_i32(fout, 4); // n_text_layer
write_i32(fout, 80); // n_mels
write_i32(fout, 5); // invalid ftype

if (!fout) {
return 2;
}
}

whisper_context_params params = whisper_context_default_params();
whisper_context * ctx = whisper_init_from_file_with_params(path, params);
if (ctx != nullptr) {
whisper_free(ctx);
std::remove(path);
return 3;
}

std::remove(path);
return 0;
}