【AI大模型接入SDK】 —— 数据管理 & 与Session模块进行联动

🌈欢迎来到实战项目专栏 ~~ 从零实现AI大模型接入SDK

AI大模型接入SDK

🌏数据管理模块设计

接下来将会话信息 和与模型聊天的数据 持久化存储到SQLite数据库,存储时需要注意线程安全问题

  • 注意有一些操作会涉及到SessionMessage两个表格的关联变化
cpp 复制代码
#pragma once
#include <memory>
#include <sqlite3.h>
#include <string>
#include <mutex>
#include <iostream>
#include "Common.h"


namespace ai_chat_sdk {

class DataManager {
public:
    DataManager(const std::string& dbName);
    ~DataManager();

    //Session相关操作
    //1.插入新会话
    bool insertSession(const Session& session);

    //2.获取指定会话信息
    std::shared_ptr<Session> getSession(const std::string& sessionId) const;

    //3.更新会话时间戳
    bool updateSessionTimestamp(const std::string& sessionId, std::time_t timestamp);

    //4.删除会话:也要删除会话中的所有消息
    bool deleteSession(const std::string& sessionId);

    //5.获取所有会话id
    std::vector<std::string> getAllSessionIds() const;

    //6.获取所有会话信息
    std::vector<std::shared_ptr<Session>> getAllSessions() const;

    //7.获取会话总数
    int getSessionCount() const;

    //Message相关操作
    //1.插入新消息:插入消息时,要更新会话时间戳
    bool insertMessage(const std::string& sessionId, const Message& message);

    //2.获取指定会话的历史消息
    std::vector<std::shared_ptr<Message>> getMessages(const std::string& sessionId) const;

    //3.删除指定会话中的所有消息
    bool deleteMessages(const std::string& sessionId);

private:
    //初始化数据库
    bool initDatabase();
    //执行SQL语句的工具函数
    bool executeSQL(const std::string& sql);
private:
    sqlite3* _db = nullptr;
    std::string _dbName = "";
    mutable std::mutex _mutex; // 在const函数中对锁进行操作
};

}

🌏数据管理模块实现

🔥构造 & 析构 & 初始化 & 执行语句

重点关注:初始化表里消息表的创建

cpp 复制代码
FOREIGN KEY (session_id) REFERENCES sessions (session_id) ON DELETE CASCADE
部分 含义 在本项目中的作用
FOREIGN KEY (session_id) 声明当前表(messages)的 session_id 列为外键 建立 messages 表与 sessions 表之间的关联关系
REFERENCES sessions (session_id) 该外键指向 sessions 表的 session_id 主键列 确保每条消息的 session_id 必须对应一个真实存在的会话
ON DELETE CASCADE 父表记录被删除时,自动级联删除子表中所有关联记录 删除某个会话时,SQLite 自动清理该会话下的所有消息,无需手动处理
cpp 复制代码
sessions 表                     messages 表
┌────────────┐                 ┌──────────────────────────┐
│ session_001│◄────────────────│ session_id = session_001 │
│ session_002│◄───────┐        │ session_id = session_001 │
└────────────┘        │        │ session_id = session_002 │
                      │        └──────────────────────────┘
                      │
删除 session_001 ─────┘
                      ↓
         messages 中 session_id = session_001 的行自动删除
cpp 复制代码
DataManager::DataManager(const std::string& dbName) 
    : _dbName(dbName)
    , _db(nullptr)
{
    //创建并打开数据库
    int rc = sqlite3_open(_dbName.c_str(), &_db);
    if (rc != SQLITE_OK) {
        ERR("打开数据库失败: {}", sqlite3_errmsg(_db));
    }
    INFO("数据库打开成功: {}", _dbName);

    //初始化数据库表 ------ 创建会话表和信息表
    if (!initDatabase()) {
        ERR("初始化数据库表失败");
        sqlite3_close(_db);
        _db = nullptr;
    }
}
DataManager::~DataManager() 
{
    //关闭数据库连接
    if (_db) 
    {
        sqlite3_close(_db);
    }
}

