Skip to content

Commit

Permalink
Merge branch 'dev' into chore/lint-api-reference
Browse files Browse the repository at this point in the history
  • Loading branch information
gabrielle-ong authored Dec 4, 2024
2 parents 362f8f7 + 0528553 commit ade0aa0
Show file tree
Hide file tree
Showing 58 changed files with 4,323 additions and 1,234 deletions.
2 changes: 1 addition & 1 deletion docker/entrypoint.sh
Original file line number Diff line number Diff line change
Expand Up @@ -7,10 +7,10 @@ echo "enableCors: true" >> /root/.cortexrc

# Install the engine
cortex engines install llama-cpp -s /opt/cortex.llamacpp
cortex engines list

# Start the cortex server
cortex start
cortex engines list

# Keep the container running by tailing the log files
tail -f /root/cortexcpp/logs/cortex.log &
Expand Down
4 changes: 3 additions & 1 deletion engine/CMakeLists.txt
Original file line number Diff line number Diff line change
Expand Up @@ -169,17 +169,19 @@ else()
endif()

aux_source_directory(controllers CTL_SRC)
aux_source_directory(repositories REPO_SRC)
aux_source_directory(services SERVICES_SRC)
aux_source_directory(common COMMON_SRC)
aux_source_directory(models MODEL_SRC)
aux_source_directory(cortex-common CORTEX_COMMON)
aux_source_directory(config CONFIG_SRC)
aux_source_directory(database DB_SRC)
aux_source_directory(migrations MIGR_SRC)
aux_source_directory(utils UTILS_SRC)

target_include_directories(${TARGET_NAME} PRIVATE ${CMAKE_CURRENT_SOURCE_DIR} )

target_sources(${TARGET_NAME} PRIVATE ${CONFIG_SRC} ${CTL_SRC} ${COMMON_SRC} ${SERVICES_SRC} ${DB_SRC} ${MIGR_SRC})
target_sources(${TARGET_NAME} PRIVATE ${UTILS_SRC} ${CONFIG_SRC} ${CTL_SRC} ${COMMON_SRC} ${SERVICES_SRC} ${DB_SRC} ${MIGR_SRC} ${REPO_SRC})

