跳转到主要内容

记忆服务

AG-Kit 的记忆服务为 AI Agent 提供全面的记忆管理,支持短期对话历史和长期知识持久化。该服务为不同的部署场景提供多种实现,从开发到企业生产环境。

概述

记忆服务由两个主要组件组成:
  • 短期记忆: 管理对话历史、上下文窗口和会话状态
  • 长期记忆: 存储持久化知识、用户偏好和提取的见解
这两个组件都支持智能上下文管理、自动令牌优化,以及与 AI Agent 框架的无缝集成。

记忆实现

AG-Kit 为不同的用例和部署场景提供多种短期记忆实现。每种实现都支持统一的分支和摘要架构以及上下文工程能力。

可用的实现

快速比较

实现存储类型持久化可扩展性用例
InMemoryMemory易失性单实例开发、测试
TDAIMemory云端生产、企业
TypeORMMemory数据库中高自定义模式、企业
MySQLMemoryMySQLMySQL 优化应用
MongoDBMemoryNoSQL非常高灵活模式、分析
CloudBaseMemory无服务器自动中国市场、无服务器

基本用法示例

import { InMemoryMemory, TDAIMemory, TypeORMMemory } from '@ag-kit/agents/storage';

// 根据需求选择实现
const memory = new InMemoryMemory(); // 用于开发
// const memory = new TDAIMemory({ ... }); // 用于生产
// const memory = new TypeORMMemory({ ... }); // 用于自定义数据库

// 所有实现共享相同的接口
await memory.add({
  message: {
    id: 'msg-1',
    role: 'user',
    content: 'Hello, I need help with my project',
    timestamp: new Date()
  },
  state: { userId: 'user-123', context: 'project-help' }
});

// 跨所有实现的常用操作
const events = await memory.list({ limit: 10, maxTokens: 4000 });
const results = await memory.retrieve('project help');
const count = await memory.getCount();
有关详细的实现指南、配置选项和高级功能,请参阅上面链接的各个实现文档。

核心数据结构

Message

id
string
必填
唯一消息标识符
role
'user' | 'assistant' | 'system' | 'tool'
必填
消息角色类型
content
string
必填
消息内容文本
timestamp
Date
消息时间戳
toolCalls
any[]
与消息关联的工具调用
toolCallId
string
工具调用标识符

IMemoryEvent

message
Message
必填
消息数据
state
Record<string, any>
必填
事件状态和元数据

上下文工程

内置的自动上下文管理,用于在长对话中实现最佳性能。

配置类型

ContextThresholds

preRotThreshold
number
默认值:"150_000"
性能开始下降的阈值
compactionTrigger
number
默认值:"0.8"
在 preRotThreshold 的此百分比时触发压缩
summarizationTrigger
number
默认值:"0.95"
在 preRotThreshold 的此百分比时触发摘要

StructuredSummary

modifiedFiles
string[]
已更改的文件
userGoal
string
用户的目标
lastStep
string
最后完成的步骤
keyDecisions
string[]
已做出的重要决策
criticalContext
Record<string, any>
需要保留的关键上下文
timestamp
Date
创建摘要的时间
preSummaryDump
IMemoryEvent[]
用于恢复的可选上下文转储

通用功能

所有记忆实现共享以下核心能力:

上下文工程

具有智能压缩和摘要的自动上下文管理:
// 配置上下文阈值以进行自动管理
const memory = new SomeMemory({
  enableContextManagement: true,
  thresholds: {
    preRotThreshold: 8000,        // 在 8000 个令牌时开始管理
    compactionTrigger: 0.8,       // 在阈值的 80% 时压缩
    summarizationTrigger: 0.95,   // 在阈值的 95% 时摘要
    recentToKeep: 10              // 始终保留最后 10 条消息
  }
});

// 在操作期间自动管理上下文
await memory.add(event); // 如果需要,自动触发压缩

令牌管理