//初始化数据库
bool DataManager::initDatabase() 
{
    //创建会话表
    std::string createSessionTableSQL = R"(
        CREATE TABLE IF NOT EXISTS sessions (
            session_id TEXT PRIMARY KEY,
            model_name TEXT NOT NULL,
            create_time INTEGER NOT NULL,
            update_time INTEGER NOT NULL
        );
    )";

    //执行创建Session表的SQL语句
    if (!executeSQL(createSessionTableSQL)) {
        return false;
    }

    //创建消息表
    std::string createMessageTableSQL = R"(
        CREATE TABLE IF NOT EXISTS messages (
            message_id TEXT PRIMARY KEY,
            session_id TEXT NOT NULL,
            role TEXT NOT NULL,
            content TEXT NOT NULL,
            timestamp INTEGER NOT NULL,
            FOREIGN KEY (session_id) REFERENCES sessions (session_id) ON DELETE CASCADE
        );
    )";

    //执行创建Message表的SQL语句
    if (!executeSQL(createMessageTableSQL)) {
        return false;
    }
    return true;
}

//执行SQL语句的工具函数
bool DataManager::executeSQL(const std::string& sql) 
{
    if(_db == nullptr)
    {
        ERR("数据库连接为空,无法执行SQL语句");
        return false;
    }
    char* errorMessage = nullptr;
    int rc = sqlite3_exec(_db, sql.c_str(), nullptr, nullptr, &errorMessage);
    if (rc != SQLITE_OK) 
    {
        ERR("执行SQL语句失败: {}", errorMessage);
        sqlite3_free(errorMessage);
        return false;
    }
    return true;
}

🔥插入新会话 & 获取会话信息 & 更新会话的时间戳 & 删除指定会话

四个操作都遵循:构建SQL语句 ------ 准备SQL语句 ------ 绑定参数 ------ 执行SQL语句 ------ 清理stmt对象

  • 大体的实现逻辑都大差不差,只有获取指定会话信息的实现 :要将获取到的信息用于新构建出来的Session并返回
cpp 复制代码
//插入新会话
bool DataManager::insertSession(const Session& session) 
{
    std::lock_guard<std::mutex> lock(_mutex);   //保证插入时会话的线程安全

    //构建SQL语句
    std::string insertSessionSQL = R"(
        INSERT INTO sessions (session_id, model_name, create_time, update_time)
        VALUES (?, ?, ?, ?);
    )";

    //准备SQL语句
    sqlite3_stmt* stmt;
    int rc = sqlite3_prepare_v2(_db, insertSessionSQL.c_str(), -1, &stmt, nullptr);
    if (rc != SQLITE_OK) 
    {
        ERR("insertSession - 准备SQL语句失败: {}", sqlite3_errmsg(_db));
        return false;
    }

    //绑定参数
    sqlite3_bind_text(stmt, 1, session._sessionId.c_str(), -1, SQLITE_STATIC);
    sqlite3_bind_text(stmt, 2, session._modelName.c_str(), -1, SQLITE_STATIC);
    sqlite3_bind_int64(stmt, 4, static_cast<int64_t>(session._updatedAt));
    sqlite3_bind_int64(stmt, 4, static_cast<int64_t>(session._updatedAt));

    //执行SQL语句
    rc = sqlite3_step(stmt);
    if (rc != SQLITE_DONE) 
    {
        ERR("insertSession - 执行SQL语句失败: {}", sqlite3_errmsg(_db));
        return false;
    }

    //清理stmt对象
    sqlite3_finalize(stmt);
    INFO("insertSession - 插入会话成功: {}", session._sessionId);
    return true;
}

