AI大模型接入SDK—通用模块设计
模块设计详解myLog 与 common一、日志模块myLog1.1 设计概述日志模块基于spdlog库封装采用单例模式提供全局唯一的日志实例支持同步/异步日志写入、多级别日志输出、文件/stdout 双输出方式。设计目标统一日志接口简化使用线程安全的初始化与访问支持不同输出目标控制台/文件日志格式统一包含文件名和行号1.2 myLog.h 接口设计1.2.1 Logger 类单例封装classLogger{public:staticvoidinitLogger(conststd::stringlogName,conststd::stringlogFile,spdlog::level::level_enum logLevelspdlog::level::info);staticstd::shared_ptrspdlog::loggergetLogger();private:Logger();Logger(constLogger)delete;Loggeroperator(constLogger)delete;private:staticstd::shared_ptrspdlog::logger_logger;staticstd::mutex _mutex;};成员说明initLogger()初始化日志器设置名称、输出目标、日志级别getLogger()获取日志器实例返回shared_ptr_logger静态成员存储全局唯一的日志器实例_mutex静态互斥锁保护初始化过程的线程安全私有构造函数禁止外部实例化强制通过静态方法访问单例模式实现要点构造函数声明为private禁止外部创建实例拷贝构造和赋值运算符使用 delete删除防止通过拷贝创建新实例所有成员函数均为静态无需实例化即可调用1.2.2 日志宏定义//fmt格式化输出跟踪日志#defineTRACE(fmt,...)bite::Logger::getLogger()-trace(std::string([{:10s}:{:4d}])fmt,__FILE__,__LINE__,##__VA_ARGS__)//fmt格式化输出调试日志#defineDBG(fmt,...)bite::Logger::getLogger()-debug(std::string([{:10s}:{:4d}])fmt,__FILE__,__LINE__,##__VA_ARGS__)//fmt格式化输出信息日志#defineINFO(fmt,...)bite::Logger::getLogger()-info(std::string([{:10s}:{:4d}])fmt,__FILE__,__LINE__,##__VA_ARGS__)//fmt格式化输出警告日志#defineWARN(fmt,...)bite::Logger::getLogger()-warn(std::string([{:10s}:{:4d}])fmt,__FILE__,__LINE__,##__VA_ARGS__)//fmt格式化输出错误日志#defineERR(fmt,...)bite::Logger::getLogger()-error(std::string([{:10s}:{:4d}])fmt,__FILE__,__LINE__,##__VA_ARGS__)//fmt格式化输出严重错误日志#defineCRIT(fmt,...)bite::Logger::getLogger()-critical(std::string([{:10s}:{:4d}])fmt,__FILE__,__LINE__,##__VA_ARGS__)宏设计亮点特性实现方式效果文件行号追踪__FILE__、__LINE__宏日志自动附带调用位置格式化输出fmt库语法支持{}占位符格式化可变参数##__VA_ARGS__兼容 C99 可变参数宏对齐美化{:10s}、{:4d}文件名右对齐10位行号左对齐4位日志输出格式[14:32:58][ChatSDK][INFO ][ChatSDK.cpp: 45] Initialize deepseek-chat success1.3 myLog.cpp 实现细节文件[myLog.cpp](file:///workspace/CPP_AI_Model_Access/AIModelAccess/sdk/src/util/myLog.cpp)1.3.1 静态成员初始化std::shared_ptrspdlog::loggerLogger::_loggernullptr;std::mutex Logger::_mutex;静态成员必须在类外部初始化初始值为nullptr表示日志器尚未初始化。1.3.2 initLogger() 核心实现voidLogger::initLogger(conststd::stringlogName,conststd::stringlogFile,spdlog::level::level_enum logLevel){if(_loggernullptr){std::lock_guardstd::mutexlock(_mutex);if(_loggernullptr){spdlog::flush_on(logLevel);spdlog::init_thread_pool(32768,1);if(stdoutlogFile)_loggerspdlog::stdout_color_mt(logName);else_loggerspdlog::basic_logger_mt(logName,logFile);}_logger-set_pattern([%H:%M:%S][%n][%-7l]%v);_logger-set_level(logLevel);}}关键技术点技术点实现方式作用双重检查锁两次判断_logger nullptr保证多线程环境下只初始化一次避免竞态条件lock_guardRAII 自动加锁/解锁异常安全防止死锁flush_on设置自动刷新级别级别 logLevel 的日志立即刷新到文件init_thread_pool初始化异步日志线程池线程池大小 32KB1 个工作线程stdout_color_mt彩色控制台输出多线程安全区分不同级别日志颜色basic_logger_mt文件输出多线程安全将日志写入指定文件1.3.3 日志格式设置_logger-set_pattern([%H:%M:%S][%n][%-7l]%v);格式说明[%H:%M:%S]- 时分秒时间戳24小时制[%n]- 日志器名称初始化时指定[%7l]- 日志级别左对齐占用7个字符%v- 具体日志内容包含文件:行号信息1.3.4 getLogger() 实现std::shared_ptrspdlog::loggerLogger::getLogger(){return_logger;}直接返回静态成员_logger调用者通过返回的shared_ptr访问日志方法。1.4 使用方式// 在程序入口初始化日志bite::Logger::initLogger(ChatServer,chat_server.log,spdlog::level::debug);// 在任意模块使用日志宏INFO(Server started on port {},8080);ERR(Failed to connect to database: {},errorMsg);WARN(API key not set, some models may not work);二、公共数据结构common.h2.1 设计概述common.h定义了项目中所有模块共享的数据结构是整个 SDK 的数据契约层。设计遵循以下原则职责单一每个结构体只负责一类数据继承扩展通过继承实现配置的多态性默认构造提供合理的默认值便于对象创建安全性配置基类提供虚析构支持安全的向下转型2.2 数据结构体系Config (基类) ├── ApiConfig (云端API配置) └── OllamaConfig (本地Ollama配置) Message (消息结构) ModelInfo (模型元信息) Session (会话结构)2.3 Message 结构structMessage{std::string _messageId;// 消息唯一标识std::string _role;// 角色user / assistant / systemstd::string _content;// 消息内容std::time_t _timestamp;// 消息发送时间戳Message(conststd::stringrole,conststd::stringcontent):_role(role),_content(content){}};设计要点_role字段遵循 OpenAI API 规范支持 user/assistant/system 三种角色_messageId在SessionManager中生成用于消息追踪和持久化提供默认参数的构造函数便于快速创建用户消息使用场景LLMProvider 发送请求时构造消息列表SessionManager 维护历史消息记录DataManager 持久化消息到 SQLite2.4 Config 层次结构2.4.1 Config 基类structConfig{std::string _modelName;// 模型名称double_temperature;// 温度参数控制输出随机性默认0.7int_maxTokens;// 最大令牌数限制输出长度默认2048virtual~Config()default;// 虚析构支持安全的多态删除};设计要点字段作用取值范围_modelName模型唯一标识如 “deepseek-chat”, “gpt-4o-mini”_temperature控制输出随机性0~2越大越随机越小越确定_maxTokens限制输出长度正整数防止输出过长虚析构的必要性// 如果没有虚析构以下代码会导致未定义行为Config*confignewApiConfig();deleteconfig;// 只调用 Config 的析构函数不会调用 ApiConfig 的析构2.4.2 ApiConfig云端 API 模型配置structApiConfig:publicConfig{std::string _apiKey;// API 密钥用于身份认证};设计要点继承自Config复用模型名称、温度、最大 token 配置新增_apiKey字段用于云端模型的 API 认证适用于 ChatGPT、DeepSeek、Gemini 等云端 API 模型2.4.3 OllamaConfig本地 Ollama 模型配置structOllamaConfig:publicConfig{std::string _modelName;// Ollama 模型名称如 deepseek-r1:1.5bstd::string _modelDesc;// 模型描述信息std::string _endpoint;// Ollama 服务地址如 http://localhost:11434};设计要点继承自Config但覆盖了_modelName字段Ollama 模型名格式不同无需 API Key本地模型需要指定 Ollama 服务的 endpoint 地址包含模型描述用于展示和区分不同模型2.4.4 配置层次结构总结配置类型适用模型特有字段Config所有模型基类_modelName,_temperature,_maxTokensApiConfigChatGPT、DeepSeek、Gemini_apiKeyOllamaConfigOllama 本地模型_modelDesc,_endpoint多态使用示例// 在 ChatSDK 中统一处理不同类型的配置std::vectorstd::shared_ptrConfigconfigs;// 添加云端模型配置autodeepseekConfigstd::make_sharedApiConfig();deepseekConfig-_modelNamedeepseek-chat;deepseekConfig-_apiKeysk-xxx;configs.push_back(deepseekConfig);// 添加本地模型配置autoollamaConfigstd::make_sharedOllamaConfig();ollamaConfig-_modelNamedeepseek-r1:1.5b;ollamaConfig-_endpointhttp://localhost:11434;configs.push_back(ollamaConfig);// 通过 dynamic_pointer_cast 区分处理for(constautoconfig:configs){if(autoapiConfigstd::dynamic_pointer_castApiConfig(config)){// 处理云端模型}elseif(autoollamaConfigstd::dynamic_pointer_castOllamaConfig(config)){// 处理本地模型}}2.5 ModelInfo 结构structModelInfo{std::string _modelName;// 模型名称std::string _modelDesc;// 模型描述std::string _provider;// 模型提供方std::string _endpoint;// API endpoint 地址bool_isAvailablefalse;// 模型是否可用ModelInfo(conststd::stringmodelName,conststd::stringmodelDesc,conststd::stringprovider,conststd::stringendpoint):_modelName(modelName),_modelDesc(modelDesc),_provider(provider),_endpoint(endpoint){}};设计要点用于展示模型的元信息供前端或 API 返回使用_isAvailable标记模型是否已成功初始化提供全参数构造函数便于快速创建使用场景LLMManager 维护已注册模型的状态信息ChatServer 的/api/models接口返回可用模型列表2.6 Session 结构structSession{std::string _sessionId;// 会话唯一标识std::string _modelName;// 会话使用的模型名称std::vectorMessage_messages;// 会话历史消息std::time_t _createAt;// 会话创建时间std::time_t _updateAt;// 会话最后更新时间Session(conststd::stringmodelName):_modelName(modelName){}};设计要点_sessionId由SessionManager生成全局唯一_messages存储完整的对话历史用于上下文管理_createAt和_updateAt用于会话管理如清理长时间未使用的会话使用场景SessionManager 管理活跃会话DataManager 将会话持久化到 SQLiteChatServer 通过/api/session/{id}/history返回会话历史2.7 数据结构关系图┌─────────────────────────────────────────────────────────────┐ │ common.h 数据结构 │ ├─────────────────────────────────────────────────────────────┤ │ │ │ ┌─────────────────────┐ │ │ │ Config │ (基类虚析构) │ │ │ ────────────────── │ │ │ │ _modelName │ │ │ │ _temperature │ │ │ │ _maxTokens │ │ │ └──────────┬──────────┘ │ │ │ │ │ ┌──────┴──────┐ │ │ ▼ ▼ │ │ ┌──────────┐ ┌──────────────┐ │ │ │ApiConfig │ │OllamaConfig │ │ │ │ ─────── │ │ ─────────── │ │ │ │ _apiKey │ │ _modelDesc │ │ │ └──────────┘ │ _endpoint │ │ │ └──────────────┘ │ │ │ │ ┌─────────────────────┐ │ │ │ Message │ (消息单元) │ │ │ ────────────────── │ │ │ │ _messageId │ │ │ │ _role │ │ │ │ _content │ │ │ │ _timestamp │ │ │ └─────────────────────┘ │ │ │ │ ┌─────────────────────┐ │ │ │ ModelInfo │ (模型元信息) │ │ │ ────────────────── │ │ │ │ _modelName │ │ │ │ _modelDesc │ │ │ │ _provider │ │ │ │ _endpoint │ │ │ │ _isAvailable │ │ │ └─────────────────────┘ │ │ │ │ ┌─────────────────────┐ │ │ │ Session │ (会话上下文) │ │ │ ────────────────── │ │ │ │ _sessionId │ │ │ │ _modelName │ │ │ │ _messages[] │ ◀─── 包含多个 Message │ │ │ _createAt │ │ │ │ _updateAt │ │ │ └─────────────────────┘ │ │ │ └─────────────────────────────────────────────────────────────┘三、模块间依赖关系3.1 myLog 的依赖关系┌──────────────┐ │ myLog.h │ │ ─────────── │ │ Logger 类 │ │ 日志宏定义 │ └──────┬───────┘ │ ┌─────────────────┼─────────────────┐ │ │ │ ▼ ▼ ▼ ┌──────────┐ ┌──────────┐ ┌──────────┐ │ChatSDK │ │LLMManager│ │所有Provider│ └──────────┘ └──────────┘ └──────────┘ │ │ │ ▼ ▼ ▼ ┌──────────┐ ┌──────────┐ ┌──────────┐ │Session- │ │Data- │ │ChatServer │ │Manager │ │Manager │ └──────────┘ └──────────┘ └──────────┘依赖特性myLog 不依赖任何项目内部模块仅依赖 spdlog 第三方库项目中所有模块均依赖 myLog日志输出myLog 通过全局宏提供无侵入的日志记录能力3.2 common.h 的依赖关系┌──────────────┐ │ common.h │ │ ─────────── │ │ 数据结构定义 │ └──────┬───────┘ │ ┌─────────────────┼─────────────────┐ │ │ │ ▼ ▼ ▼ ┌──────────┐ ┌──────────┐ ┌──────────┐ │LLMProvider│ │ChatSDK │ │Session- │ │(抽象接口) │ └──────────┘ │Manager │ └────┬─────┘ └────┬─────┘ │ │ ▼ ▼ ┌─────────────────┐ ┌──────────┐ │ 所有 Provider │ │Data- │ │ (4个实现类) │ │Manager │ └─────────────────┘ └──────────┘依赖特性common.h 不依赖任何项目内部模块仅依赖标准库LLMProvider、ChatSDK、SessionManager、DataManager 均依赖 common.h是整个 SDK 的数据契约定义了模块间交互的数据格式四、设计模式应用4.1 myLog - 单例模式要素实现私有构造Logger()声明为 private静态实例static std::shared_ptrspdlog::logger _logger全局访问static getLogger()方法线程安全双重检查锁 std::lock_guard禁止拷贝Logger(const Logger) delete4.2 common.h - 模板方法模式隐式通过配置基类Config和子类ApiConfig、OllamaConfig实现了配置的多态处理// ChatSDK 中统一处理配置模板方法模式的应用voidinitProviders(conststd::vectorstd::shared_ptrConfigconfigs){for(constautoconfig:configs){if(autoapiConfigstd::dynamic_pointer_castApiConfig(config)){initAPIModelProvider(apiConfig-_modelName,apiConfig);}elseif(autoollamaConfigstd::dynamic_pointer_castOllamaConfig(config)){initOllamaModelProvider(ollamaConfig-_modelName,ollamaConfig);}}}五、总结模块核心职责设计模式依赖关系myLog全局日志管理单例模式仅依赖 spdlogcommon.h公共数据结构定义继承/多态仅依赖标准库这两个模块是项目的基础设施myLog提供统一的日志能力是调试和运维的基础common.h定义了模块间的数据契约是 SDK 设计的核心两者都不依赖项目内部其他模块体现了良好的模块化设计原则

相关新闻

最新新闻

日新闻

周新闻

月新闻