set_target_properties(${TARGET_NAME} PROPERTIES
RUNTIME_OUTPUT_DIRECTORY_DEBUG ${CMAKE_BINARY_DIR}
Expand Down
4 changes: 4 additions & 0 deletions engine/cli/CMakeLists.txt
Original file line number Diff line number Diff line change
Expand Up @@ -84,6 +84,10 @@ add_executable(${TARGET_NAME} main.cc
${CMAKE_CURRENT_SOURCE_DIR}/../services/hardware_service.cc
${CMAKE_CURRENT_SOURCE_DIR}/utils/easywsclient.cc
${CMAKE_CURRENT_SOURCE_DIR}/utils/download_progress.cc
${CMAKE_CURRENT_SOURCE_DIR}/../utils/config_yaml_utils.cc
${CMAKE_CURRENT_SOURCE_DIR}/../utils/file_manager_utils.cc
${CMAKE_CURRENT_SOURCE_DIR}/../utils/curl_utils.cc
${CMAKE_CURRENT_SOURCE_DIR}/../utils/system_info_utils.cc
)

target_link_libraries(${TARGET_NAME} PRIVATE CLI11::CLI11)
Expand Down
1 change: 0 additions & 1 deletion engine/cli/commands/engine_install_cmd.cc
Original file line number Diff line number Diff line change
Expand Up @@ -179,7 +179,6 @@ bool EngineInstallCmd::Exec(const std::string& engine,
auto response = curl_utils::SimplePostJson(install_url.ToFullPath(),
body.toStyledString());
if (response.has_error()) {
// TODO: namh refactor later
Json::Value root;
Json::Reader reader;
if (!reader.parse(response.error(), root)) {
Expand Down
1 change: 1 addition & 0 deletions engine/cli/commands/engine_list_cmd.cc
Original file line number Diff line number Diff line change
Expand Up @@ -4,6 +4,7 @@
#include "common/engine_servicei.h"
#include "server_start_cmd.h"
#include "utils/curl_utils.h"
#include "utils/engine_constants.h"
#include "utils/logging_utils.h"
#include "utils/url_parser.h"
// clang-format off
Expand Down
1 change: 1 addition & 0 deletions engine/cli/commands/ps_cmd.cc
Original file line number Diff line number Diff line change
Expand Up @@ -2,6 +2,7 @@
#include <string>
#include <tabulate/table.hpp>
#include "utils/curl_utils.h"
#include "utils/engine_constants.h"
#include "utils/format_utils.h"
#include "utils/logging_utils.h"
#include "utils/string_utils.h"
Expand Down
5 changes: 5 additions & 0 deletions engine/cli/commands/server_start_cmd.cc
Original file line number Diff line number Diff line change
@@ -1,6 +1,7 @@
#include "server_start_cmd.h"
#include "commands/cortex_upd_cmd.h"
#include "utils/cortex_utils.h"
#include "utils/engine_constants.h"
#include "utils/file_manager_utils.h"
#include "utils/widechar_conv.h"

Expand All @@ -27,6 +28,10 @@ bool TryConnectToServer(const std::string& host, int port) {

bool ServerStartCmd::Exec(const std::string& host, int port,
const std::optional<std::string>& log_level) {
if (IsServerAlive(host, port)) {
CLI_LOG("The server has already started");
return true;
}
std::string log_level_;
if (!log_level.has_value()) {
log_level_ = "INFO";
Expand Down
2 changes: 1 addition & 1 deletion engine/cli/main.cc
Original file line number Diff line number Diff line change
Expand Up @@ -148,7 +148,6 @@ int main(int argc, char* argv[]) {

if (should_check_for_latest_llamacpp_version) {
std::thread t1([]() {
auto config = file_manager_utils::GetCortexConfig();
// TODO: namh current we only check for llamacpp. Need to add support for other engine
auto get_latest_version = []() -> cpp::result<std::string, std::string> {
try {
Expand Down Expand Up @@ -176,6 +175,7 @@ int main(int argc, char* argv[]) {

auto now = std::chrono::system_clock::now();
CTL_DBG("latest llama.cpp version: " << res.value());
auto config = file_manager_utils::GetCortexConfig();
config.checkedForLlamacppUpdateAt =
std::chrono::duration_cast<std::chrono::milliseconds>(
now.time_since_epoch())
Expand Down
19 changes: 19 additions & 0 deletions engine/common/api-dto/messages/delete_message_response.h
Original file line number Diff line number Diff line change
@@ -0,0 +1,19 @@
#pragma once

#include "common/json_serializable.h"

namespace api_response {
struct DeleteMessageResponse : JsonSerializable {
std::string id;
std::string object;
bool deleted;

cpp::result<Json::Value, std::string> ToJson() override {
Json::Value json;
json["id"] = id;
json["object"] = object;
json["deleted"] = deleted;
return json;
}
};
} // namespace api_response
11 changes: 11 additions & 0 deletions engine/common/json_serializable.h
Original file line number Diff line number Diff line change
@@ -0,0 +1,11 @@
#pragma once

#include <json/value.h>
#include "utils/result.hpp"

struct JsonSerializable {

virtual cpp::result<Json::Value, std::string> ToJson() = 0;

virtual ~JsonSerializable() = default;
};
213 changes: 213 additions & 0 deletions engine/common/message.h
Original file line number Diff line number Diff line change
@@ -0,0 +1,213 @@
#pragma once

#include <json/reader.h>
#include <json/value.h>
#include <json/writer.h>
#include <cstdint>
#include <string>
#include "common/message_attachment.h"
#include "common/message_attachment_factory.h"
#include "common/message_content.h"
#include "common/message_content_factory.h"
#include "common/message_incomplete_detail.h"
#include "common/message_role.h"
#include "common/message_status.h"
#include "common/variant_map.h"
#include "json_serializable.h"
#include "utils/logging_utils.h"
#include "utils/result.hpp"

namespace ThreadMessage {

// Represents a message within a thread.
struct Message : JsonSerializable {
Message() = default;

Message(Message&&) = default;

Message& operator=(Message&&) = default;

Message(const Message&) = delete;

Message& operator=(const Message&) = delete;

// The identifier, which can be referenced in API endpoints.
std::string id;

// The object type, which is always thread.message.
std::string object = "thread.message";

// The Unix timestamp (in seconds) for when the message was created.
uint32_t created_at;

// The thread ID that this message belongs to.
std::string thread_id;

// The status of the message, which can be either in_progress, incomplete, or completed.
Status status;

// On an incomplete message, details about why the message is incomplete.
std::optional<IncompleteDetail> incomplete_details;

// The Unix timestamp (in seconds) for when the message was completed.
std::optional<uint32_t> completed_at;

// The Unix timestamp (in seconds) for when the message was marked as incomplete.
std::optional<uint32_t> incomplete_at;

Role role;

// The content of the message in array of text and/or images.
std::vector<std::unique_ptr<Content>> content;

// If applicable, the ID of the assistant that authored this message.
std::optional<std::string> assistant_id;

// The ID of the run associated with the creation of this message. Value is null when messages are created manually using the create message or create thread endpoints.
std::optional<std::string> run_id;

// A list of files attached to the message, and the tools they were added to.
std::optional<std::vector<Attachment>> attachments;

// Set of 16 key-value pairs that can be attached to an object. This can be useful for storing additional information about the object in a structured format. Keys can be a maximum of 64 characters long and values can be a maximum of 512 characters long.
Cortex::VariantMap metadata;

static cpp::result<Message, std::string> FromJsonString(
std::string&& json_str) {
Json::Value root;
Json::Reader reader;
if (!reader.parse(json_str, root)) {
return cpp::fail("Failed to parse JSON: " +
reader.getFormattedErrorMessages());
}

Message message;

try {
message.id = std::move(root["id"].asString());
message.object =
std::move(root.get("object", "thread.message").asString());
message.created_at = root["created_at"].asUInt();
if (message.created_at == 0 && root["created"].asUInt64() != 0) {
message.created_at = root["created"].asUInt64() / 1000;
}
message.thread_id = std::move(root["thread_id"].asString());
message.status = StatusFromString(std::move(root["status"].asString()));

message.incomplete_details =
IncompleteDetail::FromJson(std::move(root["incomplete_details"]))
.value();
message.completed_at = root["completed_at"].asUInt();
message.incomplete_at = root["incomplete_at"].asUInt();
message.role = RoleFromString(std::move(root["role"].asString()));
message.content = ParseContents(std::move(root["content"])).value();

message.assistant_id = std::move(root["assistant_id"].asString());
message.run_id = std::move(root["run_id"].asString());
message.attachments =
ParseAttachments(std::move(root["attachments"])).value();

if (root["metadata"].isObject() && !root["metadata"].empty()) {
auto res = Cortex::ConvertJsonValueToMap(root["metadata"]);
if (res.has_error()) {
CTL_WRN("Failed to convert metadata to map: " + res.error());
} else {
message.metadata = res.value();
}
}

return message;
} catch (const std::exception& e) {
return cpp::fail(std::string("FromJsonString failed: ") + e.what());
}
}

cpp::result<std::string, std::string> ToSingleLineJsonString() {
auto json_result = ToJson();
if (json_result.has_error()) {
return cpp::fail(json_result.error());
}

Json::FastWriter writer;
try {
return writer.write(json_result.value());
} catch (const std::exception& e) {
return cpp::fail(std::string("Failed to write JSON: ") + e.what());
}
}

cpp::result<Json::Value, std::string> ToJson() override {
try {
Json::Value json;

json["id"] = id;
json["object"] = object;
json["created_at"] = created_at;
json["thread_id"] = thread_id;
json["status"] = StatusToString(status);

if (incomplete_details.has_value()) {
if (auto it = incomplete_details->ToJson(); it.has_value()) {
json["incomplete_details"] = it.value();
} else {
CTL_WRN("Failed to convert incomplete_details to json: " +
it.error());
}
}
if (completed_at.has_value() && completed_at.value() != 0) {
json["completed_at"] = *completed_at;
}
if (incomplete_at.has_value() && incomplete_at.value() != 0) {
json["incomplete_at"] = *incomplete_at;
}

json["role"] = RoleToString(role);

Json::Value content_json_arr{Json::arrayValue};
for (auto& child_content : content) {
if (auto it = child_content->ToJson(); it.has_value()) {
content_json_arr.append(it.value());
} else {
CTL_WRN("Failed to convert content to json: " + it.error());
}
}
json["content"] = content_json_arr;
if (assistant_id.has_value() && !assistant_id->empty()) {
json["assistant_id"] = *assistant_id;
}
if (run_id.has_value() && !run_id->empty()) {
json["run_id"] = *run_id;
}
if (attachments.has_value()) {
Json::Value attachments_json_arr{Json::arrayValue};
for (auto& attachment : *attachments) {
if (auto it = attachment.ToJson(); it.has_value()) {
attachments_json_arr.append(it.value());
} else {
CTL_WRN("Failed to convert attachment to json: " + it.error());
}
}
json["attachments"] = attachments_json_arr;
}

Json::Value metadata_json{Json::objectValue};
for (const auto& [key, value] : metadata) {
if (std::holds_alternative<bool>(value)) {
metadata_json[key] = std::get<bool>(value);
} else if (std::holds_alternative<uint64_t>(value)) {
metadata_json[key] = std::get<uint64_t>(value);
} else if (std::holds_alternative<double>(value)) {
metadata_json[key] = std::get<double>(value);
} else {
metadata_json[key] = std::get<std::string>(value);
}
}
json["metadata"] = metadata_json;

return json;
} catch (const std::exception& e) {
return cpp::fail(std::string("ToJson failed: ") + e.what());
}
}
};
}; // namespace ThreadMessage
50 changes: 50 additions & 0 deletions engine/common/message_attachment.h
Original file line number Diff line number Diff line change
@@ -0,0 +1,50 @@
#pragma once

#include <json/reader.h>
#include "common/json_serializable.h"

namespace ThreadMessage {

// The tools to add this file to.
struct Tool {
std::string type;

Tool(const std::string& type) : type{type} {}
};

// The type of tool being defined: code_interpreter
struct CodeInterpreter : Tool {
CodeInterpreter() : Tool{"code_interpreter"} {}
};

// The type of tool being defined: file_search
struct FileSearch : Tool {
FileSearch() : Tool{"file_search"} {}
};

// A list of files attached to the message, and the tools they were added to.
struct Attachment : JsonSerializable {

// The ID of the file to attach to the message.
std::string file_id;

std::vector<Tool> tools;

cpp::result<Json::Value, std::string> ToJson() override {
try {
Json::Value json;
json["file_id"] = file_id;
Json::Value tools_json_arr{Json::arrayValue};
for (auto& tool : tools) {
Json::Value tool_json;
tool_json["type"] = tool.type;
tools_json_arr.append(tool_json);
}
json["tools"] = tools_json_arr;
return json;
} catch (const std::exception& e) {
return cpp::fail(std::string("ToJson failed: ") + e.what());
}
}
};
}; // namespace ThreadMessage
Loading

0 comments on commit ade0aa0

Please sign in to comment.