AI大模型接入SDK—SDK设计
·
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保存配置,发送消息时用于提取temperature和max_tokensLLMManager和SessionManager是值成员,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,不保存temperature和max_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 模板方法模式(变体)
sendMessage 和 sendMessageStream 遵循相同的模板方法:
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 机制实现流式响应,提升用户体验
更多推荐




所有评论(0)