内置令牌计数和修剪,支持多种策略:
import { TokenTrimmer, TiktokenTokenizer } from '@ag-kit/agents/storage';

// 创建分词器和修剪器
const tokenizer = new TiktokenTokenizer('gpt-4');
const trimmer = new TokenTrimmer(tokenizer);

// 计数令牌
const tokenCount = tokenizer.countTokens('Hello, world!');

// 修剪消息以适应上下文窗口
const events = await memory.list();
const trimmed = trimmer.trimMessages(events, 4000, 'newest_first');

基于内容的搜索

跨所有实现的相似性搜索和相关性评分:
// 语义搜索相关记忆
const results = await memory.retrieve('project help', {
  limit: 5,
  threshold: 0.7,
  sessionId: 'user-session'
});

// 结果包含相关性分数
results.forEach(event => {
  console.log(`Score: ${event.score}, Content: ${event.message.content}`);
});

会话管理

多会话支持,具有隔离的对话上下文:
// 使用不同的会话
await memory.add(event1, { sessionId: 'session-A' });
await memory.add(event2, { sessionId: 'session-B' });

// 会话实用程序
const sessionIds = memory.getSessionIds?.() || [];
const count = await memory.getCount({ sessionId: 'session-A' });
await memory.clear({ sessionId: 'session-A' });

会话分支

会话分支启用类 Git 的对话实验和时间旅行功能。创建实验性对话路径,测试不同的响应,并回滚到以前的状态。

关键特性

  • 对话实验: 在不丢失原始对话的情况下尝试不同的路径
  • 时间旅行: 检出到任何先前的事件并从那里继续
  • A/B 测试: 在并行分支中比较不同的 Agent 响应
  • 撤销/回滚: 轻松恢复不需要的更改

基本操作

// 创建并切换到新分支
await memory.branch('experiment-1');
await memory.checkout('experiment-1');

// 列出所有分支
const branches = await memory.listBranches();

// 时间旅行到特定事件
await memory.checkout('msg-5', { type: 'event' });

// 清理未使用的分支
await memory.cleanupBranches();

实现支持

实现分支支持
InMemoryMemory✅ 完全支持
TDAIMemory❌ 不可用
TypeORMMemory✅ 完全支持
MySQLMemory✅ 完全支持
MongoDBMemory✅ 完全支持
CloudBaseMemory✅ 完全支持
有关详细的分支操作和示例,请参阅各个实现文档。

令牌管理

AG-Kit 提供全面的令牌管理实用程序,用于处理 LLM 上下文窗口和优化内存使用。

关键特性

  • 精确分词: TiktokenTokenizer 用于精确的 OpenAI 模型令牌计数
  • 智能修剪: 具有多种策略的自动消息修剪
  • 上下文管理: 与所有记忆实现的内置集成
  • 性能优化: 具有资源管理的高效令牌操作

基本用法

import { TokenTrimmer, TiktokenTokenizer } from '@ag-kit/agents/storage';

// 创建分词器和修剪器
const tokenizer = new TiktokenTokenizer('gpt-4');
const trimmer = new TokenTrimmer(tokenizer);

// 计数令牌
const tokenCount = tokenizer.countTokens('Hello, world!');

// 修剪消息以适应上下文窗口
const events = await memory.list();
const trimmed = trimmer.trimMessages(events, 4000, 'newest_first');

长期记忆

长期记忆智能地从对话中提取和存储重要信息,以构建持久的用户档案、偏好和知识库。

关键特性

  • 智能提取: 自动识别重要信息
  • 语义搜索: 基于高级相似性的检索
  • 记忆合并: 去重和关系映射
  • 基于策略的组织: 按类型和用途对记忆进行分类

可用的实现

基本用法

import { Mem0LongTermMemory } from '@ag-kit/agents/storage';

const longTermMemory = new Mem0LongTermMemory({
  apiKey: 'your-mem0-api-key',
  userId: 'user-123'
});

