char-fork/llama.cpp
git clone https://git.t4t.associates/char-fork/llama.cpp
a94d563ed
char/aliceai-t5-moe
1#include "arg.h" 2#include "common.h" 3#include "console.h" 4#include "log.h" 5#include "sampling.h" 6#include "llama.h" 7#include "chat.h" 8 9#include <clocale> 10#include <cstdio> 11#include <cstring> 12#include <ctime> 13#include <fstream> 14#include <iostream> 15#include <sstream> 16#include <string> 17#include <vector> 18 19#if defined (__unix__ )|| (defined (__APPLE__ )&& defined (__MACH__ )) 20#include <signal.h> 21#include <unistd.h> 22#elif defined (_WIN32 ) 23#define WIN32_LEAN_AND_MEAN 24#ifndef NOMINMAX 25#define NOMINMAX 26#endif 27#include <windows.h> 28#include <signal.h> 29#endif 30 31#if defined(_MSC_VER ) 32#pragma warning(disable: 4244 4267) // possible loss of data 33#endif 34 35static llama_context ** g_ctx ; 36static common_sampler ** g_smpl ; 37static common_params * g_params ; 38static bool is_interacting = false; 39static bool need_insert_eot = false; 40 41static void print_usage (int argc ,char ** argv ) { 42 (void )argc ; 43 44LOG ("\nexample usage:\n" ); 45LOG ("\n text generation: %s -m your_model.gguf -p \"I believe the meaning of life is\" -n 128 -no-cnv\n" ,argv [0 ]); 46LOG ("\n chat (conversation): %s -m your_model.gguf -sys \"You are a helpful assistant\"\n" ,argv [0 ]); 47LOG ("\n" ); 48} 49 50static bool file_exists (const std::string & path ) { 51 std::ifstream f (path .c_str ()); 52return f .good (); 53} 54 55static bool file_is_empty (const std::string & path ) { 56 std::ifstream f ; 57f .exceptions (std::ifstream::failbit | std::ifstream::badbit ); 58f .open (path .c_str (), std::ios::in | std::ios::binary | std::ios::ate ); 59return f .tellg ()== 0 ; 60} 61 62#if defined (__unix__ )|| (defined (__APPLE__ )&& defined (__MACH__ ))|| defined (_WIN32 ) 63static void sigint_handler (int signo ) { 64if (signo == SIGINT ) { 65if (!is_interacting && g_params -> interactive ) { 66is_interacting = true; 67need_insert_eot = true; 68 }else { 69 console::cleanup (); 70LOG ("\n" ); 71common_perf_print (* g_ctx ,* g_smpl ); 72 73// make sure all logs are flushed 74LOG ("Interrupted by user\n" ); 75common_log_pause (common_log_main ()); 76 77_exit (130 ); 78 } 79 } 80} 81#endif 82 83// satisfies -Wmissing-declarations 84int llama_completion (int argc ,char ** argv ); 85 86int llama_completion (int argc ,char ** argv ) { 87 std::setlocale (LC_NUMERIC ,"C" ); 88 89common_params params ; 90g_params = & params ; 91 92common_init (); 93 94if (!common_params_parse (argc ,argv ,params ,LLAMA_EXAMPLE_COMPLETION ,print_usage )) { 95return 1 ; 96 } 97 98auto & sparams = params .sampling ; 99 100// save choice to use color for later 101// (note for later: this is a slightly awkward choice) 102 console::init (params .simple_io ,params .use_color ); 103atexit ([]() { console::cleanup (); }); 104 105if (params .embedding ) { 106LOG_ERR ("************\n" ); 107LOG_ERR ("%s: please use the 'embedding' tool for embedding calculations\n" ,__func__ ); 108LOG_ERR ("************\n\n" ); 109 110return 0 ; 111 } 112 113if (params .n_ctx != 0 && params .n_ctx < 8 ) { 114LOG_WRN ("%s: warning: minimum context size is 8, using minimum size.\n" ,__func__ ); 115params .n_ctx = 8 ; 116 } 117 118if (params .rope_freq_base != 0.0 ) { 119LOG_WRN ("%s: warning: changing RoPE frequency base to %g.\n" ,__func__ ,params .rope_freq_base ); 120 } 121 122if (params .rope_freq_scale != 0.0 ) { 123LOG_WRN ("%s: warning: scaling RoPE frequency by %g.\n" ,__func__ ,params .rope_freq_scale ); 124 } 125 126LOG_INF ("%s: llama backend init\n" ,__func__ ); 127 128llama_backend_init (); 129llama_numa_init (params .numa ); 130 131llama_model * model = nullptr ; 132llama_context * ctx = nullptr ; 133common_sampler * smpl = nullptr ; 134 135g_ctx = & ctx ; 136g_smpl = & smpl ; 137 138 std::vector < common_chat_msg > chat_msgs ; 139 140// load the model and apply lora adapter, if any 141LOG_INF ("%s: load the model and apply lora adapter, if any\n" ,__func__ ); 142 143auto llama_init = common_init_from_params (params ); 144 145ctx = llama_init -> context (); 146model = llama_init -> model (); 147smpl = llama_init -> sampler (0 ); 148 149if (ctx == NULL ) { 150LOG_ERR ("%s: error: unable to create context\n" ,__func__ ); 151return 1 ; 152 } 153 154llama_memory_t mem = llama_get_memory (ctx ); 155const llama_vocab * vocab = llama_model_get_vocab (model ); 156 157// note: the time for chat template initialization is not negligible: 158auto chat_templates = common_chat_templates_init (model ,params .chat_template ); 159 160// start measuring performance timings from here 161llama_perf_context_reset (ctx ); 162 163const int n_ctx_train = llama_model_n_ctx_train (model ); 164const int n_ctx = llama_n_ctx (ctx ); 165 166if (n_ctx > n_ctx_train ) { 167LOG_WRN ("%s: model was trained on only %d context tokens (%d specified)\n" ,__func__ ,n_ctx_train ,n_ctx ); 168 } 169 170// auto enable conversation mode if chat template is available 171const bool has_chat_template = common_chat_templates_was_explicit (chat_templates .get ()); 172if (params .conversation_mode == COMMON_CONVERSATION_MODE_AUTO ) { 173if (has_chat_template ) { 174LOG_INF ("%s: chat template is available, enabling conversation mode (disable it with -no-cnv)\n" ,__func__ ); 175params .conversation_mode = COMMON_CONVERSATION_MODE_ENABLED ; 176 }else { 177params .conversation_mode = COMMON_CONVERSATION_MODE_DISABLED ; 178 } 179 } 180 181// in case user force-activate conversation mode (via -cnv) without proper chat template, we show a warning 182if (params .conversation_mode && !has_chat_template ) { 183LOG_WRN ("%s: chat template is not available or is not supported. This may cause the model to output suboptimal responses\n" ,__func__ ); 184 } 185 186// print chat template example in conversation mode 187if (params .conversation_mode ) { 188if (params .enable_chat_template ) { 189if (!params .prompt .empty ()&& params .system_prompt .empty ()) { 190LOG_WRN ("*** User-specified prompt will pre-start conversation, did you mean to set --system-prompt (-sys) instead?\n" ); 191 } 192 193LOG_INF ("%s: chat template example:\n%s\n" ,__func__ ,common_chat_format_example (chat_templates .get (),params .use_jinja ,params .default_template_kwargs ).c_str ()); 194 }else { 195LOG_INF ("%s: in-suffix/prefix is specified, chat template will be disabled\n" ,__func__ ); 196 } 197 } 198 199// print system information 200 { 201LOG_INF ("\n" ); 202LOG_INF ("%s\n" ,common_params_get_system_info (params ).c_str ()); 203LOG_INF ("\n" ); 204 } 205 206 std::string path_session = params .path_prompt_cache ; 207 std::vector < llama_token > session_tokens ; 208 209if (!path_session .empty ()) { 210LOG_INF ("%s: attempting to load saved session from '%s'\n" ,__func__ ,path_session .c_str ()); 211if (!file_exists (path_session )) { 212LOG_INF ("%s: session file does not exist, will create.\n" ,__func__ ); 213 }else if (file_is_empty (path_session )) { 214LOG_INF ("%s: The session file is empty. A new session will be initialized.\n" ,__func__ ); 215 }else { 216// The file exists and is not empty 217session_tokens .resize (n_ctx ); 218size_t n_token_count_out = 0 ; 219if (!llama_state_load_file (ctx ,path_session .c_str (),session_tokens .data (),session_tokens .capacity (),& n_token_count_out )) { 220LOG_ERR ("%s: failed to load session file '%s'\n" ,__func__ ,path_session .c_str ()); 221return 1 ; 222 } 223session_tokens .resize (n_token_count_out ); 224LOG_INF ("%s: loaded a session with prompt size of %d tokens\n" ,__func__ , (int )session_tokens .size ()); 225 } 226 } 227 228const bool add_bos = llama_vocab_get_add_bos (vocab )&& !params .use_jinja ; 229if (!llama_model_has_encoder (model )) { 230GGML_ASSERT (!llama_vocab_get_add_eos (vocab )); 231 } 232 233LOG_DBG ("n_ctx: %d, add_bos: %d\n" ,n_ctx ,add_bos ); 234 235 std::vector < llama_token > embd_inp ; 236 237bool waiting_for_first_input = false; 238auto chat_add_and_format = [& chat_msgs ,& chat_templates ](const std::string & role ,const std::string & content ) { 239common_chat_msg new_msg ; 240new_msg .role = role ; 241new_msg .content = content ; 242auto formatted = common_chat_format_single (chat_templates .get (),chat_msgs ,new_msg ,role == "user" ,g_params -> use_jinja ); 243chat_msgs .push_back (new_msg ); 244LOG_DBG ("formatted: '%s'\n" ,formatted .c_str ()); 245return formatted ; 246 }; 247 248 std::string prompt ; 249 { 250if (params .conversation_mode && params .enable_chat_template ) { 251if (!params .system_prompt .empty ()) { 252// format the system prompt (will use template default if empty) 253chat_add_and_format ("system" ,params .system_prompt ); 254 } 255 256if (!params .prompt .empty ()) { 257// format and append the user prompt 258chat_add_and_format ("user" ,params .prompt ); 259 }else { 260waiting_for_first_input = true; 261 } 262 263if (!params .system_prompt .empty ()|| !params .prompt .empty ()) { 264common_chat_templates_inputs inputs ; 265inputs .use_jinja = g_params -> use_jinja ; 266inputs .messages = chat_msgs ; 267inputs .add_generation_prompt = !params .prompt .empty (); 268inputs .force_pure_content = params .force_pure_content_parser ; 269 270prompt = common_chat_templates_apply (chat_templates .get (),inputs ).prompt ; 271 } 272 }else { 273// otherwise use the prompt as is 274prompt = params .prompt ; 275 } 276 277if (params .interactive_first || !prompt .empty ()|| session_tokens .empty ()) { 278LOG_DBG ("tokenize the prompt\n" ); 279embd_inp = common_tokenize (ctx ,prompt , true, true); 280 }else { 281LOG_DBG ("use session tokens\n" ); 282embd_inp = session_tokens ; 283 } 284 285LOG_DBG ("prompt: \"%s\"\n" ,prompt .c_str ()); 286LOG_DBG ("tokens: %s\n" ,string_from (ctx ,embd_inp ).c_str ()); 287 } 288 289// Should not run without any tokens 290if (!waiting_for_first_input && embd_inp .empty ()) { 291if (add_bos ) { 292embd_inp .push_back (llama_vocab_bos (vocab )); 293LOG_WRN ("embd_inp was considered empty and bos was added: %s\n" ,string_from (ctx ,embd_inp ).c_str ()); 294 }else { 295LOG_ERR ("input is empty\n" ); 296return -1 ; 297 } 298 } 299 300// Tokenize negative prompt 301if ((int )embd_inp .size ()> n_ctx - 4 ) { 302LOG_ERR ("%s: prompt is too long (%d tokens, max %d)\n" ,__func__ , (int )embd_inp .size (),n_ctx - 4 ); 303return 1 ; 304 } 305 306bool session_do_save = false; 307 308 { 309size_t n_match = 0 ; 310 311if (!session_tokens .empty ()) { 312for (llama_token id :session_tokens ) { 313if (n_match >=embd_inp .size ()|| id != embd_inp [n_match ]) { 314break ; 315 } 316n_match ++ ; 317 } 318if (params .prompt .empty ()&& n_match == embd_inp .size ()) { 319LOG_INF ("%s: using full prompt from session file\n" ,__func__ ); 320 }else if (n_match >=embd_inp .size ()) { 321LOG_INF ("%s: session file has exact match for prompt!\n" ,__func__ ); 322 }else if (n_match < (embd_inp .size () /2 )) { 323LOG_WRN ("%s: session file has low similarity to prompt (%zu / %zu tokens); will mostly be reevaluated\n" , 324__func__ ,n_match ,embd_inp .size ()); 325 }else { 326LOG_INF ("%s: session file matches %zu / %zu tokens of prompt\n" , 327__func__ ,n_match ,embd_inp .size ()); 328 } 329 330// remove any "future" tokens that we might have inherited from the previous session 331if (session_tokens .size ()> n_match ) { 332llama_pos pos = n_match > 0 ? (llama_pos )(n_match - 1 ) :0 ; 333if (!llama_memory_seq_rm (mem ,-1 ,pos ,-1 )) { 334LOG_WRN ("%s: unable to reuse common prefix (for example, when the memory is recurrent)\n" ,__func__ ); 335llama_memory_clear (mem , true); 336session_tokens .clear (); 337n_match = 0 ; 338 }else { 339session_tokens .resize (n_match ); 340 } 341 } 342 } 343 344session_do_save = !path_session .empty ()&& n_match < embd_inp .size ()&& !params .prompt_cache_ro ; 345 346// Logits are not stored as part of the session state so we need to 347// "replay" the last token to get logits for sampling. 348if (!session_tokens .empty ()&& n_match > 0 && n_match == session_tokens .size ()) { 349if (!common_replay_last_token (ctx ,session_tokens .back (),n_match - 1 )) { 350return 1 ; 351 } 352 353session_do_save = false; 354LOG_INF ("%s: replayed last token from session\n" ,__func__ ); 355 } 356 } 357 358// number of tokens to keep when resetting context 359if (params .n_keep < 0 || params .n_keep > (int )embd_inp .size ()) { 360params .n_keep = (int )embd_inp .size (); 361 }else { 362params .n_keep += add_bos ;// always keep the BOS token 363 } 364 365if (params .conversation_mode ) { 366if (params .single_turn && !params .prompt .empty ()) { 367params .interactive = false; 368params .interactive_first = false; 369 }else { 370params .interactive_first = true; 371 } 372 } 373 374// enable interactive mode if interactive start is specified 375if (params .interactive_first ) { 376params .interactive = true; 377 } 378 379if (params .verbose_prompt ) { 380LOG_INF ("%s: prompt: '%s'\n" ,__func__ ,params .prompt .c_str ()); 381LOG_INF ("%s: number of tokens in prompt = %zu\n" ,__func__ ,embd_inp .size ()); 382for (int i = 0 ;i < (int )embd_inp .size ();i ++ ) { 383LOG_INF ("%6d -> '%s'\n" ,embd_inp [i ],common_token_to_piece (ctx ,embd_inp [i ]).c_str ()); 384 } 385 386if (params .n_keep > add_bos ) { 387LOG_INF ("%s: static prompt based on n_keep: '" ,__func__ ); 388for (int i = 0 ;i < params .n_keep ;i ++ ) { 389LOG_CNT ("%s" ,common_token_to_piece (ctx ,embd_inp [i ]).c_str ()); 390 } 391LOG_CNT ("'\n" ); 392 } 393LOG_INF ("\n" ); 394 } 395 396// ctrl+C handling 397 { 398#if defined (__unix__ )|| (defined (__APPLE__ )&& defined (__MACH__ )) 399struct sigaction sigint_action ; 400sigint_action .sa_handler = sigint_handler ; 401sigemptyset (& sigint_action .sa_mask ); 402sigint_action .sa_flags = 0 ; 403sigaction (SIGINT ,& sigint_action ,NULL ); 404#elif defined (_WIN32 ) 405auto console_ctrl_handler = + [](DWORD ctrl_type )-> BOOL { 406return (ctrl_type == CTRL_C_EVENT ) ? (sigint_handler (SIGINT ), true) : false; 407 }; 408SetConsoleCtrlHandler (reinterpret_cast < PHANDLER_ROUTINE > (console_ctrl_handler ), true); 409#endif 410 } 411 412if (params .interactive ) { 413LOG_INF ("%s: interactive mode on.\n" ,__func__ ); 414 415if (!params .antiprompt .empty ()) { 416for (const auto & antiprompt :params .antiprompt ) { 417LOG_INF ("Reverse prompt: '%s'\n" ,antiprompt .c_str ()); 418if (params .verbose_prompt ) { 419auto tmp = common_tokenize (ctx ,antiprompt , false, true); 420for (int i = 0 ;i < (int )tmp .size ();i ++ ) { 421LOG_INF ("%6d -> '%s'\n" ,tmp [i ],common_token_to_piece (ctx ,tmp [i ]).c_str ()); 422 } 423 } 424 } 425 } 426 427if (params .input_prefix_bos ) { 428LOG_INF ("Input prefix with BOS\n" ); 429 } 430 431if (!params .input_prefix .empty ()) { 432LOG_INF ("Input prefix: '%s'\n" ,params .input_prefix .c_str ()); 433if (params .verbose_prompt ) { 434auto tmp = common_tokenize (ctx ,params .input_prefix , true, true); 435for (int i = 0 ;i < (int )tmp .size ();i ++ ) { 436LOG_INF ("%6d -> '%s'\n" ,tmp [i ],common_token_to_piece (ctx ,tmp [i ]).c_str ()); 437 } 438 } 439 } 440 441if (!params .input_suffix .empty ()) { 442LOG_INF ("Input suffix: '%s'\n" ,params .input_suffix .c_str ()); 443if (params .verbose_prompt ) { 444auto tmp = common_tokenize (ctx ,params .input_suffix , false, true); 445for (int i = 0 ;i < (int )tmp .size ();i ++ ) { 446LOG_INF ("%6d -> '%s'\n" ,tmp [i ],common_token_to_piece (ctx ,tmp [i ]).c_str ()); 447 } 448 } 449 } 450 } 451 452LOG_INF ("sampler seed: %u\n" ,common_sampler_get_seed (smpl )); 453LOG_INF ("sampler params: \n%s\n" ,sparams .c_str ()); 454LOG_INF ("sampler chain: %s\n" ,common_sampler_print (smpl ).c_str ()); 455 456LOG_INF ("generate: n_ctx = %d, n_batch = %d, n_predict = %d, n_keep = %d\n" ,n_ctx ,params .n_batch ,params .n_predict ,params .n_keep ); 457 458// group-attention state 459// number of grouped KV tokens so far (used only if params.grp_attn_n > 1) 460int ga_i = 0 ; 461 462const int ga_n = params .grp_attn_n ; 463const int ga_w = params .grp_attn_w ; 464 465if (ga_n != 1 ) { 466GGML_ASSERT (ga_n > 0 && "grp_attn_n must be positive" );// NOLINT 467GGML_ASSERT (ga_w %ga_n == 0 && "grp_attn_w must be a multiple of grp_attn_n" );// NOLINT 468//GGML_ASSERT(n_ctx_train % ga_w == 0 && "n_ctx_train must be a multiple of grp_attn_w"); // NOLINT 469//GGML_ASSERT(n_ctx >= n_ctx_train * ga_n && "n_ctx must be at least n_ctx_train * grp_attn_n"); // NOLINT 470LOG_INF ("self-extend: n_ctx_train = %d, grp_attn_n = %d, grp_attn_w = %d\n" ,n_ctx_train ,ga_n ,ga_w ); 471 } 472LOG_INF ("\n" ); 473 474if (params .interactive ) { 475const char * control_message ; 476if (params .multiline_input ) { 477control_message = " - To return control to the AI, end your input with '\\'.\n" 478" - To return control without starting a new line, end your input with '/'.\n" ; 479 }else { 480control_message = " - Press Return to return control to the AI.\n" 481" - To return control without starting a new line, end your input with '/'.\n" 482" - If you want to submit another line, end your input with '\\'.\n" ; 483 } 484LOG_INF ("== Running in interactive mode. ==\n" ); 485#if defined (__unix__ )|| (defined (__APPLE__ )&& defined (__MACH__ ))|| defined (_WIN32 ) 486LOG_INF (" - Press Ctrl+C to interject at any time.\n" ); 487#endif 488LOG_INF ("%s" ,control_message ); 489if (params .conversation_mode && params .enable_chat_template && params .system_prompt .empty ()) { 490LOG_INF (" - Not using system message. To change it, set a different value via -sys PROMPT\n" ); 491 } 492LOG_INF ("\n" ); 493 494is_interacting = params .interactive_first ; 495 } 496 497bool is_antiprompt = false; 498bool input_echo = true; 499bool display = true; 500 501int n_past = 0 ; 502int n_remain = params .n_predict ; 503int n_consumed = 0 ; 504int n_session_consumed = 0 ; 505 506 std::vector < int > input_tokens ; 507 std::vector < int > output_tokens ; 508 std::ostringstream output_ss ; 509 std::ostringstream assistant_ss ;// for storing current assistant message, used in conversation mode 510 511// the first thing we will do is to output the prompt, so set color accordingly 512 console::set_display (DISPLAY_TYPE_PROMPT ); 513display = params .display_prompt ; 514 515 std::vector < llama_token > embd ; 516 517// single-token antiprompts 518 std::vector < llama_token > antiprompt_token ; 519 520for (const std::string & antiprompt :params .antiprompt ) { 521auto ids = ::common_tokenize (ctx ,antiprompt , false, true); 522if (ids .size ()== 1 ) { 523antiprompt_token .push_back (ids [0 ]); 524 } 525 } 526 527if (llama_model_has_encoder (model )) { 528int enc_input_size = embd_inp .size (); 529llama_token * enc_input_buf = embd_inp .data (); 530 531if (llama_encode (ctx ,llama_batch_get_one (enc_input_buf ,enc_input_size ))) { 532LOG_ERR ("%s : failed to eval\n" ,__func__ ); 533return 1 ; 534 } 535 536llama_token decoder_start_token_id = llama_model_decoder_start_token (model ); 537if (decoder_start_token_id == LLAMA_TOKEN_NULL ) { 538decoder_start_token_id = llama_vocab_bos (vocab ); 539 } 540 541embd_inp .clear (); 542embd_inp .push_back (decoder_start_token_id ); 543 } 544 545while ((n_remain != 0 && !is_antiprompt )|| params .interactive ) { 546// predict 547if (!embd .empty ()) { 548// Note: (n_ctx - 4) here is to match the logic for commandline prompt handling via 549// --prompt or --file which uses the same value. 550int max_embd_size = n_ctx - 4 ; 551 552// Ensure the input doesn't exceed the context size by truncating embd if necessary. 553if ((int )embd .size ()> max_embd_size ) { 554const int skipped_tokens = (int )embd .size ()- max_embd_size ; 555embd .resize (max_embd_size ); 556 557 console::set_display (DISPLAY_TYPE_ERROR ); 558LOG_WRN ("<<input too long: skipped %d token%s>>" ,skipped_tokens ,skipped_tokens != 1 ?"s" :"" ); 559 console::set_display (DISPLAY_TYPE_RESET ); 560 } 561 562if (ga_n == 1 ) { 563// infinite text generation via context shifting 564// if we run out of context: 565// - take the n_keep first tokens from the original prompt (via n_past) 566// - take half of the last (n_ctx - n_keep) tokens and recompute the logits in batches 567 568if (n_past + (int )embd .size () >=n_ctx ) { 569if (!params .ctx_shift ){ 570LOG_WRN ("\n\n%s: context full and context shift is disabled => stopping\n" ,__func__ ); 571break ; 572 } 573 574if (params .n_predict == -2 ) { 575LOG_WRN ("\n\n%s: context full and n_predict == %d => stopping\n" ,__func__ ,params .n_predict ); 576break ; 577 } 578 579const int n_left = n_past - params .n_keep ; 580const int n_discard = n_left /2 ; 581 582LOG_DBG ("context full, swapping: n_past = %d, n_left = %d, n_ctx = %d, n_keep = %d, n_discard = %d\n" , 583n_past ,n_left ,n_ctx ,params .n_keep ,n_discard ); 584 585llama_memory_seq_rm (mem ,0 ,params .n_keep ,params .n_keep + n_discard ); 586llama_memory_seq_add (mem ,0 ,params .n_keep + n_discard ,n_past ,- n_discard ); 587 588n_past -= n_discard ; 589 590LOG_DBG ("after swap: n_past = %d\n" ,n_past ); 591 592LOG_DBG ("embd: %s\n" ,string_from (ctx ,embd ).c_str ()); 593 594LOG_DBG ("clear session path\n" ); 595path_session .clear (); 596 } 597 }else { 598// context extension via Self-Extend 599while (n_past >=ga_i + ga_w ) { 600const int ib = (ga_n * ga_i )/ga_w ; 601const int bd = (ga_w /ga_n )* (ga_n - 1 ); 602const int dd = (ga_w /ga_n )- ib * bd - ga_w ; 603 604LOG_DBG ("\n" ); 605LOG_DBG ("shift: [%6d, %6d] + %6d -> [%6d, %6d]\n" ,ga_i ,n_past ,ib * bd ,ga_i + ib * bd ,n_past + ib * bd ); 606LOG_DBG ("div: [%6d, %6d] / %6d -> [%6d, %6d]\n" ,ga_i + ib * bd ,ga_i + ib * bd + ga_w ,ga_n , (ga_i + ib * bd )/ga_n , (ga_i + ib * bd + ga_w )/ga_n ); 607LOG_DBG ("shift: [%6d, %6d] + %6d -> [%6d, %6d]\n" ,ga_i + ib * bd + ga_w ,n_past + ib * bd ,dd ,ga_i + ib * bd + ga_w + dd ,n_past + ib * bd + dd ); 608 609llama_memory_seq_add (mem ,0 ,ga_i ,n_past ,ib * bd ); 610llama_memory_seq_div (mem ,0 ,ga_i + ib * bd ,ga_i + ib * bd + ga_w ,ga_n ); 611llama_memory_seq_add (mem ,0 ,ga_i + ib * bd + ga_w ,n_past + ib * bd ,dd ); 612 613n_past -= bd ; 614 615ga_i += ga_w /ga_n ; 616 617LOG_DBG ("\nn_past_old = %d, n_past = %d, ga_i = %d\n\n" ,n_past + bd ,n_past ,ga_i ); 618 } 619 } 620 621// try to reuse a matching prefix from the loaded session instead of re-eval (via n_past) 622if (n_session_consumed < (int )session_tokens .size ()) { 623size_t i = 0 ; 624for ( ;i < embd .size ();i ++ ) { 625if (embd [i ]!= session_tokens [n_session_consumed ]) { 626session_tokens .resize (n_session_consumed ); 627break ; 628 } 629 630n_past ++ ; 631n_session_consumed ++ ; 632 633if (n_session_consumed >= (int )session_tokens .size ()) { 634++ i ; 635break ; 636 } 637 } 638if (i > 0 ) { 639embd .erase (embd .begin (),embd .begin ()+ i ); 640 } 641 } 642 643if (!embd .empty ()) { 644const bool is_last_batch = (n_consumed >= (int )embd_inp .size ()); 645const bool save_now = session_do_save && is_last_batch ; 646session_tokens .insert (session_tokens .end (),embd .begin (),embd .end ()); 647if (!common_prompt_batch_decode (ctx ,session_tokens ,embd .size (),n_past ,params .n_batch ,path_session ,save_now )) { 648return 1 ; 649 } 650n_session_consumed += embd .size (); 651if (save_now ) { 652session_do_save = false; 653 } 654 655LOG_DBG ("n_past = %d\n" ,n_past ); 656 657// Display total tokens alongside total time 658if (params .n_print > 0 && n_past %params .n_print == 0 ) { 659LOG_DBG ("\n\033[31mTokens consumed so far = %d / %d \033[0m\n" ,n_past ,n_ctx ); 660 } 661 } 662 } 663 664embd .clear (); 665 666if ((int )embd_inp .size () <=n_consumed && !is_interacting ) { 667 668const llama_token id = common_sampler_sample (smpl ,ctx ,-1 ); 669 670common_sampler_accept (smpl ,id ,/* accept_grammar= */ true); 671 672// LOG_DBG("last: %s\n", string_from(ctx, smpl->prev.to_vector()).c_str()); 673 674embd .push_back (id ); 675 676if (params .conversation_mode && !waiting_for_first_input && !llama_vocab_is_eog (vocab ,id )) { 677assistant_ss <<common_token_to_piece (ctx ,id , false); 678 } 679 680// echo this to console 681input_echo = true; 682 683// decrement remaining sampling budget 684-- n_remain ; 685 686LOG_DBG ("n_remain: %d\n" ,n_remain ); 687 }else { 688// some user input remains from prompt or interaction, forward it to processing 689LOG_DBG ("embd_inp.size(): %d, n_consumed: %d\n" , (int )embd_inp .size (),n_consumed ); 690while ((int )embd_inp .size ()> n_consumed ) { 691embd .push_back (embd_inp [n_consumed ]); 692 693// push the prompt in the sampling context in order to apply repetition penalties later 694// for the prompt, we don't apply grammar rules 695common_sampler_accept (smpl ,embd_inp [n_consumed ],/* accept_grammar= */ false); 696 697++ n_consumed ; 698if ((int )embd .size ()== params .n_batch ) { 699break ; 700 } 701 } 702 } 703 704// display text 705if (input_echo && display ) { 706for (auto id :embd ) { 707const std::string token_str = common_token_to_piece (ctx ,id ,params .special ); 708 709// Console/Stream Output 710LOG ("%s" ,token_str .c_str ()); 711 712// Record Displayed Tokens To Log 713// Note: Generated tokens are created one by one hence this check 714if (embd .size ()> 1 ) { 715// Incoming Requested Tokens 716input_tokens .push_back (id ); 717 }else { 718// Outgoing Generated Tokens 719output_tokens .push_back (id ); 720output_ss <<token_str ; 721 } 722 } 723 } 724 725// reset color to default if there is no pending user input 726if (input_echo && (int )embd_inp .size ()== n_consumed ) { 727 console::set_display (DISPLAY_TYPE_RESET ); 728display = true; 729 } 730 731// if not currently processing queued inputs; 732if ((int )embd_inp .size () <=n_consumed ) { 733// check for reverse prompt in the last n_prev tokens 734if (!params .antiprompt .empty ()) { 735const int n_prev = 32 ; 736const std::string last_output = common_sampler_prev_str (smpl ,ctx ,n_prev ); 737 738is_antiprompt = false; 739// Check if each of the reverse prompts appears at the end of the output. 740// If we're not running interactively, the reverse prompt might be tokenized with some following characters 741// so we'll compensate for that by widening the search window a bit. 742for (std::string & antiprompt :params .antiprompt ) { 743size_t extra_padding = params .interactive ?0 :2 ; 744size_t search_start_pos = last_output .length ()> static_cast < size_t > (antiprompt .length ()+ extra_padding ) 745 ?last_output .length ()- static_cast < size_t > (antiprompt .length ()+ extra_padding ) 746 :0 ; 747 748if (last_output .find (antiprompt ,search_start_pos )!= std::string::npos ) { 749if (params .interactive ) { 750is_interacting = true; 751 } 752is_antiprompt = true; 753break ; 754 } 755 } 756 757// check for reverse prompt using special tokens 758// avoid calling common_sampler_last() if last_output is empty 759if (!last_output .empty ()) { 760llama_token last_token = common_sampler_last (smpl ); 761for (auto token :antiprompt_token ) { 762if (token == last_token ) { 763if (params .interactive ) { 764is_interacting = true; 765 } 766is_antiprompt = true; 767break ; 768 } 769 } 770 } 771 772if (is_antiprompt ) { 773LOG_DBG ("found antiprompt: %s\n" ,last_output .c_str ()); 774 } 775 } 776 777// deal with end of generation tokens in interactive mode 778if (!waiting_for_first_input && llama_vocab_is_eog (vocab ,common_sampler_last (smpl ))) { 779LOG_DBG ("found an EOG token\n" ); 780 781if (params .interactive ) { 782if (!params .antiprompt .empty ()) { 783// tokenize and inject first reverse prompt 784const auto first_antiprompt = common_tokenize (ctx ,params .antiprompt .front (), false, true); 785embd_inp .insert (embd_inp .end (),first_antiprompt .begin (),first_antiprompt .end ()); 786is_antiprompt = true; 787 } 788 789if (params .enable_chat_template ) { 790chat_add_and_format ("assistant" ,assistant_ss .str ()); 791 } 792is_interacting = true; 793LOG ("\n" ); 794 } 795 } 796 797if (params .conversation_mode && !waiting_for_first_input ) { 798if (!prompt .empty ()) { 799prompt .clear (); 800is_interacting = false; 801 } 802 } 803 804if ((n_past > 0 || waiting_for_first_input )&& is_interacting ) { 805LOG_DBG ("waiting for user input\n" ); 806 807if (params .conversation_mode ) { 808LOG ("\n> " ); 809 } 810 811if (params .input_prefix_bos ) { 812LOG_DBG ("adding input prefix BOS token\n" ); 813embd_inp .push_back (llama_vocab_bos (vocab )); 814 } 815 816 std::string buffer ; 817if (!params .input_prefix .empty ()&& !params .conversation_mode ) { 818LOG_DBG ("appending input prefix: '%s'\n" ,params .input_prefix .c_str ()); 819LOG ("%s" ,params .input_prefix .c_str ()); 820 } 821 822// color user input only 823 console::set_display (DISPLAY_TYPE_USER_INPUT ); 824display = params .display_prompt ; 825 826 std::string line ; 827bool another_line = true; 828do { 829another_line = console::readline (line ,params .multiline_input ); 830buffer += line ; 831 }while (another_line ); 832 833// done taking input, reset color 834 console::set_display (DISPLAY_TYPE_RESET ); 835display = true; 836 837if (buffer .empty ()) {// Ctrl+D on empty line exits 838LOG ("EOF by user\n" ); 839break ; 840 } 841 842if (buffer .back ()== '\n' ) { 843// Implement #587: 844// If the user wants the text to end in a newline, 845// this should be accomplished by explicitly adding a newline by using \ followed by return, 846// then returning control by pressing return again. 847buffer .pop_back (); 848 } 849 850if (buffer .empty ()) {// Enter key on empty line lets the user pass control back 851LOG_DBG ("empty line, passing control back\n" ); 852 }else {// Add tokens to embd only if the input buffer is non-empty 853// append input suffix if any 854if (!params .input_suffix .empty ()&& !params .conversation_mode ) { 855LOG_DBG ("appending input suffix: '%s'\n" ,params .input_suffix .c_str ()); 856LOG ("%s" ,params .input_suffix .c_str ()); 857 } 858 859LOG_DBG ("buffer: '%s'\n" ,buffer .c_str ()); 860 861const size_t original_size = embd_inp .size (); 862 863if (params .escape ) { 864string_process_escapes (buffer ); 865 } 866 867bool format_chat = params .conversation_mode && params .enable_chat_template ; 868 std::string user_inp = format_chat 869 ?chat_add_and_format ("user" , std::move (buffer )) 870 : std::move (buffer ); 871// TODO: one inconvenient of current chat template implementation is that we can't distinguish between user input and special tokens (prefix/postfix) 872const auto line_pfx = common_tokenize (ctx ,params .input_prefix , false, true); 873const auto line_inp = common_tokenize (ctx ,user_inp , false,format_chat ); 874const auto line_sfx = common_tokenize (ctx ,params .input_suffix , false, true); 875 876LOG_DBG ("input tokens: %s\n" ,string_from (ctx ,line_inp ).c_str ()); 877 878// if user stop generation mid-way, we must add EOT to finish model's last response 879if (need_insert_eot && format_chat ) { 880llama_token eot = llama_vocab_eot (vocab ); 881embd_inp .push_back (eot == LLAMA_TOKEN_NULL ?llama_vocab_eos (vocab ) :eot ); 882need_insert_eot = false; 883 } 884 885embd_inp .insert (embd_inp .end (),line_pfx .begin (),line_pfx .end ()); 886embd_inp .insert (embd_inp .end (),line_inp .begin (),line_inp .end ()); 887embd_inp .insert (embd_inp .end (),line_sfx .begin (),line_sfx .end ()); 888 889if (params .verbose_prompt ) { 890LOG_INF ("%s: number of tokens in prompt = %zu\n" ,__func__ ,embd_inp .size ()- original_size ); 891 } 892 893for (size_t i = original_size ;i < embd_inp .size ();++ i ) { 894const llama_token token = embd_inp [i ]; 895const std::string token_str = common_token_to_piece (ctx ,token ); 896output_tokens .push_back (token ); 897output_ss <<token_str ; 898 899if (params .verbose_prompt ) { 900LOG_INF ("%6d -> '%s'\n" ,token ,token_str .c_str ()); 901 } 902 } 903 904// reset assistant message 905assistant_ss .str ("" ); 906 907n_remain -= line_inp .size (); 908LOG_DBG ("n_remain: %d\n" ,n_remain ); 909 } 910 911input_echo = false;// do not echo this again 912 } 913 914if (n_past > 0 || waiting_for_first_input ) { 915if (is_interacting ) { 916common_sampler_reset (smpl ); 917 } 918is_interacting = false; 919 920if (waiting_for_first_input && params .single_turn ) { 921params .interactive = false; 922params .interactive_first = false; 923 } 924waiting_for_first_input = false; 925 } 926 } 927 928// end of generation 929if (!embd .empty ()&& llama_vocab_is_eog (vocab ,embd .back ())&& !(params .interactive )) { 930LOG (" [end of text]\n" ); 931break ; 932 } 933 934// In interactive mode, respect the maximum number of tokens and drop back to user input when reached. 935// We skip this logic when n_predict == -1 (infinite) or -2 (stop at context size). 936if (params .interactive && n_remain <=0 && params .n_predict >=0 ) { 937n_remain = params .n_predict ; 938is_interacting = true; 939 } 940 } 941 942if (!path_session .empty ()&& params .prompt_cache_all && !params .prompt_cache_ro ) { 943LOG ("\n%s: saving final output to session file '%s'\n" ,__func__ ,path_session .c_str ()); 944session_tokens .insert (session_tokens .end (),embd .begin (),embd .end ()); 945llama_state_save_file (ctx ,path_session .c_str (),session_tokens .data (),session_tokens .size ()); 946LOG_INF ("saved final session to %s, n_tokens = %zu\n" ,path_session .data (),session_tokens .size ()); 947 948 } 949 950LOG ("\n\n" ); 951common_perf_print (ctx ,smpl ); 952 953llama_backend_free (); 954 955return 0 ; 956}