【AI大模型接入SDK】 —— 模型管理 会话管理

发布时间:2026/9/15 8:26:45

【AI大模型接入SDK】 —— 模型管理  会话管理 欢迎来到实战项目专栏 ~~ 从零实现AI大模型接入SDK博客主页张小姐的猫~江湖背景所属专栏C项目 ~ AI大模型接入SDK作者水平很有限如果发现错误可在评论区指正感谢AI大模型接入SDK欢迎来到实战项目专栏 ~~ 从零实现AI大模型接入SDK 模型管理 会话管理会话介绍会话管理数据结构设计会话实现写在最后 模型管理现在deepseek-chat、gpt-5.6-sol 、gemini-3.7-flash模型已经接入成功每个模型都对应单独的Provider类为了后续使用简单再封装⼀个LLMManager类将模型管理起来后续通过多态的方式实现模型路由LLMManager.h 的实现#pragmaonce#includeLLMProvider.h#includemap#includememorynamespaceai_chat_sdk{classLLMManager{public://注册LLM提供者voidregisterProvider(conststd::unique_ptrLLMProviderprovider);//初始化指定模型boolinitModel(conststd::stringmodelName,conststd::mapstd::string,std::stringmodelParams);//获取可用的模型std::vectorLLMInfogetAvailableModels()const;//检测模型是否可用boolisModelAvailable(conststd::stringmodelName)const;//发送全量信息给指定模型 (模型名历史消息请求参数)std::stringsendMessage(conststd::stringmodelName,conststd::vectorMessagemessages,conststd::mapstd::string,std::stringrequestParams);//发送流式信息给指定模型std::stringsendMessageStream(conststd::stringmodelName,conststd::vectorMessagemessages,conststd::mapstd::string,std::stringrequestParams,std::functionvoid(conststd::string,bool)callback);private://key:模型名称, value: 模型提供器 ~ 基类的指针std::mapstd::string,std::unique_ptrLLMProviderproviders;//key:模型名称, value: 模型信息std::mapstd::string,LLMInfomodelInfos;};}LLMManager.cpp 的实现#include../include/util/LLMManager.h#include../include/util/myLog.h#include../include/util/Common.hnamespaceai_chat_sdk{//注册LLM提供者boolLLMManager::registerProvider(conststd::stringmodelName,std::unique_ptrLLMProviderprovider){//参数检测if(!provider){ERR(can not register a null provider, modelname {},modelName);returnfalse;}//因为unique_ptr是不允许赋值的, 但是可以进行移动构造//std::move把一个左值强制转成右值引用说明不再需要这个对象了_providers[modelName]std::move(provider);//添加模型信息_modelInfos[modelName]LLMInfo(modelName);//模型初始化成功INFO(register provider success, modelname {},modelName);returntrue;}//初始化指定模型boolLLMManager::initModel(conststd::stringmodelName,conststd::mapstd::string,std::stringmodelParams){//检测模型是否注册了autoit_providers.find(modelName);if(it_providers.end()){ERR(model not registered, modelname {},modelName);returnfalse;}//模型注册成功,可以开始初始化了 ———— 调用模型自己的initModel方法boolisSuccessit-second-initModel(modelParams);if(!isSuccess){ERR(model init failed, modelname {},modelName);}else{INFO(model init success, modelname {},modelName);_modelInfos[modelName]._modelDescit-second-getModelDesc();_modelInfos[modelName]._isAvailabletrue;}returnisSuccess;}//获取可用的模型std::vectorLLMInfoLLMManager::getAvailableModels()const{std::vectorLLMInfoavailableModels;// 可用的模型数组for(constautopair:_modelInfos){// 遍历所有模型信息if(pair.second._isAvailable){// 如果模型可用availableModels.push_back(pair.second);// 添加到可用模型数组}}returnavailableModels;}//检测模型是否可用boolLLMManager::isModelAvailable(conststd::stringmodelName)const{autoit_modelInfos.find(modelName);if(it_modelInfos.end()){returnfalse;}returnit-second._isAvailable;// 返回模型是否可用}//发送全量信息给指定模型 (模型名历史消息请求参数)std::stringLLMManager::sendMessage(conststd::stringmodelName,conststd::vectorMessagemessages,conststd::mapstd::string,std::stringrequestParams){//检测模型是否注册了autoit_providers.find(modelName);if(it_providers.end()){ERR(model not registered, modelname {},modelName);return;}//检测模型是否可用if(!it-second-isAvailable()){ERR(model not available, modelname {},modelName);return;}//模型注册并且可用,发送消息returnit-second-sendMessage(messages,requestParams);}std::stringLLMManager::sendMessageStream(conststd::stringmodelName,conststd::vectorMessagemessages,conststd::mapstd::string,std::stringrequestParams,std::functionvoid(conststd::string,bool)callback){//检测模型是否注册了autoit_providers.find(modelName);if(it_providers.end()){ERR(model not registered, modelname {},modelName);return;}//检测模型是否可用if(!it-second-isAvailable()){ERR(model not available, modelname {},modelName);return;}//模型注册并且可用,发送消息returnit-second-sendMessageStream(messages,requestParams,callback);return;}} 会话管理假设现在借助LLMManager搭建⼀个大模型后端服务用户和模型进行了多轮会话每个会话中都包含了好多条消息在某个会话中和模型聊天的多轮消息该如何管理多个会话该如何管理解决该问题的⼀种方式是引入Session每次和模型开启新一轮聊天都可以看成是一次会话。在一次会话中会和模型进行多次聊天这些聊天信息可以保存在本次会话中除了保存会话信息外还需要保存模型名称、会话创建时间等都需要保存会话介绍会话是用户与大语言模型之间的⼀系列连续交互它通过维护上下⽂和状态信息确保对话的连贯性和⼀致性。由于大模型不会为用户管理会话信息因此需要程序员手动完成会话管理会话管理涉及以下内容注意会话管理模块会保存所有的会话在同一时刻可能会对多个会话进行操作因此创建会话、更新会话、删除会话等时需要考虑线程安全问题会话管理数据结构设计//会话信息structSession{std::string _sessionId;//会话IDstd::string _modelName;//模型名称std::vectorMessage_messages;//会话中的消息列表std::time_t _updatedAt;//会话最后更新时间戳std::time_t _createdAt;//会话创建时间戳//构造函数Session()default;Session(conststd::stringmodelName)//创建时间是要我们创建会话时填入:_modelName(modelName){}};会话实现SessionManager.h实现实现有个细节有几个函数是设置成const只读函数的但是为了保证线程安全仍需要加锁mutable修饰锁即使在 const 函数中也可以被修改加锁/解锁而其他成员变量仍然受 const 保护不会被意外修改#pragmaonce#includeatomic#includemutex#includememory#includeunordered_map#includeCommon.hnamespaceai_chat_sdk{classSessionManager{public://创建会话提供模型返回会话idstd::stringcreateSession(conststd::stringmodelName);//通过会话id获取会话信息std::shared_ptrSessiongetSession(conststd::stringSessionId)const;//往某个会话中添加消息booladdMessage(conststd::stringSessionId,constMessagemessage);//获取某个会话的所有历史信息std::vectorMessagegetHistoryMessages(conststd::stringSessionId)const;//更新会话的时间戳voidupdateSessionTimestamp(conststd::stringSessionId);//获取所有会话列表std::vectorstd::stringgetSessionLists()const;//删除某个会话booldelteSession(conststd::string sessionId);//清空所有会话voidclearAllSessions();//获取会话总数size_tgetSessionCount()const;private:std::stringgenerateSessionId();//生成会话idstd::stringgenerateMessageId(size_t messageCount);//生成消息idprivate://管理所有会话信息key会话idvalue会话信息std::unordered_mapstd::string,std::shared_ptrSession_sessions;mutablestd::mutex _mutex;//表明在当前成员变量_mutex在const成员函数当中也是允许被修改的std::atomicint64_t_sessionCounter{0};//记录所有会话的总数};}SessionManager.cpp实现fetch_add_sessionCounter— 是类的成员变量被多个线程共享所以需要 std::atomic 保证线程安全一般在调用generateMessageId前就已经是加过锁了所以这里不需要原子操作创建会话是用智能指针去进行管理的避免会话太多时数据过大往会话中添加消息因为message是const的不能修改其_messageId所以要创建一个复制体来更新其_messageId//生成会话id 格式session_时间戳_会话计数std::stringSessionManager::generateSessionId(){_sessionCounter.fetch_add(1);//原子操作会话计数加1std::time_t timestd::time(nullptr);//获取当前时间戳std::ostringstream oss;//字符串流写入将数据拼接成字符串// session_1672531200_0001设置会话计数的宽度为4不足4位的用0填充osssession_time_std::setw(4)std::setfill(0)_sessionCounter;returnoss.str();}//生成消息idstd::stringSessionManager::generateMessageId(size_t messageCount){messageCount;std::time_t timestd::time(nullptr);//格式同上std::ostringstream oss;ossmsg_time_std::setw(4)std::setfill(0)messageCount;returnoss.str();}//创建会话提供模型返回会话idstd::stringSessionManager::createSession(conststd::stringmodelName){std::lock_guardstd::mutexlock(_mutex);//生成会话idstd::string sessionIdgenerateSessionId();//创建会话设置会话id、模型名称autosessionstd::make_sharedSession(modelName);session-_sessionIdsessionId;//加入到会话列表_sessions[sessionId]session;returnsessionId;}//通过会话id获取会话信息std::shared_ptrSessionSessionManager::getSession(conststd::stringsessionId)const{std::lock_guardstd::mutexlock(_mutex);autoit_sessions.find(sessionId);if(it_sessions.end()){returnnullptr;}returnit-second;}//往某个会话中添加消息boolSessionManager::addMessage(conststd::stringsessionId,constMessagemessage){std::lock_guardstd::mutexlock(_mutex);//通过会话id获取会话信息autoit_sessions.find(sessionId);if(it_sessions.end()){returnfalse;}//添加消息 —— 因为message是const的不能修改其_messageIdMessagemsg(message._role,message._content);msg._messageIdgenerateMessageId(it-second-_messages.size());//消息添加到会话中it-second-_messages.push_back(msg);//添加消息it-second-_updatedAtstd::time(nullptr);//更新会话时间戳INFO(Add message to session successfully: message_id {}, message_content {},msg._messageId,msg._content);returntrue;}//获取某个会话的所有历史信息std::vectorMessageSessionManager::getHistoryMessages(conststd::stringsessionId)const{std::lock_guardstd::mutexlock(_mutex);autoit_sessions.find(sessionId);if(it_sessions.end()){return{};}returnit-second-_messages;}//更新会话的时间戳voidSessionManager::updateSessionTimestamp(conststd::stringsessionId){std::lock_guardstd::mutexlock(_mutex);autoit_sessions.find(sessionId);if(it_sessions.end()){return;}it-second-_updatedAtstd::time(nullptr);}获取会话列表实现获取所有会话列表, 实际返回的是所有会话的会话id能否直接返回会话的对象呢可以的但是不够友好原因如下直接返回会话对象在返回时候会增加内存拷贝的开销影响程序的运行效率SessionManager中基本都是通过会话id来操作对应的会话对象的如果要返回会话对象的话其他模块就要对会话对象进行操作SessionManager和其他模块的耦合度增加不便于后期维护所以返回会话对象不友好并且会话信息存储在sqlite中获取会话历史消息、删除会话等都是通过会话id来进行的因此返回会话id更利于CURD返回会话id会更好注意在返回的这里会话id中最好将会话按照更新的时间戳进行降序排列更加关心最近的聊天//获取所有会话列表, 实际返回的是所有会话的会话idstd::vectorstd::stringSessionManager::getSessionLists()const{std::lock_guardstd::mutexlock(_mutex);//构造一个临时的会话列表将其内容按照更新时间降序排列std::vectorstd::pairstd::time_t,std::shared_ptrSessiontemp;temp.reserve(_sessions.size());//将所有会话信息复制到临时会话列表中for(constautopair:_sessions){temp.emplace_back(pair.second-_updatedAt,pair.second);}//按照更新时间降序排列自定义比较器std::sort(temp.begin(),temp.end(),[](constautoa,constautob){returna.firstb.first;});std::vectorstd::stringsessionList;sessionList.reserve(temp.size());for(constautopair:temp){sessionList.push_back(pair.second-_sessionId);}returnsessionList;}剩下的函数实现 删除会话、清理会话、获取会话总数//删除会话boolSessionManager::delteSession(conststd::string sessionId){std::lock_guardstd::mutexlock(_mutex);autoit_sessions.find(sessionId);if(it_sessions.end())returnfalse;_sessions.erase(it);returntrue;}//清空所有会话voidSessionManager::clearAllSessions(){std::lock_guardstd::mutexlock(_mutex);_sessions.clear();}//获取会话总数size_tSessionManager::getSessionCount()const{std::lock_guardstd::mutexlock(_mutex);return_sessions.size();}写在最后接下来登场的是
延伸阅读