// 记录记忆
await longTermMemory.record({
  id: 'mem-1',
  strategy: 'user_preferences',
  content: 'User prefers dark mode and minimal UI',
  metadata: { confidence: 0.9 },
  createdAt: new Date()
});

// 语义搜索
const results = await longTermMemory.semanticSearch('UI preferences');
有关详细的长期记忆文档,请参阅长期记忆指南

核心数据结构

interface MemoryEntity {
  id: string;
  strategy: string;                    // 用于组织的记忆策略/类别
  role?: 'user' | 'assistant';         // 可选角色信息
  content: string;                     // 记忆内容文本
  metadata: Record<string, any>;       // 额外的上下文和元数据
  createdAt: Date;                     // 创建时间戳
  updatedAt?: Date;                    // 最后更新时间戳
}

interface MemoryQuery {
  query?: string;                      // 用于搜索的语义查询文本
  strategy?: string | string[];        // 策略过滤器
  limit?: number;                      // 返回的最大结果数
  offset?: number;                     // 分页偏移量
  threshold?: number;                  // 相似性阈值 (0-1)
  filters?: Record<string, any>;       // 额外过滤器
  orderBy?: Record<string, 'asc' | 'desc'>; // 排序选项
  [key: string]: any;                  // 可扩展以用于特定实现的选项
}

基础接口

abstract class BaseLongTermMemory {
  // 核心 CRUD 操作
  abstract record(memory: MemoryEntity): Promise<void>;
  abstract recordBatch(memories: MemoryEntity[]): Promise<void>;
  abstract retrieve(query: MemoryQuery): Promise<MemoryEntity[]>;
  abstract delete(memoryId: string | MemoryQuery): Promise<void>;
  abstract update(memoryId: string, updates: Partial<MemoryEntity>): Promise<void>;
  abstract clear(strategy?: string): Promise<void>;

  // 高级功能
  abstract extractAndRecord(messages: Message[], context: Record<string, any>): Promise<MemoryEntity[]>;
  abstract semanticSearch(query: string, options?: MemoryQuery): Promise<MemoryEntity[]>;
  abstract getRelatedMemories(memoryId: string, depth?: number): Promise<MemoryEntity[]>;
  abstract consolidate(): Promise<void>;
}

API 参考

BaseMemory (抽象类)

所有记忆实现的基础类,具有内置的上下文工程。所有记忆实现都继承自此类并提供一致的接口方法。

构造函数

config
BaseMemoryConfig
记忆和上下文工程的配置

核心接口方法

所有记忆实现都从 BaseMemory 继承这些方法,以实现跨不同存储后端的一致记忆管理。
基本操作
list(options?): Promise<IMemoryEvent[]>
使用过滤和分页支持检索事件。
options
ListOptions
可选的过滤和分页参数
Promise<IMemoryEvent[]>
Promise<IMemoryEvent[]>
必填
符合条件的记忆事件数组
add(event, options?): Promise<void>
将单个事件添加到记忆存储。
event
IMemoryEvent
必填
要存储的记忆事件
options
AddOptions
事件存储的可选参数
addList(events, options?): Promise<void>
在批量操作中高效地添加多个事件。
events
IMemoryEvent[]
必填
要存储的记忆事件数组
options
AddOptions
批量存储的可选参数
delete(idOrIndex, options?): Promise<void>
从记忆中删除特定事件。
idOrIndex
string | number
必填
要删除的事件 ID 或索引
options
DeleteOptions
删除的可选参数
retrieve(query, options?): Promise<IMemoryEvent[]>
使用相似性匹配按内容搜索事件。
query
string
必填
用于内容匹配的搜索查询文本
options
RetrieveOptions
可选的搜索参数
Promise<IMemoryEvent[]>
Promise<IMemoryEvent[]>
必填
具有相关性分数的匹配事件数组
clear(options?): Promise<void>
使用可选过滤从存储中清除事件。
options
ClearOptions
选择性清除的可选参数
getCount(options?): Promise<number>
获取存储中的事件总数。
options
CountOptions
计数的可选参数
Promise<number>
Promise<number>
必填
符合条件的事件总数
isEmpty(options?): Promise<boolean>
检查记忆存储是否为空。
options
CountOptions
空检查的可选参数
Promise<boolean>
Promise<boolean>
必填
如果不存在符合条件的事件,则为 True
分支方法(在支持的地方)
在支持对话分支的实现中可用 (InMemoryMemory、TypeORMMemory、MySQLMemory、MongoDBMemory、CloudBaseMemory)。
branch(name, fromEventId?): Promise<void>
创建一个新的对话分支以进行实验。
name
string
必填
新分支的唯一名称
fromEventId
string
要从中分支的事件 ID(默认为当前 HEAD)
checkout(target, options?): Promise<void>
切换到不同的分支或检出特定事件。
target
string
必填
要检出的分支名称或事件 ID
options
CheckoutOptions
可选的检出参数
listBranches(): Promise<string[]>
列出记忆存储中的所有可用分支。
Promise<string[]>
Promise<string[]>
必填
分支名称数组
deleteBranch(name): Promise<void>
删除特定分支及其所有事件。
name
string
必填
要删除的分支名称
cleanupBranches(keep?): Promise<void>
删除未使用的分支以优化存储。
keep
string[]
要保留的分支名称数组(默认为当前分支)

