Skip to content

Commit

Permalink
Merge branch 'platform-readme' of https://github.com/janhq/cortex.cpp
Browse files Browse the repository at this point in the history
…into platform-readme
  • Loading branch information
irfanpena committed Sep 9, 2024
2 parents da195cc + 4b72283 commit 66d4d11
Show file tree
Hide file tree
Showing 29 changed files with 818 additions and 175 deletions.
5 changes: 5 additions & 0 deletions engine/CMakeLists.txt
Original file line number Diff line number Diff line change
Expand Up @@ -59,6 +59,10 @@ if(DEBUG)
add_compile_definitions(ALLOW_ALL_CORS)
endif()

if(NOT DEFINED CORTEX_CONFIG_FILE_PATH)
set(CORTEX_CONFIG_FILE_PATH "user_home")
endif()

if(NOT DEFINED CORTEX_CPP_VERSION)
set(CORTEX_CPP_VERSION "default_version")
endif()
Expand All @@ -80,6 +84,7 @@ if(DEFINED CMAKE_JS_INC)
endif()

add_compile_definitions(CORTEX_CPP_VERSION="${CORTEX_CPP_VERSION}")
add_compile_definitions(CORTEX_CONFIG_FILE_PATH="${CORTEX_CONFIG_FILE_PATH}")

option(CMAKE_BUILD_TEST "Enable testing" OFF)
if(CMAKE_BUILD_TEST)
Expand Down
171 changes: 171 additions & 0 deletions engine/commands/cortex_upd_cmd.cc
Original file line number Diff line number Diff line change
@@ -0,0 +1,171 @@
// clang-format off
#include "utils/cortex_utils.h"
// clang-format on
#include "cortex_upd_cmd.h"
#include "httplib.h"
#include "nlohmann/json.hpp"
#include "services/download_service.h"
#include "utils/archive_utils.h"
#include "utils/file_manager_utils.h"
#include "utils/logging_utils.h"
#include "utils/system_info_utils.h"

namespace commands {

namespace {
const std::string kCortexBinary = "cortex-cpp";
}

CortexUpdCmd::CortexUpdCmd() {}

void CortexUpdCmd::Exec(std::string v) {
// TODO(sang) stop server if it is running
// Check if the architecture and OS are supported
auto system_info = system_info_utils::GetSystemInfo();
if (system_info.arch == system_info_utils::kUnsupported ||
system_info.os == system_info_utils::kUnsupported) {
CTL_ERR("Unsupported OS or architecture: " << system_info.os << ", "
<< system_info.arch);
return;
}
CTL_INF("OS: " << system_info.os << ", Arch: " << system_info.arch);

// Download file
constexpr auto github_host = "https://api.github.com";
// std::string version = v.empty() ? "latest" : std::move(v);
// TODO(sang): support download with version
std::string version = "latest";
std::ostringstream release_path;
release_path << "/repos/janhq/cortex.cpp/releases/" << version;
CTL_INF("Engine release path: " << github_host << release_path.str());

httplib::Client cli(github_host);
if (auto res = cli.Get(release_path.str())) {
if (res->status == httplib::StatusCode::OK_200) {
try {
auto jsonResponse = nlohmann::json::parse(res->body);
auto assets = jsonResponse["assets"];
auto os_arch{system_info.os + "-" + system_info.arch};

std::string matched_variant = "";
for (auto& asset : assets) {
auto asset_name = asset["name"].get<std::string>();
if (asset_name.find("cortex-cpp") != std::string::npos &&
asset_name.find(os_arch) != std::string::npos) {
matched_variant = asset_name;
break;
}
CTL_INF(asset_name);
}
if (matched_variant.empty()) {
CTL_ERR("No variant found for " << os_arch);
return;
}
CTL_INF("Matched variant: " << matched_variant);

for (auto& asset : assets) {
auto asset_name = asset["name"].get<std::string>();
if (asset_name == matched_variant) {
std::string host{"https://github.com"};

auto full_url = asset["browser_download_url"].get<std::string>();
std::string path = full_url.substr(host.length());

auto fileName = asset["name"].get<std::string>();
CTL_INF("URL: " << full_url);

auto download_task = DownloadTask{.id = "cortex",
.type = DownloadType::Cortex,
.error = std::nullopt,
.items = {DownloadItem{
.id = "cortex",
.host = host,
.fileName = fileName,
.type = DownloadType::Cortex,
.path = path,
}}};

DownloadService download_service;
download_service.AddDownloadTask(
download_task,
[this](const std::string& absolute_path, bool unused) {
// try to unzip the downloaded file
std::filesystem::path download_path{absolute_path};
CTL_INF("Downloaded engine path: " << download_path.string());

std::filesystem::path extract_path =
download_path.parent_path().parent_path();

archive_utils::ExtractArchive(download_path.string(),
extract_path.string());

// remove the downloaded file
// TODO(any) Could not delete file on Windows because it is currently hold by httplib(?)
// Not sure about other platforms
try {
std::filesystem::remove(absolute_path);
} catch (const std::exception& e) {
CTL_WRN("Could not delete file: " << e.what());
}
CTL_INF("Finished!");
});
break;
}
}
} catch (const nlohmann::json::parse_error& e) {
std::cerr << "JSON parse error: " << e.what() << std::endl;
return;
}
} else {
CTL_ERR("HTTP error: " << res->status);
return;
}
} else {
auto err = res.error();
CTL_ERR("HTTP error: " << httplib::to_string(err));
return;
}
#if defined(_WIN32)
auto executable_path = file_manager_utils::GetExecutableFolderContainerPath();
auto temp = executable_path / "cortex_tmp.exe";
remove(temp.string().c_str()); // ignore return code

auto src =
executable_path / "cortex" / kCortexBinary / (kCortexBinary + ".exe");
auto dst = executable_path / (kCortexBinary + ".exe");
// Rename
rename(dst.string().c_str(), temp.string().c_str());
// Update
CopyFile(const_cast<char*>(src.string().c_str()),
const_cast<char*>(dst.string().c_str()), false);
auto download_folder = executable_path / "cortex";
remove(download_folder);
remove(temp.string().c_str());
#else
auto executable_path = file_manager_utils::GetExecutableFolderContainerPath();
auto temp = executable_path / "cortex_tmp";
auto src = executable_path / "cortex" / kCortexBinary / kCortexBinary;
auto dst = executable_path / kCortexBinary;
if (std::rename(dst.string().c_str(), temp.string().c_str())) {
CTL_ERR("Failed to rename from " << dst.string() << " to "
<< temp.string());
return;
}
try {
std::filesystem::copy_file(
src, dst, std::filesystem::copy_options::overwrite_existing);
std::filesystem::permissions(dst, std::filesystem::perms::owner_all |
std::filesystem::perms::group_all |
std::filesystem::perms::others_read |
std::filesystem::perms::others_exec);
std::filesystem::remove(temp);
auto download_folder = executable_path / "cortex/";
std::filesystem::remove_all(download_folder);
} catch (const std::exception& e) {
CTL_WRN("Something wrong happened: " << e.what());
return;
}
#endif
CLI_LOG("Update cortex sucessfully");
}
} // namespace commands
13 changes: 13 additions & 0 deletions engine/commands/cortex_upd_cmd.h
Original file line number Diff line number Diff line change
@@ -0,0 +1,13 @@
#pragma once
#include <string>
#include <optional>

