ITPub博客

首页 > 应用开发 > IT综合 > C++大模型SDK开发实践:日志系统、数据结构与策略模式实现

C++大模型SDK开发实践:日志系统、数据结构与策略模式实现

翻译 IT综合 作者:bhluo 时间:2026-02-03 15:13:28 0 删除 编辑

# C++大模型SDK开发实践:日志系统、数据结构与策略模式实现


## 架构设计概述


大模型服务SDK开发面临多重挑战:复杂的功能集成需求、跨平台兼容性要求、多线程环境下的稳定性保障,以及高效错误处理机制。本文探讨的解决方案基于模块化设计理念,通过分层架构实现功能解耦,采用接口抽象提升扩展能力。


## 日志系统封装实现


### 多层级日志架构设计


日志系统采用适配器模式封装spdlog,提供统一接口同时保留底层灵活性:


```cpp

// 日志级别枚举增强

enum class LogLevel {

    TRACE = 0,

    DEBUG = 1,

    INFO = 2,

    WARNING = 3,

    ERROR = 4,

    CRITICAL = 5,

    OFF = 6

};


// 日志消息封装类

struct LogMessage {

    LogLevel level;

    std::string message;

    std::string module;

    std::thread::id thread_id;

    std::chrono::system_clock::time_point timestamp;

    std::source_location location;

    

    LogMessage(LogLevel lvl, std::string msg, 

               std::string mod = "", 

               std::source_location loc = std::source_location::current())

        : level(lvl), message(std::move(msg)), module(std::move(mod)),

          thread_id(std::this_thread::get_id()),

          timestamp(std::chrono::system_clock::now()),

          location(loc) {}

};


// 抽象日志接口

class ILogger {

public:

    virtual ~ILogger() = default;

    

    virtual void log(const LogMessage& msg) = 0;

    virtual void flush() = 0;

    virtual void set_level(LogLevel level) = 0;

    virtual LogLevel get_level() const = 0;

    

    // 便捷方法

    template<typename... Args>

    void info(const std::string& format, Args&&... args) {

        log_impl(LogLevel::INFO, format, std::forward<Args>(args)...);

    }

    

    template<typename... Args>

    void error(const std::string& format, Args&&... args) {

        log_impl(LogLevel::ERROR, format, std::forward<Args>(args)...);

    }

    

protected:

    template<typename... Args>

    void log_impl(LogLevel level, const std::string& format, Args&&... args) {

        if (level >= get_level()) {

            std::string formatted = fmt::format(format, std::forward<Args>(args)...);

            log(LogMessage(level, formatted, "", std::source_location::current()));

        }

    }

};

```


### spdlog适配器实现