//获取指定会话信息
std::shared_ptr<Session> DataManager::getSession(const std::string& sessionId) const 
{
    std::lock_guard<std::mutex> lock(_mutex);

    //构建SQL语句
    std::string getSessionSQL = R"(
        SELECT model_name, create_time, update_time
        FROM sessions
        WHERE session_id = ?;
    )";

    //准备SQL语句
    sqlite3_stmt* stmt;

    int rc = sqlite3_prepare_v2(_db, getSessionSQL.c_str(), -1, &stmt, nullptr);
    if (rc != SQLITE_OK) 
    {
        ERR("getSession - 准备SQL语句失败: {}", sqlite3_errmsg(_db));
        return nullptr;
    }

    //参数绑定
    sqlite3_bind_text(stmt, 1, sessionId.c_str(), -1, SQLITE_STATIC);

    //执行SQL语句
    rc = sqlite3_step(stmt);
    if (rc != SQLITE_ROW) 
    {
        ERR("getSession - 执行SQL语句失败: {}", sessionId);
        sqlite3_finalize(stmt);
        return nullptr;
    }

    //从表中获取数据:sqlite3_column_text返回的是const unsigned char*,需要转换为const char*
    std::string modelName = reinterpret_cast<const char*>(sqlite3_column_text(stmt, 0));
    int64_t createTime = sqlite3_column_int64(stmt, 1);
    int64_t updateTime = sqlite3_column_int64(stmt, 2);
    
    //创建Session对象
    auto session = std::make_shared<Session>(modelName);
    session->_sessionId = sessionId;
    session->_createdAt = createTime;
    session->_updatedAt = updateTime;

    //获取该会话的所有消息
    session->_messages = getMessages(sessionId);

    //清理stmt对象
    sqlite3_finalize(stmt);
    return session;
}

//更新指定会话的时间戳
bool DataManager::updateSessionTimestamp(const std::string& sessionId, std::time_t timestamp) 
{
    std::lock_guard<std::mutex> lock(_mutex);

    //构建SQL语句
    std::string updateSessionSQL = R"(
        UPDATE sessions
        SET update_time = ?
        WHERE session_id = ?;
    )";

    //准备SQL语句
    sqlite3_stmt* stmt;
    int rc = sqlite3_prepare_v2(_db, updateSessionSQL.c_str(), -1, &stmt, nullptr);
    if (rc != SQLITE_OK) 
    {
        ERR("updateSessionTimestamp - 准备SQL语句失败: {}", sqlite3_errmsg(_db));
        return false;
    }

    //绑定参数
    sqlite3_bind_int64(stmt, 1, static_cast<int64_t>(timestamp));
    sqlite3_bind_text(stmt, 2, sessionId.c_str(), -1, SQLITE_STATIC);

    //执行SQL语句
    rc = sqlite3_step(stmt);
    if (rc != SQLITE_DONE) 
    {
        ERR("updateSessionTimestamp - 执行SQL语句失败: {}", sqlite3_errmsg(_db));
        return false;
    }

    //清理stmt对象
    sqlite3_finalize(stmt);
    INFO("updateSessionTimestamp - 更新会话时间戳成功: {}", sessionId);
    return true;
}

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

    //构建SQL语句
    std::string deleteSessionSQL = R"(
        DELETE FROM sessions
        WHERE session_id = ?;
    )";

    //准备SQL语句
    sqlite3_stmt* stmt;
    int rc = sqlite3_prepare_v2(_db, deleteSessionSQL.c_str(), -1, &stmt, nullptr);
    if (rc != SQLITE_OK) 
    {
        ERR("deleteSession - 准备SQL语句失败: {}", sqlite3_errmsg(_db));
        return false;
    }

    //绑定参数
    sqlite3_bind_text(stmt, 1, sessionId.c_str(), -1, SQLITE_STATIC);

    //执行SQL语句
    rc = sqlite3_step(stmt);
    if (rc != SQLITE_DONE) 
    {
        ERR("deleteSession - 执行SQL语句失败: {}", sqlite3_errmsg(_db));
        return false;
    }

    //清理stmt对象
    sqlite3_finalize(stmt);
    INFO("deleteSession - 删除会话成功: {}", sessionId);
    return true;
}

