ChatSDK 详解:统一入口与协调者

一、概述

1.1 角色定位

ChatSDK 是整个 SDK 的统一入口协调者,对外封装所有功能,对内协调 LLMManager(模型管理)和 SessionManager(会话管理)两大子系统。

┌──────────────────────────────────────────────────────────────────┐
│                          外部调用方                              │
│              (ChatServer / 测试代码 / 应用程序)                  │
└──────────────────────────────┬───────────────────────────────────┘
                               │
                               ▼
                    ┌─────────────────────┐
                    │      ChatSDK        │  ← 统一入口
                    │   (协调者)         │
                    └──────────┬──────────┘
                               │
            ┌──────────────────┼──────────────────┐
            │                  │                  │
            ▼                  ▼                  ▼
   ┌─────────────────┐  ┌──────────────┐  ┌──────────────────┐
   │  LLMManager     │  │SessionManager│  │  _modelConfigs   │
   │  (模型管理)    │  │ (会话管理)  │  │  (配置缓存)    │
   └─────────────────┘  └──────┬───────┘  └──────────────────┘
                               │
                               ▼
                        ┌──────────────┐
                        │ DataManager  │
                        │(数据持久化) │
                        └──────────────┘

1.2 核心职责

职责 说明
模型注册与初始化 根据用户传入的配置,注册并初始化所有支持的模型
会话生命周期管理 创建、查询、删除会话
消息发送协调 协调会话历史、模型调用、结果保存的完整闭环
配置缓存 保存各模型的配置参数(temperature、max_tokens 等)
初始化状态保护 所有操作前检查 SDK 是否已初始化

二、类设计

2.1 类结构

class ChatSDK
{
public:
    // ===== 模型管理 =====
    bool initModels(const std::vector<std::shared_ptr<Config>>& configs);
    std::vector<ModelInfo> getAvailableModels() const;

    // ===== 会话管理 =====
    std::string createSession(const std::string& modelName);
    std::shared_ptr<Session> getSession(const std::string& sessionId);
    std::vector<std::string> getSessionLists() const;
    bool deleteSession(const std::string& sessionId);

    // ===== 消息发送 =====
    std::string sendMessage(const std::string& sessionId, const std::string& message);
    std::string sendMessageStream(const std::string& sessionId, const std::string& message,
                                   std::function<void(const std::string&, bool)> callback);

private:
    // ===== 内部辅助方法 =====
    void registerAllProviders(const std::vector<std::shared_ptr<Config>>& configs);
    void initProviders(const std::vector<std::shared_ptr<Config>>& configs);
    bool initAPIModelProvider(const std::string& modelName, const std::shared_ptr<ApiConfig>& apiConfig);
    bool initOllamaModelProvider(const std::string& modelName, const std::shared_ptr<OllamaConfig>& ollamaConfig);

private:
    // ===== 成员变量 =====
    bool _initialized = false;                                           
    // 初始化标志
    std::unordered_map<std::string, std::shared_ptr<Config>> _modelConfigs;  	 // 模型配置缓存
    LLMManager _llmManager;                                              
    // 模型管理器
    SessionManager _sessionManager;                                      
    // 会话管理器
};

2.2 成员变量说明

成员 类型 作用
_initialized bool SDK 初始化标志,所有操作前必须检查
_modelConfigs unordered_map<string, shared_ptr<Config>> 缓存各模型的配置参数
_llmManager LLMManager 模型管理器(值类型,生命周期与 ChatSDK 绑定)
_sessionManager SessionManager 会话管理器

设计亮点

  • _modelConfigs 保存配置,发送消息时用于提取 temperaturemax_tokens
  • LLMManagerSessionManager 是值成员,ChatSDK 析构时自动析构它们

三、核心方法详解

3.1 initModels:SDK 初始化入口

bool ChatSDK::initModels(const std::vector<std::shared_ptr<Config>>& configs)
{
    // 步骤 1:注册所有 Provider
    registerAllProviders(configs);
    
    // 步骤 2:初始化所有 Provider
    initProviders(configs);
    
    // 步骤 3:标记初始化完成
    _initialized = true;
    
    return true;
}

