char-fork/llama.cpp
git clone https://git.t4t.associates/char-fork/llama.cpp
41361c859
char/aliceai-t5-moe
1#include "arg.h" 2#include "common.h" 3#include "log.h" 4#include "llama.h" 5 6#include <clocale> 7#include <ctime> 8#include <algorithm> 9 10#if defined(_MSC_VER ) 11#pragma warning(disable: 4244 4267) // possible loss of data 12#endif 13 14static std::vector < std::string > split_lines (const std::string & s ,const std::string & separator = "\n" ) { 15 std::vector < std::string > lines ; 16size_t start = 0 ; 17size_t end = s .find (separator ); 18 19while (end != std::string::npos ) { 20lines .push_back (s .substr (start ,end - start )); 21start = end + separator .length (); 22end = s .find (separator ,start ); 23 } 24 25lines .push_back (s .substr (start ));// Add the last part 26 27return lines ; 28} 29 30static void batch_add_seq (llama_batch & batch ,const std::vector < int32_t > & tokens ,llama_seq_id seq_id ) { 31size_t n_tokens = tokens .size (); 32for (size_t i = 0 ;i < n_tokens ;i ++ ) { 33common_batch_add (batch ,tokens [i ],i , {seq_id }, true); 34 } 35} 36 37static void batch_decode (llama_context * ctx ,llama_batch & batch ,float * output ,int n_seq ,int n_embd_out ,int embd_norm ) { 38const enum llama_pooling_type pooling_type = llama_pooling_type (ctx ); 39 40// clear previous kv_cache values (irrelevant for embeddings) 41llama_memory_clear (llama_get_memory (ctx ), true); 42 43// run model 44LOG_INF ("%s: n_tokens = %d, n_seq = %d\n" ,__func__ ,batch .n_tokens ,n_seq ); 45if (llama_decode (ctx ,batch )< 0 ) { 46LOG_ERR ("%s : failed to process\n" ,__func__ ); 47 } 48 49for (int i = 0 ;i < batch .n_tokens ;i ++ ) { 50if (!batch .logits [i ]) { 51continue ; 52 } 53 54const float * embd = nullptr ; 55int embd_pos = 0 ; 56 57if (pooling_type == LLAMA_POOLING_TYPE_NONE ) { 58// try to get token embeddings 59embd = llama_get_embeddings_ith (ctx ,i ); 60embd_pos = i ; 61GGML_ASSERT (embd != NULL && "failed to get token embeddings" ); 62 }else { 63// try to get sequence embeddings - supported only when pooling_type is not NONE 64embd = llama_get_embeddings_seq (ctx ,batch .seq_id [i ][0 ]); 65embd_pos = batch .seq_id [i ][0 ]; 66GGML_ASSERT (embd != NULL && "failed to get sequence embeddings" ); 67 } 68 69float * out = output + embd_pos * n_embd_out ; 70common_embd_normalize (embd ,out ,n_embd_out ,embd_norm ); 71 } 72} 73 74// plain, pipe-friendly output: one embedding per line 75static void print_raw_embeddings (const float * emb , 76int n_embd_count , 77int n_embd , 78const llama_model * model , 79enum llama_pooling_type pooling_type , 80int embd_normalize ) { 81const uint32_t n_cls_out = llama_model_n_cls_out (model ); 82const bool is_rank = (pooling_type == LLAMA_POOLING_TYPE_RANK ); 83const int cols = is_rank ? std::min < int > (n_embd , (int )n_cls_out ) :n_embd ; 84 85for (int j = 0 ;j < n_embd_count ;++ j ) { 86for (int i = 0 ;i < cols ;++ i ) { 87if (embd_normalize == 0 ) { 88LOG ("%1.0f%s" ,emb [j * n_embd + i ], (i + 1 < cols ?" " :"" )); 89 }else { 90LOG ("%1.7f%s" ,emb [j * n_embd + i ], (i + 1 < cols ?" " :"" )); 91 } 92 } 93LOG ("\n" ); 94 } 95} 96 97int main (int argc ,char ** argv ) { 98 std::setlocale (LC_NUMERIC ,"C" ); 99 100common_params params ; 101 102common_init (); 103 104if (!common_params_parse (argc ,argv ,params ,LLAMA_EXAMPLE_EMBEDDING )) { 105return 1 ; 106 } 107 108params .embedding = true; 109 110// get max number of sequences per batch 111const int n_seq_max = llama_max_parallel_sequences (); 112 113// if the number of prompts that would be encoded is known in advance, it's more efficient to specify the 114// --parallel argument accordingly. for convenience, if not specified, we fallback to unified KV cache 115// in order to support any number of prompts 116if (params .n_parallel == 1 ) { 117LOG_INF ("%s: n_parallel == 1 -> unified KV cache is enabled\n" ,__func__ ); 118params .kv_unified = true; 119params .n_parallel = n_seq_max ; 120 } 121 122// utilize the full context 123if (params .n_batch < params .n_ctx ) { 124LOG_WRN ("%s: setting batch size to %d\n" ,__func__ ,params .n_ctx ); 125params .n_batch = params .n_ctx ; 126 } 127 128// for non-causal models, batch size must be equal to ubatch size 129if (params .attention_type != LLAMA_ATTENTION_TYPE_CAUSAL ) { 130params .n_ubatch = params .n_batch ; 131 } 132 133llama_backend_init (); 134llama_numa_init (params .numa ); 135 136// load the model 137auto llama_init = common_init_from_params (params ); 138 139auto * model = llama_init -> model (); 140auto * ctx = llama_init -> context (); 141 142if (model == NULL ) { 143LOG_ERR ("%s: unable to load model\n" ,__func__ ); 144return 1 ; 145 } 146 147const llama_vocab * vocab = llama_model_get_vocab (model ); 148 149const int n_ctx_train = llama_model_n_ctx_train (model ); 150const int n_ctx = llama_n_ctx (ctx ); 151 152const enum llama_pooling_type pooling_type = llama_pooling_type (ctx ); 153 154if (llama_model_has_encoder (model )&& llama_model_has_decoder (model )) { 155LOG_ERR ("%s: computing embeddings in encoder-decoder models is not supported\n" ,__func__ ); 156return 1 ; 157 } 158 159if (n_ctx > n_ctx_train ) { 160LOG_WRN ("%s: warning: model was trained on only %d context tokens (%d specified)\n" , 161__func__ ,n_ctx_train ,n_ctx ); 162 } 163 164// print system information 165 { 166LOG_INF ("\n" ); 167LOG_INF ("%s\n" ,common_params_get_system_info (params ).c_str ()); 168 } 169 170// split the prompt into lines 171 std::vector < std::string > prompts = split_lines (params .prompt ,params .embd_sep ); 172 173// max batch size 174const uint64_t n_batch = params .n_batch ; 175 176// get added sep and eos token, if any 177const std::string added_sep_token = llama_vocab_get_add_sep (vocab ) ?llama_vocab_get_text (vocab ,llama_vocab_sep (vocab )) :"" ; 178const std::string added_eos_token = llama_vocab_get_add_eos (vocab ) ?llama_vocab_get_text (vocab ,llama_vocab_eos (vocab )) :"" ; 179const char * rerank_prompt = llama_model_chat_template (model ,"rerank" ); 180 181// tokenize the prompts and trim 182 std::vector < std::vector < int32_t >> inputs ; 183for (const auto & prompt :prompts ) { 184 std::vector < llama_token > inp ; 185 186// split classification pairs and insert expected separator tokens 187if (pooling_type == LLAMA_POOLING_TYPE_RANK && prompt .find (params .cls_sep )!= std::string::npos ) { 188 std::vector < std::string > pairs = split_lines (prompt ,params .cls_sep ); 189if (rerank_prompt != nullptr ) { 190const std::string query = pairs [0 ]; 191const std::string doc = pairs [1 ]; 192 std::string final_prompt = rerank_prompt ; 193string_replace_all (final_prompt ,"{query}" ,query ); 194string_replace_all (final_prompt ,"{document}" ,doc ); 195inp = common_tokenize (vocab ,final_prompt , true, true); 196 }else { 197 std::string final_prompt ; 198for (size_t i = 0 ;i < pairs .size ();i ++ ) { 199final_prompt += pairs [i ]; 200if (i != pairs .size ()- 1 ) { 201if (!added_eos_token .empty ()) { 202final_prompt += added_eos_token ; 203 } 204if (!added_sep_token .empty ()) { 205final_prompt += added_sep_token ; 206 } 207 } 208 } 209inp = common_tokenize (ctx ,final_prompt , true, true); 210 } 211 }else { 212inp = common_tokenize (ctx ,prompt , true, true); 213 } 214if (inp .size ()> n_batch ) { 215LOG_ERR ("%s: number of tokens in input line (%lld) exceeds batch size (%lld), increase batch size and re-run\n" , 216__func__ , (long long int )inp .size (), (long long int )n_batch ); 217return 1 ; 218 } 219inputs .push_back (inp ); 220 } 221 222// check if the last token is SEP/EOS 223// it should be automatically added by the tokenizer when 'tokenizer.ggml.add_eos_token' is set to 'true' 224for (auto & inp :inputs ) { 225if (inp .empty ()|| (inp .back ()!= llama_vocab_sep (vocab )&& inp .back ()!= llama_vocab_eos (vocab ))) { 226LOG_WRN ("%s: last token in the prompt is not SEP or EOS\n" ,__func__ ); 227LOG_WRN ("%s: 'tokenizer.ggml.add_eos_token' should be set to 'true' in the GGUF header\n" ,__func__ ); 228 } 229 } 230 231// tokenization stats 232if (params .verbose_prompt ) { 233for (int i = 0 ;i < (int )inputs .size ();i ++ ) { 234LOG_INF ("%s: prompt %d: '%s'\n" ,__func__ ,i ,prompts [i ].c_str ()); 235LOG_INF ("%s: number of tokens in prompt = %zu\n" ,__func__ ,inputs [i ].size ()); 236for (int j = 0 ;j < (int )inputs [i ].size ();j ++ ) { 237LOG ("%6d -> '%s'\n" ,inputs [i ][j ],common_token_to_piece (ctx ,inputs [i ][j ]).c_str ()); 238 } 239LOG ("\n\n" ); 240 } 241 } 242 243// initialize batch 244const int n_prompts = prompts .size (); 245struct llama_batch batch = llama_batch_init (n_batch ,0 ,1 ); 246 247// count number of embeddings 248int n_embd_count = 0 ; 249if (pooling_type == LLAMA_POOLING_TYPE_NONE ) { 250for (int k = 0 ;k < n_prompts ;k ++ ) { 251n_embd_count += inputs [k ].size (); 252 } 253 }else { 254n_embd_count = n_prompts ; 255 } 256 257// allocate output 258const int n_embd_out = llama_model_n_embd_out (model ); 259 std::vector < float > embeddings (n_embd_count * n_embd_out ,0 ); 260float * emb = embeddings .data (); 261 262// break into batches 263int e = 0 ;// number of embeddings already stored 264int s = 0 ;// number of prompts in current batch 265for (int k = 0 ;k < n_prompts ;k ++ ) { 266// clamp to n_batch tokens 267auto & inp = inputs [k ]; 268 269const uint64_t n_toks = inp .size (); 270 271// encode if at capacity 272if (batch .n_tokens + n_toks > n_batch || s >=n_seq_max ) { 273float * out = emb + e * n_embd_out ; 274batch_decode (ctx ,batch ,out ,s ,n_embd_out ,params .embd_normalize ); 275e += pooling_type == LLAMA_POOLING_TYPE_NONE ?batch .n_tokens :s ; 276s = 0 ; 277common_batch_clear (batch ); 278 } 279 280// add to batch 281batch_add_seq (batch ,inp ,s ); 282s += 1 ; 283 } 284 285// final batch 286float * out = emb + e * n_embd_out ; 287batch_decode (ctx ,batch ,out ,s ,n_embd_out ,params .embd_normalize ); 288 289if (params .embd_out .empty ()) { 290LOG ("\n" ); 291 292if (pooling_type == LLAMA_POOLING_TYPE_NONE ) { 293for (int j = 0 ;j < n_embd_count ;j ++ ) { 294LOG ("embedding %d: " ,j ); 295for (int i = 0 ;i < std::min (3 ,n_embd_out );i ++ ) { 296if (params .embd_normalize == 0 ) { 297LOG ("%6.0f " ,emb [j * n_embd_out + i ]); 298 }else { 299LOG ("%9.6f " ,emb [j * n_embd_out + i ]); 300 } 301 } 302LOG (" ... " ); 303for (int i = n_embd_out - 3 ;i < n_embd_out ;i ++ ) { 304if (params .embd_normalize == 0 ) { 305LOG ("%6.0f " ,emb [j * n_embd_out + i ]); 306 }else { 307LOG ("%9.6f " ,emb [j * n_embd_out + i ]); 308 } 309 } 310LOG ("\n" ); 311 } 312 }else if (pooling_type == LLAMA_POOLING_TYPE_RANK ) { 313const uint32_t n_cls_out = llama_model_n_cls_out (model ); 314 std::vector < std::string > cls_out_labels ; 315 316for (uint32_t i = 0 ;i < n_cls_out ;i ++ ) { 317const char * label = llama_model_cls_label (model ,i ); 318const std::string label_i (label == nullptr ?"" :label ); 319cls_out_labels .emplace_back (label_i .empty () ? std::to_string (i ) :label_i ); 320 } 321 322for (int j = 0 ;j < n_embd_count ;j ++ ) { 323for (uint32_t i = 0 ;i < n_cls_out ;i ++ ) { 324// NOTE: if you change this log - update the tests in ci/run.sh 325if (n_cls_out == 1 ) { 326LOG ("rerank score %d: %8.3f\n" ,j ,emb [j * n_embd_out ]); 327 }else { 328LOG ("rerank score %d: %8.3f [%s]\n" ,j ,emb [j * n_embd_out + i ],cls_out_labels [i ].c_str ()); 329 } 330 } 331 } 332 }else { 333// print the first part of the embeddings or for a single prompt, the full embedding 334for (int j = 0 ;j < n_prompts ;j ++ ) { 335LOG ("embedding %d: " ,j ); 336for (int i = 0 ;i < (n_prompts > 1 ? std::min (16 ,n_embd_out ) :n_embd_out );i ++ ) { 337if (params .embd_normalize == 0 ) { 338LOG ("%6.0f " ,emb [j * n_embd_out + i ]); 339 }else { 340LOG ("%9.6f " ,emb [j * n_embd_out + i ]); 341 } 342 } 343LOG ("\n" ); 344 } 345 346// print cosine similarity matrix 347if (n_prompts > 1 ) { 348LOG ("\n" ); 349LOG ("cosine similarity matrix:\n\n" ); 350for (int i = 0 ;i < n_prompts ;i ++ ) { 351LOG ("%6.6s " ,prompts [i ].c_str ()); 352 } 353LOG ("\n" ); 354for (int i = 0 ;i < n_prompts ;i ++ ) { 355for (int j = 0 ;j < n_prompts ;j ++ ) { 356float sim = common_embd_similarity_cos (emb + i * n_embd_out ,emb + j * n_embd_out ,n_embd_out ); 357LOG ("%6.2f " ,sim ); 358 } 359LOG ("%1.10s" ,prompts [i ].c_str ()); 360LOG ("\n" ); 361 } 362 } 363 } 364 } 365 366if (params .embd_out == "json" || params .embd_out == "json+" || params .embd_out == "array" ) { 367const bool notArray = params .embd_out != "array" ; 368 369LOG (notArray ?"{\n \"object\": \"list\",\n \"data\": [\n" :"[" ); 370for (int j = 0 ;;) {// at least one iteration (one prompt) 371if (notArray )LOG (" {\n \"object\": \"embedding\",\n \"index\": %d,\n \"embedding\": " ,j ); 372LOG ("[" ); 373for (int i = 0 ;;) {// at least one iteration (n_embd > 0) 374LOG (params .embd_normalize == 0 ?"%1.0f" :"%1.7f" ,emb [j * n_embd_out + i ]); 375i ++ ; 376if (i < n_embd_out )LOG ("," );else break ; 377 } 378LOG (notArray ?"]\n }" :"]" ); 379j ++ ; 380if (j < n_embd_count )LOG (notArray ?",\n" :"," );else break ; 381 } 382LOG (notArray ?"\n ]" :"]\n" ); 383 384if (params .embd_out == "json+" && n_prompts > 1 ) { 385LOG (",\n \"cosineSimilarity\": [\n" ); 386for (int i = 0 ;;) {// at least two iteration (n_embd_count > 1) 387LOG (" [" ); 388for (int j = 0 ;;) {// at least two iteration (n_embd_count > 1) 389float sim = common_embd_similarity_cos (emb + i * n_embd_out ,emb + j * n_embd_out ,n_embd_out ); 390LOG ("%6.2f" ,sim ); 391j ++ ; 392if (j < n_embd_count )LOG (", " );else break ; 393 } 394LOG (" ]" ); 395i ++ ; 396if (i < n_embd_count )LOG (",\n" );else break ; 397 } 398LOG ("\n ]" ); 399 } 400 401if (notArray )LOG ("\n}\n" ); 402 }else if (params .embd_out == "raw" ) { 403print_raw_embeddings (emb ,n_embd_count ,n_embd_out ,model ,pooling_type ,params .embd_normalize ); 404 } 405 406LOG ("\n" ); 407llama_perf_context_print (ctx ); 408 409// clean up 410llama_batch_free (batch ); 411llama_backend_free (); 412 413return 0 ; 414}