上下文工程方法

isCompacted(event: IMemoryEvent): boolean
检查事件是否已压缩。
event
IMemoryEvent
必填
要检查压缩的事件
boolean
boolean
必填
如果事件具有压缩元数据,则为 True
decompressEvent(event: IMemoryEvent): IMemoryEvent
解压缩已压缩的事件以恢复原始内容。
event
IMemoryEvent
必填
要解压缩的已压缩事件
IMemoryEvent
IMemoryEvent
必填
具有原始内容和状态的解压缩事件
decompressEvents(events: IMemoryEvent[]): IMemoryEvent[]
解压缩多个已压缩的事件。
events
IMemoryEvent[]
必填
要解压缩的事件数组
IMemoryEvent[]
IMemoryEvent[]
必填
解压缩的事件数组
getMetrics(): object
获取上下文管理操作的性能指标。
object
object
必填
包含性能统计信息的指标对象

长期记忆 API

Mem0LongTermMemory

构造函数
constructor(config: Mem0LongTermMemoryConfig)
config
Mem0LongTermMemoryConfig
必填
Mem0 配置对象
方法
record(memory: MemoryEntity): Promise<void>
使用智能处理将新的记忆实体记录到 Mem0 服务。
memory
MemoryEntity
必填
包含内容和元数据的完整记忆实体
semanticSearch(query: string, options?: MemoryQuery): Promise<MemoryEntity[]>
使用 Mem0 的 AI 驱动相似性匹配执行高级语义搜索。
query
string
必填
用于语义匹配的搜索查询文本
options
MemoryQuery
搜索配置选项
Promise<MemoryEntity[]>
Promise<MemoryEntity[]>
必填
具有相关性分数的匹配记忆数组
extractAndRecord(messages: Message[], context: Record<string, any>): Promise<MemoryEntity[]>
使用 AI 自动从对话消息中提取和记录重要记忆。
messages
Message[]
必填
要分析的对话消息数组
context
Record<string, any>
必填
用于记忆提取的额外上下文
Promise<MemoryEntity[]>
Promise<MemoryEntity[]>
必填
提取和记录的记忆数组

令牌管理 API

TiktokenTokenizer

构造函数
constructor(encodingName?: TiktokenEncoding)
encodingName
TiktokenEncoding
默认值:"o200k_base"
Tiktoken 编码名称。支持的编码: 'o200k_base', 'cl100k_base', 'p50k_base', 'r50k_base', 'gpt2'
方法
encode(text: string): Uint32Array
使用 tiktoken 将文本编码为令牌数组。
text
string
必填
要编码为令牌的文本
Uint32Array
Uint32Array
必填
令牌 ID 数组
decode(tokens: Uint32Array): string
将令牌解码回文本。
tokens
Uint32Array
必填
要解码的令牌 ID 数组
string
string
必填
解码的文本字符串
countTokens(text: string): number
计算文本中的令牌数。
text
string
必填
要计数令牌的文本
number
number
必填
文本中的令牌数
free(): void
释放编码资源。