两阶段初始化设计

┌──────────────────────────────────────────────────────────────┐
│                  initModels 两阶段初始化                       │
├──────────────────────────────────────────────────────────────┤
│                                                              │
│  阶段一:registerAllProviders                                 │
│  ─────────────────────────                                   │
│  ├── 创建 DeepSeekProvider 实例                              │
│  ├── 创建 ChatGPTProvider 实例                               │
│  ├── 创建 GeminiProvider 实例                                │
│  ├── 遍历 configs,创建 OllamaLLMProvider 实例               │
│  └── 所有 Provider 注册到 LLMManager(此时未初始化)          │
│                                                              │
│  阶段二:initProviders                                        │
│  ─────────────────────────                                   │
│  ├── 遍历 configs                                            │
│  ├── 对 ApiConfig 类型 → initAPIModelProvider                │
│  │   └── 传入 api_key → LLMManager::initModel               │
│  ├── 对 OllamaConfig 类型 → initOllamaModelProvider          │
│  │   └── 传入 model_name, model_desc, endpoint              │
│  └── 初始化成功后,缓存配置到 _modelConfigs                  │
│                                                              │
└──────────────────────────────────────────────────────────────┘

为什么分两阶段

  • 注册阶段:创建 Provider 实例,建立模型名称到 Provider 的映射
  • 初始化阶段:传入配置参数(API Key 等),使 Provider 可用
  • 分离后支持延迟初始化按需初始化

3.2 registerAllProviders:Provider 注册

void ChatSDK::registerAllProviders(const std::vector<std::shared_ptr<Config>>& configs)
{
    // 1. 注册云端 API 模型(固定三个)
    if(!_llmManager.isModelAvailable("deepseek-chat")) {
        auto deepseekProvider = std::make_unique<DeepSeekProvider>();
        _llmManager.registerProvider("deepseek-chat", std::move(deepseekProvider));
    }
    
    if(!_llmManager.isModelAvailable("gpt-4o-mini")) {
        auto gpt4oProvider = std::make_unique<ChatGPTProvider>();
        _llmManager.registerProvider("gpt-4o-mini", std::move(gpt4oProvider));
    }
    
    if(!_llmManager.isModelAvailable("gemini-2.0-flash")) {
        auto geminiProvider = std::make_unique<GeminiProvider>();
        _llmManager.registerProvider("gemini-2.0-flash", std::move(geminiProvider));
    }
    
    // 2. 注册本地 Ollama 模型(动态,根据用户配置)
    std::unordered_set<std::string> modelNames;  // 用于去重
    for(const auto& config : configs) {
        auto ollamaConfig = std::dynamic_pointer_cast<OllamaConfig>(config);
        if(ollamaConfig) {
            auto modelName = ollamaConfig->_modelName;
            if(modelNames.find(modelName) == modelNames.end()) {
                modelNames.insert(modelName);
                if(!_llmManager.isModelAvailable(modelName)) {
                    auto ollamaProvider = std::make_unique<OllamaLLMProvider>();
                    _llmManager.registerProvider(modelName, std::move(ollamaProvider));
                }
            }
        }
    }
}

设计要点

设计点 说明
固定 + 动态结合 云端模型(DeepSeek/ChatGPT/Gemini)固定注册,Ollama 模型动态注册
std::move 转移所有权 unique_ptr 不能拷贝,必须用 std::move 转移到 LLMManager
去重检查 使用 unordered_set 防止重复注册同名 Ollama 模型
幂等性 通过 isModelAvailable 检查,避免重复注册
RTTI 类型识别 std::dynamic_pointer_cast<OllamaConfig> 区分配置类型

dynamic_pointer_cast 的作用

// 父类指针向子类指针的安全转换
std::shared_ptr<Config> config = ...;
auto ollamaConfig = std::dynamic_pointer_cast<OllamaConfig>(config);
// 如果 config 实际指向 OllamaConfig → 转换成功
// 如果 config 实际指向 ApiConfig → 返回 nullptr

3.3 initProviders:Provider 初始化

