《Linux操作系统编程详解》《笔试/面试常见算法:从基础到进阶》《Python干货分享》
🎬 艾莉丝的简介:
文章目录
- 1 ~> ChatSDK 整体测试概述
- 1.1 测试目标
- 1.2 测试前置条件
- 2 ~> ChatSDK 核心数据结构与接口
- 2.1 模型配置基类与派生配置
- 2.1.1 基类 Config
- 2.1.2 云端 API 模型配置 APIConfig
- 2.1.3 Ollama 本地模型配置 OllamaConfig
- 2.2 ChatSDK 关键成员
- 2.3 核心接口定义
- 2.3.1 模型初始化接口
- 2.3.2 会话管理接口
- 2.3.3 消息发送接口
- 2.4 SessionManager 内部获取历史消息逻辑
- 3 ~> 测试用例实现(testLLM.cpp)
- 3.1 测试整体流程
- 3.2 测试代码片段
- 3.3 CMakeLists.txt 配置要点
- 4 ~> 编译运行流程
- 5 ~> 常见问题分析
- 5.1 Gemini 返回 429 错误 "You exceeded your current quota"
- 5.2 云端模型初始化失败
- 5.3 Ollama 本地模型初始化失败
- 6 ~> 业务流程验证结果
- 6.1 云端模型(DeepSeek 示例)
- 6.2 Ollama 本地 deepseek‑r1:1.5b
- 7 ~> 测试总结与后续工作
- 7.1 测试覆盖
- 7.2 待完成工作
- 结尾
1 ~> ChatSDK 整体测试概述
1.1 测试目标
- 验证
ChatSDK整体流程正确性,间接校验SessionManager会话管理模块、DataManager数据持久化模块(SQLite 存储)功能正常。 - 完成云端 API 模型、本地 Ollama 模型的初始化、会话创建、消息发送、全量应答、历史消息读取完整链路测试。
- 模块依赖关系:
ChatSDK内部组合LLMManager、SessionManager、DataManager,模块之间强耦合。
1.2 测试前置条件
- 编译依赖:gtest 测试框架、spdlog 日志库、openssl、cpp‑httplib、nlohmann‑json、sqlite3。
- 环境变量配置:各类大模型 API‑Key 通过系统环境变量注入,不在代码硬编码密钥。
- Ollama 环境:本地启动 Ollama 服务,默认监听
http://localhost:11434,预先拉取对应本地模型。
2 ~> ChatSDK 核心数据结构与接口
2.1 模型配置基类与派生配置
2.1.1 基类 Config
// 模型公共基础配置structConfig{std::string _modelName;// 模型名称double_temperature=0.7;// 生成随机性温度参数int_maxTokens=2048;// 最大输出token数量virtual~Config()=default;// 虚析构,保障dynamic_pointer_cast向下转型安全};2.1.2 云端 API 模型配置 APIConfig
// 对接云端HTTP API的模型配置,继承ConfigstructAPIConfig:publicConfig{std::string _apikey;// 云端服务API密钥};2.1.3 Ollama 本地模型配置 OllamaConfig
// 对接本地Ollama服务模型配置,继承ConfigstructOllamaConfig:publicConfig{std::string _modelDesc;// 模型描述信息std::string _endpoint;// Ollama服务地址,例:http://localhost:11434};2.2 ChatSDK 关键成员
classChatSDK{private:bool_initialized=false;std::unordered_map<std::string,std::shared_ptr<Config>>_modelConfigs;LLMManager _llmManager;// 测试阶段临时改为public,生产环境必须恢复为privatepublic:SessionManager _sessionManager;};2.3 核心接口定义
2.3.1 模型初始化接口
/** * @brief 批量初始化多个模型 * @param configs 模型配置对象vector容器 * @return 初始化成功返回true */boolChatSDK::initModel(conststd::vector<std::shared_ptr<Config>>&configs){registerAllProvider(configs);// 注册模型提供者initProviders(configs);// 完成模型初始化_initialized=true;returntrue;}registerAllProvider:完成各个模型 Provider 注册,存入LLMManager。initProviders:运行时 RTTI 识别配置实际类型,区分 API 模型 / Ollama 本地模型,分别调用对应初始化函数。
2.3.2 会话管理接口
std::string createSession(const std::string& modelName):基于指定模型创建会话,返回唯一 sessionId。std::vector<Message> getHistoryMessages(const std::string& sessionId):获取会话全部历史消息。
2.3.3 消息发送接口
- 全量返回:
std::string sendMessage(const std::string& sessionId, const std::string& userInput),阻塞等待完整模型应答返回。 - 流式返回:
sendMessageStream(会话ID,输入消息,回调函数),分片通过回调返回模型输出,回调参数chunk为分片字符串,last标记是否为最后一片。
2.4 SessionManager 内部获取历史消息逻辑
/** * @brief 获取会话历史消息,优先读取内存缓存,缓存缺失读取SQLite数据库 * @param sessionId 会话唯一标识 * @return 会话全部消息vector */std::vector<Message>SessionManager::getHistoryMessages(conststd::string&sessionId)const{_mutex.lock();autoit=_sessions.find(sessionId);if(it!=_sessions.end()){_mutex.unlock();returnit->second->_messages;}_mutex.unlock();// 内存中不存在该会话,从sqlite数据库加载消息return_dataManager.getSessionMessages(sessionId);}- 线程安全:访问内存会话哈希表必须加互斥锁保护。
- 数据读取策略:内存优先,内存未命中回落到持久层 SQLite。
3 ~> 测试用例实现(testLLM.cpp)
3.1 测试整体流程
- 初始化 spdlog 日志库。
- 初始化 gtest 测试框架。
- 构造多个模型配置对象(DeepSeek、GPT‑4o‑mini、Gemini、Ollama‑deepseek‑r1:1.5b)。
- 将配置装入
vector<std::shared_ptr<Config>>,调用sdk->initModels()完成批量初始化。 - 调用
createSession创建会话,获取 sessionId。 - 循环读取控制台用户输入,调用
sendMessage发送消息。 - 通过
_sessionManager读取会话历史消息,打印角色 + 消息内容。 - 断言校验:SDK 实例非空、sessionId 非空、应答字符串非空、历史消息非空。
3.2 测试代码片段
TEST(ChatSDKTest,sendMessage){autosdk=std::make_shared<ai_chat_sdk::ChatSDK>();ASSERT_TRUE(sdk!=nullptr);// ========== 1.构造云端DeepSeek配置 ==========autodeepseekConfig=std::make_shared<ai_chat_sdk::APIConfig>();ASSERT_TRUE(deepseekConfig!=nullptr);deepseekConfig->_modelName="deepseek‑chat";deepseekConfig->_apikey=std::getenv("deepseek_apikey");ASSERT_FALSE(deepseekConfig->_apikey.empty());deepseekConfig->_temperature=0.7;deepseekConfig->_maxTokens=2048;// ========== 2.构造GPT‑4o‑mini配置 ==========autogpt4oConfig=std::make_shared<ai_chat_sdk::APIConfig>();ASSERT_TRUE(gpt4oConfig!=nullptr);gpt4oConfig->_modelName="gpt‑4o‑mini";gpt4oConfig->_apikey=std::getenv("chatgpt_apikey");ASSERT_FALSE(gpt4oConfig->_apikey.empty());gpt4oConfig->_temperature=0.7;gpt4oConfig->_maxTokens=2048;// ========== 3.构造Gemini配置 ==========autogeminiConfig=std::make_shared<ai_chat_sdk::APIConfig>();ASSERT_TRUE(geminiConfig!=nullptr);geminiConfig->_modelName="gemini‑2.0‑flash";geminiConfig->_apikey=std::getenv("gemini_apikey");ASSERT_FALSE(geminiConfig->_apikey.empty());geminiConfig->_temperature=0.7;geminiConfig->_maxTokens=2048;// ========== 4.构造Ollama本地模型配置 ==========autoollamaConfig=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->_temperature=0.7;ollamaConfig->_maxTokens=2048;// 将全部配置装入vector,交给SDK初始化std::vector<std::shared_ptr<ai_chat_sdk::Config>>modelConfigs={deepseekConfig,gpt4oConfig,geminiConfig,ollamaConfig};ASSERT_TRUE(sdk->initModel(modelConfigs));// 创建会话,可以切换为ollamaConfig->_modelName测试本地模型std::string sessionId=sdk->createSession(deepseekConfig->_modelName);ASSERT_FALSE(sessionId.empty());// 循环读取控制台输入,交互测试std::string message;std::cout<<">>>";std::getline(std::cin,message);autoresponse=sdk->sendMessage(sessionId,message);ASSERT_FALSE(response.empty());std::cout<<">>>";std::getline(std::cin,message);response=sdk->sendMessage(sessionId,message);ASSERT_FALSE(response.empty());// 获取会话历史消息automessages=sdk->_sessionManager.getHistoryMessages(sessionId);ASSERT_FALSE(messages.empty());for(constauto&msg:messages){std::cout<<msg._role<<":"<<msg._content<<std::endl;}}intmain(intargc,char**argv){// 初始化日志,输出到stdout,日志等级debugbite::Logger::initLogger("testLLM","stdout",spdlog::level::debug);// gtest初始化testing::InitGoogleTest(&argc,argv);// 执行所有测试用例returnRUN_ALL_TESTS();}3.3 CMakeLists.txt 配置要点
cmake_minimum_required(VERSION3.10)project(testLLM)set(CMAKE_CXX_STANDARD17)set(CMAKE_CXX_STANDARD_REQUIRED ON)set(CMAKE_BUILD_TYPE Debug)# 编译生成测试可执行文件testLLM,汇总全部SDK源码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/DataManager.cpp../sdk/src/SessionManager.cpp../sdk/src/LLMManager.cpp../sdk/src/ChatSDK.cpp)set(EXECUTABLE_OUTPUT_PATH${CMAKE_BINARY_DIR})# 头文件搜索路径include_directories(${CMAKE_PROJECT_INCLUDE_DIR}/../sdk/include)# OpenSSL依赖find_package(OpenSSL REQUIRED)include_directories(${OPENSSL_INCLUDE_DIR})# 开启cpp‑httplib的openssl支持target_compile_definitions(testLLM PRIVATE CPPHTTPLIB_OPENSSL_SUPPORT)# 链接库:gtest、spdlog、openssl、sqlite3等target_link_libraries(testLLM gtest gtest_main spdlog OpenSSL::SSL OpenSSL::Crypto sqlite3)- 必须链接
sqlite3库,DataManager依赖 SQLite 数据库做会话持久化。 - 定义宏
CPPHTTPLIB_OPENSSL_SUPPORT开启 http‑lib 的 HTTPS 能力,云端模型 API 均使用 HTTPS 协议。
4 ~> 编译运行流程
- 创建 build 构建目录,进入 build 文件夹。
cmake ..:解析 CMakeLists 生成 Makefile 构建脚本。make:编译全部源码生成testLLM可执行程序。- 执行
./testLLM运行 gtest 测试用例。 - 运行后会在当前目录生成
chatDB.dbsqlite 数据库文件,存储会话、消息持久化数据。
注意:编译成功仅代表语法无错误,必须运行测试验证业务逻辑正确性。
5 ~> 常见问题分析
5.1 Gemini 返回 429 错误 “You exceeded your current quota”
- 根因:Google Gemini 免费额度耗尽。
- 背景:Google 提供免费 token 配额,存在上限;耗尽后需要付费。Google Cloud 付费验证仅支持境外银行卡,国内实体卡无法完成身份校验;市面虚拟卡会触发风控校验失败(错误码
OR_BACR2_44),极易封号。 - 解决方案:
- 使用新的有效付费 API‑Key;
- 环境变量更新:
vim ~/.bashrc设置新环境变量,执行source ~/.bashrc使环境变量生效; - 代码读取更新后的环境变量。
- 风险提示:第三方倒卖 API‑Key 存在中间人转发劫持风险,用户对话明文会被中间人窃取,生产环境禁止使用非官方中转服务。
5.2 云端模型初始化失败
- 排查方向:
- API‑Key 环境变量是否正确导出,
std::getenv读取是否为空; - 网络连通性:GPT/Gemini 需要代理网络;DeepSeek 国内网络可直连;
- 端点 base_url 是否配置正确,不要硬编码,代码配置可兼容服务商地址变更。
- API‑Key 环境变量是否正确导出,
5.3 Ollama 本地模型初始化失败
- 确认 Ollama 服务启动,端口 11434 监听正常;
- 确认本地已经 pull 对应模型,模型名称和配置中
_modelName严格一致; - endpoint 填写
http://localhost:11434。
6 ~> 业务流程验证结果
6.1 云端模型(DeepSeek 示例)
完整链路:
- SDK 初始化成功,Provider 注册;
- SQLite 数据库打开;
- 创建会话,会话写入数据库;
- 用户输入消息,消息存入内存
Session对象,同时持久化写入 SQLite; - SDK 组装包含完整上下文历史的 HTTP 请求发送云端 API;
- 获取 200 应答,模型返回结果;
- 助手回复存入内存会话,写入 SQLite;
- 读取历史消息,可以拿到多轮对话完整上下文;
- 下一轮请求自动携带全部历史消息给大模型,实现多轮对话记忆。
6.2 Ollama 本地 deepseek‑r1:1.5b
- 整体流程和云端模型完全一致;
- HTTP 请求发送至本地 Ollama 服务,不走公网;
- Ollama 完成模型推理,返回应答给 SDK;
- 会话、消息存储逻辑与云端模型完全复用同一套
SessionManager+DataManager。
7 ~> 测试总结与后续工作
7.1 测试覆盖
- 测试两类接入方式:云端 API 接入、本地 Ollama 接入;
- 覆盖功能点:模型注册初始化、会话创建、多轮消息交互、内存缓存会话、SQLite 持久化、历史消息读取;
- 验证模块协同:
ChatSDK、LLMManager、SessionManager、DataManager协同工作正常。
7.2 待完成工作
- 封装 Web Demo,提供网页聊天界面,调用 ChatSDK 完成对话。
- 补充流式返回场景完整测试用例。
- 测试结束将
SessionManager访问权限恢复为private,禁止外部直接访问内部成员。 - 补充异常用例:非法 sessionId、空 API‑Key、网络断开、模型不存在等边界场景测试。
结尾
uu们,本文的内容到这里就全部结束了,艾莉丝在这里再次感谢您的阅读!
|
结语:希望对学习Linux相关内容的uu有所帮助,不要忘记给博主“一键四连”哦!
往期回顾:
【AI大模型接入SDK】ChatSDK整体实现
🗡博主在这里放了一只小狗,大家看完了摸摸小狗放松一下吧!🗡 ૮₍ ˶ ˊ ᴥ ˋ˶₎ა