```cpp

// spdlog适配器

class SpdLoggerAdapter : public ILogger {

public:

    explicit SpdLoggerAdapter(const std::string& name, 

                             const std::string& pattern = "%Y-%m-%d %H:%M:%S.%e [%l] [%n] %v")

        : logger_(spdlog::get(name)) {

        

        if (!logger_) {

            // 创建多接收器日志器

            std::vector<spdlog::sink_ptr> sinks;

            

            // 控制台输出

            auto console_sink = std::make_shared<spdlog::sinks::stdout_color_sink_mt>();

            console_sink->set_pattern(pattern);

            sinks.push_back(console_sink);

            

            // 文件输出

            auto file_sink = std::make_shared<spdlog::sinks::rotating_file_sink_mt>(

                "logs/" + name + ".log", 1024 * 1024 * 10, 5);

            file_sink->set_pattern(pattern);

            sinks.push_back(file_sink);

            

            // 异步日志器

            logger_ = std::make_shared<spdlog::async_logger>(

                name, sinks.begin(), sinks.end(),

                spdlog::thread_pool(),

                spdlog::async_overflow_policy::block);

            

            logger_->set_level(spdlog::level::trace);

            spdlog::register_logger(logger_);

        }

        

        update_spdlog_level();

    }

    

    void log(const LogMessage& msg) override {

        spdlog::level::level_enum spd_level = to_spdlog_level(msg.level);

        

        logger_->log(spdlog::source_loc{

            msg.location.file_name(),

            static_cast<int>(msg.location.line()),

            msg.location.function_name()

        }, spd_level, "[{}] {}", msg.module, msg.message);

    }

    

    void flush() override {

        logger_->flush();

    }

    

    void set_level(LogLevel level) override {

        level_ = level;

        update_spdlog_level();

    }

    

    LogLevel get_level() const override {

        return level_;

    }

    

private:

    std::shared_ptr<spdlog::logger> logger_;

    LogLevel level_ = LogLevel::INFO;

    

    spdlog::level::level_enum to_spdlog_level(LogLevel level) {

        static const std::unordered_map<LogLevel, spdlog::level::level_enum> mapping = {

            {LogLevel::TRACE, spdlog::level::trace},

            {LogLevel::DEBUG, spdlog::level::debug},

            {LogLevel::INFO, spdlog::level::info},

            {LogLevel::WARNING, spdlog::level::warn},

            {LogLevel::ERROR, spdlog::level::err},

            {LogLevel::CRITICAL, spdlog::level::critical}

        };

        return mapping.at(level);

    }

    

    void update_spdlog_level() {

        logger_->set_level(to_spdlog_level(level_));

    }

};


// 日志管理器单例

class LoggerManager {

public:

    static LoggerManager& instance() {

        static LoggerManager instance;

        return instance;

    }

    

    std::shared_ptr<ILogger> get_logger(const std::string& name) {

        std::lock_guard<std::mutex> lock(mutex_);

        

        auto it = loggers_.find(name);

        if (it != loggers_.end()) {

            return it->second;

        }

        

        auto logger = std::make_shared<SpdLoggerAdapter>(name);

        loggers_[name] = logger;

        return logger;

    }

    

private:

    LoggerManager() = default;

    std::unordered_map<std::string, std::shared_ptr<ILogger>> loggers_;

    std::mutex mutex_;

};

```


## 通用数据结构定义


### 响应数据容器


```cpp

// 模型响应包装器

template<typename T>

class ModelResponse {

public:

    ModelResponse() = default;

    

    explicit ModelResponse(T data, 

                          const std::string& request_id = "",

                          int64_t timestamp = 0)

        : data_(std::move(data))

        , request_id_(request_id.empty() ? generate_uuid() : request_id)

        , timestamp_(timestamp > 0 ? timestamp : 

                    std::chrono::duration_cast<std::chrono::milliseconds>(

                        std::chrono::system_clock::now().time_since_epoch()).count())

        , success_(true) {}

    

    // 错误响应构造

    static ModelResponse<T> error(const std::string& error_msg,

                                 int error_code = -1,

                                 const std::string& request_id = "") {

        ModelResponse<T> response;

        response.success_ = false;

        response.error_code_ = error_code;

        response.error_message_ = error_msg;

        response.request_id_ = request_id.empty() ? generate_uuid() : request_id;

        response.timestamp_ = std::chrono::duration_cast<std::chrono::milliseconds>(

            std::chrono::system_clock::now().time_since_epoch()).count();

        return response;

    }

    

    // 序列化方法

    std::string to_json() const {

        nlohmann::json j;

        j["success"] = success_;

        j["request_id"] = request_id_;

        j["timestamp"] = timestamp_;

        

        if (success_) {

            j["data"] = serialize_data(data_);

        } else {

            j["error_code"] = error_code_;

            j["error_message"] = error_message_;

        }

        

        return j.dump(2); // 缩进2个空格

    }

    

    // 状态检查

    bool is_success() const { return success_; }

    const T& get_data() const { return data_; }

    T& get_data_mutable() { return data_; }

    const std::string& get_error_message() const { return error_message_; }

    int get_error_code() const { return error_code_; }

    

private:

    T data_;

    std::string request_id_;

    int64_t timestamp_;

    bool success_ = false;

    int error_code_ = 0;

    std::string error_message_;

    

    static std::string generate_uuid() {

        static std::random_device rd;

        static std::mt19937 gen(rd());

        static std::uniform_int_distribution<> dis(0, 15);

        

        const char* hex_chars = "0123456789abcdef";

        std::string uuid(36, '-');

        

        for (size_t i = 0; i < 36; ++i) {

            if (i == 8 || i == 13 || i == 18 || i == 23) {

                uuid[i] = '-';

            } else {

                uuid[i] = hex_chars[dis(gen)];

            }

        }

        

        return uuid;

    }

    

    template<typename U>

    auto serialize_data(const U& data) const 

        -> decltype(nlohmann::json(data)) {

        return nlohmann::json(data);

    }

};

```