🔥剩余函数实现

cpp 复制代码
//获取所有会话ID
std::vector<std::string> DataManager::getAllSessionIds() const 
{
    std::lock_guard<std::mutex> lock(_mutex);

    //构建SQL语句: 按 update_time 列的值降序排列查询结果。
    std::string getAllSessionIdsSQL = R"(
        SELECT session_id
        FROM sessions
        ORDER BY update_time DESC;
    )";

    //准备SQL语句
    sqlite3_stmt* stmt;
    int rc = sqlite3_prepare_v2(_db, getAllSessionIdsSQL.c_str(), -1, &stmt, nullptr);
    if (rc != SQLITE_OK) 
    {
        ERR("getAllSessionIds - 准备SQL语句失败: {}", sqlite3_errmsg(_db));
        return {};
    }

    //执行会有多条结果
    std::vector<std::string> sessionIds;
    while (sqlite3_step(stmt) == SQLITE_ROW)
    {
        std::string sessionId = reinterpret_cast<const char*>(sqlite3_column_text(stmt, 0));
        sessionIds.push_back(sessionId);
    }

    //清理stmt对象
    sqlite3_finalize(stmt);
    INFO("getAllSessionIds - 获取所有会话ID成功, 会话总数: {}", sessionIds.size());
    return sessionIds;
}

//获取所有会话 - 并按照更新时间降序排列
std::vector<std::shared_ptr<Session>> DataManager::getAllSessions() const
{
    std::lock_guard<std::mutex> lock(_mutex);

    //构建SQL语句
    std::string getAllSessionsSQL = R"(
        SELECT session_id, model_name, create_time, update_time
        FROM sessions
        ORDER BY update_time DESC;
    )";

    //准备SQL语句
    sqlite3_stmt* stmt;
    int rc = sqlite3_prepare_v2(_db, getAllSessionsSQL.c_str(), -1, &stmt, nullptr);
    if (rc != SQLITE_OK) 
    {
        ERR("getAllSessions - 准备SQL语句失败: {}", sqlite3_errmsg(_db));
        return {};
    }

    //执行SQL语句
    std::vector<std::shared_ptr<Session>> sessions;
    while (sqlite3_step(stmt) == SQLITE_ROW)  //拿到一行的信息
    {
        //从表中获取数据
        std::string sessionId = reinterpret_cast<const char*>(sqlite3_column_text(stmt, 0));
        std::string modelName = reinterpret_cast<const char*>(sqlite3_column_text(stmt, 1));
        int64_t createTime = sqlite3_column_int64(stmt, 2);
        int64_t updateTime = sqlite3_column_int64(stmt, 3);

        //创建Session对象
        auto session = std::make_shared<Session>(modelName);
        session->_sessionId = sessionId;
        session->_createdAt = static_cast<std::time_t>(createTime);
        session->_updatedAt = static_cast<std::time_t>(updateTime);
        sessions.push_back(session);

        //历史消息暂时不获取,需要时再通过会话id来进行获取
        // session->_messages = getMessages(sessionId);
    }

    //清理stmt对象
    sqlite3_finalize(stmt);
    INFO("getAllSessions - 获取所有会话成功, 会话总数: {}", sessions.size());
    return sessions;
}