void ChatSDK::initProviders(const std::vector<std::shared_ptr<Config>>& configs)
{
    for (const auto& config : configs) {
        // 类型判断:ApiConfig
        if(auto apiConfig = std::dynamic_pointer_cast<ApiConfig>(config)) {
            if(apiConfig->_modelName == "deepseek-chat" ||
               apiConfig->_modelName == "gpt-4o-mini" ||
               apiConfig->_modelName == "gemini-2.0-flash") {
                initAPIModelProvider(apiConfig->_modelName, apiConfig);
            } else {
                ERR("Model {} not supported", apiConfig->_modelName);
            }
        }
        // 类型判断:OllamaConfig
        else if(auto ollamaConfig = std::dynamic_pointer_cast<OllamaConfig>(config)) {
            initOllamaModelProvider(ollamaConfig->_modelName, ollamaConfig);
        }
        else {
            ERR("Model {} not supported", config->_modelName);
        }
    }
}

设计要点

  • 使用 dynamic_pointer_cast 进行运行时类型识别(RTTI)
  • 根据配置类型分发到不同的初始化方法
  • 支持白名单校验:只有指定的云端模型名才会被初始化

3.4 initAPIModelProvider:API 模型初始化

bool ChatSDK::initAPIModelProvider(const std::string& modelName, 
                                    const std::shared_ptr<ApiConfig>& apiConfig)
{
    // 1. 参数校验
    if(modelName.empty()) return false;
    if(!apiConfig || apiConfig->_apiKey.empty()) return false;
    
    // 2. 幂等检查
    if(_llmManager.isModelAvailable(modelName)) {
        return true;  // 已初始化,直接返回
    }
    
    // 3. 构造参数 map
    std::map<std::string, std::string> modelParams;
    modelParams["api_key"] = apiConfig->_apiKey;
    
    
    // 4. 调用 LLMManager 初始化
    if(!_llmManager.initModel(modelName, modelParams)) {
        return false;
    }
    
    // 5. 缓存配置
    _modelConfigs[modelName] = apiConfig;
    return true;
}

3.5 initOllamaModelProvider:Ollama 模型初始化

bool ChatSDK::initOllamaModelProvider(const std::string& modelName, 
                                       const std::shared_ptr<OllamaConfig>& ollamaConfig)
{
    // 1. 参数校验
    if(modelName.empty()) return false;
    if(!ollamaConfig || ollamaConfig->_modelName.empty()) return false;
    
    // 2. 幂等检查
    if(_llmManager.isModelAvailable(modelName)) {
        return true;
    }
    
    // 3. 构造参数 map(三个参数都传)
    std::map<std::string, std::string> modelParams;
    modelParams["model_name"] = ollamaConfig->_modelName;
    modelParams["model_desc"] = ollamaConfig->_modelDesc;
    modelParams["endpoint"] = ollamaConfig->_endpoint;
    
    // 4. 调用 LLMManager 初始化
    if(!_llmManager.initModel(modelName, modelParams)) {
        return false;
    }
    
    // 5. 缓存配置
    _modelConfigs[modelName] = ollamaConfig;
    return true;
}

3.6 会话管理方法

createSession
std::string ChatSDK::createSession(const std::string& modelName)
{
    // 1. 初始化检查
    if(!_initialized) {
        ERR("SDK not initialized");
        return "";
    }
    
    // 2. 委托 SessionManager 创建会话
    auto sessionId = _sessionManager.createSession(modelName);
    if(sessionId.empty()) {
        ERR("Create session failed");
        return "";
    }
    
    return sessionId;
}

设计模式:ChatSDK 是代理,在调用前添加初始化检查,实际工作委托给 SessionManager

getSession / getSessionLists / deleteSession
// 共同的模式
std::shared_ptr<Session> ChatSDK::getSession(const std::string& sessionId)
{
    if(!_initialized) {         // 1. 初始化检查
        return nullptr;
    }
    
    auto session = _sessionManager.getSession(sessionId);  // 2. 委托
    if(!session) {              // 3. 错误处理
        ERR("Session {} not found", sessionId);
        return nullptr;
    }
    
    return session;             // 4. 返回结果
}

统一模式

初始化检查 → 委托调用 → 错误处理 → 返回结果

