# 服务子系统设计 — 会话记忆与上下文 ## 元数据 - 项目名称: 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 Tags); ``` `MemoryType` 用于区分会话记忆、自动梦境摘要与团队共享记忆。`MemoryEntry` 记录统一承载记忆内容、来源会话、创建时间和标签,便于检索与同步。 ## 3. 会话记忆服务 ```csharp public interface ISessionMemoryService { Task ExtractAsync( string sessionId, int tokenCount, int toolCallCount, CancellationToken cancellationToken = default); Task SaveAsync(MemoryEntry entry, CancellationToken cancellationToken = default); Task> 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 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> GetRecentAsync(string sessionId, CancellationToken cancellationToken = default) => Task.FromResult>(Array.Empty()); } ``` ## 4. 自动梦境服务 ```csharp public interface IAutoDreamService { Task 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 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 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 PullAsync(string memoryId, CancellationToken cancellationToken = default) => Task.FromResult(null); } ``` ## 6. 设计说明 - 记忆相关操作使用轻量模型 `claude-haiku-4-5`,优先保证低延迟与低成本。 - 记忆抽取优先走阈值触发,避免每轮上下文都进行重处理。 - 团队记忆同步前必须进行 secret scanning,防止把密钥、令牌或隐私数据外发。 - 该子系统与查询引擎联动,用于补充局部上下文,而不是替代主对话历史。