| 8 | // #define GRIT_DEBUG |
| 9 | |
| 10 | static std::vector<std::vector<float>> encode(llama_context * ctx, const std::vector<std::string> & sentences, const std::string & instruction) { |
| 11 | std::vector<std::vector<float>> result; |
| 12 | |
| 13 | const llama_model * model = llama_get_model(ctx); |
| 14 | const llama_vocab * vocab = llama_model_get_vocab(model); |
| 15 | |
| 16 | llama_batch batch = llama_batch_init(llama_n_batch(ctx), 0, 1); |
| 17 | |
| 18 | for (uint64_t i = 0; i < sentences.size(); i++) { |
| 19 | common_batch_clear(batch); |
| 20 | |
| 21 | const std::string input_string = instruction + sentences[i]; |
| 22 | |
| 23 | std::vector<llama_token> inputs = common_tokenize(vocab, input_string, true, false); |
| 24 | |
| 25 | const int32_t n_toks = inputs.size(); |
| 26 | |
| 27 | // GritLM seems to have EOS = "" |
| 28 | // https://github.com/ContextualAI/gritlm/blob/92025b16534712b31b3c4aaaf069350e222bd5f8/gritlm/gritlm.py#L18 |
| 29 | // inputs.push_back(llama_vocab_eos(vocab)); |
| 30 | |
| 31 | // we want to ignore instruction tokens for mean pooling |
| 32 | const int32_t n_inst = common_tokenize(vocab, instruction, true, false).size(); |
| 33 | |
| 34 | #ifdef GRIT_DEBUG |
| 35 | // debug tokens - should be matching as referenced in the GritLM sample |
| 36 | std::for_each(inputs.begin(), inputs.end(), [&ctx](llama_token t) { |
| 37 | std::printf("[%u:%s]", t, llama_token_to_piece(ctx, t).c_str()); |
| 38 | }); |
| 39 | std::printf("\n"); |
| 40 | #endif |
| 41 | |
| 42 | // add input to batch (this increments n_tokens) |
| 43 | for (int32_t j = 0; j < n_toks; j++) { |
| 44 | common_batch_add(batch, inputs[j], j, { 0 }, j >= n_inst); |
| 45 | } |
| 46 | |
| 47 | // clear previous kv_cache values (irrelevant for embeddings) |
| 48 | llama_kv_self_clear(ctx); |
| 49 | llama_set_embeddings(ctx, true); |
| 50 | llama_set_causal_attn(ctx, false); |
| 51 | |
| 52 | // run model |
| 53 | llama_decode(ctx, batch); |
| 54 | |
| 55 | // get embedding dimensions |
| 56 | uint64_t n_embd = llama_model_n_embd(model); |
| 57 | |
| 58 | // allocate embedding output |
| 59 | std::vector<float> emb_unorm(n_embd, 0.0f); |
| 60 | |
| 61 | // sum up all token embeddings |
| 62 | for (int32_t k = n_inst; k < n_toks; k++) { |
| 63 | float * emb = llama_get_embeddings_ith(ctx, k); |
| 64 | for (uint64_t j = 0; j < n_embd; j++) { |
| 65 | emb_unorm[j] += emb[j]; |
| 66 | } |
| 67 | } |
no test coverage detected