171 lines
5.9 KiB
Markdown
171 lines
5.9 KiB
Markdown
# 服务子系统设计 — 会话记忆与上下文
|
||
|
||
## 元数据
|
||
- 项目名称: free-code
|
||
- 文档类型: 服务子系统设计
|
||
- 原始代码来源: `../../src/utils/memory/`
|
||
- 关联总览: [服务子系统设计总览](服务子系统设计.md)
|
||
- 原始映射: [原始代码映射](reference/原始代码映射-服务子系统.md)
|
||
- 相关模块: [核心模块设计 — 查询引擎](../核心模块设计/核心模块设计-查询引擎-QueryEngine.md)
|
||
- 相关模块: [基础设施设计 — 后台任务管理](../基础设施设计/基础设施设计-后台任务管理.md)
|
||
- 相关模块: [基础设施设计 — 特性开关](../UI与扩展设计/UI与扩展设计-特性开关系统.md)
|
||
|
||
## 1. 设计目标
|
||
会话记忆与上下文子系统负责把长会话中的关键内容压缩、沉淀、同步,并在需要时为查询引擎提供可控、低成本的上下文补充。该子系统强调阈值触发、轻量模型处理、以及在写入团队知识库前的安全校验。
|
||
|
||
## 2. 核心数据结构
|
||
|
||
```csharp
|
||
public enum MemoryType
|
||
{
|
||
Session,
|
||
Dream,
|
||
Team
|
||
}
|
||
|
||
public sealed record MemoryEntry(
|
||
string Id,
|
||
MemoryType Type,
|
||
string SessionId,
|
||
string Content,
|
||
DateTimeOffset CreatedAt,
|
||
IReadOnlyList<string> Tags);
|
||
```
|
||
|
||
`MemoryType` 用于区分会话记忆、自动梦境摘要与团队共享记忆。`MemoryEntry` 记录统一承载记忆内容、来源会话、创建时间和标签,便于检索与同步。
|
||
|
||
## 3. 会话记忆服务
|
||
|
||
```csharp
|
||
public interface ISessionMemoryService
|
||
{
|
||
Task<MemoryEntry?> ExtractAsync(
|
||
string sessionId,
|
||
int tokenCount,
|
||
int toolCallCount,
|
||
CancellationToken cancellationToken = default);
|
||
|
||
Task SaveAsync(MemoryEntry entry, CancellationToken cancellationToken = default);
|
||
|
||
Task<IReadOnlyList<MemoryEntry>> GetRecentAsync(
|
||
string sessionId,
|
||
CancellationToken cancellationToken = default);
|
||
}
|
||
```
|
||
|
||
`ISessionMemoryService` 使用阈值触发提取:当 token 数或 tool call 数超过阈值时,触发一次记忆抽取,生成摘要型 `MemoryEntry`。
|
||
|
||
```csharp
|
||
public sealed class SessionMemoryService : ISessionMemoryService
|
||
{
|
||
private readonly int _tokenThreshold = 12000;
|
||
private readonly int _toolCallThreshold = 24;
|
||
|
||
public async Task<MemoryEntry?> ExtractAsync(
|
||
string sessionId,
|
||
int tokenCount,
|
||
int toolCallCount,
|
||
CancellationToken cancellationToken = default)
|
||
{
|
||
var shouldExtract = tokenCount >= _tokenThreshold || toolCallCount >= _toolCallThreshold;
|
||
if (!shouldExtract)
|
||
{
|
||
return null;
|
||
}
|
||
|
||
return await Task.FromResult(new MemoryEntry(
|
||
Id: Guid.NewGuid().ToString("N"),
|
||
Type: MemoryType.Session,
|
||
SessionId: sessionId,
|
||
Content: "基于会话上下文生成的压缩记忆。",
|
||
CreatedAt: DateTimeOffset.UtcNow,
|
||
Tags: new[] { "session", "summary" }));
|
||
}
|
||
|
||
public Task SaveAsync(MemoryEntry entry, CancellationToken cancellationToken = default) => Task.CompletedTask;
|
||
|
||
public Task<IReadOnlyList<MemoryEntry>> GetRecentAsync(string sessionId, CancellationToken cancellationToken = default)
|
||
=> Task.FromResult<IReadOnlyList<MemoryEntry>>(Array.Empty<MemoryEntry>());
|
||
}
|
||
```
|
||
|
||
## 4. 自动梦境服务
|
||
|
||
```csharp
|
||
public interface IAutoDreamService
|
||
{
|
||
Task<MemoryEntry?> GenerateAsync(
|
||
string sessionId,
|
||
TimeSpan idleDuration,
|
||
int sessionCount,
|
||
CancellationToken cancellationToken = default);
|
||
}
|
||
```
|
||
|
||
`IAutoDreamService` 在两类条件触发:会话空闲超过 24 小时,或会话累计次数达到设定阈值。它用于生成更高层级的长期偏好、主题趋势和待办线索。
|
||
|
||
```csharp
|
||
public sealed class AutoDreamService : IAutoDreamService
|
||
{
|
||
private readonly TimeSpan _idleThreshold = TimeSpan.FromHours(24);
|
||
private readonly int _sessionCountThreshold = 10;
|
||
|
||
public async Task<MemoryEntry?> GenerateAsync(
|
||
string sessionId,
|
||
TimeSpan idleDuration,
|
||
int sessionCount,
|
||
CancellationToken cancellationToken = default)
|
||
{
|
||
if (idleDuration < _idleThreshold && sessionCount < _sessionCountThreshold)
|
||
{
|
||
return null;
|
||
}
|
||
|
||
return await Task.FromResult(new MemoryEntry(
|
||
Id: Guid.NewGuid().ToString("N"),
|
||
Type: MemoryType.Dream,
|
||
SessionId: sessionId,
|
||
Content: "基于空闲周期与会话积累生成的自动梦境摘要。",
|
||
CreatedAt: DateTimeOffset.UtcNow,
|
||
Tags: new[] { "dream", "long-term" }));
|
||
}
|
||
}
|
||
```
|
||
|
||
## 5. 团队记忆同步服务
|
||
|
||
```csharp
|
||
public interface ITeamMemorySyncService
|
||
{
|
||
Task PushAsync(MemoryEntry entry, CancellationToken cancellationToken = default);
|
||
Task<MemoryEntry?> PullAsync(string memoryId, CancellationToken cancellationToken = default);
|
||
}
|
||
```
|
||
|
||
`ITeamMemorySyncService` 支持推送与拉取团队记忆。推送前必须执行 secret scanning,避免把敏感信息写入共享知识库。
|
||
|
||
```csharp
|
||
public sealed class TeamMemorySyncService : ITeamMemorySyncService
|
||
{
|
||
public Task PushAsync(MemoryEntry entry, CancellationToken cancellationToken = default)
|
||
{
|
||
var hasSecret = false;
|
||
if (hasSecret)
|
||
{
|
||
throw new InvalidOperationException("检测到敏感信息,禁止推送团队记忆。");
|
||
}
|
||
|
||
return Task.CompletedTask;
|
||
}
|
||
|
||
public Task<MemoryEntry?> PullAsync(string memoryId, CancellationToken cancellationToken = default)
|
||
=> Task.FromResult<MemoryEntry?>(null);
|
||
}
|
||
```
|
||
|
||
## 6. 设计说明
|
||
- 记忆相关操作使用轻量模型 `claude-haiku-4-5`,优先保证低延迟与低成本。
|
||
- 记忆抽取优先走阈值触发,避免每轮上下文都进行重处理。
|
||
- 团队记忆同步前必须进行 secret scanning,防止把密钥、令牌或隐私数据外发。
|
||
- 该子系统与查询引擎联动,用于补充局部上下文,而不是替代主对话历史。
|