/*! * Copyright (c) 2023-2025 by Contributors * \file json_ffi/openai_api_protocol.h * \brief The header of OpenAI API Protocol in MLC LLM. */ #ifndef MLC_LLM_JSON_FFI_OPENAI_API_PROTOCOL_H #define MLC_LLM_JSON_FFI_OPENAI_API_PROTOCOL_H #include #include #include #include #include #include #include #include "../serve/config.h" #include "../support/result.h" namespace mlc { namespace llm { namespace json_ffi { using serve::DebugConfig; using serve::ResponseFormat; enum class Type { text, json_object, function }; enum class FinishReason { stop, length, tool_calls, error }; inline std::string GenerateUUID(size_t length) { auto randchar = []() -> char { const char charset[] = "0123456789" "ABCDEFGHIJKLMNOPQRSTUVWXYZ" "abcdefghijklmnopqrstuvwxyz"; const size_t max_index = (sizeof(charset) - 1); return charset[rand() % max_index]; }; std::string str(length, 0); std::generate_n(str.begin(), length, randchar); return str; } class ChatFunction { public: std::optional description = std::nullopt; std::string name; // Todo: change to std::vector>? std::unordered_map parameters; // Assuming parameters are string key-value pairs static Result FromJSON(const tvm::ffi::json::Object& json); tvm::ffi::json::Object AsJSON() const; }; class ChatTool { public: Type type = Type::function; ChatFunction function; static Result FromJSON(const tvm::ffi::json::Object& json); tvm::ffi::json::Object AsJSON() const; }; class ChatFunctionCall { public: std::string name; std::optional> arguments = std::nullopt; // Assuming arguments are string key-value pairs static Result FromJSON(const tvm::ffi::json::Object& json); tvm::ffi::json::Object AsJSON() const; }; class ChatToolCall { public: std::string id = "call_" + GenerateUUID(8); Type type = Type::function; ChatFunctionCall function; static Result FromJSON(const tvm::ffi::json::Object& json); tvm::ffi::json::Object AsJSON() const; }; class ChatCompletionMessageContent { public: ChatCompletionMessageContent() = default; ChatCompletionMessageContent(std::nullopt_t) {} // NOLINT(*) ChatCompletionMessageContent(std::string text) : text_(text) {} // NOLINT(*) ChatCompletionMessageContent( std::vector> parts) // NOLINT(*) : parts_(parts) {} bool IsNull() const { return !IsText() && !IsParts(); } bool IsText() const { return text_.operator bool(); } bool IsParts() const { return parts_.operator bool(); } const std::string& Text() const { return text_.value(); } const std::vector>& Parts() const { return parts_.value(); } private: /*! \brief used to store text content */ std::optional text_; std::optional>> parts_; }; class ChatCompletionMessage { public: ChatCompletionMessageContent content = std::nullopt; // Assuming content is a list of string key-value pairs std::string role; std::optional name = std::nullopt; std::optional> tool_calls = std::nullopt; std::optional tool_call_id = std::nullopt; static Result FromJSON(const tvm::ffi::json::Object& json); tvm::ffi::json::Object AsJSON() const; }; class ChatCompletionRequest { public: std::vector messages; std::optional model = std::nullopt; std::optional frequency_penalty = std::nullopt; std::optional presence_penalty = std::nullopt; bool logprobs = false; int top_logprobs = 0; std::optional>> logit_bias = std::nullopt; std::optional max_tokens = std::nullopt; int n = 1; std::optional seed = std::nullopt; std::optional> stop = std::nullopt; bool stream = false; std::optional temperature = std::nullopt; std::optional top_p = std::nullopt; std::optional> tools = std::nullopt; std::optional tool_choice = std::nullopt; std::optional user = std::nullopt; bool ignore_eos = false; std::optional response_format = std::nullopt; std::optional debug_config = std::nullopt; /*! \brief Parse and create a ChatCompletionRequest instance from the given JSON string. */ static Result FromJSON(const std::string& json_str); // TODO: check_penalty_range, check_logit_bias, check_logprobs }; class ChatCompletionResponseChoice { public: std::optional finish_reason; int index = 0; ChatCompletionMessage message; // TODO: logprobs tvm::ffi::json::Object AsJSON() const; }; class ChatCompletionStreamResponseChoice { public: std::optional finish_reason; int index = 0; ChatCompletionMessage delta; // TODO: logprobs tvm::ffi::json::Object AsJSON() const; }; class ChatCompletionResponse { public: std::string id; std::vector choices; int created = static_cast(std::time(nullptr)); std::string model; std::string system_fingerprint; std::string object = "chat.completion"; // TODO: usage_info tvm::ffi::json::Object AsJSON() const; }; class ChatCompletionStreamResponse { public: std::string id; std::vector choices; int created = static_cast(std::time(nullptr)); std::string model; std::string system_fingerprint; std::string object = "chat.completion.chunk"; std::optional usage; tvm::ffi::json::Object AsJSON() const; }; } // namespace json_ffi } // namespace llm } // namespace mlc #endif // MLC_LLM_JSON_FFI_OPENAI_API_PROTOCOL_H