### 配置管理系统


```cpp

// 通用配置类

class ConfigManager {

public:

    using ConfigValue = std::variant<

        std::string, int, double, bool, 

        std::vector<std::string>,

        std::unordered_map<std::string, std::string>

    >;

    

    // 加载配置

    bool load_config(const std::string& config_path) {

        try {

            std::ifstream file(config_path);

            if (!file.is_open()) {

                get_logger()->error("无法打开配置文件: {}", config_path);

                return false;

            }

            

            nlohmann::json config_json;

            file >> config_json;

            

            // 解析配置

            parse_config(config_json);

            

            get_logger()->info("配置文件加载成功: {}", config_path);

            return true;

            

        } catch (const std::exception& e) {

            get_logger()->error("配置文件解析失败: {}", e.what());

            return false;

        }

    }

    

    // 类型安全的值获取

    template<typename T>

    std::optional<T> get_value(const std::string& key, 

                              const std::optional<T>& default_value = std::nullopt) const {

        std::shared_lock lock(mutex_);

        

        auto it = config_map_.find(key);

        if (it == config_map_.end()) {

            return default_value;

        }

        <"avg.a8k1.org.cn"><"avr.a8k1.org.cn"><"evs.a8k1.org.cn">

        try {

            return std::get<T>(it->second);

        } catch (const std::bad_variant_access&) {

            get_logger()->warning("配置项类型不匹配: {}", key);

            return default_value;

        }

    }

    

    // 动态配置更新

    void update_config(const std::string& key, ConfigValue value) {

        std::unique_lock lock(mutex_);

        

        auto it = config_map_.find(key);

        if (it != config_map_.end()) {

            get_logger()->info("更新配置项: {} -> {}", key, value_to_string(value));

        } else {

            get_logger()->info("新增配置项: {} -> {}", key, value_to_string(value));

        }

        

        config_map_[key] = std::move(value);

        notify_config_changed(key);

    }

    

private:

    mutable std::shared_mutex mutex_;

    std::unordered_map<std::string, ConfigValue> config_map_;

    std::vector<std::function<void(const std::string&)>> observers_;

    

    std::shared_ptr<ILogger> get_logger() const {

        return LoggerManager::instance().get_logger("ConfigManager");

    }

    

    void parse_config(const nlohmann::json& json_config) {

        for (const auto& [key, value] : json_config.items()) {

            config_map_[key] = parse_json_value(value);

        }

    }

    

    ConfigValue parse_json_value(const nlohmann::json& value) {

        if (value.is_string()) return value.get<std::string>();

        if (value.is_number_integer()) return value.get<int>();

        if (value.is_number_float()) return value.get<double>();

        if (value.is_boolean()) return value.get<bool>();

        if (value.is_array()) return value.get<std::vector<std::string>>();

        if (value.is_object()) {

            std::unordered_map<std::string, std::string> map;

            for (const auto& [k, v] : value.items()) {

                map[k] = v.is_string() ? v.get<std::string>() : v.dump();

            }

            return map;

        }

        return std::string("null");

    }

    

    std::string value_to_string(const ConfigValue& value) const {

        return std::visit([](auto&& arg) -> std::string {

            using T = std::decay_t<decltype(arg)>;

            if constexpr (std::is_same_v<T, std::string>) {

                return arg;

            } else {

                return std::to_string(arg);

            }

        }, value);

    }

    

    void notify_config_changed(const std::string& key) {

        for (const auto& observer : observers_) {

            try {

                observer(key);

            } catch (const std::exception& e) {

                get_logger()->error("配置变更通知异常: {}", e.what());

            }

        }

    }

};

```


## 策略模式应用实现


### 模型推理策略


