Skip to content
Closed
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
25 changes: 25 additions & 0 deletions CMakeLists.txt
Original file line number Diff line number Diff line change
@@ -1,6 +1,7 @@
cmake_minimum_required(VERSION 3.14) # for add_link_options and implicit target directories.
project("llama.cpp" C CXX)
include(CheckIncludeFileCXX)
include(FetchContent)

#set(CMAKE_WARN_DEPRECATED YES)
set(CMAKE_WARN_UNUSED_CLI YES)
Expand Down Expand Up @@ -87,6 +88,30 @@ option(LLAMA_BUILD_SERVER "llama: build server example" ${LLAMA_STANDALONE})
option(LLAMA_CURL "llama: use libcurl to download model from an URL" ON)
option(LLAMA_LLGUIDANCE "llama-common: include LLGuidance library for structured output in common utils" OFF)

# Add yaml-cpp dependency
FetchContent_Declare(
yaml-cpp
GIT_REPOSITORY https://github.com/jbeder/yaml-cpp.git
GIT_TAG yaml-cpp-0.7.0
)

# Configure yaml-cpp for platform compatibility
if(WIN32 AND (CMAKE_GENERATOR MATCHES "MSYS Makefiles" OR MSYS))
set(YAML_BUILD_SHARED_LIBS ON CACHE BOOL "Build yaml-cpp as shared library for MSYS2")
set(YAML_CPP_BUILD_CONTRIB OFF CACHE BOOL "Disable yaml-cpp contrib for MSYS2")
set(CMAKE_POLICY_DEFAULT_CMP0077 NEW CACHE STRING "Use NEW policy for option() behavior")
endif()

# Set CMake policy version minimum for yaml-cpp compatibility
set(CMAKE_POLICY_VERSION_MINIMUM 3.5 CACHE STRING "Minimum CMake policy version for yaml-cpp compatibility")

# Disable yaml-cpp tests and tools to avoid build issues
set(YAML_CPP_BUILD_TESTS OFF CACHE BOOL "Disable yaml-cpp tests")
set(YAML_CPP_BUILD_TOOLS OFF CACHE BOOL "Disable yaml-cpp tools")
set(YAML_CPP_BUILD_CONTRIB OFF CACHE BOOL "Disable yaml-cpp contrib")

FetchContent_MakeAvailable(yaml-cpp)

# Required for relocatable CMake package
include(${CMAKE_CURRENT_SOURCE_DIR}/cmake/build-info.cmake)
include(${CMAKE_CURRENT_SOURCE_DIR}/cmake/common.cmake)
Expand Down
2 changes: 1 addition & 1 deletion common/CMakeLists.txt
Original file line number Diff line number Diff line change
Expand Up @@ -135,7 +135,7 @@ endif ()

target_include_directories(${TARGET} PUBLIC . ../vendor)
target_compile_features (${TARGET} PUBLIC cxx_std_17)
target_link_libraries (${TARGET} PRIVATE ${LLAMA_COMMON_EXTRA_LIBS} PUBLIC llama Threads::Threads)
target_link_libraries (${TARGET} PRIVATE ${LLAMA_COMMON_EXTRA_LIBS} yaml-cpp PUBLIC llama Threads::Threads)


#
Expand Down
331 changes: 328 additions & 3 deletions common/arg.cpp

Large diffs are not rendered by default.

