Agent Memory

Agent Memory System 设计:短期记忆、长期记忆与知识图谱

深入解析 AI Agent 记忆系统的架构设计,包括短期记忆管理、长期记忆存储和知识图谱构建的完整方案。

人类的记忆分为工作记忆、短期记忆和长期记忆。Agent 的记忆系统也需要类似的分层设计——工作记忆处理当前任务,短期记忆保持对话连贯,长期记忆积累知识和经验。

记忆系统架构

┌─────────────────────────────────────────┐
│            Agent Memory System           │
│                                         │
│  ┌─────────────┐  ┌──────────────────┐  │
│  │ 工作记忆     │  │ 短期记忆          │  │
│  │ (当前上下文) │  │ (对话历史)        │  │
│  └──────┬──────┘  └────────┬─────────┘  │
│         │                  │             │
│         └────────┬─────────┘             │
│                  │                       │
│         ┌────────┴─────────┐             │
│         │ 长期记忆          │             │
│         │ (向量数据库)      │             │
│         └────────┬─────────┘             │
│                  │                       │
│         ┌────────┴─────────┐             │
│         │ 知识图谱          │             │
│         │ (结构化知识)      │             │
│         └──────────────────┘             │
└─────────────────────────────────────────┘

工作记忆

工作记忆是 LLM 当前上下文窗口中的信息,是最快速但最有限的记忆。

class WorkingMemory {
  private content: string[] = [];
  private maxTokens: number;

  constructor(maxTokens: number = 4000) {
    this.maxTokens = maxTokens;
  }

  add(item: string): void {
    this.content.push(item);
    this.trim();
  }

  getContext(): string {
    return this.content.join('\n\n');
  }

  private trim(): void {
    let total = this.estimateTokens();
    while (total > this.maxTokens && this.content.length > 1) {
      this.content.shift();
      total = this.estimateTokens();
    }
  }

  private estimateTokens(): number {
    return this.content.reduce((sum, c) => sum + c.length / 4, 0);
  }
}

短期记忆

短期记忆保存最近的对话历史,支持快速检索。

class ShortTermMemory {
  private conversations: Map<string, Message[]> = new Map();
  private maxMessages: number;

  constructor(maxMessages: number = 50) {
    this.maxMessages = maxMessages;
  }

  addMessage(conversationId: string, message: Message): void {
    if (!this.conversations.has(conversationId)) {
      this.conversations.set(conversationId, []);
    }

    const messages = this.conversations.get(conversationId)!;
    messages.push(message);

    // 限制消息数量
    if (messages.length > this.maxMessages) {
      messages.splice(0, messages.length - this.maxMessages);
    }
  }

  getRecent(conversationId: string, count: number = 10): Message[] {
    const messages = this.conversations.get(conversationId) || [];
    return messages.slice(-count);
  }

  search(conversationId: string, query: string): Message[] {
    const messages = this.conversations.get(conversationId) || [];
    const keywords = query.toLowerCase().split(' ');

    return messages.filter(msg => {
      const content = (msg.content || '').toLowerCase();
      return keywords.some(kw => content.includes(kw));
    });
  }
}

长期记忆

长期记忆使用向量数据库存储,支持语义检索。

class LongTermMemory {
  private vectorStore: VectorStore;
  private embedder: Embedder;

  async store(memory: MemoryEntry): Promise<string> {
    const embedding = await this.embedder.embed(memory.content);
    const id = generateId();

    await this.vectorStore.upsert({
      id,
      vector: embedding,
      metadata: {
        content: memory.content,
        type: memory.type,
        agentId: memory.agentId,
        timestamp: Date.now(),
      },
    });

    return id;
  }

  async recall(query: string, agentId: string, limit: number = 5): Promise<MemoryEntry[]> {
    const queryEmbedding = await this.embedder.embed(query);

    const results = await this.vectorStore.query({
      vector: queryEmbedding,
      filter: { agentId },
      topK: limit,
    });

    return results.map(r => ({
      content: r.metadata.content,
      type: r.metadata.type,
      score: r.score,
    }));
  }

  async consolidate(agentId: string): Promise<void> {
    // 将短期记忆中的重要信息转移到长期记忆
    const recentMemories = await this.getRecent(agentId);
    const important = await this.filterImportant(recentMemories);

    for (const memory of important) {
      await this.store(memory);
    }
  }
}

知识图谱

知识图谱存储结构化的实体和关系,支持复杂推理。

class KnowledgeGraph {
  private nodes: Map<string, KGNode> = new Map();
  private edges: KGEdge[] = [];

  addNode(id: string, type: string, properties: Record<string, any>): void {
    this.nodes.set(id, { id, type, properties });
  }

  addEdge(from: string, to: string, relation: string, properties?: Record<string, any>): void {
    this.edges.push({ from, to, relation, properties });
  }

  query(startNode: string, relation: string): KGNode[] {
    const connectedEdges = this.edges.filter(
      e => e.from === startNode && e.relation === relation
    );
    return connectedEdges
      .map(e => this.nodes.get(e.to))
      .filter((n): n is KGNode => n !== undefined);
  }

  async buildFromText(text: string): Promise<void> {
    // 使用 LLM 从文本中提取实体和关系
    const extraction = await this.llmExtract(text);

    for (const entity of extraction.entities) {
      this.addNode(entity.id, entity.type, entity.properties);
    }

    for (const rel of extraction.relations) {
      this.addEdge(rel.from, rel.to, rel.type);
    }
  }
}

记忆整合策略

class MemoryManager {
  private working: WorkingMemory;
  private shortTerm: ShortTermMemory;
  private longTerm: LongTermMemory;
  private knowledgeGraph: KnowledgeGraph;

  async processInteraction(interaction: Interaction): Promise<void> {
    // 1. 更新工作记忆
    this.working.add(interaction.userMessage);
    this.working.add(interaction.agentResponse);

    // 2. 存储到短期记忆
    this.shortTerm.addMessage(interaction.conversationId, {
      role: 'user',
      content: interaction.userMessage,
    });
    this.shortTerm.addMessage(interaction.conversationId, {
      role: 'assistant',
      content: interaction.agentResponse,
    });

    // 3. 定期整合到长期记忆
    if (this.shouldConsolidate()) {
      await this.longTerm.consolidate(interaction.agentId);
    }

    // 4. 提取知识到图谱
    if (this.hasNewKnowledge(interaction)) {
      await this.knowledgeGraph.buildFromText(interaction.agentResponse);
    }
  }

  async recall(query: string, agentId: string): Promise<RecallResult> {
    // 从多个记忆层检索
    const longTermResults = await this.longTerm.recall(query, agentId);
    const kgResults = await this.queryKnowledgeGraph(query);

    return {
      memories: longTermResults,
      knowledge: kgResults,
    };
  }
}

常见问题(FAQ)

记忆系统的存储成本如何控制?

对长期记忆实施过期策略,定期清理低价值记忆。使用向量数据库的量化功能减少存储空间。

如何处理记忆冲突?

当新信息与旧记忆冲突时,以新信息为准。保留旧记忆的版本历史,支持回溯。

记忆系统的隐私保护如何实现?

对敏感信息进行脱敏处理后再存储。实施访问控制,确保不同用户的记忆隔离。

总结

Agent 记忆系统是实现长期、连贯交互的关键。通过分层设计(工作记忆、短期记忆、长期记忆、知识图谱),Agent 可以在不同的时间尺度上积累和利用知识。