3.7 sendMessage:全量消息发送

这是 ChatSDK 最核心的方法,体现了协调者的角色。

std::string ChatSDK::sendMessage(const std::string& sessionId, const std::string& message)
{
    // 1. 初始化检查
    if(!_initialized) { return ""; }
    
    // 2. 获取会话
    auto session = _sessionManager.getSession(sessionId);
    if(!session) { return ""; }
    
    // 3. 构造用户消息并添加到会话历史
    Message userMessage("user", message);
    _sessionManager.addMessage(sessionId, userMessage);
    
    // 4. 获取完整历史消息(含本次用户消息)
    auto historyMessages = _sessionManager.getHistoryMessages(sessionId);
    
    // 5. 构建请求参数(从 _modelConfigs 提取)
    auto it = _modelConfigs.find(session->_modelName);
    if(it == _modelConfigs.end()) { return ""; }
    
    std::map<std::string, std::string> requestParam;
    requestParam["temperature"] = std::to_string(it->second->_temperature);
    requestParam["max_tokens"] = std::to_string(it->second->_maxTokens);
    
    // 6. 调用 LLMManager 发送消息
    auto response = _llmManager.sendMessage(session->_modelName, historyMessages, requestParam);
    if(response.empty()) { return ""; }
    
    // 7. 添加助手回复到会话历史
    Message assistantMessage("assistant", response);
    _sessionManager.addMessage(sessionId, assistantMessage);
    
    // 8. 更新会话时间戳
    _sessionManager.updateSessionTimestamp(sessionId);
    
    return response;
}

完整调用链路

┌─────────────────────────────────────────────────────────────────────┐
│                     sendMessage 完整流程                             │
├─────────────────────────────────────────────────────────────────────┤
│                                                                     │
│  1. 初始化检查                                                       │
│     └── _initialized == true ?                                      │
│                                                                     │
│  2. 获取会话                                                         │
│     └── SessionManager::getSession(sessionId)                       │
│                                                                     │
│  3. 添加用户消息到历史                                                │
│     └── SessionManager::addMessage(sessionId, userMessage)          │
│         ├── 内存:_sessions[sessionId]._messages.push_back          │
│         └── 数据库:DataManager::insertMessage                      │
│                                                                     │
│  4. 获取完整历史消息                                                 │
│     └── SessionManager::getHistoryMessages(sessionId)               │
│         └── [user: "你好", assistant: "你好!", user: "介绍一下自己"]│
│                                                                     │
│  5. 构建请求参数                                                     │
│     ├── 从 _modelConfigs 查找配置                                   │
│     └── 提取 temperature, max_tokens                                │
│                                                                     │
│  6. 调用 LLMManager 发送消息                                         │
│     └── LLMManager::sendMessage(modelName, messages, params)         │
│         └── Provider::sendMessage()                                 │
│             └── HTTP POST → AI API → 返回响应                      │
│                                                                     │
│  7. 添加助手回复到历史                                                │
│     └── SessionManager::addMessage(sessionId, assistantMessage)     │
│         ├── 内存:_messages.push_back("assistant", response)        │
│         └── 数据库:DataManager::insertMessage                      │
│                                                                     │
│  8. 更新会话时间戳                                                   │
│     └── SessionManager::updateSessionTimestamp(sessionId)           │
│         ├── 内存:_updateAt = now()                                │
│         └── 数据库:DataManager::updateSessionTimestamp            │
│                                                                     │
│  9. 返回响应内容                                                     │
│                                                                     │
└─────────────────────────────────────────────────────────────────────┘

3.8 sendMessageStream:流式消息发送

std::string ChatSDK::sendMessageStream(const std::string& sessionId, 
                                        const std::string& message,
                                        std::function<void(const std::string&, bool)> callback)
{
    // 1~5 步与 sendMessage 完全相同
    // ...
    
    // 6. 调用 LLMManager 流式发送(传递 callback)
    auto response = _llmManager.sendMessageStream(
        session->_modelName, historyMessages, requestParam, callback);
    
    // 7~8 步与 sendMessage 完全相同
    // 添加助手回复 + 更新时间戳
    
    return response;
}