2 changes: 2 additions & 0 deletions common/common.h
Original file line number Diff line number Diff line change
Expand Up @@ -348,6 +348,8 @@ struct common_params {
int32_t control_vector_layer_end = -1; // layer range for control vector
bool offline = false;

std::string config_file = ""; // path to YAML configuration file

int32_t ppl_stride = 0; // stride for perplexity calculations. If left at 0, the pre-existing approach will be used.
int32_t ppl_output_type = 0; // = 0 -> ppl output is as usual, = 1 -> ppl output is num_tokens, ppl, one per line
// (which is more convenient to use for plotting)
Expand Down
4 changes: 4 additions & 0 deletions tests/CMakeLists.txt
Original file line number Diff line number Diff line change
Expand Up @@ -190,6 +190,10 @@ llama_build_and_test(test-thread-safety.cpp ARGS -hf ggml-org/models -hff tinyll
# this fails on windows (github hosted runner) due to curl DLL not found (exit code 0xc0000135)
if (NOT WIN32)
llama_build_and_test(test-arg-parser.cpp)

# YAML configuration tests
llama_build_and_test(test-yaml-config.cpp)
llama_build_and_test(test-yaml-backward-compat.cpp)
endif()

if (NOT LLAMA_SANITIZE_ADDRESS)
Expand Down
179 changes: 179 additions & 0 deletions tests/test-yaml-backward-compat.cpp
Original file line number Diff line number Diff line change
@@ -0,0 +1,179 @@
#include "common.h"
#include "arg.h"
#include <cassert>
#include <iostream>
#include <vector>
#include <string>
#include <fstream>
#include <filesystem>
#include <cmath>

struct TestCase {
std::vector<std::string> args;
std::string description;
};

static void test_cli_args_without_yaml() {
std::cout << "Testing CLI arguments without YAML..." << std::endl;

std::vector<TestCase> test_cases = {
{{"test", "-n", "100"}, "Basic n_predict"},
{{"test", "-p", "Hello world"}, "Basic prompt"},
{{"test", "--temp", "0.8"}, "Temperature setting"},
{{"test", "-c", "2048"}, "Context size"},
{{"test", "-b", "512"}, "Batch size"},
{{"test", "--top-k", "40"}, "Top-k sampling"},
{{"test", "--top-p", "0.9"}, "Top-p sampling"},
{{"test", "-s", "42"}, "Random seed"},
{{"test", "-n", "50", "-p", "Test", "--temp", "0.7"}, "Multiple arguments"},
{{"test", "--help"}, "Help flag (should exit)"},
};

for (const auto& test_case : test_cases) {
if (test_case.description == "Help flag (should exit)") {
continue;
}

std::cout << " Testing: " << test_case.description << std::endl;

common_params params;
std::vector<char*> argv;
for (const auto& arg : test_case.args) {
argv.push_back(const_cast<char*>(arg.c_str()));
}

bool result = common_params_parse(argv.size(), argv.data(), params, LLAMA_EXAMPLE_COMMON);

if (!result && test_case.description != "Help flag (should exit)") {
std::cout << " Warning: " << test_case.description << " failed to parse" << std::endl;
}
}

std::cout << "CLI arguments without YAML test completed!" << std::endl;
}

static void test_equivalent_yaml_and_cli() {
std::cout << "Testing equivalent YAML and CLI produce same results..." << std::endl;

std::ofstream yaml_file("equivalent_test.yaml");
yaml_file << R"(
n_predict: 100
n_ctx: 2048
n_batch: 512
prompt: "Test prompt"
sampling:
seed: 42
temp: 0.8
top_k: 40
top_p: 0.9
penalty_repeat: 1.1
)";
yaml_file.close();

common_params yaml_params;
const char* yaml_argv[] = {"test", "--config", "equivalent_test.yaml"};
bool yaml_result = common_params_parse(3, const_cast<char**>(yaml_argv), yaml_params, LLAMA_EXAMPLE_COMMON);

common_params cli_params;
const char* cli_argv[] = {
"test",
"-n", "100",
"-c", "2048",
"-b", "512",
"-p", "Test prompt",
"-s", "42",
"--temp", "0.8",
"--top-k", "40",
"--top-p", "0.9",
"--repeat-penalty", "1.1"
};
const int cli_argc = sizeof(cli_argv) / sizeof(cli_argv[0]);

bool cli_result = common_params_parse(cli_argc, const_cast<char**>(cli_argv), cli_params, LLAMA_EXAMPLE_COMMON);

assert(yaml_result == true);
assert(cli_result == true);
(void)yaml_result; // Suppress unused variable warning
(void)cli_result; // Suppress unused variable warning

assert(yaml_params.n_predict == cli_params.n_predict);
assert(yaml_params.n_ctx == cli_params.n_ctx);
assert(yaml_params.n_batch == cli_params.n_batch);
assert(yaml_params.prompt == cli_params.prompt);
assert(yaml_params.sampling.seed == cli_params.sampling.seed);
assert(yaml_params.sampling.temp == cli_params.sampling.temp);
assert(yaml_params.sampling.top_k == cli_params.sampling.top_k);
assert(yaml_params.sampling.top_p == cli_params.sampling.top_p);

const float epsilon = 1e-6f;
assert(std::abs(yaml_params.sampling.penalty_repeat - cli_params.sampling.penalty_repeat) < epsilon);

std::filesystem::remove("equivalent_test.yaml");
std::cout << "Equivalent YAML and CLI test passed!" << std::endl;
}

static void test_all_major_cli_options() {
std::cout << "Testing all major CLI options still work..." << std::endl;

struct CliTest {
std::vector<std::string> args;
std::string param_name;
bool should_succeed;
};

std::vector<CliTest> cli_tests = {
{{"test", "-m", "model.gguf"}, "model path", true},
{{"test", "-n", "200"}, "n_predict", true},
{{"test", "-c", "4096"}, "context size", true},
{{"test", "-b", "1024"}, "batch size", true},
{{"test", "-p", "Hello"}, "prompt", true},
{{"test", "-s", "123"}, "seed", true},
{{"test", "--temp", "0.7"}, "temperature", true},
{{"test", "--top-k", "50"}, "top_k", true},
{{"test", "--top-p", "0.95"}, "top_p", true},
{{"test", "--repeat-penalty", "1.05"}, "repeat penalty", true},
{{"test", "-t", "4"}, "threads", true},
{{"test", "-ngl", "32"}, "gpu layers", true},
{{"test", "--interactive"}, "interactive mode", true},
{{"test", "--color"}, "color output", true},
{{"test", "--verbose"}, "verbose mode", true},
};

for (const auto& test : cli_tests) {
std::cout << " Testing: " << test.param_name << std::endl;

common_params params;
std::vector<char*> argv;
for (const auto& arg : test.args) {
argv.push_back(const_cast<char*>(arg.c_str()));
}

bool result = common_params_parse(argv.size(), argv.data(), params, LLAMA_EXAMPLE_COMMON);

if (result != test.should_succeed) {
std::cout << " Unexpected result for " << test.param_name
<< ": expected " << test.should_succeed << ", got " << result << std::endl;
}
}

std::cout << "Major CLI options test completed!" << std::endl;
}

int main() {
std::cout << "Running backward compatibility tests..." << std::endl;

try {
test_cli_args_without_yaml();
test_equivalent_yaml_and_cli();
test_all_major_cli_options();

std::cout << "All backward compatibility tests completed!" << std::endl;
return 0;
} catch (const std::exception& e) {
std::cerr << "Test failed with exception: " << e.what() << std::endl;
return 1;
} catch (...) {
std::cerr << "Test failed with unknown exception" << std::endl;
return 1;
}
}
Loading
Loading