```cpp

// 推理策略接口

class IInferenceStrategy {

public:

    virtual ~IInferenceStrategy() = default;

    

    virtual ModelResponse<std::string> generate(

        const std::string& prompt,

        const std::unordered_map<std::string, ConfigManager::ConfigValue>& params) = 0;

    

    virtual std::vector<std::string> get_supported_models() const = 0;

    virtual std::string get_strategy_name() const = 0;

    

protected:

    std::shared_ptr<ILogger> get_logger() const {

        return LoggerManager::instance().get_logger("InferenceStrategy");

    }

};


// OpenAI兼容策略

class OpenAICompatibleStrategy : public IInferenceStrategy {

public:

    explicit OpenAICompatibleStrategy(std::shared_ptr<ConfigManager> config)

        : config_(std::move(config)) {

        

        base_url_ = config_->get_value<std::string>("openai.base_url")

            .value_or("https://api.openai.com/v1");

        api_key_ = config_->get_value<std::string>("openai.api_key")

            .value_or("");

        timeout_ = config_->get_value<int>("openai.timeout_seconds")

            .value_or(30);

    }

    

    ModelResponse<std::string> generate(

        const std::string& prompt,

        const std::unordered_map<std::string, ConfigManager::ConfigValue>& params) override {

        

        auto logger = get_logger();

        logger->info("开始OpenAI推理,提示长度: {}", prompt.length());

        

        try {

            // 构建请求参数

            nlohmann::json request_body = {

                {"model", get_model_from_params(params)},

                {"prompt", prompt},

                {"max_tokens", get_param<int>(params, "max_tokens", 100)},

                {"temperature", get_param<double>(params, "temperature", 0.7)},

                {"top_p", get_param<double>(params, "top_p", 1.0)}

            };

            

            // 发送HTTP请求

            auto response = send_http_request(request_body);

            

            // 解析响应

            if (response.contains("error")) {

                return ModelResponse<std::string>::error(

                    response["error"]["message"],

                    response["error"]["code"]);

            }

            

            std::string generated_text = response["choices"][0]["text"];

            logger->info("推理完成,生成文本长度: {}", generated_text.length());

            

            return ModelResponse<std::string>(generated_text);

            

        } catch (const std::exception& e) {

            logger->error("OpenAI推理失败: {}", e.what());

            return ModelResponse<std::string>::error(e.what());

        }

    }

    

    std::vector<std::string> get_supported_models() const override {

        return {"gpt-3.5-turbo", "gpt-4", "text-davinci-003"};

    }

    

    std::string get_strategy_name() const override {

        return "OpenAICompatible";

    }

    

private:

    std::shared_ptr<ConfigManager> config_;

    std::string base_url_;

    std::string api_key_;

    int timeout_;

    

    template<typename T>

    T get_param(const std::unordered_map<std::string, ConfigManager::ConfigValue>& params,

                const std::string& key, T default_value) {

        auto it = params.find(key);

        if (it != params.end()) {

            try {

                return std::get<T>(it->second);

            } catch (...) {

                return default_value;

            }

        }<"vrb.a8k1.org.cn"><"muy.a8k1.org.cn"><"bnd.a8k1.org.cn">

        return default_value;

    }

    

    std::string get_model_from_params(

        const std::unordered_map<std::string, ConfigManager::ConfigValue>& params) {

        return get_param<std::string>(params, "model", "gpt-3.5-turbo");

    }

    

    nlohmann::json send_http_request(const nlohmann::json& body) {

        // HTTP客户端实现

        // 这里简化为返回模拟数据

        return {

            {"choices", {

                {{"text", "这是模拟生成的文本"}}

            }}

        };

    }

};


// 策略管理器

class StrategyManager {

public:

    void register_strategy(const std::string& name,

                          std::shared_ptr<IInferenceStrategy> strategy) {

        std::lock_guard lock(mutex_);

        strategies_[name] = std::move(strategy);

        get_logger()->info("注册策略: {}", name);

    }

    

    std::shared_ptr<IInferenceStrategy> get_strategy(const std::string& name) {

        std::shared_lock lock(mutex_);

        auto it = strategies_.find(name);

        if (it != strategies_.end()) {

            return it->second;

        }

        

        get_logger()->warning("策略未找到: {}", name);

        return nullptr;

    }

    

    std::vector<std::string> get_available_strategies() const {

        std::shared_lock lock(mutex_);

        std::vector<std::string> names;

        for (const auto& [name, _] : strategies_) {

            names.push_back(name);

        }

        return names;

    }

    

private:

    std::shared_ptr<ILogger> get_logger() const {

        return LoggerManager::instance().get_logger("StrategyManager");

    }

    

    mutable std::shared_mutex mutex_;

    std::unordered_map<std::string, std::shared_ptr<IInferenceStrategy>> strategies_;

};

```


