11#if defined(_WIN32)
22# include < windows.h>
33#else
4+ # include < sys/ioctl.h>
45# include < unistd.h>
56#endif
67
@@ -70,7 +71,7 @@ class Opt {
7071 " )\n "
7172 " -n, --ngl <value>\n "
7273 " Number of GPU layers (default: " +
73- std::to_string (ngl_ );
74+ std::to_string (llama_model_default_params (). n_gpu_layers );
7475 help_str_ +=
7576 " )\n "
7677 " -h, --help\n "
@@ -96,8 +97,8 @@ class Opt {
9697 " llama-run https://example.com/some-file1.gguf\n "
9798 " llama-run some-file2.gguf\n "
9899 " llama-run file://some-file3.gguf\n "
99- " llama-run --ngl 99 some-file4.gguf\n "
100- " llama-run --ngl 99 some-file5.gguf Hello World\n " ;
100+ " llama-run --ngl 999 some-file4.gguf\n "
101+ " llama-run --ngl 999 some-file5.gguf Hello World\n " ;
101102 }
102103
103104 int parse (int argc, const char ** argv) {
@@ -119,6 +120,10 @@ class Opt {
119120 help_ = true ;
120121 return 0 ;
121122 } else if (!positional_args_i) {
123+ if (!argv[0 ] || argv[1 ] == ' -' ) {
124+ return 1 ;
125+ }
126+
122127 ++positional_args_i;
123128 model_ = argv[i];
124129 } else if (positional_args_i == 1 ) {
@@ -151,6 +156,18 @@ struct FileDeleter {
151156
152157typedef std::unique_ptr<FILE, FileDeleter> FILE_ptr;
153158
159+ static int get_terminal_width () {
160+ #if defined(_WIN32)
161+ CONSOLE_SCREEN_BUFFER_INFO csbi;
162+ GetConsoleScreenBufferInfo (GetStdHandle (STD_OUTPUT_HANDLE), &csbi);
163+ return csbi.srWindow .Right - csbi.srWindow .Left + 1 ;
164+ #else
165+ struct winsize w;
166+ ioctl (STDOUT_FILENO, TIOCGWINSZ, &w);
167+ return w.ws_col ;
168+ #endif
169+ }
170+
154171#ifdef LLAMA_USE_CURL
155172class CurlWrapper {
156173 public:
@@ -270,9 +287,9 @@ class CurlWrapper {
270287
271288 static std::string human_readable_size (curl_off_t size) {
272289 static const char * suffix[] = { " B" , " KB" , " MB" , " GB" , " TB" };
273- char length = sizeof (suffix) / sizeof (suffix[0 ]);
274- int i = 0 ;
275- double dbl_size = size;
290+ char length = sizeof (suffix) / sizeof (suffix[0 ]);
291+ int i = 0 ;
292+ double dbl_size = size;
276293 if (size > 1024 ) {
277294 for (i = 0 ; (size / 1024 ) > 0 && i < length - 1 ; i++, size /= 1024 ) {
278295 dbl_size = size / 1024.0 ;
@@ -293,27 +310,75 @@ class CurlWrapper {
293310
294311 total_to_download += data->file_size ;
295312 const curl_off_t now_downloaded_plus_file_size = now_downloaded + data->file_size ;
296- const curl_off_t percentage = (now_downloaded_plus_file_size * 100 ) / total_to_download;
297- const curl_off_t pos = (percentage / 5 );
313+ const curl_off_t percentage = calculate_percentage (now_downloaded_plus_file_size, total_to_download);
314+ std::string progress_prefix = generate_progress_prefix (percentage);
315+
316+ const double speed = calculate_speed (now_downloaded, data->start_time );
317+ const double time = (total_to_download - now_downloaded) / speed;
318+ std::string progress_suffix =
319+ generate_progress_suffix (now_downloaded_plus_file_size, total_to_download, speed, time);
320+
321+ int progress_bar_width = calculate_progress_bar_width (progress_prefix, progress_suffix);
298322 std::string progress_bar;
299- for (int i = 0 ; i < 20 ; ++i) {
300- progress_bar.append ((i < pos) ? " █" : " " );
301- }
323+ generate_progress_bar (progress_bar_width, percentage, progress_bar);
302324
303- // Calculate download speed and estimated time to completion
304- const auto now = std::chrono::steady_clock::now ();
305- const std::chrono::duration<double > elapsed_seconds = now - data->start_time ;
306- const double speed = now_downloaded / elapsed_seconds.count ();
307- const double estimated_time = (total_to_download - now_downloaded) / speed;
308- printe (" \r %ld%% |%s| %s/%s %.2f MB/s %s " , percentage, progress_bar.c_str (),
309- human_readable_size (now_downloaded).c_str (), human_readable_size (total_to_download).c_str (),
310- speed / (1024 * 1024 ), human_readable_time (estimated_time).c_str ());
311- fflush (stderr);
325+ print_progress (progress_prefix, progress_bar, progress_suffix);
312326 data->printed = true ;
313327
314328 return 0 ;
315329 }
316330
331+ static curl_off_t calculate_percentage (curl_off_t now_downloaded_plus_file_size, curl_off_t total_to_download) {
332+ return (now_downloaded_plus_file_size * 100 ) / total_to_download;
333+ }
334+
335+ static std::string generate_progress_prefix (curl_off_t percentage) {
336+ std::ostringstream progress_output;
337+ progress_output << percentage << " % |" ;
338+ return progress_output.str ();
339+ }
340+
341+ static double calculate_speed (curl_off_t now_downloaded, const std::chrono::steady_clock::time_point & start_time) {
342+ const auto now = std::chrono::steady_clock::now ();
343+ const std::chrono::duration<double > elapsed_seconds = now - start_time;
344+ return now_downloaded / elapsed_seconds.count ();
345+ }
346+
347+ static std::string generate_progress_suffix (curl_off_t now_downloaded_plus_file_size, curl_off_t total_to_download,
348+ double speed, double estimated_time) {
349+ std::ostringstream progress_output;
350+ progress_output << human_readable_size (now_downloaded_plus_file_size).c_str () << " /"
351+ << human_readable_size (total_to_download).c_str () << " " << std::fixed << std::setprecision (2 )
352+ << speed / (1024 * 1024 ) << " MB/s " << human_readable_time (estimated_time).c_str ();
353+ return progress_output.str ();
354+ }
355+
356+ static int calculate_progress_bar_width (const std::string & progress_prefix, const std::string & progress_suffix) {
357+ int progress_bar_width = get_terminal_width () - progress_prefix.size () - progress_suffix.size () - 5 ;
358+ if (progress_bar_width < 10 ) {
359+ progress_bar_width = 10 ;
360+ }
361+ return progress_bar_width;
362+ }
363+
364+ static std::string generate_progress_bar (int progress_bar_width, curl_off_t percentage,
365+ std::string & progress_bar) {
366+ const curl_off_t pos = (percentage * progress_bar_width) / 100 ;
367+ for (int i = 0 ; i < progress_bar_width; ++i) {
368+ progress_bar.append ((i < pos) ? " █" : " " );
369+ }
370+
371+ return progress_bar;
372+ }
373+
374+ static void print_progress (const std::string & progress_prefix, const std::string & progress_bar,
375+ const std::string & progress_suffix) {
376+ std::ostringstream progress_output;
377+ progress_output << progress_prefix << progress_bar << " | " << progress_suffix;
378+ printe (" \r %*s\r %s" , get_terminal_width (), " " , progress_output.str ().c_str ());
379+ fflush (stderr);
380+ }
381+
317382 // Function to write data to a file
318383 static size_t write_data (void * ptr, size_t size, size_t nmemb, void * stream) {
319384 FILE * out = static_cast <FILE *>(stream);
@@ -467,6 +532,7 @@ class LlamaData {
467532 llama_model_params model_params = llama_model_default_params ();
468533 model_params.n_gpu_layers = opt.ngl_ >= 0 ? opt.ngl_ : model_params.n_gpu_layers ;
469534 resolve_model (opt.model_ );
535+ printe (" Loading model" );
470536 llama_model_ptr model (llama_load_model_from_file (opt.model_ .c_str (), model_params));
471537 if (!model) {
472538 printe (" %s: error: unable to load model from file: %s\n " , __func__, opt.model_ .c_str ());
@@ -642,8 +708,9 @@ static int handle_user_input(std::string & user_input, const std::string & user_
642708 }
643709
644710 printf (
645- " \r "
646- " \r\033 [32m> \033 [0m" );
711+ " \r %*s"
712+ " \r\033 [32m> \033 [0m" ,
713+ get_terminal_width (), " " );
647714 return read_user_input (user_input); // Returns true if input ends the loop
648715}
649716
0 commit comments