AI大模型接入SDK—通用模块设计

模块设计详解:myLog 与 common

一、日志模块(myLog)

1.1 设计概述

日志模块基于 spdlog 库封装,采用单例模式提供全局唯一的日志实例,支持同步/异步日志写入、多级别日志输出、文件/stdout 双输出方式。

设计目标

  • 统一日志接口,简化使用
  • 线程安全的初始化与访问
  • 支持不同输出目标(控制台/文件)
  • 日志格式统一,包含文件名和行号

1.2 myLog.h 接口设计

1.2.1 Logger 类(单例封装)
cpp 复制代码
class Logger
{
public:
    static void initLogger(const std::string& logName, 
                           const std::string& logFile, 
                           spdlog::level::level_enum logLevel = 		  								spdlog::level::info);
    static std::shared_ptr<spdlog::logger> getLogger();

private:
    Logger();
    Logger(const Logger&) = delete;
    Logger& operator=(const Logger&) = delete;

private:
    static std::shared_ptr<spdlog::logger> _logger;
    static std::mutex _mutex;
};
成员 说明
initLogger() 初始化日志器,设置名称、输出目标、日志级别
getLogger() 获取日志器实例(返回 shared_ptr
_logger 静态成员,存储全局唯一的日志器实例
_mutex 静态互斥锁,保护初始化过程的线程安全
私有构造函数 禁止外部实例化,强制通过静态方法访问

单例模式实现要点

  • 构造函数声明为 private,禁止外部创建实例
  • 拷贝构造和赋值运算符使用 = delete 删除,防止通过拷贝创建新实例
  • 所有成员函数均为静态,无需实例化即可调用
1.2.2 日志宏定义
cpp 复制代码
    //fmt格式化输出跟踪日志
    #define TRACE(fmt, ...) bite::Logger::getLogger()->trace(std::string("[{:>10s}:{:<4d}]")+fmt, __FILE__, __LINE__, ##__VA_ARGS__)
    //fmt格式化输出调试日志
    #define DBG(fmt, ...) bite::Logger::getLogger()->debug(std::string("[{:>10s}:{:<4d}]")+fmt, __FILE__, __LINE__, ##__VA_ARGS__)
    //fmt格式化输出信息日志
    #define INFO(fmt, ...) bite::Logger::getLogger()->info(std::string("[{:>10s}:{:<4d}]")+fmt, __FILE__, __LINE__, ##__VA_ARGS__)
    //fmt格式化输出警告日志
    #define WARN(fmt, ...) bite::Logger::getLogger()->warn(std::string("[{:>10s}:{:<4d}]")+fmt, __FILE__, __LINE__, ##__VA_ARGS__)
    //fmt格式化输出错误日志
    #define ERR(fmt, ...) bite::Logger::getLogger()->error(std::string("[{:>10s}:{:<4d}]")+fmt, __FILE__, __LINE__, ##__VA_ARGS__)
    //fmt格式化输出严重错误日志
    #define CRIT(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 success

1.3 myLog.cpp 实现细节

文件myLog.cpp(file:///workspace/CPP_AI_Model_Access/AIModelAccess/sdk/src/util/myLog.cpp)

1.3.1 静态成员初始化
cpp 复制代码
std::shared_ptr<spdlog::logger> Logger::_logger = nullptr;
std::mutex Logger::_mutex;

静态成员必须在类外部初始化 ,初始值为 nullptr 表示日志器尚未初始化。

1.3.2 initLogger() 核心实现
cpp 复制代码
void Logger::initLogger(const std::string& logName, 
                        const std::string& logFile, 
                        spdlog::level::level_enum logLevel)
{
    if(_logger == nullptr)
    {
        std::lock_guard<std::mutex> lock(_mutex);
        if(_logger == nullptr)
        {
            spdlog::flush_on(logLevel);
            spdlog::init_thread_pool(32768, 1);
            
            if("stdout" == logFile)
                _logger = spdlog::stdout_color_mt(logName);
            else
                _logger = spdlog::basic_logger_mt(logName, logFile);
        }
        
        _logger->set_pattern("[%H:%M:%S][%n][%-7l]%v");
        _logger->set_level(logLevel);
    }
}

关键技术点

技术点 实现方式 作用
双重检查锁 两次判断 _logger == nullptr 保证多线程环境下只初始化一次,避免竞态条件
lock_guard RAII 自动加锁/解锁 异常安全,防止死锁
flush_on 设置自动刷新级别 级别 >= logLevel 的日志立即刷新到文件
init_thread_pool 初始化异步日志线程池 线程池大小 32KB,1 个工作线程
stdout_color_mt 彩色控制台输出(多线程安全) 区分不同级别日志颜色
basic_logger_mt 文件输出(多线程安全) 将日志写入指定文件
1.3.3 日志格式设置
cpp 复制代码
_logger->set_pattern("[%H:%M:%S][%n][%-7l]%v");

格式说明:

  • [%H:%M:%S] - 时分秒时间戳(24小时制)
  • [%n] - 日志器名称(初始化时指定)
  • [%7l] - 日志级别,左对齐,占用7个字符
  • %v - 具体日志内容(包含文件:行号信息)
1.3.4 getLogger() 实现
cpp 复制代码
std::shared_ptr<spdlog::logger> Logger::getLogger()
{
    return _logger;
}

直接返回静态成员 _logger,调用者通过返回的 shared_ptr 访问日志方法。

1.4 使用方式

cpp 复制代码
// 在程序入口初始化日志
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.h)

2.1 设计概述

common.h 定义了项目中所有模块共享的数据结构,是整个 SDK 的数据契约层。设计遵循以下原则:

  • 职责单一:每个结构体只负责一类数据
  • 继承扩展:通过继承实现配置的多态性
  • 默认构造:提供合理的默认值,便于对象创建
  • 安全性:配置基类提供虚析构,支持安全的向下转型

2.2 数据结构体系

复制代码
Config (基类)
 ├── ApiConfig (云端API配置)
 └── OllamaConfig (本地Ollama配置)

Message (消息结构)
ModelInfo (模型元信息)
Session (会话结构)

2.3 Message 结构

cpp 复制代码
struct Message
{
    std::string _messageId;     // 消息唯一标识
    std::string _role;          // 角色:"user" / "assistant" / "system"
    std::string _content;       // 消息内容
    std::time_t _timestamp;     // 消息发送时间戳

    Message(const std::string& role = "", const std::string& content = "")
        : _role(role), _content(content)
    {}
};

设计要点

  • _role 字段遵循 OpenAI API 规范,支持 user/assistant/system 三种角色
  • _messageIdSessionManager 中生成,用于消息追踪和持久化
  • 提供默认参数的构造函数,便于快速创建用户消息

使用场景

  • LLMProvider 发送请求时,构造消息列表
  • SessionManager 维护历史消息记录
  • DataManager 持久化消息到 SQLite

2.4 Config 层次结构

2.4.1 Config 基类
cpp 复制代码
struct Config
{
    std::string _modelName;       // 模型名称
    double _temperature;          // 温度参数,控制输出随机性(默认0.7)
    int _maxTokens;               // 最大令牌数,限制输出长度(默认2048)

    virtual ~Config() = default;  // 虚析构,支持安全的多态删除
};

设计要点

字段 作用 取值范围
_modelName 模型唯一标识 如 "deepseek-chat", "gpt-4o-mini"
_temperature 控制输出随机性 0~2,越大越随机,越小越确定
_maxTokens 限制输出长度 正整数,防止输出过长

虚析构的必要性

cpp 复制代码
// 如果没有虚析构,以下代码会导致未定义行为
Config* config = new ApiConfig();
delete config;  // 只调用 Config 的析构函数,不会调用 ApiConfig 的析构
2.4.2 ApiConfig(云端 API 模型配置)
cpp 复制代码
struct ApiConfig : public Config
{
    std::string _apiKey;         // API 密钥,用于身份认证
};

设计要点

  • 继承自 Config,复用模型名称、温度、最大 token 配置
  • 新增 _apiKey 字段,用于云端模型的 API 认证
  • 适用于 ChatGPT、DeepSeek、Gemini 等云端 API 模型
2.4.3 OllamaConfig(本地 Ollama 模型配置)
cpp 复制代码
struct OllamaConfig : public Config
{
    std::string _modelName;   // Ollama 模型名称(如 "deepseek-r1:1.5b")
    std::string _modelDesc;   // 模型描述信息
    std::string _endpoint;    // Ollama 服务地址(如 "http://localhost:11434")
};

设计要点

  • 继承自 Config,但覆盖了 _modelName 字段(Ollama 模型名格式不同)
  • 无需 API Key(本地模型)
  • 需要指定 Ollama 服务的 endpoint 地址
  • 包含模型描述,用于展示和区分不同模型
2.4.4 配置层次结构总结
配置类型 适用模型 特有字段
Config 所有模型(基类) _modelName, _temperature, _maxTokens
ApiConfig ChatGPT、DeepSeek、Gemini _apiKey
OllamaConfig Ollama 本地模型 _modelDesc, _endpoint

多态使用示例

cpp 复制代码
// 在 ChatSDK 中统一处理不同类型的配置
std::vector<std::shared_ptr<Config>> configs;

// 添加云端模型配置
auto deepseekConfig = std::make_shared<ApiConfig>();
deepseekConfig->_modelName = "deepseek-chat";
deepseekConfig->_apiKey = "sk-xxx";
configs.push_back(deepseekConfig);

// 添加本地模型配置
auto ollamaConfig = std::make_shared<OllamaConfig>();
ollamaConfig->_modelName = "deepseek-r1:1.5b";
ollamaConfig->_endpoint = "http://localhost:11434";
configs.push_back(ollamaConfig);

// 通过 dynamic_pointer_cast 区分处理
for (const auto& config : configs) {
    if (auto apiConfig = std::dynamic_pointer_cast<ApiConfig>(config)) {
        // 处理云端模型
    } else if (auto ollamaConfig = std::dynamic_pointer_cast<OllamaConfig>(config)) {
        // 处理本地模型
    }
}

2.5 ModelInfo 结构

cpp 复制代码
struct ModelInfo
{
    std::string _modelName;       // 模型名称
    std::string _modelDesc;       // 模型描述
    std::string _provider;        // 模型提供方
    std::string _endpoint;        // API endpoint 地址
    bool _isAvailable = false;    // 模型是否可用

    ModelInfo(const std::string& modelName = "", 
              const std::string& modelDesc = "", 
              const std::string& provider = "", 
              const std::string& endpoint = "")
        : _modelName(modelName), _modelDesc(modelDesc), 
          _provider(provider), _endpoint(endpoint)
    {}
};

设计要点

  • 用于展示模型的元信息,供前端或 API 返回使用
  • _isAvailable 标记模型是否已成功初始化
  • 提供全参数构造函数,便于快速创建

使用场景

  • LLMManager 维护已注册模型的状态信息
  • ChatServer 的 /api/models 接口返回可用模型列表

2.6 Session 结构

cpp 复制代码
struct Session
{
    std::string _sessionId;       // 会话唯一标识
    std::string _modelName;       // 会话使用的模型名称
    std::vector<Message> _messages; // 会话历史消息
    std::time_t _createAt;       // 会话创建时间
    std::time_t _updateAt;       // 会话最后更新时间

    Session(const std::string& modelName = "")
        : _modelName(modelName)
    {}
};

设计要点

  • _sessionIdSessionManager 生成,全局唯一
  • _messages 存储完整的对话历史,用于上下文管理
  • _createAt_updateAt 用于会话管理(如清理长时间未使用的会话)

使用场景

  • SessionManager 管理活跃会话
  • DataManager 将会话持久化到 SQLite
  • ChatServer 通过 /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_ptr<spdlog::logger> _logger
全局访问 static getLogger() 方法
线程安全 双重检查锁 + std::lock_guard
禁止拷贝 Logger(const Logger&) = delete

4.2 common.h - 模板方法模式(隐式)

通过配置基类 Config 和子类 ApiConfigOllamaConfig,实现了配置的多态处理:

cpp 复制代码
// ChatSDK 中统一处理配置(模板方法模式的应用)
void initProviders(const std::vector<std::shared_ptr<Config>>& configs) {
    for (const auto& config : configs) {
        if (auto apiConfig = std::dynamic_pointer_cast<ApiConfig>(config)) {
            initAPIModelProvider(apiConfig->_modelName, apiConfig);
        } else if (auto ollamaConfig = std::dynamic_pointer_cast<OllamaConfig>(config)) {
            initOllamaModelProvider(ollamaConfig->_modelName, ollamaConfig);
        }
    }
}

五、总结

模块 核心职责 设计模式 依赖关系
myLog 全局日志管理 单例模式 仅依赖 spdlog
common.h 公共数据结构定义 继承/多态 仅依赖标准库

这两个模块是项目的基础设施:

  • myLog 提供统一的日志能力,是调试和运维的基础
  • common.h 定义了模块间的数据契约,是 SDK 设计的核心
  • 两者都不依赖项目内部其他模块,体现了良好的模块化设计原则
相关推荐
行思理17 小时前
微信支付“商家转账用户确认模式”,新手教程
java·开发语言·微信
麻瓜老宋17 小时前
AI开发C语言应用按步走,表达式计算器calc的第一步,中缀表达式词法分析
c语言·开发语言·atomcode
Ai拆代码的曹操18 小时前
K8s Pod Pending 逐层排查:从 FailedScheduling 到 PVC StorageClass 不存在的实战记录
java·linux·kubernetes
hold?fish:palm18 小时前
RDB全量快照备份
c++·redis·后端
灯澜忆梦18 小时前
GO_文件处理---字符串操作
开发语言·golang
-银雾鸢尾-18 小时前
里氏替换原则
开发语言·c#·里氏替换原则
এ慕ོ冬℘゜18 小时前
JavaScript 数组核心方法实战|新增元素 + 数组转字符串 零基础详解
开发语言·javascript·ecmascript
一个初入编程的小白18 小时前
C语言:函数栈帧与销毁
c语言·开发语言
czhc114007566318 小时前
718:public internl class;partial []
开发语言