char-fork/llama.cpp
git clone https://git.t4t.associates/char-fork/llama.cpp
aff6eb6e7
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 <cstdio> 8#include <cstring> 9#include <fstream> 10#include <string> 11#include <vector> 12#include <iostream> 13#include <sstream> 14 15#if defined(_WIN32 ) 16#define WIN32_LEAN_AND_MEAN 17#include <windows.h> 18#endif 19 20static void print_usage (int argc ,char ** argv ) { 21 (void )argc ; 22 23LOG ("\nexample usage:\n" ); 24LOG ("\n %s -m your_model.gguf -p \"Hello world\"\n" ,argv [0 ]); 25LOG ("\n %s -m your_model.gguf -f prompt.txt --ids\n" ,argv [0 ]); 26LOG ("\n cat prompt.txt | %s -m your_model.gguf --stdin --show-count\n" ,argv [0 ]); 27LOG ("\n" ); 28} 29 30// 31// Function: write_utf8_cstr_to_stdout(const char *) -> <writes to stdout> 32// 33// writes a string to standard output; taking into account that on Windows 34// to display correctly you have to use special handling. Works even if the 35// user has not set a unicode code page on a Windows cmd.exe. 36// 37// In case of invalid UTF-8, invalid_utf8 is set to true on Windows, and something 38// a human-readable is written instead. 39// 40// On non-Windows systems, simply printfs() the string. 41static void write_utf8_cstr_to_stdout (const char * str ,bool & invalid_utf8 ) { 42invalid_utf8 = false; 43 44#if defined(_WIN32 ) 45// Are we in a console? 46HANDLE hConsole = GetStdHandle (STD_OUTPUT_HANDLE ); 47DWORD dwMode = 0 ; 48 49// According to Microsoft docs: 50// "WriteConsole fails if it is used with a standard handle that is redirected to a file." 51// Also according to the docs, you can use GetConsoleMode to check for that. 52if (hConsole == INVALID_HANDLE_VALUE || !GetConsoleMode (hConsole ,& dwMode )) { 53printf ("%s" ,str ); 54return ; 55 } 56 57// MultiByteToWideChar reports an error if str is empty, don't report 58// them as invalid_utf8. 59if (* str == 0 ) { 60return ; 61 } 62int length_needed = MultiByteToWideChar (CP_UTF8 ,MB_ERR_INVALID_CHARS ,str ,strlen (str ),NULL ,0 ); 63if (length_needed == 0 ) { 64DWORD err = GetLastError (); 65if (err == ERROR_NO_UNICODE_TRANSLATION ) { 66invalid_utf8 = true; 67int len = strlen (str ); 68printf ("<" ); 69for (int i = 0 ;i < len ;++ i ) { 70if (i > 0 ) { 71printf (" " ); 72 } 73printf ("%02x" , (uint8_t )str [i ]); 74 } 75printf (">" ); 76return ; 77 } 78GGML_ABORT ("MultiByteToWideChar() failed in an unexpected way." ); 79 } 80 81LPWSTR wstr = (LPWSTR )calloc (length_needed + 1 ,sizeof (* wstr )); 82GGML_ASSERT (wstr ); 83 84MultiByteToWideChar (CP_UTF8 ,0 ,str ,strlen (str ),wstr ,length_needed ); 85WriteConsoleW (hConsole ,wstr ,length_needed ,NULL ,NULL ); 86 87free (wstr ); 88#else 89// TODO: reporting invalid_utf8 would be useful on non-Windows too. 90// printf will silently just write bad unicode. 91printf ("%s" ,str ); 92#endif 93} 94 95int main (int argc ,char ** argv ) { 96 std::setlocale (LC_NUMERIC ,"C" ); 97 98common_params params ; 99 100common_init (); 101 102if (!common_params_parse (argc ,argv ,params ,LLAMA_EXAMPLE_TOKENIZE ,print_usage )) { 103return 1 ; 104 } 105 106// -f and -p both land in params.prompt; -f also sets prompt_file. -f and -p 107// resolve like the other tools (no mutual exclusion), --stdin takes precedence. 108const bool use_stdin = params .tokenize_stdin ; 109const bool use_file = !params .prompt_file .empty (); 110 111// must have some prompt 112if (!use_stdin && !use_file && params .prompt .empty ()) { 113LOG_ERR ("error: must specify one of: --stdin, --file or --prompt\n" ); 114return 1 ; 115 } 116 117 std::string prompt ; 118if (use_file ) { 119// read the file verbatim: common's -f handler strips a single trailing 120// newline, but for a tokenizer the input bytes must be preserved exactly 121// (a trailing newline is itself a token). escapes are applied locally 122// to match the behavior of -p/--prompt and --stdin. 123 std::ifstream in (params .prompt_file , std::ios::binary ); 124if (!in ) { 125LOG_ERR ("error: could not open file '%s' for reading\n" ,params .prompt_file .c_str ()); 126return 1 ; 127 } 128 std::stringstream ss ; 129ss <<in .rdbuf (); 130prompt = ss .str (); 131if (params .escape ) { 132string_process_escapes (prompt ); 133 } 134 }else if (!use_stdin ) { 135// -p/--prompt is already escape-processed by common_params_parse() 136// (controlled by --escape/--no-escape), so use it verbatim here. 137prompt = params .prompt ; 138 } 139// else: we read stdin *after* loading the model (early exit if the 140// model cannot be loaded, which is a nicer user experience) 141 142llama_backend_init (); 143 144// load only the vocabulary (no weights), since tokenizing does not need them 145llama_model_params model_params = llama_model_default_params (); 146model_params .vocab_only = true; 147llama_model * model = llama_model_load_from_file (params .model .path .c_str (),model_params ); 148if (!model ) { 149LOG_ERR ("error: could not load model from file '%s'.\n" ,params .model .path .c_str ()); 150return 1 ; 151 } 152 153const llama_vocab * vocab = llama_model_get_vocab (model ); 154 155llama_context_params ctx_params = llama_context_default_params (); 156llama_context * ctx = llama_init_from_model (model ,ctx_params ); 157if (!ctx ) { 158LOG_ERR ("error: could not create context.\n" ); 159return 1 ; 160 } 161 162// read entire prompt from stdin? 163if (params .tokenize_stdin ) { 164 std::stringstream stdin_buffer ; 165stdin_buffer << std::cin .rdbuf (); 166if (std::cin .fail ()) { 167LOG_ERR ("error: could not read the entire standard input.\n" ); 168return 1 ; 169 } 170 171prompt = stdin_buffer .str (); 172 173// stdin is not seen by common_params_parse(), so apply escape handling 174// here to match the behavior of -p/--prompt and -f/--file. 175if (params .escape ) { 176string_process_escapes (prompt ); 177 } 178 } 179 180const bool model_wants_add_bos = llama_vocab_get_add_bos (vocab ); 181const bool add_bos = model_wants_add_bos && !params .tokenize_no_bos ; 182const bool parse_special = params .parse_special ; 183 184 std::vector < llama_token > tokens ; 185tokens = common_tokenize (vocab ,prompt ,add_bos ,parse_special ); 186 187if (params .tokenize_ids ) { 188printf ("[" ); 189 } 190 191for (int i = 0 ;i < (int )tokens .size ();i ++ ) { 192if (params .tokenize_ids ) { 193if (i > 0 ) { 194printf (", " ); 195 } 196printf ("%d" ,tokens [i ]); 197 }else { 198bool invalid_utf8 = false; 199printf ("%6d -> '" ,tokens [i ]); 200write_utf8_cstr_to_stdout (common_token_to_piece (ctx ,tokens [i ]).c_str (),invalid_utf8 ); 201if (invalid_utf8 ) { 202printf ("' (utf-8 decode failure)\n" ); 203 }else { 204printf ("'\n" ); 205 } 206 } 207 } 208 209if (params .tokenize_ids ) { 210printf ("]\n" ); 211 } 212 213if (params .tokenize_show_count ) { 214printf ("Total number of tokens: %zu\n" ,tokens .size ()); 215 } 216 217// silence valgrind 218llama_free (ctx ); 219llama_model_free (model ); 220 221return 0 ; 222}