更多相关文章

2026/9/15 8:26:45

PDF加密;PDF文件加密解密;PDF加密技巧;文件加密

当你需要将一份PDF文件发给他人查阅,但又不想让对方打印出来时,PDF自带的“权限密码”功能就能派上用场。通过设置打印限制,你可以精准控制文档的使用权限——允许对方在屏幕上阅读,但禁止打印输出,从而有效防止敏感信…

2026/9/15 8:21:45

【MATLAB代码】二维A*路径规划与AOA测角定位仿真,完整源代码,订阅专栏后可直接查看

如需帮助,或有导航、定位滤波相关的代码定制需求,可从个人主页左侧联系我 订阅专栏后,可直接查看源代码,粘贴到MATLAB空脚本中即可直接运行、得到结果 文章目录 运行结果 真实截图 MATLAB源代码 程序详解 概览 路径规划模型 量测模型 运行结果 运行程序后,程序会完成二维…

2026/9/15 8:36:47

AI能测试还需要测试人员吗

一、核心结论:仍然必须有测试人员参与,角色从执行转向管控 在「AI写代码 AI做单元/集成测试 AI修bug验证」的模式下,测试人员不仅不能缺席,其质量守门人的核心价值反而更加重要。 完全脱离人工的AI测试会陷入自证正确性陷阱&…

