分享:【AI大模型接入SDK】C++会话管理模块(SessionManager)设计与实现

最近在做优化的时候涉及到了这块内容,觉得值得写下来,方便以后翻阅。

**

🎬 个人主页:艾莉丝努力练剑

❄专栏传送门:《C语言》《数据结构与算法》《C/C++干货分享&学习过程记录
Linux操作系统编程详解》《笔试/面试常见算法:从基础到进阶》《Python干货分享

⭐️为天地立心,为生民立命,为往圣继绝学,为万世开太平


🎬 艾莉丝的简介:

文章目录

1.2 公共数据结构 common.h 1.3 SessionManager 头文件 SessionManager.h 1.4 SessionManager 源文件 SessionManager.cpp1.5 核心技术细节拆解 1.6 常见面试考点 1.7 业务易错坑点总结 结尾

1 ~> C++大模型SDK会话管理模块 SessionManager

核心业务背景:大语言模型本身不会保存会话上下文,所有多轮对话的会话、消息、时间状态必须业务侧手动维护;多线程并发访问会话管理器,必须做线程安全控制。

1.1 会话基础概念

1.1.1 会话定义

  • 会话:用户与大模型之间一组连续交互集合,维护聊天上下文与会话状态,保障多轮对话语义连贯。
  • 核心存储模型:[session_id → Session会话对象]映射关系,实现通过会话 ID 快速定位会话。

1.1.2 会话管理完整业务需求

1. 创建会话:新建对话会话,分配唯一 session_id,绑定对话用的模型名称。
2. 通过 session_id 查询指定会话。
3. 向指定会话追加用户 / 模型消息。
4. 获取指定会话全部历史消息,用于组装给大模型的上下文请求。
5. 获取全部会话 ID 列表,UI 展示历史会话。
6. 删除指定会话。
7. 更新会话最后更新时间戳。
8. 清空全部会话。
9. 获取当前会话总数量。
10. 生成全局唯一会话 ID session_id
11. 生成全局唯一消息 ID message_id
12. 线程安全:多线程并发增删改查会话,互斥锁保护共享资源。

1.2 公共数据结构 common.h

1.2.1 Message 消息结构体

单条聊天消息,存储角色、消息内容、消息唯一 ID。

// common.h
#pragma once
#include

struct Message {
    std::string _messageId;     // 消息唯一ID
    std::string _role;          // 角色:user / assistant / system
    std::string _content;        // 消息文本内容

    Message(const std::string& role, const std::string& content)
        : _role(role), _content(content) {}
};

1.2.2 Session 会话结构体

一个会话对应多组 Message,维护会话元信息与消息列表。

// common.h
#include
#include

struct Session {
    std::string _sessionId;             // 会话唯一ID
    std::string _modelName;             // 当前会话使用的大模型名称
    std::vector _messages;     // 会话内全部消息集合
    std::time_t _createdAt;             // 会话创建时间戳
    std::time_t _updatedAt;             // 会话最后更新时间戳

    explicit Session(const std::string& modelName = "")
        : _modelName(modelName), _createdAt(std::time(nullptr)), _updatedAt(std::time(nullptr)) {}
};

1.3 SessionManager 头文件 SessionManager.h

1.3.1 头文件依赖说明

  • ``:会话哈希存储,O (1) 平均麻烦度查询;相比 map 红黑树,查询性能更高,会话 ID 有序性无业务要求。
  • ``:互斥锁,多线程保护共享会话资源。
  • `std::shared_ptr`智能指针,管理堆上 Session 对象生命周期,规避裸指针风险。
  • ``:原子变量,无锁计数,用于生成会话 ID 序号。
  • ``:时间戳接口。
  • ``:字符串流,拼接格式化 ID 字符串。
  • ``:sort 排序,会话列表按更新时间降序。

1.3.2 完整头文件代码

// sdk/include/SessionManager.h
#pragma once
#include
#include
#include
#include
#include
#include
#include
#include
#include
#include "common.h"

namespace ai_chat_sdk {

class SessionManager {
public:
    // 创建会话,传入模型名称,返回生成的session_id
    std::string createSession(const std::string& modelName);

    // 根据session_id获取会话,返回shared_ptr,不存在返回nullptr;const成员函数
    std::shared_ptr getSession(const std::string& sessionId) const;

    // 向指定会话追加消息;成功返回true,会话不存在返回false
    bool addMessage(const std::string& sessionId, const Message& message);

    // 获取指定会话全部历史消息;会话不存在返回空vector;const
    std::vector getHistoryMessages(const std::string& sessionId) const;

    // 更新会话最后更新时间戳
    void updateSessionTimestamp(const std::string& sessionId);

    // 获取全部会话ID列表,返回的列表按照会话_updatedAt时间戳降序排列;const
    std::vector getSessionLists() const;

    // 删除指定session_id会话;存在删除返回true,不存在返回false
    bool deleteSession(const std::string& sessionId);

    // 清空内存中全部会话
    void clearAllSessions();

    // 获取当前会话总数量;const
    size_t getSessionCount() const;

private:
    // 私有工具:生成会话唯一ID,格式 session_时间戳_8位序号
    std::string generateSessionId();

    // 私有工具:生成消息唯一ID,格式 msg_时间戳_8位序号
    std::string generateMessageId(size_t messageCounter);

private:
    /**
     * 会话存储容器
     * key: session_id字符串
     * value: Session会话对象的shared_ptr,对象分配在堆内存
     * 使用unordered_map哈希表,平均O(1)查询效率
     */
    std::unordered_map _sessions;