//获取会话总数
int DataManager::getSessionCount() const
{
    std::lock_guard<std::mutex> lock(_mutex);

    //构建SQL语句
    std::string getSessionCountSQL = R"(
        SELECT COUNT(*)
        FROM sessions;
    )";
    
    //准备SQL语句
    sqlite3_stmt* stmt;
    int rc = sqlite3_prepare_v2(_db, getSessionCountSQL.c_str(), -1, &stmt, nullptr);
    if (rc != SQLITE_OK) 
    {
        ERR("getSessionCount - 准备SQL语句失败: {}", sqlite3_errmsg(_db));
        return 0;
    }

    //执行SQL语句
    rc = sqlite3_step(stmt);
    if (rc != SQLITE_ROW) 
    {
        ERR("getSessionCount - 执行SQL语句失败: {}", sqlite3_errmsg(_db));
        return 0;
    }

    //获取会话总数
    int count = sqlite3_column_int(stmt, 0);

    //清理stmt对象
    sqlite3_finalize(stmt);
    INFO("getSessionCount - 获取会话总数成功: {}", count);
    return count;
}

🔥Message相关函数实现

注意在:在插入新消息的时候,要更新会话时间戳

  • 也就是不仅要执行一条插入消息的SQL语句,还需执行更新会话时间戳的SQL语句

  • 如果获取的消息不止一条,需要多轮的获取

    c 复制代码
    while (sqlite3_step(stmt) == SQLITE_ROW)
cpp 复制代码
//插入新消息:插入消息时,要更新会话时间戳
bool DataManager::insertMessage(const std::string& sessionId, const Message& message)
{
    std::lock_guard<std::mutex> lock(_mutex);

    //构建SQL语句
    std::string insertMessageSQL = R"(
        INSERT INTO messages (message_id, session_id, role, content, timestamp)
        VALUES (?, ?, ?, ?);
    )";

    //准备SQL语句
    sqlite3_stmt* stmt;
    int rc = sqlite3_prepare_v2(_db, insertMessageSQL.c_str(), -1, &stmt, nullptr);
    if (rc != SQLITE_OK) 
    {
        ERR("insertMessage - 准备SQL语句失败: {}", sqlite3_errmsg(_db));
        return false;
    }

    //绑定参数
    sqlite3_bind_text(stmt, 1, message._messageId.c_str(), -1, SQLITE_STATIC);
    sqlite3_bind_text(stmt, 2, sessionId.c_str(), -1, SQLITE_STATIC);
    sqlite3_bind_text(stmt, 3, message._role.c_str(), -1, SQLITE_STATIC);
    sqlite3_bind_text(stmt, 4, message._content.c_str(), -1, SQLITE_STATIC);
    sqlite3_bind_int64(stmt, 5, static_cast<int64_t>(message._timestamp));

    //执行SQL语句
    rc = sqlite3_step(stmt);
    if (rc != SQLITE_DONE) 
    {
        ERR("insertMessage - 执行SQL语句失败: {}", sqlite3_errmsg(_db));
        return false;
    }

    //更新会话时间戳
    std::string updateSessionTimestampSQL = R"(
        UPDATE sessions
        SET update_time = ?
        WHERE session_id = ?;
    )";

    //准备SQL语句
    sqlite3_stmt* updatestmt;
    rc = sqlite3_prepare_v2(_db, updateSessionTimestampSQL.c_str(), -1, &stmt, nullptr);
    if (rc != SQLITE_OK) 
    {
        ERR("insertMessage - 准备SQL语句失败: {}", sqlite3_errmsg(_db));
        return false;
    }

    //绑定参数
    sqlite3_bind_int64(updatestmt, 1, static_cast<int64_t>(message._timestamp));
    sqlite3_bind_text(updatestmt, 2, sessionId.c_str(), -1, SQLITE_STATIC);

    //执行SQL语句
    rc = sqlite3_step(updatestmt);
    if (rc != SQLITE_DONE) 
    {
        ERR("insertMessage - 执行SQL语句失败: {}", sqlite3_errmsg(_db));
        return false;
    }

    //清理stmt对象
    sqlite3_finalize(stmt);
    sqlite3_finalize(updatestmt);
    INFO("insertMessage - 插入消息成功: {}", message._messageId);
    return true;
}