2026/9/15 8:36:47

如何整理项目信息,写出高质量技术博文?

/* MD / 富文本中的 .toc(含博客园搬家等嵌套结构);.toc-box 在侧栏,不受影响 */#content_views .toc,/* 编辑器常在目录前后插入空 p(:empty 仍占 20px),一并去掉避免顶空隙 */#content_views.markdown_views > p:empty:has(+ .toc),#content_views.markdown_views …

2026/9/15 8:36:47

储能参与调峰的配置方案及经济性分析Matlab复现实战

/* MD / 富文本中的 .toc(含博客园搬家等嵌套结构);.toc-box 在侧栏,不受影响 */#content_views .toc,/* 编辑器常在目录前后插入空 p(:empty 仍占 20px),一并去掉避免顶空隙 */#content_views.markdown_views > p:empty:has(+ .toc),#content_views.markdown_views …

2026/9/15 8:36:47

PHP开发者生存地图:从环境搭建到安全攻防的实战指南

/* MD / 富文本中的 .toc(含博客园搬家等嵌套结构);.toc-box 在侧栏,不受影响 */#content_views .toc,/* 编辑器常在目录前后插入空 p(:empty 仍占 20px),一并去掉避免顶空隙 */#content_views.markdown_views > p:empty:has(+ .toc),#content_views.markdown_views …