namespace commands {

class CortexUpdCmd{
public:
CortexUpdCmd();
void Exec(std::string version);
};

} // namespace commands
28 changes: 28 additions & 0 deletions engine/commands/engine_get_cmd.cc
Original file line number Diff line number Diff line change
@@ -0,0 +1,28 @@
#include "engine_get_cmd.h"
#include <iostream>
#include <tabulate/table.hpp>
#include "services/engine_service.h"
#include "utils/logging_utils.h"

namespace commands {

void EngineGetCmd::Exec() const {
CTL_INF("[EngineGetCmd] engine: " << engine_);

auto engine_service = EngineService();
try {
auto status = engine_service.GetEngineInfo(engine_);
tabulate::Table table;
table.add_row({"name", "description", "version", "product name", "status"});
table.format().font_color(tabulate::Color::green);
table.add_row({status.name, status.description, status.version,
status.product_name, status.status});
std::cout << table << std::endl;
} catch (const std::runtime_error& e) {
std::cerr << "Engine " << engine_ << " is not supported!" << "\n";
} catch (const std::exception& e) {
std::cerr << "Failed to get engine info for " << engine_ << ": " << e.what()
<< "\n";
}
}
}; // namespace commands
15 changes: 15 additions & 0 deletions engine/commands/engine_get_cmd.h
Original file line number Diff line number Diff line change
@@ -0,0 +1,15 @@
#pragma once

#include <string>