//获取指定会话的历史消息
std::vector<Message> DataManager::getMessages(const std::string& sessionId) const
{
    std::lock_guard<std::mutex> lock(_mutex);

    //构建SQL语句
    std::string getMessagesSQL = R"(
        SELECT message_id, role, content, timestamp
        FROM messages
        WHERE session_id = ?
        ORDER BY timestamp ASC;
    )";

    //准备SQL语句
    sqlite3_stmt* stmt;
    int rc = sqlite3_prepare_v2(_db, getMessagesSQL.c_str(), -1, &stmt, nullptr);
    if (rc != SQLITE_OK) 
    {
        ERR("getMessages - 准备SQL语句失败: {}", sqlite3_errmsg(_db));
        return {};
    }

    //绑定参数
    sqlite3_bind_text(stmt, 1, sessionId.c_str(), -1, SQLITE_STATIC);

    //执行SQL语句
    std::vector<Message> messages;
    while (sqlite3_step(stmt) == SQLITE_ROW)
    {
        //从表中获取数据
        std::string messageId = reinterpret_cast<const char*>(sqlite3_column_text(stmt, 0));
        std::string role = reinterpret_cast<const char*>(sqlite3_column_text(stmt, 1));
        std::string content = reinterpret_cast<const char*>(sqlite3_column_text(stmt, 2));
        int64_t timestamp = sqlite3_column_int64(stmt, 3);

        //创建Message对象
        Message message(role, content);
        message._messageId = messageId;
        message._timestamp = static_cast<std::time_t>(timestamp);
        messages.push_back(message);
    }

    //在执行语句过程中出现异常
    if(rc != SQLITE_DONE){
        ERR("getMessages - 执行SQL语句失败: {}", sqlite3_errmsg(_db));
        sqlite3_finalize(stmt);
        return {};
    }

    //正常执行: 清理stmt对象
    sqlite3_finalize(stmt);
    INFO("getMessages - 获取历史消息成功, 消息总数: {}", messages.size());
    return messages;
}

//删除指定会话中的所有消息
bool DataManager::deleteMessages(const std::string& sessionId)
{
    std::lock_guard<std::mutex> lock(_mutex);

    //构建SQL语句
    std::string deleteMessagesSQL = R"(
        DELETE FROM messages
        WHERE session_id = ?;
    )";

    //准备SQL语句
    sqlite3_stmt* stmt;
    int rc = sqlite3_prepare_v2(_db, deleteMessagesSQL.c_str(), -1, &stmt, nullptr);
    if (rc != SQLITE_OK) 
    {
        ERR("deleteMessages - 准备SQL语句失败: {}", sqlite3_errmsg(_db));
        return false;
    }

    //绑定参数
    sqlite3_bind_text(stmt, 1, sessionId.c_str(), -1, SQLITE_STATIC);

    //执行SQL语句
    rc = sqlite3_step(stmt);
    if (rc != SQLITE_DONE) 
    {
        ERR("deleteMessages - 执行SQL语句失败: {}", sqlite3_errmsg(_db));
        return false;
    }

    //清理stmt对象
    sqlite3_finalize(stmt);
    INFO("deleteMessages - 删除消息成功: {}", sessionId);
    return true;
}

🌏会话数据同步到数据库

之前我们实现的创建会话数据都是在内存里保存的,一旦断电就死翘翘

每次创建新会话、删除会话、更新会话、以及生成消息记录等都需要同步到SQLite因此让SessionManager类持有一个DataManager的对象,当发生上述操作时,通过DataManager的对象持久化会话数据。

所以对于SessionManager中的方法还需要重新过一遍

cpp 复制代码
class SessionManager{
private:
	// ...
	// 通过会话数据到数据库
	DataManager _dataManager;
};

1️⃣创建会话

将新创建的会话保存到数据库中 ,注意insertSession操作是加了锁的,所以我们这里手动的加锁

  • session指针解引用,得到session对象