与 sendMessage 的差异

差异点 sendMessage sendMessageStream
方法签名 无 callback 参数 有 callback 参数
调用 LLMManager sendMessage() sendMessageStream(callback)
响应方式 一次性返回完整内容 边生成边通过 callback 返回
返回值 完整响应 聚合的完整响应(与 sendMessage 相同)

关键设计

  • 流式发送时,callback透传到最终的 Provider
  • Provider 在收到增量数据时调用 callback(content, false)
  • ChatSDK 不关心 callback 的具体实现,只负责传递

四、数据流分析

4.1 消息发送的数据流

用户输入: "介绍一下 C++"
     │
     ▼
┌────────────────────────────────────────────────────────────────┐
│ ChatSDK::sendMessage(sessionId, "介绍一下 C++")                │
│                                                                │
│ ┌─ SessionManager ─────────────────────────────────────────┐  │
│ │                                                          │  │
│ │  addMessage(sessionId, {role: "user", content: "...C++"})│  │
│ │  └─→ _messages.push_back(userMessage)                    │  │
│ │  └─→ DataManager::insertMessage → SQLite                 │  │
│ │                                                          │  │
│ │  getHistoryMessages(sessionId)                           │  │
│ │  └─→ [user: "你好", assistant: "你好!",                │  │
│ │       user: "介绍一下 C++"]                              │  │
│ └──────────────────────────────────────────────────────────┘  │
│                                                                │
│ ┌─ _modelConfigs ──────────────────────────────────────────┐  │
│ │  find("deepseek-chat")                                   │  │
│ │  └─→ {temperature: 0.7, max_tokens: 2048}              │  │
│ └──────────────────────────────────────────────────────────┘  │
│                                                                │
│ ┌─ LLMManager ─────────────────────────────────────────────┐  │
│ │  sendMessage("deepseek-chat", messages, params)          │  │
│ │  └─→ DeepSeekProvider::sendMessage()                     │  │
│ │      └─→ HTTP POST → DeepSeek API                       │  │
│ │      └─→ 返回 "C++ 是一种通用编程语言..."               │  │
│ └──────────────────────────────────────────────────────────┘  │
│                                                                │
│ ┌─ SessionManager ─────────────────────────────────────────┐  │
│ │  addMessage(sessionId, {role: "assistant", content: "..."})│  │
│ │  └─→ _messages.push_back(assistantMessage)               │  │
│ │  └─→ DataManager::insertMessage → SQLite                │  │
│ │                                                          │  │
│ │  updateSessionTimestamp(sessionId)                        │  │
│ │  └─→ _updateAt = now()                                  │  │
│ │  └─→ DataManager::updateSessionTimestamp                │  │
│ └──────────────────────────────────────────────────────────┘  │
│                                                                │
│ 返回: "C++ 是一种通用编程语言..."                              │
└────────────────────────────────────────────────────────────────┘

4.2 配置缓存的作用

// 初始化时缓存配置
_modelConfigs[modelName] = apiConfig;  // 或 ollamaConfig

// 发送消息时提取参数
auto it = _modelConfigs.find(session->_modelName);
requestParam["temperature"] = std::to_string(it->second->_temperature);
requestParam["max_tokens"] = std::to_string(it->second->_maxTokens);

为什么需要配置缓存

  • Session 对象只保存 modelName,不保存 temperaturemax_tokens
  • 发送消息时需要从 _modelConfigs 查找对应配置
  • 支持不同会话使用不同模型的不同配置

五、设计模式分析

5.1 外观模式(Facade)

ChatSDK 是典型的外观模式实现:

 without Facade                          with Facade
┌───────────────┐                      ┌───────────────┐
│   Client      │                      │   Client      │
└───────┬───────┘                      └───────┬───────┘
        │                                      │
        │ 直接调用多个子系统                     │ 只调用 Facade
        │                                      │
   ┌────┼────┬────────┐                 ┌───────┴───────┐
   ▼    ▼    ▼        ▼                 │   ChatSDK     │
 LLM  Session Data   Provider           │   (Facade)    │
 Mgr  Mgr    Mgr                       └───────┬───────┘
                                              │
                                       ┌──────┼──────┬────────┐
                                       ▼      ▼      ▼        ▼
                                      LLM  Session Data   Provider
                                      Mgr  Mgr    Mgr

