From 05c338bd87f4ceb2275b79e24189ed20136ecaba Mon Sep 17 00:00:00 2001 From: Eric Curtin Date: Wed, 15 Jan 2025 19:01:08 +0000 Subject: [PATCH] Integrate linenoise We get prompt history etc. Signed-off-by: Eric Curtin --- .github/workflows/build.yml | 4 +++ examples/run/CMakeLists.txt | 2 +- examples/run/linenoise.cpp/LICENSE | 26 +++++++++++++++ .../run/{ => linenoise.cpp}/linenoise.cpp | 1 + examples/run/{ => linenoise.cpp}/linenoise.h | 5 +-- examples/run/run.cpp | 33 ++++++++++++++----- 6 files changed, 60 insertions(+), 11 deletions(-) create mode 100644 examples/run/linenoise.cpp/LICENSE rename examples/run/{ => linenoise.cpp}/linenoise.cpp (99%) rename examples/run/{ => linenoise.cpp}/linenoise.h (96%) diff --git a/.github/workflows/build.yml b/.github/workflows/build.yml index c85999b89af64a..332bbd04e4e788 100644 --- a/.github/workflows/build.yml +++ b/.github/workflows/build.yml @@ -87,6 +87,7 @@ jobs: if: ${{ ( github.event_name == 'push' && github.ref == 'refs/heads/master' ) || github.event.inputs.create_release == 'true' }} run: | 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/* - name: Upload artifacts @@ -149,6 +150,7 @@ jobs: if: ${{ ( github.event_name == 'push' && github.ref == 'refs/heads/master' ) || github.event.inputs.create_release == 'true' }} run: | 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/* - name: Upload artifacts @@ -217,6 +219,7 @@ jobs: if: ${{ ( github.event_name == 'push' && github.ref == 'refs/heads/master' ) || github.event.inputs.create_release == 'true' }} run: | 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/* - name: Upload artifacts @@ -796,6 +799,7 @@ jobs: if: ${{ ( github.event_name == 'push' && github.ref == 'refs/heads/master' ) || github.event.inputs.create_release == 'true' }} run: | 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\* - name: Upload artifacts diff --git a/examples/run/CMakeLists.txt b/examples/run/CMakeLists.txt index 056ec2ac3c8434..cd6b0520e08bb4 100644 --- a/examples/run/CMakeLists.txt +++ b/examples/run/CMakeLists.txt @@ -1,5 +1,5 @@ set(TARGET llama-run) -add_executable(${TARGET} run.cpp linenoise.cpp) +add_executable(${TARGET} run.cpp linenoise.cpp/linenoise.cpp) install(TARGETS ${TARGET} RUNTIME) target_link_libraries(${TARGET} PRIVATE common llama ${CMAKE_THREAD_LIBS_INIT}) target_compile_features(${TARGET} PRIVATE cxx_std_17) diff --git a/examples/run/linenoise.cpp/LICENSE b/examples/run/linenoise.cpp/LICENSE new file mode 100644 index 00000000000000..b006b3b24dcf79 --- /dev/null +++ b/examples/run/linenoise.cpp/LICENSE @@ -0,0 +1,26 @@ +Copyright (c) 2010-2014, Salvatore Sanfilippo +Copyright (c) 2010-2013, Pieter Noordhuis +Copyright (c) 2025, Eric Curtin + +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. diff --git a/examples/run/linenoise.cpp b/examples/run/linenoise.cpp/linenoise.cpp similarity index 99% rename from examples/run/linenoise.cpp rename to examples/run/linenoise.cpp/linenoise.cpp index 6e8f56d08dce77..c82682747bcdae 100644 --- a/examples/run/linenoise.cpp +++ b/examples/run/linenoise.cpp/linenoise.cpp @@ -11,6 +11,7 @@ * * Copyright (c) 2010-2023, Salvatore Sanfilippo * Copyright (c) 2010-2013, Pieter Noordhuis + * Copyright (c) 2025, Eric Curtin * * All rights reserved. * diff --git a/examples/run/linenoise.h b/examples/run/linenoise.cpp/linenoise.h similarity index 96% rename from examples/run/linenoise.h rename to examples/run/linenoise.cpp/linenoise.h index bab14c1bdd4f45..3e25f4de3b2062 100644 --- a/examples/run/linenoise.h +++ b/examples/run/linenoise.cpp/linenoise.h @@ -1,14 +1,15 @@ /* 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. + * needs to be 20,000 lines of C++ code. * - * See linenoise.c for more information. + * See linenoise.cpp for more information. * * ------------------------------------------------------------------------ * * Copyright (c) 2010-2023, Salvatore Sanfilippo * Copyright (c) 2010-2013, Pieter Noordhuis + * Copyright (c) 2025, Eric Curtin * * All rights reserved. * diff --git a/examples/run/run.cpp b/examples/run/run.cpp index 0ad8bb15b27fbc..f8e57b8dfa2e50 100644 --- a/examples/run/run.cpp +++ b/examples/run/run.cpp @@ -25,6 +25,7 @@ #include "common.h" #include "json.hpp" +#include "linenoise.cpp/linenoise.h" #include "llama-cpp.h" #if defined(__unix__) || (defined(__APPLE__) && defined(__MACH__)) || defined(_WIN32) @@ -807,24 +808,44 @@ static int generate(LlamaData & llama_data, const std::string & prompt, std::str batch = llama_batch_get_one(&new_token_id, 1); } + printf("\033[0m"); return 0; } -static int read_user_input(std::string & user) { - std::getline(std::cin, user); +static int read_user_input(std::string & user_input) { + 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()) { printf("\n"); return 1; } +#else + std::unique_ptr line(const_cast(linenoise(prompt_prefix)), free); + if (!line) { + return 1; + } - if (user == "/bye") { + user_input = line.get(); +#endif + + if (user_input == "/bye") { return 1; } - if (user.empty()) { + if (user_input.empty()) { return 2; } +#ifndef WIN32 + linenoiseHistoryAdd(line.get()); +#endif + return 0; // Should have data in happy path } @@ -865,10 +886,6 @@ static int handle_user_input(std::string & user_input, const std::string & user) 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 }