| 1034 | } |
| 1035 | |
| 1036 | int32_t mtmd_encode(mtmd_context * ctx, const mtmd_image_tokens * image_tokens) { |
| 1037 | clip_ctx * ctx_clip = ctx->ctx_v; |
| 1038 | if (!ctx_clip) { |
| 1039 | LOG_ERR("%s: this API does not support non-vision input, please use mtmd_encode_chunk instead\n", __func__); |
| 1040 | return 1; |
| 1041 | } |
| 1042 | auto proj_type = clip_get_projector_type(ctx_clip); |
| 1043 | int n_mmproj_embd = clip_n_mmproj_embd(ctx_clip); |
| 1044 | ctx->image_embd_v.resize(image_tokens->n_tokens() * n_mmproj_embd); |
| 1045 | bool ok = false; |
| 1046 | |
| 1047 | if (clip_is_llava(ctx_clip) |
| 1048 | || clip_is_minicpmv(ctx_clip) |
| 1049 | || clip_is_glm(ctx_clip) |
| 1050 | || proj_type == PROJECTOR_TYPE_INTERNVL) { |
| 1051 | // TODO @ngxson : llava does not support batched encoding ; this should be fixed inside clip_image_batch_encode() |
| 1052 | const auto & entries = image_tokens->batch_f32.entries; |
| 1053 | for (size_t i = 0; i < entries.size(); i++) { |
| 1054 | int n_tokens_per_image = clip_n_output_tokens(ctx_clip, entries[i].get()); |
| 1055 | ok = clip_image_encode( |
| 1056 | ctx_clip, |
| 1057 | ctx->n_threads, |
| 1058 | entries[i].get(), |
| 1059 | ctx->image_embd_v.data() + i*n_mmproj_embd*n_tokens_per_image); |
| 1060 | } |
| 1061 | } else { |
| 1062 | ok = clip_image_batch_encode( |
| 1063 | ctx_clip, |
| 1064 | ctx->n_threads, |
| 1065 | &image_tokens->batch_f32, |
| 1066 | ctx->image_embd_v.data()); |
| 1067 | } |
| 1068 | |
| 1069 | return ok ? 0 : 1; |
| 1070 | } |
| 1071 | |
| 1072 | float * mtmd_get_output_embd(mtmd_context * ctx) { |
| 1073 | return ctx->image_embd_v.data(); |
no test coverage detected