持久化聊天会话可让您的 .NET 应用程序在重启后仍能运行,提供对话的备份,并实现会话在不同机器之间的迁移。在本指南中,我们将使用 Aspose.LLM 逐步演示 在 C# 中持久化和恢复聊天会话,涵盖何时使用此模式、如何保存和加载会话、哪些数据会被存储、可移植性考虑以及安全最佳实践。
为什么要持久化和恢复聊天会话?
开发人员经常构建交互式助手、支持机器人或长期运行的数据分析工作流。在许多场景中,聊天上下文必须在单个进程的生命周期之外保持存活:
- 桌面支持工具,用户期望在应用关闭后仍能保留之前的查询。
- 跨多个步骤的服务器端自动化,可能因维护而需要重新启动。
- 审计或合规要求,需要对整个对话进行快照。
- 将故障排除会话从开发者的笔记本电脑迁移到生产服务器。
通过将会话持久化到 JSON 文件,您可以捕获完整的消息历史记录以及实现精确续写所需的内部 KV 缓存,从而使上述用例的实现变得简洁明了。
开始使用 Aspose.LLM
首先,将 Aspose.LLM 包添加到您的项目中:
Install-Package Aspose.LLM
您可以在Aspose.LLM .NET 产品页面找到更多产品详情。SDK 需要有效的许可证,请确保您已准备好临时或永久许可证文件。
先决条件
- 安装 Aspose.LLM NuGet 包。
- 使用
Aspose.LLM.License应用 Aspose.LLM 许可证。 - 创建
AsposeLLMApi实例(例如,使用Qwen25Preset)。
何时使用此模式
此模式在您需要对话在当前进程之外保持持久,或希望获得可靠的备份或迁移快照时表现出色。典型场景包括:
- 桌面或服务器应用程序,用户期望聊天在启动之间保持持久。
- 需要对话在进程结束后仍然存在的长时间运行工作流。
- 通过对活动对话进行快照进行备份和审计。
- 在具有相同 SDK 版本和预设的机器之间迁移会话状态。
前提条件
在保存或恢复会话之前,请确保以下条件已就绪:
- Aspose.LLM NuGet package – 已通过前面显示的命令进行安装。
- License – 创建一个
Aspose.LLM.License对象并使用您的.lic文件调用SetLicense。 - API instance – 使用所需的预设实例化
AsposeLLMApi(例如,new Qwen25Preset())。
这些步骤在文章后面的完整示例中演示。
保存会话
SDK 提供三种便捷方式来持久化聊天会话。请按照以下步骤操作,然后查看代码示例。
- 调用
SaveChatSession并提供明确的文件路径,如果您需要将文件保存到已知位置。 - 省略路径,让 SDK 在可执行文件旁边写入
<sessionId>.json。 - 使用
Path.Combine构建临时路径,确保目录存在,并在隔离或沙箱场景中保存到该位置。
代码示例 – 保存会话
以下示例演示了所有三种方法:
api.SaveChatSession(sessionId, "session-42.json");
api.SaveChatSession(sessionId); // writes <sessionId>.json next to the executable
string path = Path.Combine(Path.GetTempPath(), "chats", $"{sessionId}.json");
Directory.CreateDirectory(Path.GetDirectoryName(path)!);
api.SaveChatSession(sessionId, path);
*api.SaveChatSession(sessionId, "session-42.json") 将 JSON 文件写入提供的位置。
*如果在调用 SaveChatSession 时未提供路径,SDK 会在当前工作目录中创建一个以会话 ID 命名的文件。
*当需要确定的或临时的位置时,结合 Path.GetTempPath 与您自己的文件夹结构,并在保存之前创建该目录。
注意: 这些代码片段摘自官方 Aspose 文档,尚未在沙箱中执行。请在生产环境使用前先在您的环境中验证它们。
恢复会话
加载先前保存的会话同样简单。API 读取 JSON 文件,重新创建内部状态,并返回会话标识符,这样您就可以继续发送消息,而无需手动传递 ID。
- 调用
LoadChatSession并提供 JSON 文件的路径。 - 保存返回的
sessionId。 - 使用
SendMessageToSessionAsync并传入恢复的 ID 以继续对话。
代码示例 – 恢复会话
string sessionId = await api.LoadChatSession("session-42.json");
string reply = await api.SendMessageToSessionAsync(sessionId, "What did we discuss?");
LoadChatSession 读取文件并返回恢复的会话 ID。
恢复的会话会自动设为活动会话,允许立即调用 SendMessageToSessionAsync。
注意: 这些代码片段摘自官方 Aspose 文档,未在沙箱中执行。请在将其用于生产环境之前,在您的环境中进行验证。
完整示例 — 保存、重新启动、恢复
以下是一个完整的端到端演示。第一个块启动聊天,发送几条消息,并保存会话。第二个块模拟一个新进程,加载已保存的文件并继续对话。
代码示例 – 端到端工作流
using Aspose.LLM;
using Aspose.LLM.Abstractions.Parameters.Presets;
// ---------- First run: save ----------
{
var license = new Aspose.LLM.License();
license.SetLicense("Aspose.LLM.lic");
using var api = AsposeLLMApi.Create(new Qwen25Preset());
string sessionId = await api.StartNewChatAsync(sessionId: "support-ticket-1234");
await api.SendMessageToSessionAsync(sessionId,
"Customer reports that the migration from v25 to v26 broke their startup script.");
await api.SendMessageToSessionAsync(sessionId,
"Their environment: Windows Server 2022, .NET 8, CUDA 12.6.");
await api.SendMessageToSessionAsync(sessionId,
"What questions should I ask them next?");
api.SaveChatSession(sessionId, "support-ticket-1234.json");
Console.WriteLine("Session saved.");
}
// ---------- Second run: resume ----------
{
var license = new Aspose.LLM.License();
license.SetLicense("Aspose.LLM.lic");
using var api = AsposeLLMApi.Create(new Qwen25Preset());
string sessionId = await api.LoadChatSession("support-ticket-1234.json");
Console.WriteLine($"Resumed session: {sessionId}");
string reply = await api.SendMessageToSessionAsync(sessionId,
"They replied that they use a custom build step that copies native DLLs. How should I proceed?");
Console.WriteLine(reply);
}
第一个代码块创建许可证,使用 Qwen25Preset 实例化 API,启动一个名为 support-ticket-1234 的新聊天,发送三条消息以构建上下文,最后将会话写入 support-ticket-1234.json。第二个代码块重新创建许可证和 API,加载 JSON 文件,并继续对话,演示模型保留了之前的消息。
注意: 这些代码片段摘自官方 Aspose 文档,未在沙箱中执行。请在生产环境使用前在您的环境中验证它们。
保存了什么?
SaveChatSession 生成一个包含三个关键部分的 JSON 文档:
- Session Identifier – 您在开始聊天时提供的唯一 ID。
- Message History – 所有用户和助手消息的有序列表,包括角色、内容以及任何媒体元数据。
- KV Cache Metadata – 每条消息的键‑值缓存的内部位置和大小,使模型能够准确地从上次停止的地方继续。
因为包含了缓存数据,恢复的会话可以在不重新计算先前注意力的情况下继续生成,从而使恢复操作快速且确定性。
可移植性约束
虽然 JSON 文件包含实现完美续写所需的一切,但它仅在特定条件下可移植:
- 相同的 SDK 主版本 – 文件格式在主要发行版之间可能会更改,因此双方必须使用相同的 Aspose.LLM 主版本。
- 相同的模型文件 – 基础的 Hugging Face 模型(包括量化)必须完全匹配;否则 KV 缓存将不兼容。
- 匹配 BinaryManagerParameters.ReleaseTag – 用于加载模型的 llama.cpp 运行时版本必须相同,否则低层张量布局会不同。
如果违反了这些约束,您可能会看到类似 InvalidOperationException 的错误或输出乱码。
已知的加载时细微差别
当您调用 LoadChatSession 时,SDK 会重建对话,但会应用 默认 ContextParameters、ChatParameters 和 SamplerParameters。您在原始会话期间使用的任何自定义设置(例如 temperature、max tokens、system prompts)不会 自动恢复。为了保持完全相同的生成行为,请在加载后重新应用自定义参数,或在具有所需设置的全新会话中重新播放对话。
常见错误
以下是加载会话时可能遇到的典型问题的快速检查清单:
- FileNotFoundException – 验证文件路径;相对路径相对于当前工作目录进行解析。
- InvalidOperationException on load – 表明 SDK 版本不兼容或 JSON 文件已损坏。
- Garbled output after load – 通常是模型文件或 ReleaseTag 不匹配导致。确保加载机器上存在完全相同的模型二进制文件。
优雅地处理这些异常并记录详细的诊断信息将使您的应用程序更加健壮。
安全
持久化的 JSON 文件包含每个用户和助手消息的 纯文本 副本。将其存储在未受保护的位置可能会泄露敏感数据。请考虑以下缓解措施:
- 在将文件写入磁盘之前对其进行加密(例如,Windows DPAPI、Azure Key Vault,或像 libsodium 这样的跨平台库)。
- 限制文件系统权限,仅允许运行应用程序的服务账户读取/写入文件。
- 如果文件必须通过网络传输,请使用 TLS 加密通道,并考虑对文件进行签名以检测篡改。
接下来
既然您已经可以持久化并恢复聊天,您可以探索相关功能:
- 多轮聊天用例 – 在许多交互中保持更长的对话。
- 自定义预设配置 – 在持久化之前将模型预设调整到您的领域。
- 完整会话持久化参考 – 查看 API 参考,以深入了解
SaveChatSession及相关元数据。
选择合适的方法
本文介绍了三种保存会话的方法以及一种直接的加载方法。请选择与您的部署场景相匹配的方法。
- Explicit path – 最佳情况是文件必须位于已知位置,例如用户特定文件夹或共享网络驱动器。
- Default filename – 适用于快速原型或会话与可执行文件并存的情况。
- Temporary path with directory creation – 适合沙箱环境、CI 管道,或希望由操作系统管理清理的场景。
所有方法使用相同的底层 API;它们仅在文件系统的管理方式上有所不同。
获取免费许可证
如果您还没有永久许可证,您可以从 Aspose 临时许可证页面 获取临时评估许可证。
免费附加资源
结论
使用 Aspose.LLM 持久化聊天会话可为您提供持久性、可审计性以及在进程或机器之间移动对话的灵活性。您已经了解了何时应用此模式、如何以三种不同方式保存会话、如何恢复会话、JSON 文件包含哪些内容,以及需要牢记的兼容性和安全性考虑因素。拥有完整示例后,您现在可以将会话持久化集成到任何 .NET 聊天解决方案中。
常见问题
何时持久化聊天会话有用?
持久化对于需要在启动之间保持对话状态的桌面或服务器应用、长期运行的工作流、审计或备份需求,以及在使用相同 SDK 版本的机器之间迁移会话非常有帮助。如何在保存会话时指定自定义文件路径?
调用api.SaveChatSession(sessionId, "myfolder\myfile.json");,或使用Path.Combine构建路径,并在保存前确保目录存在。LoadChatSession 返回什么?
它返回恢复后的会话标识符,使您可以在无需再次提供 ID 的情况下继续发送消息。我可以将已保存的会话文件移动到另一台机器吗?
可以,只要目标机器使用相同的主要 SDK 版本、相同的模型文件以及匹配的 llama.cpp ReleaseTag。保存的 JSON 文件安全吗?
该文件以纯文本形式存储对话数据,因此在存放到不受信任的位置之前应对其进行加密。为什么加载后我的自定义采样器或上下文设置没有恢复?
LoadChatSession 会应用默认参数;加载后请重新应用任何自定义设置,或在新会话中重放历史记录。
