# 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/ ,如需转载,请注明出处,否则将追究法律责任。