    /**
     * mutable修饰互斥锁
     * const成员函数不能修改普通成员变量;
     * 但const方法依然需要加锁解锁修改mutex内部状态,因此使用mutable放开修改权限
     */
    mutable std::mutex _mutex;

    // 原子会话计数器;线程安全自增;用于拼接会话ID序号,初始值0
    std::atomic _sessionCounter{0};
};

} // end namespace ai_chat_sdk

1.3.3 关键设计要点

1. 存储选择unordered_map
不直接存储 Session 对象值:避免 map 容器存储大量大对象带来的拷贝开销;会话对象放到堆内存,智能指针管理生命周期。
2. key 会话 ID 字符串,平均 O (1) 查找。

mutable std::mutex _mutex

1. const 修饰成员函数语义:承诺不修改对象业务数据;
2. 但是锁的 lock/unlock 会修改 mutex 对象内部状态,普通 mutex 无法在 const 函数使用;mutable专门用于这种场景。

std::atomic<int64_t> _sessionCounter

1. 原子变量,无锁线程安全自增,多线程并发创建会话不会出现序号重复。

对外接口全部使用 session_id 操作会话,不暴露内部 Session 对象给外部模块:

1. 降低模块耦合;适配持久化 SQLite 数据库 CURD;避免跨进程传递裸内存指针。

1.4 SessionManager 源文件 SessionManager.cpp

```
// sdk/src/SessionManager.cpp

include "SessionManager.h"


include // std::setw std::setfill

namespace ai_chat_sdk {

// 创建会话
std::string SessionManager::createSession(const std::string& modelName)
{
// lock_guard RAII自动加锁解锁,离开作用域自动释放互斥锁
std::lock_guard lock(_mutex);

// 生成唯一会话ID
std::string sessionId = generateSessionId();

// 在堆上构造Session对象,智能指针接管生命周期
auto session = std::make_shared(modelName);
session->_sessionId = sessionId;

// 存入哈希map
_sessions[sessionId] = session;

return sessionId;
}

// 通过session_id获取会话
std::shared_ptr SessionManager::getSession(const std::string& sessionId) const
{
std::lock_guard lock(_mutex);

auto iter = _sessions.find(sessionId);
if (iter == _sessions.end()) {
return nullptr;
}
return iter->second;
}

// 向会话追加消息
bool SessionManager::addMessage(const std::string& sessionId, const Message& message)
{
std::lock_guard lock(_mutex);

auto iter = _sessions.find(sessionId);
if (iter == _sessions.end()) {
return false;
}

// 当前会话消息数量作为消息序号入参
size_t msgSeq = iter->second->_messages.size();
Message newMsg(message._role, message._content);
newMsg._messageId = generateMessageId(msgSeq);

// 消息追加进会话消息列表
iter->second->_messages.push_back(newMsg);

// 添加消息后更新会话最后修改时间戳
iter->second->_updatedAt = std::time(nullptr);

return true;
}

// 获取会话全部历史消息
std::vector SessionManager::getHistoryMessages(const std::string& sessionId) const
{
std::lock_guard lock(_mutex);

auto iter = _sessions.find(sessionId);
if (iter == _sessions.end()) {
return {};
}
return iter->second->_messages;
}

// 更新会话时间戳
void SessionManager::updateSessionTimestamp(const std::string& sessionId)
{
std::lock_guard lock(_mutex);

auto iter = _sessions.find(sessionId);
if (iter == _sessions.end()) {
return;
}
iter->second->_updatedAt = std::time(nullptr);
}

// 获取会话ID列表,按updatedAt降序(最新会话排在最前面)
std::vector SessionManager::getSessionLists() const
{
std::lock_guard lock(_mutex);

// 临时vector存储 pair
std::vector tempList;
tempList.reserve(_sessions.size());

for (const auto& item : _sessions) {
tempList.emplace_back(item.second->_updatedAt, item.second);
}

// lambda比较器:时间戳降序,大的时间在前
std::sort(tempList.begin(), tempList.end(),
[](const std::pair& a,
const std::pair& b)
{
return a.first > b.first;
});

// 提取排序搞定后的session_id
std::vector resultIds;
resultIds.reserve(tempList.size());
for (const auto& item : tempList) {
resultIds.push_back(item.second->_sessionId);
}
return resultIds;
}

// 删除指定会话
bool SessionManager::deleteSession(const std::string& sessionId)
{
std::lock_guard lock(_mutex);

auto iter = _sessions.find(sessionId);
if (iter == _sessions.end()) {
return false;
}
_sessions.erase(iter);
return true;
}

// 清空全部会话
void SessionManager::clearAllSessions()
{
std::lock_guard lock(_mutex);
_sessions.clear();
}

// 获取会话总数
size_t SessionManager::getSessionCount() const
{
std::lock_guard lock(_mutex);
return _sessions.size();
}

// 生成会话ID 格式: session_时间戳_8位0填充序号
std::string SessionManager::generateSessionId()
{
// 原子变量fetch_add(1)线程安全自增
int64_t seq = _sessionCounter.fetch_add(1, std::memory_order_relaxed);
std::time_t now = std::time(nullptr);

std::ostringstream oss;
oss


就写这么多吧,内容比较基础,适合入门回顾。有补充的地方欢迎留言一起完善。

评论 (0)

暂无评论