C++AI大模型接入SDK---ChatSDK封装
文章目录
项目地址: 橘子师兄/ai-model-acess-tech - Gitee.com
博客专栏:C++AI大模型接入SDK_橘子师兄的博客-CSDN博客
博主首页:橘子师兄-CSDN博客
1、什么是SDK
假设你的电脑在运行时风扇声音特别大,需要清理灰尘,或者玩游戏时比较卡,考虑添加一个内存条。如果要进行上述操作,就需要借助一些专业工具,比如特定螺丝刀、撬棒、镊子、吸盘等,将电脑拆开才能进行后续操作。这些工具一般会放在一个箱子中,该箱子称为工具箱,里面存放各种各样以供使用的工具。

SDK就是程序员的工具箱,Software Develop Kit的缩写,一套帮开发者方便开发特定功能的工具包。比如:
-
微信支付SDK:你只要接入SDK,就能在程序中支持微信支付,不用自己研究支付安全、加密、银
行对接等。
-
相机SDK:使用厂商提供的SDK,就能让APP调用收集摄像头拍照、录像
SDK中通常包含:
-
库文件:被人已经写好的功能,需要实现什么功能直接调用即可。
-
API接口:告诉你该怎么和平台打交道。
-
文档:说明书,告诉你怎么用
-
示例代码:相当于菜谱,照这些就能跑通
-
调试工具:出错时能帮你查问题
也就是说:SDK就是厂商打包好的一套"现成工具+说明书",让开发者可以更快、更安全、更省心地在自己的软件中实现特定功能。
SDK和API的区别:
| 特性 | API | SDK |
|---|---|---|
| 概念 | 一组规则和定义、用于标准化不同软件的交互方式 | 包含API、库、文档、示例代码等的一个全面的工具包 |
| 优势 | 提供与特定服务或系统交互的接口 | 提供了完整的开发环境和工具 |
| 形式 | 接口文档,比如:RESTful API | 一个可本地下载的完整工具包 |
| 关系 | SDK包含API | API是SDK的一部分 |
| 选择 | 如果需要与某个服务进行交互,但不需要开发完整的应用程序 | 需要开发一个完整的应用程序,并且需要一系列工具和资源俩支持开发 |
你想做一道菜(开发应用):
API就像是菜谱,告诉你需要什么食材和步骤。但需要自己准备锅、灶台、刀(相当于你自己要写底层代码)。
SDK则是一个食材配送盒+菜谱,里面不仅有意面、酱料(库文件)、菜谱(API文档),甚至可能附赠一把
锅铲和一个小锅(开发工具和示例代码)
2、ChatSDK代码实现
将模型管理和Session管理结合 起来,为用户提供统一接口。
c++
///////////////////////////// ChatSDK.h
//////////////////////////////////////
#pragma once
#include "LLMManager.h"
#include "common.h"
#include "SessionManager.h"
#include <memory>
#include <string>
#include <ctime>
#include <vector>
namespace ai_chat_sdk {
class ChatSDK {
public:
// 初始化模型
bool initModels(const std::vector<std::shared_ptr<Config>>& configs);
// 创建session
std::string createSession(const std::string& modelName);
// 获取会话
std::shared_ptr<Session> getSession(const std::string& sessionId);
// 获取所有会话列表
std::vector<std::string> getSessionList();
// 删除会话
bool deleteSession(const std::string& sessionId);
// 获取可用模型列表
std::vector<ModelInfo> getAvailableModels();
// 发送消息 - 全量返回
std::string sendMessage(const std::string sessionId, const std::string& message);
// 发送消息 - 流式响应
void sendMessageStream(const std::string sessionId, const std::string& message,
std::function<void(const std::string&, bool)> callback);
private:
// 注册所有模型
void registerAllProvider(const std::vector<std::shared_ptr<Config>>& configs);
// 初始化所有模型提供者
void initProviders(const std::vector<std::shared_ptr<Config>>& configs);
// 初始化模型提供者-通过api调用
bool apiProviderInit(const std::string& modelName,
const std::shared_ptr<ApiConfig>& apiConfig);
// 初始化模型提供者-通过ollama
bool ollamaProviderInit(const std::string& modelName,
const std::shared_ptr<OllamaConfig>& ollamaConfig);
private:
bool _initialized;
std::unordered_map<std::string, std::shared_ptr<Config>> _configs;
LLMManager _llmManager;
SessionManager _sessionManager;
};
} // end ai_chat_sdk
c++
/////////////////////////////// ChatSDK.cpp
//////////////////////////////////////
#include "ChatSDK.h"
#include "ChatGPTProvider.h"
#include "DeepSeekProvider.h"
#include "OllamaDeepSeekProvider.h"
#include "GeminiProvider.h"
#include "../../util/myLog.h"
#include <memory>
#include <string>
#include <unordered_set>
namespace ai_chat_sdk {
// 初始化模型
bool ChatSDK::initModels(const std::vector<std::shared_ptr<Config>>& configs)
{
// 注册所支持模型提供者
registerAllProvider(configs);
// 初始化所有模型
initProviders(configs);
_initialized = true;
return true;
}
// 创建session
std::string ChatSDK::createSession(const std::string& modelName)
{
if (!_initialized) {
ERR("ChatSDK is not initialized!!!");
return "";
}
std::string sessionId = _sessionManager.createSession(modelName);
INFO("create session {} success with model {}!!!", sessionId, modelName);
return sessionId;
}
// 获取会话
std::shared_ptr<Session> ChatSDK::getSession(const std::string& sessionId)
{
return _sessionManager.getSession(sessionId);
}
// 获取所有会话列表
std::vector<std::string> ChatSDK::getSessionList()
{
return _sessionManager.getSessionList();
}
// 删除会话
bool ChatSDK::deleteSession(const std::string& sessionId)
{
bool result = _sessionManager.deleteSession(sessionId);
if (result) {
INFO("delete session {} success!!!", sessionId);
}
return result;
}
// 获取可用模型列表
std::vector<ModelInfo> ChatSDK::getAvailableModels()
{
return _llmManager.getAvailableModel();
}
// 发送消息 - 全量返回
std::string ChatSDK::sendMessage(const std::string sessionId, const std::string& message)
{
if (!_initialized) {
ERR("ChatSDK is not initialized!!!");
return "";
}
// 获取当前会话的session对象
auto session = _sessionManager.getSession(sessionId);
if (!session) {
ERR("sessionId {} not found!!!", sessionId);
return "";
}
// 构建消息并添加至会话
Message userMessage("user", message);
_sessionManager.addMessage(sessionId, userMessage);
// 构建请求参数
auto it = _configs.find(session->model_name);
if (it == _configs.end()) {
ERR("config model {} not found!!!", session->model_name);
return "";
}
std::map<std::string, std::string> requestParams;
requestParams["temperature"] = std::to_string(it->second->temperature);
requestParams["max_tokens"] = std::to_string(it->second->max_tokens);
// 给模型发送请求
// 获取完整历史会话
std::vector<Message> history = _sessionManager.getSessionHistory(sessionId);
std::string response = _llmManager.sendMessage(session->model_name, history, requestParams);
// 添加助手响应并更新会话时间
Message assistantMsg("assistant", response);
_sessionManager.addMessage(sessionId, assistantMsg);
_sessionManager.updateSessionTimestamp(sessionId);
INFO("Message send and response received for session {}, round {}",
sessionId, history.size() / 2 + 1);
return response;
}
// 发送消息 - 流式响应
void ChatSDK::sendMessageStream(const std::string sessionId,
const std::string& message,
std::function<void(const std::string&, bool)> callback)
{
if (!_initialized) {
ERR("ChatSDK is not initialized!!!");
return;
}
// 获取当前会话的session对象
auto session = _sessionManager.getSession(sessionId);
if (!session) {
ERR("sessionId {} not found!!!", sessionId);
return;
}
// 构建消息并添加至会话
Message userMessage("user", message);
_sessionManager.addMessage(sessionId, userMessage);
// 构建请求参数
auto it = _configs.find(session->model_name);
if (it == _configs.end()) {
ERR("config model {} not found!!!", session->model_name);
return;
}
std::map<std::string, std::string> requestParams;
requestParams["temperature"] = std::to_string(it->second->temperature);
requestParams["max_tokens"] = std::to_string(it->second->max_tokens);
// 给模型发送请求
// 获取完整历史会话
std::vector<Message> history = _sessionManager.getSessionHistory(sessionId);
std::string response = _llmManager.sendMessageStream(session->model_name,
history,
requestParams,
callback);
// 添加助手响应并更新会话时间
Message assistantMsg("assistant", response);
_sessionManager.addMessage(sessionId, assistantMsg);
_sessionManager.updateSessionTimestamp(sessionId);
INFO("Message send and response received for session {}, round {}",
sessionId, history.size() / 2 + 1);
}
void ChatSDK::registerAllProvider(const std::vector<std::shared_ptr<Config>>& configs)
{
// 如果模型没有注册,就注册已支持的模型
if (!_llmManager.isModelAvailable("deepseek-chat")) {
auto deepseekProvider = std::make_unique<DeepSeekProvider>();
// unique_ptr 不允许自动类型转换,即使底层指针类型之间存在继承关系。
// unique_ptr 独占资源,不允许赋值和拷贝,虽然DeepSeekProvider和LLMProvider之间存在继承关系,
// 但编译器会认为 unique_ptr<LLMProvider> 与 unique_ptr<DeepSeekProvider>
// 是不同类型,要求模板参数必须明确匹配,禁止了自动类型转换
// 如果允许类型转换,可能会导致多个 unique_ptr 管理同一个对象,而违背 unique_ptr 的独占性
// 由于 registerProvider 的第二个参数是 unique_ptr,此处可以通过move将deepseekProvider
// 转化为右值,利用移动语义将资源转移给 registerProvider 的第二个参数
_llmManager.registerProvider("deepseek-chat", std::move(deepseekProvider));
INFO("register {} provider success!!!", "deepseek-chat");
}
if (!_llmManager.isModelAvailable("gpt-4o-mini")) {
auto gptProvider = std::make_unique<ChatGPTProvider>();
_llmManager.registerProvider("gpt-4o-mini", std::move(gptProvider));
INFO("register {} provider success!!!", "gpt-4o-mini");
}
if (!_llmManager.isModelAvailable("gemini-2.0-flash")) {
auto geminiProvider = std::make_unique<GeminiProvider>();
_llmManager.registerProvider("gemini-2.0-flash", std::move(geminiProvider));
INFO("register {} provider success!!!", "gemini-2.0-flash");
}
// Ollama具体接入那个模型,看用户实际配置的参数,Ollama对不同模型接入时进行二次处理,
// 所以接口时统一的
std::unordered_set<std::string> modelNames;
for (const auto& config : configs) {
// 动态转换为OllamaConfig
// dynamic_cast : 是C++的一种运行时类型转换操作符,主要包含虚函数类继承体系中的向下转型,
// 在运行时会检查是否转化成功
// dynamic_pointer_cast : 是标准库中提供的一个函数,用于shared_ptr 和 weak_ptr之间
// 进行安全的转换,也会在运行时检查转换是否安全
auto ollamaConfig = std::dynamic_pointer_cast<OllamaConfig>(config);
if (ollamaConfig) {
const std::string& modelName = ollamaConfig->model_name;
// 检查模型是否已经存在,存在则已经注册
if (modelNames.find(modelName) == modelNames.end()) {
modelNames.insert(modelName);
// 注册 Ollama 模型
if (!_llmManager.isModelAvailable(modelName)) {
auto ollamaProvider = std::make_unique<OllamaDeepSeekProvider>();
_llmManager.registerProvider(modelName, std::move(ollamaProvider));
INFO("ollama register {} provider success!!!", modelName);
}
}
}
}
}
void ChatSDK::initProviders(const std::vector<std::shared_ptr<Config>>& configs)
{
for (const auto& config : configs) {
if (auto apiConfig = std::dynamic_pointer_cast<ApiConfig>(config)) {
INFO("初始化模型配置信息: modelname - {} apikey - {} temerature - {}",
apiConfig->model_name,
apiConfig->api_key.substr(0, 4),
apiConfig->temperature);
if ((apiConfig->model_name == "deepseeek-chat") ||
(apiConfig->model_name == "gpt-4o-mini") ||
(apiConfig->model_name == "gemini-2.0-flash")) {
apiProviderInit(apiConfig->model_name, apiConfig);
} else {
ERR("不支持的API模型配置类型: {}", apiConfig->model_name);
}
} else if (auto ollamaConfig = std::dynamic_pointer_cast<OllamaConfig>(config)) {
INFO("初始化Ollama DeepSeeek模型配置: modelname - {} endpoint - {}",
ollamaConfig->model_name, ollamaConfig->endpoint);
ollamaProviderInit(ollamaConfig->model_name, ollamaConfig);
} else {
ERR("暂未支持的模型 {}", config->model_name);
}
}
}
// 初始化模型提供者-通过api调用
bool ChatSDK::apiProviderInit(const std::string& modelName,
const std::shared_ptr<ApiConfig>& apiConfig)
{
// 参数检测
if (modelName.empty()) {
ERR("model name is required for ChatSDK!!!");
return false;
}
if (!apiConfig || apiConfig->api_key.empty()) {
ERR("api key is required for ChatSDK!!!");
return false;
}
// 检测模型是否已经注册
if (_llmManager.isModelAvailable(modelName)) {
ERR("{} api model has initialized!!!", modelName);
}
// 初始化模型
std::map<std::string, std::string> modelParams;
modelParams["api_key"] = apiConfig->api_key;
bool initSuccess = _llmManager.initModel(modelName, modelParams);
if (!initSuccess) {
ERR("Failed to init {} model provider with api key", modelName);
return false;
}
// 管理模型配置
_configs[modelName] = apiConfig;
INFO("chat sdk init {} model provider success with api key", modelName);
INFO("Config info: temperature - {}, max_tokens - {}",
apiConfig->temperature, apiConfig->max_tokens);
return true;
}
// 初始化模型提供者-通过ollama
bool ChatSDK::ollamaProviderInit(const std::string& modelName,
const std::shared_ptr<OllamaConfig>& ollamaConfig)
{
// 参数检测
if (modelName.empty()) {
ERR("ollama model name is required for ChatSDK!!!");
return false;
}
if (!ollamaConfig && ollamaConfig->endpoint.empty()) {
ERR("ollama endpoint is required for ChatSDK!!!");
return false;
}
// 检测模型是否已经初始化
if (_llmManager.isModelAvailable(modelName)) {
ERR("ollama {} has initialized!!!", modelName);
return false;
}
// 初始化模型
std::map<std::string, std::string> modelParams;
modelParams["model_name"] = modelName;
modelParams["endpoint"] = ollamaConfig->endpoint;
modelParams["model_desc"] = ollamaConfig->modelDesc;
bool initSuccess = _llmManager.initModel(modelName, modelParams);
if (!initSuccess) {
ERR("Failed to init ollama {} with endpoint {}", modelName, ollamaConfig->endpoint);
return false;
}
_configs[modelName] = ollamaConfig;
INFO("ChatSDK init ollama {} success with endpoint {}", modelName, ollamaConfig->endpoint);
return true;
}
} // end ai_chat_sdk
3、ChatSDK测试
c++
// 测试ChatSDK
TEST(ChatSDKTest, sendMessage) {
auto sdk = std::make_shared<ai_chat_sdk::ChatSDK>();
ASSERT_TRUE(sdk != nullptr);
auto deepseekConfig = std::make_shared<ai_chat_sdk::APIConfig>();
ASSERT_TRUE(deepseekConfig != nullptr);
deepseekConfig->_apiKey = std::getenv("deepseek_apikey");
deepseekConfig->_modelName = "deepseek-chat";
deepseekConfig->_maxTokens = 2048;
deepseekConfig->_temperature = 0.7;
auto gptConfig = std::make_shared<ai_chat_sdk::APIConfig>();
ASSERT_TRUE(gptConfig != nullptr);
gptConfig->_apiKey = std::getenv("chatgpt_apikey");
gptConfig->_modelName = "gpt-4o-mini";
gptConfig->_maxTokens = 2048;
gptConfig->_temperature = 0.7;
auto geminiConfig = std::make_shared<ai_chat_sdk::APIConfig>();
ASSERT_TRUE(geminiConfig != nullptr);
geminiConfig->_apiKey = std::getenv("gemini_apikey");
geminiConfig->_modelName = "gemini-2.0-flash";
geminiConfig->_maxTokens = 2048;
geminiConfig->_temperature = 0.7;
auto ollamaConfig = std::make_shared<ai_chat_sdk::OllamaConfig>();
ASSERT_TRUE(ollamaConfig != nullptr);
ollamaConfig->_modelName = "deepseek-r1:1.5b";
ollamaConfig->_modelDesc = "本地部署deepseek-r1:1.5b模型,采用专家混合架构,"
"专注于深度理解与推理";
ollamaConfig->_endpoint = "http://localhost:11434";
ollamaConfig->_maxTokens = 2048;
ollamaConfig->_temperature = 0.7;
std::vector<std::shared_ptr<ai_chat_sdk::Config>> modelConfigs =
{deepseekConfig, gptConfig, geminiConfig, ollamaConfig};
sdk->initModels(modelConfigs);
std::string sessionId = sdk->createSession(geminiConfig->_modelName);
ASSERT_FALSE(sessionId.empty());
std::string message;
std::cout << ">>>";
std::cin >> message;
std::string response = sdk->sendMessage(sessionId, message);
ASSERT_FALSE(response.empty());
INFO("response : {}", response);
std::cout << ">>>";
std::cin >> message;
response = sdk->sendMessage(sessionId, message);
ASSERT_FALSE(response.empty());
INFO("response : {}", response);
auto historyMessages = sdk->_sessionManager.getHistroyMessages(sessionId);
for (auto& message : historyMessages) {
INFO("{}: {}", message._role, message._content);
}
}
c++
project(testLLM)
# 设置C++标准
set(CMAKE_CXX_STANDARD 17)
set(CMAKE_CXX_STANDARD_REQUIRED ON)
# 设置构建类型Debug
set(CMAKE_BUILD_TYPE Debug)
# 添加可执行文件
add_executable(testLLM
testLLM.cpp
../sdk/src/util/myLog.cpp
../sdk/src/DeepSeekProvider.cpp
../sdk/src/ChatGPTProvider.cpp
../sdk/src/GeminiProvider.cpp
../sdk/src/OllamaLLMProvider.cpp
../sdk/src/SessionManager.cpp
../sdk/src/DataManager.cpp
../sdk/src/ChatSDK.cpp
)
# 设置输出目录
set(EXECUTABLE_OUTPUT_PATH ${CMAKE_BINARY_DIR})
# 添加头文件搜索路径
include_directories(${CMAKE_PROJECT_INCLUDE_DIR}/../sdk/include)
find_package(OpenSSL REQUIRED)
include_directories(${OPENSSL_INCLUDE_DIR})
# 添加CPPHTTPLIB_OPENSSL_SUPPORT定义
target_compile_definitions(testLLM PRIVATE CPPHTTPLIB_OPENSSL_SUPPORT)
# 链接库
target_link_libraries(testLLM
jsoncpp
fmt
spdlog
gtest
OpenSSL::SSL
OpenSSL::Crypto
sqlite3
)
4、编译静态库
在sdk/src目录下创建CMakeLists.txt文件
c++
# CMake 最低版本要求
cmake_minimum_required(VERSION 3.10)
# 设置SDK的名称
set(SDK_NAME "ai_chat_sdk")
# 设置C++标准
set(CMAKE_CXX_STANDARD 17)
set(CMAKE_CXX_STANDARD_REQUIRED ON)
# 设置构建类型
set(CMAKE_BUILD_TYPE Release)
# 收集源文件
file(GLOB_RECURSE SDK_SOURCES "src/*.cpp")
file(GLOB_RECURSE SDK_HEADERS "include/*.h")
# 生成静态库
add_library(${SDK_NAME} STATIC ${SDK_SOURCES} ${SDK_HEADERS})
# 设置输出目录
set(EXECUTABLE_OUTPUT_PATH ${CMAKE_CURRENT_SOURCE_DIR}/build)
# 定义httplib中的CPPHTTPLIB_OPENSSL_SUPPORT宏
target_compile_definitions(${SDK_NAME} PUBLIC CPPHTTPLIB_OPENSSL_SUPPORT)
target_include_directories(${SDK_NAME} PUBLIC ${CMAKE_CURRENT_SOURCE_DIR}/include)
# 设置静态库的目录
link_directories(/usr/local/lib)
find_package(OpenSSL REQUIRED)
include_directories(${OPENSSL_INCLUDE_DIR})
# 添加CPPHTTPLIB_OPENSSL_SUPPORT定义
target_compile_definitions(${SDK_NAME} PRIVATE CPPHTTPLIB_OPENSSL_SUPPORT)
# 链接库
target_link_libraries(${SDK_NAME}
jsoncpp
fmt
spdlog
sqlite3
OpenSSL::SSL
OpenSSL::Crypto
)
# 安装规则 拷贝静态库到系统目录下 /usr/local/lib
install(TARGETS ${SDK_NAME}
ARCHIVE DESTINATION lib
)
# 安装规则 拷贝头文件到系统目录下 /usr/local/include
install(DIRECTORY ${CMAKE_CURRENT_SOURCE_DIR}/include/
DESTINATION include/ai_chat_sdk
FILES_MATCHING PATTERN "*.h"
)
bash
> mkdir build && cd build # 创建 build目录,并进入该目录
> cmake .. #
> make # 编译
> sudo make install # 安装静态库
编译好之后,执行make install会将静态库和头文件安装到/usr/local/lib 和 /usr/local/lib目录下
bit@bit08:~/will/AIModelAcess/ai-model-acess/sdk/build$ sudo make install
[100%] Built target ai_chat_sdk
Install the project...
-- Install configuration: ""
-- Installing: /usr/local/lib/libai_chat_sdk.a
-- Installing: /usr/local/include/ai_chat_sdk
-- Installing: /usr/local/include/ai_chat_sdk/OllamaLLMProvider.h
-- Installing: /usr/local/include/ai_chat_sdk/ILLMProvider.h
-- Installing: /usr/local/include/ai_chat_sdk/OllamaDeepSeekProvider.h
-- Installing: /usr/local/include/ai_chat_sdk/DeepSeekProvider.h
-- Installing: /usr/local/include/ai_chat_sdk/common.h
-- Installing: /usr/local/include/ai_chat_sdk/session_manager.h
-- Installing: /usr/local/include/ai_chat_sdk/LLMManager.h
-- Installing: /usr/local/include/ai_chat_sdk/ChatGPTProvider.h
-- Installing: /usr/local/include/ai_chat_sdk/GeminiProvider.h
-- Installing: /usr/local/include/ai_chat_sdk/chat_sdk.h
bit@bit08:~/will/AIModelAcess/ai-model-acess/sdk/build$ ls /usr/local/lib
libai_chat_sdk.a ollama python3.12
bit@bit08:~/will/AIModelAcess/ai-model-acess/sdk/build$ ls /usr/local/include
ai_chat_sdk
bit@bit08:~/will/AIModelAcess/ai-model-acess/sdk/build$ ls
/usr/local/include/ai_chat_sdk
ChatGPTProvider.h common.h GeminiProvider.h LLMManager.h
OllamaLLMProvider.h
chat_sdk.h DeepSeekProvider.h ILLMProvider.h
OllamaDeepSeekProvider.h session_manager.h