2026/9/15 8:36:47

RPA选型避坑指南:实施、售后与培训的隐形成本拆解

/* MD / 富文本中的 .toc(含博客园搬家等嵌套结构);.toc-box 在侧栏,不受影响 */#content_views .toc,/* 编辑器常在目录前后插入空 p(:empty 仍占 20px),一并去掉避免顶空隙 */#content_views.markdown_views > p:empty:has(+ .toc),#content_views.markdown_views …

2026/9/15 8:31:46

灰狼优化算法自动调优SVM参数:从原理到MATLAB实现

/* MD / 富文本中的 .toc(含博客园搬家等嵌套结构);.toc-box 在侧栏,不受影响 */#content_views .toc,/* 编辑器常在目录前后插入空 p(:empty 仍占 20px),一并去掉避免顶空隙 */#content_views.markdown_views > p:empty:has(+ .toc),#content_views.markdown_views …

2026/9/15 4:54:30

拯救者Y7000黑屏故障排查与维修实战指南

1. 项目概述:一台黑屏的拯救者Y7000,到底卡在哪一步? 联想拯救者Y7000系列笔记本,从2018年第一代搭载i5-8300H开始,到后来的i7-9750H、i7-10750H、i5-11400H,再到2023年款的R7-7840HS,它始终是学…