cpp 复制代码
//创建会话,提供模型,返回会话id
std::string SessionManager::createSession(const std::string &modelName) {
    //手动加锁和解锁
    _mutex.lock();

    //生成会话id
    std::string sessionId = generateSessionId();

    //创建会话,设置会话id、模型名称
    auto session = std::make_shared<Session>(modelName);
    session->_sessionId = sessionId;
    session->_createdAt = std::time(nullptr);
    session->_updatedAt = session->_createdAt;

    //加入到会话列表
    _sessions[sessionId] = session;

    _mutex.unlock();
    //🀄将会话保存到数据库中
    //🀄注意insertSession操作是加了锁的,所以我们这里手动的加锁
    _dataManager.insertSession(*session);  //对session指针解引用,得到session对象

    return sessionId;
}

2️⃣通过会话id获取会话信息

获取会话信息分两步:查内存 和 查数据库

数据 内存 _sessions 数据库 messages 说明
session_id 会话唯一标识
model_name 会话使用的模型名称
create_time / update_time 会话创建和更新时间戳
_messages(聊天历史) 没有 消息量大,不常驻内存,按需从数据库加载
  • 所以在查内存找到了,也需要在数据库中去加载历史消息数据
  • 在数据库中找不到的话,也需要将会话添加到会话列表中;属于懒加载缓存方法,如果不写回,下次获取时还是没有
cpp 复制代码
getSession(sessionId)
│
├─ 第一级:查内存(_sessions map)
│   │
│   ├─ 找到 → 解锁 → 从数据库补充消息列表 → 返回 session
│   │
│   └─ 没找到 → 进入第二级
│
├─ 第二级:查数据库(_dataManager)
│   │
│   ├─ 找到 → 加锁写入内存缓存 → 解锁 → 从数据库补充消息列表 → 返回 session
│   │
│   └─ 没找到 → WARN 日志 → 返回 nullptr
cpp 复制代码
std::shared_ptr<Session> SessionManager::getSession(const std::string &sessionId) {
    //🀄先在内存中对_sessions进行查找 
    _mutex.lock();
    auto it = _sessions.find(sessionId);
    if(it != _sessions.end())   
    {   
        _mutex.unlock();
        //获取当前会话的历史信息:从数据库中补充缺失的消息_messages
        it->second->_messages = _dataManager.getMessages(sessionId);
        return it->second;
    }
    _mutex.unlock();

    //🀄在内存中找不到,则从数据库中获取
    auto session = _dataManager.getSession(sessionId);
    if(session)
    {
        _mutex.lock();
        auto it = _sessions.find(sessionId);
        if (it == _sessions.end()) {         //在内存确实没有找到,将会话添加到会话列表中
            _sessions[sessionId] = session;  //懒加载缓存,如果不写回,下次获取时还是没有
        }
        _mutex.unlock();
        //从数据库中补充缺失的消息
        session->_messages = _dataManager.getMessages(sessionId);
        return session;
    }
    WARN("Session not found: {}", sessionId);
    return nullptr;
}

3️⃣会话中插入消息

cpp 复制代码
//往某个会话中添加消息
bool SessionManager::addMessage(const std::string &sessionId, const Message &message) {
    _mutex.lock();

    //通过会话id获取会话信息
    auto it = _sessions.find(sessionId);
    if (it == _sessions.end()) 
    {
        _mutex.unlock();
        return false;
    }

    //添加消息 ------ 因为message是const的,不能修改其_messageId
    Message msg(message._role, message._content);
    msg._messageId = generateMessageId(it->second->_messages.size());

    //消息添加到会话中                                                              
    it->second->_messages.push_back(msg);         //添加消息
    it->second->_updatedAt = std::time(nullptr);  //更新会话时间戳

    INFO("Add message to session successfully: message_id {}, message_content {}", msg._messageId, msg._content);
    _mutex.unlock();

    //🀄把消息保存到数据库中
    _dataManager.insertMessage(sessionId, msg);

    return true;
}

4️⃣获取某个会话的所有历史信息