namespace commands {
class EngineGetCmd {
public:
EngineGetCmd(const std::string& engine) : engine_{engine} {};

void Exec() const;

private:
std::string engine_;
};
} // namespace commands
9 changes: 5 additions & 4 deletions engine/commands/engine_init_cmd.cc
Original file line number Diff line number Diff line change
Expand Up @@ -29,7 +29,7 @@ bool EngineInitCmd::Exec() const {
if (system_info.arch == system_info_utils::kUnsupported ||
system_info.os == system_info_utils::kUnsupported) {
CTL_ERR("Unsupported OS or architecture: " << system_info.os << ", "
<< system_info.arch);
<< system_info.arch);
return false;
}
CTL_INF("OS: " << system_info.os << ", Arch: " << system_info.arch);
Expand Down Expand Up @@ -192,9 +192,10 @@ bool EngineInitCmd::Exec() const {
// cuda driver version should be greater than toolkit version to ensure compatibility
if (semantic_version_utils::CompareSemanticVersion(
cuda_driver_version, suitable_toolkit_version) < 0) {
CTL_ERR("Your Cuda driver version " << cuda_driver_version
<< " is not compatible with cuda toolkit version "
<< suitable_toolkit_version);
CTL_ERR("Your Cuda driver version "
<< cuda_driver_version
<< " is not compatible with cuda toolkit version "
<< suitable_toolkit_version);
return false;
}

Expand Down
62 changes: 10 additions & 52 deletions engine/commands/engine_list_cmd.cc
Original file line number Diff line number Diff line change
@@ -1,65 +1,24 @@
// clang-format off
#include "utils/cortex_utils.h"
// clang-format on
#include "engine_list_cmd.h"
#include <filesystem>
#include <tabulate/table.hpp>
#include <utility>
#include "trantor/utils/Logger.h"
#include "services/engine_service.h"

namespace commands {

bool EngineListCmd::Exec() {
auto engine_service = EngineService();
auto status_list = engine_service.GetEngineInfoList();

tabulate::Table table;
table.format().font_color(tabulate::Color::green);
table.add_row(
{"(Index)", "name", "description", "version", "product name", "status"});
table.format().font_color(tabulate::Color::green);
#ifdef _WIN32
if (std::filesystem::exists(std::filesystem::current_path().string() +
cortex_utils::kOnnxLibPath)) {
table.add_row({"1", "cortex.onnx",
"This extension enables chat completion API calls using the "
"Onnx engine",
"0.0.1", "Onnx Inference Engine", "ready"});
} else {
table.add_row({"1", "cortex.onnx",
"This extension enables chat completion API calls using the "
"Onnx engine",
"0.0.1", "Onnx Inference Engine", "not_initialized"});
for (int i = 0; i < status_list.size(); i++) {
auto status = status_list[i];
std::string index = std::to_string(i + 1);
table.add_row({index, status.name, status.description, status.version,
status.product_name, status.status});
}

#else
table.add_row(
{"1", "cortex.onnx",
"This extension enables chat completion API calls using the Onnx engine",
"0.0.1", "Onnx Inference Engine", "not_supported"});
#endif
// lllamacpp
if (std::filesystem::exists(std::filesystem::current_path().string() +
cortex_utils::kLlamaLibPath)) {
table.add_row({"2", "cortex.llamacpp",
"This extension enables chat completion API calls using the "
"LlamaCPP engine",
"0.0.1", "LlamaCPP Inference Engine", "ready"});
} else {
table.add_row({"2", "cortex.llamacpp",
"This extension enables chat completion API calls using the "
"LlamaCPP engine",
"0.0.1", "LlamaCPP Inference Engine", "not_initialized"});
}
// tensorrt llm
if (std::filesystem::exists(std::filesystem::current_path().string() +
cortex_utils::kTensorrtLlmPath)) {
table.add_row({"3", "cortex.tensorrt-llm",
"This extension enables chat completion API calls using the "
"TensorrtLLM engine",
"0.0.1", "TensorrtLLM Inference Engine", "ready"});
} else {
table.add_row({"3", "cortex.tensorrt-llm",
"This extension enables chat completion API calls using the "
"TensorrtLLM engine",
"0.0.1", "TensorrtLLM Inference Engine", "not_initialized"});
}
for (int i = 0; i < 6; i++) {
table[0][i]
.format()
Expand All @@ -77,5 +36,4 @@ bool EngineListCmd::Exec() {
std::cout << table << std::endl;
return true;
}

}; // namespace commands
6 changes: 2 additions & 4 deletions engine/commands/engine_list_cmd.h
Original file line number Diff line number Diff line change
@@ -1,11 +1,9 @@
#pragma once

#include <string>

namespace commands {
class EngineListCmd {
public:
bool Exec() ;
bool Exec();
};

} // namespace commands
} // namespace commands
21 changes: 21 additions & 0 deletions engine/commands/engine_uninstall_cmd.cc
Original file line number Diff line number Diff line change
@@ -0,0 +1,21 @@
#include "engine_uninstall_cmd.h"
#include "services/engine_service.h"
#include "utils/logging_utils.h"

namespace commands {

EngineUninstallCmd::EngineUninstallCmd(std::string engine)
: engine_{std::move(engine)} {}

void EngineUninstallCmd::Exec() const {
CTL_INF("Uninstall engine " + engine_);
auto engine_service = EngineService();

try {
engine_service.UninstallEngine(engine_);
CLI_LOG("Engine " << engine_ << " uninstalled successfully!")
} catch (const std::exception& e) {
CLI_LOG("Failed to uninstall engine " << engine_ << ": " << e.what());
}
}
}; // namespace commands
Loading

0 comments on commit 66d4d11

Please sign in to comment.