## 集成应用示例


```cpp

// SDK主类

class ModelSDK {

public:

    ModelSDK() {

        config_manager_ = std::make_shared<ConfigManager>();

        strategy_manager_ = std::make_shared<StrategyManager>();

        logger_ = LoggerManager::instance().get_logger("ModelSDK");

        

        initialize_default_strategies();

    }

    

    bool initialize(const std::string& config_path) {

        logger_->info("开始初始化SDK");

        

        if (!config_manager_->load_config(config_path)) {

            logger_->error("SDK初始化失败: 配置加载错误");

            return false;

        }

        

        logger_->info("SDK初始化完成");

        return true;

    }

    

    ModelResponse<std::string> generate_text(

        const std::string& strategy_name,

        const std::string& prompt,

        const std::unordered_map<std::string, ConfigManager::ConfigValue>& params = {}) {

        

        auto strategy = strategy_manager_->get_strategy(strategy_name);

        if (!strategy) {

            return ModelResponse<std::string>::error(

                "不支持的策略: " + strategy_name);

        }

        

        logger_->info("使用策略 [{}] 生成文本", strategy_name);

        

        auto start_time = std::chrono::high_resolution_clock::now();

        auto response = strategy->generate(prompt, params);

        auto end_time = std::chrono::high_resolution_clock::now();

        

        auto duration = std::chrono::duration_cast<std::chrono::milliseconds>(

            end_time - start_time);

        

        logger_->info("生成完成,耗时 {} 毫秒", duration.count());

        

        return response;

    }

    

private:

    std::shared_ptr<ConfigManager> config_manager_;

    std::shared_ptr<StrategyManager> strategy_manager_;

    std::shared_ptr<ILogger> logger_;

    

    void initialize_default_strategies() {

        // 注册OpenAI兼容策略

        auto openai_strategy = std::make_shared<OpenAICompatibleStrategy>(config_manager_);

        strategy_manager_->register_strategy("openai", openai_strategy);

        

        logger_->info("默认策略注册完成");

    }

};


// 使用示例

int main() {

    ModelSDK sdk;

    

    if (!sdk.initialize("config.json")) {

        return 1;

    }

    

    std::unordered_map<std::string, ConfigManager::ConfigValue> params = {

        {"max_tokens", 200},

        {"temperature", 0.8}

    };

    

    auto response = sdk.generate_text("openai", "写一篇关于人工智能的文章", params);

    

    if (response.is_success()) {

        std::cout << "生成结果:\n" << response.get_data() << std::endl;

    } else {

        std::cerr << "生成失败: " << response.get_error_message() << std::endl;

    }

    

    return 0;

}

```


## 结语


C++大模型SDK的开发实践表明,通过合理的架构设计可以构建出稳定、高效且易于维护的系统。日志系统的统一封装提供了灵活的调试和监控能力,通用数据结构的设计确保了类型安全和数据一致性,策略模式的应用则实现了算法与业务逻辑的解耦。


在实际开发过程中,需要特别注意线程安全性、错误处理机制和性能优化。本文展示的实现方案采用现代C++特性,结合设计模式的最佳实践,为大模型SDK的开发提供了可参考的技术路径。随着功能的不断扩展,这种模块化架构能够保持良好的可维护性和可扩展性。


来自 “ ITPUB博客 ” ,链接:https://blog.itpub.net/19545/viewspace-3109828/ ,如需转载,请注明出处,否则将追究法律责任。

请登录后发表评论 登录
全部评论

注册时间:2015-11-01

  • 博文量
    895
  • 访问量
    934074