mirror of
				https://github.com/ggml-org/llama.cpp.git
				synced 2025-10-31 08:51:55 +00:00 
			
		
		
		
	Adding linenoise.cpp to llama-run (#11252)
This is a fork of linenoise that is C++17 compatible. I intend on adding it to llama-run so we can do things like traverse prompt history via the up and down arrows: https://github.com/ericcurtin/linenoise.cpp Signed-off-by: Eric Curtin <ecurtin@redhat.com>
This commit is contained in:
		
							
								
								
									
										4
									
								
								.github/workflows/build.yml
									
									
									
									
										vendored
									
									
								
							
							
						
						
									
										4
									
								
								.github/workflows/build.yml
									
									
									
									
										vendored
									
									
								
							| @@ -87,6 +87,7 @@ jobs: | |||||||
|         if: ${{ ( github.event_name == 'push' && github.ref == 'refs/heads/master' ) || github.event.inputs.create_release == 'true' }} |         if: ${{ ( github.event_name == 'push' && github.ref == 'refs/heads/master' ) || github.event.inputs.create_release == 'true' }} | ||||||
|         run: | |         run: | | ||||||
|           cp LICENSE ./build/bin/ |           cp LICENSE ./build/bin/ | ||||||
|  |           cp examples/run/linenoise.cpp/LICENSE ./build/bin/LICENSE.linenoise.cpp | ||||||
|           zip -r llama-${{ steps.tag.outputs.name }}-bin-macos-arm64.zip ./build/bin/* |           zip -r llama-${{ steps.tag.outputs.name }}-bin-macos-arm64.zip ./build/bin/* | ||||||
|  |  | ||||||
|       - name: Upload artifacts |       - name: Upload artifacts | ||||||
| @@ -149,6 +150,7 @@ jobs: | |||||||
|         if: ${{ ( github.event_name == 'push' && github.ref == 'refs/heads/master' ) || github.event.inputs.create_release == 'true' }} |         if: ${{ ( github.event_name == 'push' && github.ref == 'refs/heads/master' ) || github.event.inputs.create_release == 'true' }} | ||||||
|         run: | |         run: | | ||||||
|           cp LICENSE ./build/bin/ |           cp LICENSE ./build/bin/ | ||||||
|  |           cp examples/run/linenoise.cpp/LICENSE ./build/bin/LICENSE.linenoise.cpp | ||||||
|           zip -r llama-${{ steps.tag.outputs.name }}-bin-macos-x64.zip ./build/bin/* |           zip -r llama-${{ steps.tag.outputs.name }}-bin-macos-x64.zip ./build/bin/* | ||||||
|  |  | ||||||
|       - name: Upload artifacts |       - name: Upload artifacts | ||||||
| @@ -217,6 +219,7 @@ jobs: | |||||||
|         if: ${{ ( github.event_name == 'push' && github.ref == 'refs/heads/master' ) || github.event.inputs.create_release == 'true' }} |         if: ${{ ( github.event_name == 'push' && github.ref == 'refs/heads/master' ) || github.event.inputs.create_release == 'true' }} | ||||||
|         run: | |         run: | | ||||||
|           cp LICENSE ./build/bin/ |           cp LICENSE ./build/bin/ | ||||||
|  |           cp examples/run/linenoise.cpp/LICENSE ./build/bin/LICENSE.linenoise.cpp | ||||||
|           zip -r llama-${{ steps.tag.outputs.name }}-bin-ubuntu-x64.zip ./build/bin/* |           zip -r llama-${{ steps.tag.outputs.name }}-bin-ubuntu-x64.zip ./build/bin/* | ||||||
|  |  | ||||||
|       - name: Upload artifacts |       - name: Upload artifacts | ||||||
| @@ -796,6 +799,7 @@ jobs: | |||||||
|         if: ${{ ( github.event_name == 'push' && github.ref == 'refs/heads/master' ) || github.event.inputs.create_release == 'true' }} |         if: ${{ ( github.event_name == 'push' && github.ref == 'refs/heads/master' ) || github.event.inputs.create_release == 'true' }} | ||||||
|         run: | |         run: | | ||||||
|           Copy-Item LICENSE .\build\bin\Release\llama.cpp.txt |           Copy-Item LICENSE .\build\bin\Release\llama.cpp.txt | ||||||
|  |           Copy-Item .\examples\run\linenoise.cpp\LICENSE .\build\bin\Release\linenoise.cpp.txt | ||||||
|           7z a llama-${{ steps.tag.outputs.name }}-bin-win-${{ matrix.build }}.zip .\build\bin\Release\* |           7z a llama-${{ steps.tag.outputs.name }}-bin-win-${{ matrix.build }}.zip .\build\bin\Release\* | ||||||
|  |  | ||||||
|       - name: Upload artifacts |       - name: Upload artifacts | ||||||
|   | |||||||
| @@ -1,5 +1,5 @@ | |||||||
| set(TARGET llama-run) | set(TARGET llama-run) | ||||||
| add_executable(${TARGET} run.cpp) | add_executable(${TARGET} run.cpp linenoise.cpp/linenoise.cpp) | ||||||
| install(TARGETS ${TARGET} RUNTIME) | install(TARGETS ${TARGET} RUNTIME) | ||||||
| target_link_libraries(${TARGET} PRIVATE common llama ${CMAKE_THREAD_LIBS_INIT}) | target_link_libraries(${TARGET} PRIVATE common llama ${CMAKE_THREAD_LIBS_INIT}) | ||||||
| target_compile_features(${TARGET} PRIVATE cxx_std_17) | target_compile_features(${TARGET} PRIVATE cxx_std_17) | ||||||
|   | |||||||
							
								
								
									
										26
									
								
								examples/run/linenoise.cpp/LICENSE
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										26
									
								
								examples/run/linenoise.cpp/LICENSE
									
									
									
									
									
										Normal file
									
								
							| @@ -0,0 +1,26 @@ | |||||||
|  | Copyright (c) 2010-2014, Salvatore Sanfilippo <antirez at gmail dot com> | ||||||
|  | Copyright (c) 2010-2013, Pieter Noordhuis <pcnoordhuis at gmail dot com> | ||||||
|  | Copyright (c) 2025, Eric Curtin <ericcurtin17 at gmail dot com> | ||||||
|  |  | ||||||
|  | All rights reserved. | ||||||
|  |  | ||||||
|  | Redistribution and use in source and binary forms, with or without | ||||||
|  | modification, are permitted provided that the following conditions are met: | ||||||
|  |  | ||||||
|  | * Redistributions of source code must retain the above copyright notice, | ||||||
|  |   this list of conditions and the following disclaimer. | ||||||
|  |  | ||||||
|  | * Redistributions in binary form must reproduce the above copyright notice, | ||||||
|  |   this list of conditions and the following disclaimer in the documentation | ||||||
|  |   and/or other materials provided with the distribution. | ||||||
|  |  | ||||||
|  | THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND | ||||||
|  | ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED | ||||||
|  | WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE | ||||||
|  | DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR | ||||||
|  | ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES | ||||||
|  | (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; | ||||||
|  | LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON | ||||||
|  | ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT | ||||||
|  | (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS | ||||||
|  | SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. | ||||||
							
								
								
									
										1351
									
								
								examples/run/linenoise.cpp/linenoise.cpp
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										1351
									
								
								examples/run/linenoise.cpp/linenoise.cpp
									
									
									
									
									
										Normal file
									
								
							
										
											
												File diff suppressed because it is too large
												Load Diff
											
										
									
								
							
							
								
								
									
										114
									
								
								examples/run/linenoise.cpp/linenoise.h
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										114
									
								
								examples/run/linenoise.cpp/linenoise.h
									
									
									
									
									
										Normal file
									
								
							| @@ -0,0 +1,114 @@ | |||||||
|  | /* linenoise.h -- VERSION 1.0 | ||||||
|  |  * | ||||||
|  |  * Guerrilla line editing library against the idea that a line editing lib | ||||||
|  |  * needs to be 20,000 lines of C++ code. | ||||||
|  |  * | ||||||
|  |  * See linenoise.cpp for more information. | ||||||
|  |  * | ||||||
|  |  * ------------------------------------------------------------------------ | ||||||
|  |  * | ||||||
|  |  * Copyright (c) 2010-2023, Salvatore Sanfilippo <antirez at gmail dot com> | ||||||
|  |  * Copyright (c) 2010-2013, Pieter Noordhuis <pcnoordhuis at gmail dot com> | ||||||
|  |  * Copyright (c) 2025, Eric Curtin <ericcurtin17 at gmail dot com> | ||||||
|  |  * | ||||||
|  |  * All rights reserved. | ||||||
|  |  * | ||||||
|  |  * Redistribution and use in source and binary forms, with or without | ||||||
|  |  * modification, are permitted provided that the following conditions are | ||||||
|  |  * met: | ||||||
|  |  * | ||||||
|  |  *  *  Redistributions of source code must retain the above copyright | ||||||
|  |  *     notice, this list of conditions and the following disclaimer. | ||||||
|  |  * | ||||||
|  |  *  *  Redistributions in binary form must reproduce the above copyright | ||||||
|  |  *     notice, this list of conditions and the following disclaimer in the | ||||||
|  |  *     documentation and/or other materials provided with the distribution. | ||||||
|  |  * | ||||||
|  |  * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS | ||||||
|  |  * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT | ||||||
|  |  * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR | ||||||
|  |  * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT | ||||||
|  |  * HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, | ||||||
|  |  * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT | ||||||
|  |  * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, | ||||||
|  |  * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY | ||||||
|  |  * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT | ||||||
|  |  * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE | ||||||
|  |  * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. | ||||||
|  |  */ | ||||||
|  |  | ||||||
|  | #ifndef __LINENOISE_H | ||||||
|  | #define __LINENOISE_H | ||||||
|  |  | ||||||
|  | #ifdef __cplusplus | ||||||
|  | extern "C" { | ||||||
|  | #endif | ||||||
|  |  | ||||||
|  | #include <stddef.h> /* For size_t. */ | ||||||
|  |  | ||||||
|  | extern const char *linenoiseEditMore; | ||||||
|  |  | ||||||
|  | /* The linenoiseState structure represents the state during line editing. | ||||||
|  |  * We pass this state to functions implementing specific editing | ||||||
|  |  * functionalities. */ | ||||||
|  | struct linenoiseState { | ||||||
|  |     int in_completion;  /* The user pressed TAB and we are now in completion | ||||||
|  |                          * mode, so input is handled by completeLine(). */ | ||||||
|  |     size_t completion_idx; /* Index of next completion to propose. */ | ||||||
|  |     int ifd;            /* Terminal stdin file descriptor. */ | ||||||
|  |     int ofd;            /* Terminal stdout file descriptor. */ | ||||||
|  |     char *buf;          /* Edited line buffer. */ | ||||||
|  |     size_t buflen;      /* Edited line buffer size. */ | ||||||
|  |     const char *prompt; /* Prompt to display. */ | ||||||
|  |     size_t plen;        /* Prompt length. */ | ||||||
|  |     size_t pos;         /* Current cursor position. */ | ||||||
|  |     size_t oldpos;      /* Previous refresh cursor position. */ | ||||||
|  |     size_t len;         /* Current edited line length. */ | ||||||
|  |     size_t cols;        /* Number of columns in terminal. */ | ||||||
|  |     size_t oldrows;     /* Rows used by last refrehsed line (multiline mode) */ | ||||||
|  |     int history_index;  /* The history index we are currently editing. */ | ||||||
|  | }; | ||||||
|  |  | ||||||
|  | typedef struct linenoiseCompletions { | ||||||
|  |   size_t len; | ||||||
|  |   char **cvec; | ||||||
|  | } linenoiseCompletions; | ||||||
|  |  | ||||||
|  | /* Non blocking API. */ | ||||||
|  | int linenoiseEditStart(struct linenoiseState *l, int stdin_fd, int stdout_fd, char *buf, size_t buflen, const char *prompt); | ||||||
|  | const char *linenoiseEditFeed(struct linenoiseState *l); | ||||||
|  | void linenoiseEditStop(struct linenoiseState *l); | ||||||
|  | void linenoiseHide(struct linenoiseState *l); | ||||||
|  | void linenoiseShow(struct linenoiseState *l); | ||||||
|  |  | ||||||
|  | /* Blocking API. */ | ||||||
|  | const char *linenoise(const char *prompt); | ||||||
|  | void linenoiseFree(void *ptr); | ||||||
|  |  | ||||||
|  | /* Completion API. */ | ||||||
|  | typedef void(linenoiseCompletionCallback)(const char *, linenoiseCompletions *); | ||||||
|  | typedef const char*(linenoiseHintsCallback)(const char *, int *color, int *bold); | ||||||
|  | typedef void(linenoiseFreeHintsCallback)(const char *); | ||||||
|  | void linenoiseSetCompletionCallback(linenoiseCompletionCallback *); | ||||||
|  | void linenoiseSetHintsCallback(linenoiseHintsCallback *); | ||||||
|  | void linenoiseSetFreeHintsCallback(linenoiseFreeHintsCallback *); | ||||||
|  | void linenoiseAddCompletion(linenoiseCompletions *, const char *); | ||||||
|  |  | ||||||
|  | /* History API. */ | ||||||
|  | int linenoiseHistoryAdd(const char *line); | ||||||
|  | int linenoiseHistorySetMaxLen(int len); | ||||||
|  | int linenoiseHistorySave(const char *filename); | ||||||
|  | int linenoiseHistoryLoad(const char *filename); | ||||||
|  |  | ||||||
|  | /* Other utilities. */ | ||||||
|  | void linenoiseClearScreen(void); | ||||||
|  | void linenoiseSetMultiLine(int ml); | ||||||
|  | void linenoisePrintKeyCodes(void); | ||||||
|  | void linenoiseMaskModeEnable(void); | ||||||
|  | void linenoiseMaskModeDisable(void); | ||||||
|  |  | ||||||
|  | #ifdef __cplusplus | ||||||
|  | } | ||||||
|  | #endif | ||||||
|  |  | ||||||
|  | #endif /* __LINENOISE_H */ | ||||||
| @@ -19,12 +19,14 @@ | |||||||
| #include <cstring> | #include <cstring> | ||||||
| #include <filesystem> | #include <filesystem> | ||||||
| #include <iostream> | #include <iostream> | ||||||
|  | #include <list> | ||||||
| #include <sstream> | #include <sstream> | ||||||
| #include <string> | #include <string> | ||||||
| #include <vector> | #include <vector> | ||||||
|  |  | ||||||
| #include "common.h" | #include "common.h" | ||||||
| #include "json.hpp" | #include "json.hpp" | ||||||
|  | #include "linenoise.cpp/linenoise.h" | ||||||
| #include "llama-cpp.h" | #include "llama-cpp.h" | ||||||
|  |  | ||||||
| #if defined(__unix__) || (defined(__APPLE__) && defined(__MACH__)) || defined(_WIN32) | #if defined(__unix__) || (defined(__APPLE__) && defined(__MACH__)) || defined(_WIN32) | ||||||
| @@ -536,7 +538,7 @@ class LlamaData { | |||||||
|     llama_sampler_ptr               sampler; |     llama_sampler_ptr               sampler; | ||||||
|     llama_context_ptr               context; |     llama_context_ptr               context; | ||||||
|     std::vector<llama_chat_message> messages; |     std::vector<llama_chat_message> messages; | ||||||
|     std::vector<std::string>        msg_strs; |     std::list<std::string>          msg_strs; | ||||||
|     std::vector<char>               fmtted; |     std::vector<char>               fmtted; | ||||||
|  |  | ||||||
|     int init(Opt & opt) { |     int init(Opt & opt) { | ||||||
| @@ -807,24 +809,44 @@ static int generate(LlamaData & llama_data, const std::string & prompt, std::str | |||||||
|         batch = llama_batch_get_one(&new_token_id, 1); |         batch = llama_batch_get_one(&new_token_id, 1); | ||||||
|     } |     } | ||||||
|  |  | ||||||
|  |     printf("\033[0m"); | ||||||
|     return 0; |     return 0; | ||||||
| } | } | ||||||
|  |  | ||||||
| static int read_user_input(std::string & user) { | static int read_user_input(std::string & user_input) { | ||||||
|     std::getline(std::cin, user); |     static const char * prompt_prefix = "> "; | ||||||
|  | #ifdef WIN32 | ||||||
|  |     printf( | ||||||
|  |         "\r%*s" | ||||||
|  |         "\r\033[0m%s", | ||||||
|  |         get_terminal_width(), " ", prompt_prefix); | ||||||
|  |  | ||||||
|  |     std::getline(std::cin, user_input); | ||||||
|     if (std::cin.eof()) { |     if (std::cin.eof()) { | ||||||
|         printf("\n"); |         printf("\n"); | ||||||
|         return 1; |         return 1; | ||||||
|     } |     } | ||||||
|  | #else | ||||||
|     if (user == "/bye") { |     std::unique_ptr<char, decltype(&std::free)> line(const_cast<char *>(linenoise(prompt_prefix)), free); | ||||||
|  |     if (!line) { | ||||||
|         return 1; |         return 1; | ||||||
|     } |     } | ||||||
|  |  | ||||||
|     if (user.empty()) { |     user_input = line.get(); | ||||||
|  | #endif | ||||||
|  |  | ||||||
|  |     if (user_input == "/bye") { | ||||||
|  |         return 1; | ||||||
|  |     } | ||||||
|  |  | ||||||
|  |     if (user_input.empty()) { | ||||||
|         return 2; |         return 2; | ||||||
|     } |     } | ||||||
|  |  | ||||||
|  | #ifndef WIN32 | ||||||
|  |     linenoiseHistoryAdd(line.get()); | ||||||
|  | #endif | ||||||
|  |  | ||||||
|     return 0;  // Should have data in happy path |     return 0;  // Should have data in happy path | ||||||
| } | } | ||||||
|  |  | ||||||
| @@ -865,10 +887,6 @@ static int handle_user_input(std::string & user_input, const std::string & user) | |||||||
|         return 0;  // No need for interactive input |         return 0;  // No need for interactive input | ||||||
|     } |     } | ||||||
|  |  | ||||||
|     printf( |  | ||||||
|         "\r%*s" |  | ||||||
|         "\r\033[32m> \033[0m", |  | ||||||
|         get_terminal_width(), " "); |  | ||||||
|     return read_user_input(user_input);  // Returns true if input ends the loop |     return read_user_input(user_input);  // Returns true if input ends the loop | ||||||
| } | } | ||||||
|  |  | ||||||
|   | |||||||
		Reference in New Issue
	
	Block a user
	 Eric Curtin
					Eric Curtin