好处

  • 简化外部调用:客户端只需调用 ChatSDK,无需了解内部子系统
  • 解耦:客户端与子系统解耦,子系统变化不影响客户端
  • 集中管理:统一的初始化、错误处理、日志记录

5.2 模板方法模式(变体)

sendMessagesendMessageStream 遵循相同的模板方法

1. 初始化检查
2. 获取会话
3. 添加用户消息
4. 获取历史消息
5. 构建请求参数
6. [变化点] 调用模型(全量 / 流式)
7. 添加助手回复
8. 更新时间戳
9. 返回响应

5.3 代理模式

会话管理方法都是代理模式的应用:

// ChatSDK 代理 SessionManager
std::string ChatSDK::createSession(const std::string& modelName)
{
    if(!_initialized) return "";  // 前置检查
    return _sessionManager.createSession(modelName);  // 委托
}

六、ChatSDK 在整体架构中的位置

┌─────────────────────────────────────────────────────────────────────┐
│                          ChatServer (HTTP 层)                       │
│                    ┌─────────────────────────┐                      │
│  请求处理           │  ChatServer 类          │                      │
│                    └────────────┬────────────┘                      │
│                                 │                                    │
└─────────────────────────────────┼────────────────────────────────────┘
                                  │ 调用
                                  ▼
┌─────────────────────────────────────────────────────────────────────┐
│                          SDK 层                                      │
│                    ┌─────────────────────────┐                      │
│                    │  ChatSDK (Facade)       │  ← 统一入口         │
│                    └────────────┬────────────┘                      │
│                                 │                                    │
│              ┌──────────────────┼──────────────────┐               │
│              │                  │                  │               │
│              ▼                  ▼                  ▼               │
│    ┌─────────────────┐  ┌──────────────┐  ┌──────────────────┐    │
│    │  LLMManager      │  │SessionManager│  │  _modelConfigs   │    │
│    │  (模型管理)     │  │ (会话管理)  │  │  (配置缓存)    │    │
│    └────────┬────────┘  └──────┬───────┘  └──────────────────┘    │
│             │                  │                                    │
│             ▼                  ▼                                    │
│    ┌─────────────────┐  ┌──────────────┐                          │
│    │  Providers       │  │ DataManager  │                          │
│    │  (DeepSeek等)    │  │ (SQLite)   │                          │
│    └─────────────────┘  └──────────────┘                          │
│                                                                      │
└──────────────────────────────────────────────────────────────────────┘
                                  │
                                  ▼
┌─────────────────────────────────────────────────────────────────────┐
│                          外部服务                                    │
│         ┌──────────┐  ┌──────────┐  ┌──────────┐  ┌──────────┐    │
│         │ DeepSeek │  │ OpenAI   │  │ Gemini   │  │ Ollama   │    │
│         │ API      │  │ API      │  │ API      │  │ (本地)   │    │
│         └──────────┘  └──────────┘  └──────────┘  └──────────┘    │
└─────────────────────────────────────────────────────────────────────┘

七、总结

维度 说明
角色 SDK 统一入口、协调者(Facade)
核心方法 initModels(初始化)、sendMessage(全量)、sendMessageStream(流式)
设计模式 外观模式(Facade)、代理模式、模板方法模式(变体)
成员组合 LLMManager(模型管理)+ SessionManager(会话管理)+ _modelConfigs(配置缓存)
初始化策略 两阶段:注册 → 初始化
消息发送流程 添加用户消息 → 获取历史 → 调用模型 → 添加助手回复 → 更新时间戳

ChatSDK 的核心价值

  • 简化外部调用:客户端只需调用一个类,无需管理多个子系统
  • 协调完整闭环:从会话管理到模型调用到结果保存,一站式处理
  • 支持多模型:统一接口支持云端 API 和本地 Ollama 模型
  • 流式支持:通过 callback 机制实现流式响应,提升用户体验
Logo

汇聚全球AI编程工具,助力开发者即刻编程。

更多推荐