也是分为在内存中获取在数据库中获取两个途径

  • 先从内存中获取会话消息,如果不存在则从数据库中获取
cpp 复制代码
//获取某个会话的所有历史信息
std::vector<Message> SessionManager::getHistoryMessages(const std::string &sessionId) const {
    //🀄先从内存中获取会话消息,如果不存在则从数据库中获取
    _mutex.lock();
    auto it = _sessions.find(sessionId);
    if (it != _sessions.end()) 
    {
        _mutex.unlock();
        return it->second->_messages;
    }   
    _mutex.unlock();

    //从数据库中获取
    return _dataManager.getMessages(sessionId);
}

5️⃣更新会话的时间戳

更新内存会话时间戳 + 更新数据库中会话时间戳

cpp 复制代码
//更新会话的时间戳
void SessionManager::updateSessionTimestamp(const std::string &sessionId) {
    _mutex.lock();
    //更新内存会话时间戳 
    auto it = _sessions.find(sessionId);
    if (it != _sessions.end()) {
        _mutex.unlock();
        it->second->_updatedAt = std::time(nullptr);
    }
    _mutex.unlock();
    //更新数据库中会话时间戳
    _dataManager.updateSessionTimestamp(sessionId, std::time(nullptr));
}

6️⃣获取所有会话列表

在我们进行构造函数的时候,已经把所有的会话从数据库中加载放到内存里了,所以在这个函数中,没有必要再对数据库进行额外的读取了

为了保险起见,也把数据库的会话加载到内存里 ------ 也遍历一次

7️⃣删除会话

也分成在内存中删除 和 在数据库中删除

cpp 复制代码
bool SessionManager::delteSession(const std::string sessionId) {
    _mutex.lock();
    auto it = _sessions.find(sessionId);
    if (it == _sessions.end())
    {
        _mutex.unlock();
        return false;
    }
    //从内存中删除会话
    _sessions.erase(it);
    _mutex.unlock();

    //从数据库中删除会话
    _dataManager.deleteSession(sessionId);
    return true;
}

8️⃣清空所有会话

cpp 复制代码
//清空所有会话
void SessionManager::clearAllSessions() {
    _mutex.lock();
    _sessions.clear();
    _mutex.unlock();

    //从数据库中删除所有会话
    _dataManager.deleteAllSessions();
}

9️⃣获取会话总数

直接返回即可, 内存中是session已经是所有的会话了

  • 程序启动,在构造函数就已经把会话都汇总了
  • 后续再新建会话,也是先添加到我们的内存中的
cpp 复制代码
size_t SessionManager::getSessionCount() const {
    std::lock_guard<std::mutex> lock(_mutex);
    return _sessions.size();
}

📢写在最后

接下来登场的是 SDK

相关推荐
troy1281 小时前
Python 进阶提升(十二):自动化测试与 DevOps 实战
python·devops
m4Rk_1 小时前
【论文阅读】Agent 记忆机制(67):MemPO——用记忆级信用分配训练 Agent 主动管理长程上下文
论文阅读·人工智能·学习·开源·github
Ai思想家1 小时前
企业AI网关的跨可用区容灾与多活设计
人工智能
Mr数据杨1 小时前
基于企业交易数据的OKVED行业分类实战解析
人工智能·数据分析·kaggle竞赛
AI推荐率1 小时前
品牌的核心能力只写在图片里,公开资料该怎样补充文字解释?
人工智能
能源革命1 小时前
DeepAR(概率自回归模型)介绍
人工智能·数据挖掘·回归
IvorySQL1 小时前
PostgreSQL 日报|大模型破解在线校验和(9 月 15 日)
数据库·人工智能·postgresql
ynchyong1 小时前
SQLAlchemy 更新操作:values() 与 ordered_values() 的隐藏差异
python·sqlalchemy·update·values·ordered_values
人工智能AI技术1 小时前
模型越强越翻车?GPT-6 旧配置踩坑深度避坑指南
人工智能