🌈欢迎来到实战项目专栏 ~~ 从零实现AI大模型接入SDK
- 🌍博客主页 :张小姐的猫~江湖背景
- 🔥所属专栏 :C++项目 ~ AI大模型接入SDK
- 作者水平很有限,如果发现错误,可在评论区指正,感谢🙏

AI大模型接入SDK
- [🌈欢迎来到实战项目专栏 ~~ 从零实现AI大模型接入SDK](#🌈欢迎来到实战项目专栏 ~~ 从零实现AI大模型接入SDK)
- 🌏数据管理模块设计
- 🌏数据管理模块实现
-
- [🔥构造 & 析构 & 初始化 & 执行语句](#🔥构造 & 析构 & 初始化 & 执行语句)
- [🔥插入新会话 & 获取会话信息 & 更新会话的时间戳 & 删除指定会话](#🔥插入新会话 & 获取会话信息 & 更新会话的时间戳 & 删除指定会话)
- 🔥剩余函数实现
- 🔥Message相关函数实现
- 🌏会话数据同步到数据库
- 📢写在最后

🌏数据管理模块设计
接下来将会话信息 和与模型聊天的数据 持久化存储到SQLite数据库,存储时需要注意线程安全问题
- 注意有一些操作会涉及到
Session和Message两个表格的关联变化
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语句
-
如果获取的消息不止一条,需要多轮的获取
cwhile (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