2026/9/15 0:01:16

AI英语单词APP开发:自适应学习算法与移动端优化实践

1. 项目概述 作为一名在移动应用开发领域摸爬滚打多年的老手,我最近完成了一个AI英语单词APP的开发项目。这个项目将传统单词记忆方法与现代AI技术相结合,打造了一款能够智能适应不同用户学习习惯的英语学习工具。 市面上大多数单词APP都存在一个通病&a…

2026/9/15 0:01:16

Flutter与OpenHarmony结合开发手语学习APP实战

1. 项目背景与核心价值作为一名同时接触过Flutter和OpenHarmony的开发者,最近我完成了一个基于Flutter for OpenHarmony的手语学习APP实战项目。这个项目最大的特点在于实现了跨平台框架与国产操作系统深度结合的创新实践——用Flutter开发的应用能完美运行在OpenHa…

2026/9/15 0:01:16

六个月成为机器人工程师:从ROS2到SLAM的实战路径

1. 六个月的紧迫感从哪来:先搞清楚你要成为哪种机器人工程师说实话,六个月的期限并不是一个宽松的时间线。市面上任何一本正经的机器人学教材都超过五百页,ROS2的官方文档可以翻到你怀疑人生,再加上ABB、KUKA这些工业机器人厂家动…

2026/9/14 11:59:31

USB Type-C PCB布局分区设计:电源、高速信号与PD协议全攻略

做硬件这行,Type-C接口算是典型的“看着简单,做起来全坑”的东西。光引脚就24个,高低速信号、电源、控制线全部塞在一个小小的连接器里,如果PCB布局不做规划,打样回来基本就是“插上没反应”、“高速掉线”、“静电一打…

2026/9/14 13:53:59

系统编程学习原型如何补齐稳定性边界

系统编程学习原型如何补齐稳定性边界预算有限时&#xff0c;我先优化明显多余的复制&#xff0c;而不是猜测性地换容器。用借用传递只读数据通常就能减少分配&#xff1a; fn parse(line: &str) -> Result<Item, Error> { /* ... */ }用基准确认热点确实在分配&am…

2026/9/14 11:22:57

雨花区哪家财务公司代理记账比较好?

在雨花区&#xff0c;企业处理财税事务常常面临诸多挑战&#xff0c;选择一家靠谱的财务公司至关重要。湖南巨勤财务管理咨询有限公司就是本地正规实体财税服务机构&#xff0c;深耕本地工商财税行业多年&#xff0c;熟悉当地工商局、税务局最新政策与申报流程。主营公司注册、…

还想了解更多?直接咨询顾问

免费诊断 + 免费方案 + 透明报价。

全国咨询热线400-8866-253
免费获取方案
咨询二维码