TokenTrimmer

构造函数
constructor(tokenizer?: ITokenizer)
方法
countMessageTokens(message: { role: string; content: string }): number
计算消息的令牌数,包括格式化开销。 参数:
message
{ role: string; content: string }
必填
要计数令牌的消息对象
返回:
number
number
必填
包括角色和格式化开销的总令牌数
trimMessages<T>(events: T[], maxTokens: number, strategy?: 'newest_first' | 'oldest_first'): T[]
使用指定策略修剪消息列表以适应令牌限制。 参数:
events
T[]
必填
要修剪的事件/消息数组
maxTokens
number
必填
修剪列表的最大令牌限制
strategy
'newest_first' | 'oldest_first'
默认值:"newest_first"
修剪策略 - 超出限制时保留哪些消息
返回:
T[]
T[]
必填
令牌限制内的修剪事件数组
修剪行为:
  • newest_first: 保留最新消息,修剪较旧的消息
  • oldest_first: 保留最早消息,修剪较新的消息
  • 超出限制的单个消息将使用 ”…” 后缀截断
  • 考虑 ChatML 格式化开销(每条消息 4 个令牌)
free(): void
释放分词器资源。 返回:
void
void
必填
无返回值

SimpleTokenizer

构造函数
constructor(tokensPerChar?: number)
tokensPerChar
number
默认值:"0.25"
估计的每字符令牌比率
方法
encode(text: string): Uint32Array
简单的基于字符的编码(每个字符成为一个令牌)。 参数:
text
string
必填
要编码的文本
返回:
Uint32Array
Uint32Array
必填
字符代码作为令牌的数组
decode(tokens: Uint32Array): string
将基于字符的令牌解码回文本。 参数:
tokens
Uint32Array
必填
要解码的令牌数组
返回:
string
string
必填
解码的文本字符串
countTokens(text: string): number
基于字符长度和比率估计令牌数。 参数:
text
string
必填
要计数令牌的文本
返回:
number
number
必填
估计的令牌数

完整用法示例

多会话聊天应用

import { InMemoryMemory, Mem0LongTermMemory } from '@ag-kit/agents/storage';

class ChatApplication {
  private shortTermMemory: InMemoryMemory;
  private longTermMemory: Mem0LongTermMemory;

  constructor() {
    this.shortTermMemory = new InMemoryMemory();
    this.longTermMemory = new Mem0LongTermMemory({
      apiKey: process.env.MEM0_API_KEY!,
      userId: 'default-user'
    });
  }

  async handleMessage(sessionId: string, userId: string, message: string) {
    // 存储在短期记忆中
    await this.shortTermMemory.add({
      message: {
        id: `msg-${Date.now()}`,
        role: 'user',
        content: message,
        timestamp: new Date()
      },
      state: { userId, sessionId, context: 'chat' }
    }, { sessionId });

    // 获取对话上下文(最后 10 条消息,最多 4000 个令牌)
    const context = await this.shortTermMemory.list({
      sessionId,
      limit: 10,
      order: 'desc',
      maxTokens: 4000
    });

    // 搜索长期记忆以获取相关信息
    const relevantMemories = await this.longTermMemory.semanticSearch(message, {
      threshold: 0.7,
      limit: 5
    });

    return context;
  }
}

基本操作

// 创建并切换到新分支
await memory.branch('experiment-1');
await memory.checkout('experiment-1');

// 列出所有分支
const branches = await memory.listBranches();

// 时间旅行到特定事件
await memory.checkout('msg-5', { type: 'event' });

// 清理未使用的分支
await memory.cleanupBranches();

下一步