Ohhnews

分类导航

$ cd ..
Baeldung原文

Spring AI AutoMemoryTools:为AI代理赋予长期记忆能力

#spring ai#automemorytools#长期记忆#ai代理#java开发

[LOADING...]

1. 概述

随着 AI 智能体的能力越来越强,长期记忆已变得与推理能力同样重要。ChatMemory检索增强生成(RAG)等机制负责处理对话和外部知识,但它们并未回答另一个问题:智能体应永久记住关于用户或项目的哪些内容?

Spring AI AutoMemoryTools 通过让智能体能够持久化和回忆长期记忆(如用户偏好和项目特定知识)来解决这一问题。

在本文中,我们将探讨 AutoMemoryTools 的架构和组件,并构建一个简单的 Spring Boot 聊天机器人来演示其工作方式。

2. 依赖

让我们从定义演示 Spring AI AutoMemoryTools 所需的最少依赖开始。 我们需要 spring-ai-starter-model-openaispring-ai-agent-utils。前者是用于将任何 OpenAI 兼容 API 与 Spring AI 集成的启动器,后者包含本文要探讨的工具。我们可以使用(当前)最新版本:

$ xml
<dependency>
    <groupId>org.springframework.ai</groupId>
    <artifactId>spring-ai-starter-model-openai</artifactId>
    <version>2.0.0</version>
</dependency>
<dependency>
    <groupId>org.springaicommunity</groupId>
    <artifactId>spring-ai-agent-utils</artifactId>
    <version>0.10.0</version>
</dependency>

3. Spring AI AutoMemoryTools

Spring AI AutoMemoryTools 是一个 Spring AI 社区库,为 AI 智能体实现长期记忆。它使用工具调用和基于文件的持久化。 它是 Spring AI Agent Utils 的一部分,类似于 Agent Skills。值得一提的是,它深受 Claude Code 的启发,让开发人员无需自行实现常见的智能体能力。

与用于对话记忆的 MessageChatMemoryAdvisor 类似,Spring AI AutoMemoryTools 也实现了 BaseChatMemoryAdvisor。这意味着它与对话记忆相关,但不关注对话部分,而是旨在存储关于用户偏好、项目、反馈等概念的信息。

3.1. 记忆类型

我们来看看 Spring AI AutoMemoryTools 所针对的记忆类型:

  • 用户:记住用户是谁,以及如何最好地帮助他们
  • 反馈:记住用户希望 AI 如何表现
  • 项目:记住重要的项目背景和决策
  • 参考:记住在哪里可以找到外部系统中的信息

稍后我们将看到,这些在 AUTO_MEMORY_TOOLS_SYSTEM_PROMPT.md 中得到了最好的描述,该文件是依赖资源的一部分。我们还会看到如何用自定义的 PromptSystemSpec 覆盖这个默认文件。这意味着,除非我们定义这些记忆类型,否则它们可能不再存在。

3.2. 工具

现在,让我们逐一了解 AutoMemoryTools 的六个不同工具:

  • MemoryView:读取记忆文件的内容,或列出目录中可用的记忆文件
  • MemoryCreate:创建新的记忆文件以持久化长期信息
  • MemoryStrReplace:通过替换一段精确文本来更新现有记忆
  • MemoryInsert:在现有记忆文件中的特定位置插入新内容
  • MemoryDelete:从持久化存储中删除记忆文件或目录
  • MemoryRename:重命名或移动记忆文件,同时保留其内容

3.3. 记忆系统提示词

正如我们之前看到的,AUTO_MEMORY_TOOLS_SYSTEM_PROMPT.md 是库的一部分。该库提供两种不同级别的抽象。第一种是沙箱化的,即使用 Spring AI AutoMemoryTools 限制智能体访问的受限环境。另一种是 FileSystemToolsShellTools 的不受限制使用。

实际上,AutoMemoryTools 是构建在通用文件系统操作之上的专用抽象。智能体可以访问和管理指定记忆目录(如 memory/usermemory/feedback 等)中的记忆文件,但不应具有在记忆目录之外执行任何操作的权限。相反,FileSystemToolsShellTools 是不受限制的,除非开发人员恰当地处理这个问题。

3.4. 工作原理——综合展示

既然我们已经介绍了各个组件,让我们看看请求如何流经 Spring AI AutoMemoryTools。

当用户发送请求时,LLM 将记忆系统提示词与用户消息结合起来,以确定是应该从记忆读取还是写入记忆。 如果需要,它会调用 AutoMemoryTools 来管理配置的记忆目录中的 Markdown 文件,如默认的 AUTO_MEMORY_TOOLS_SYSTEM_PROMPT.md 所描述。

生成响应后,LLM 可能会执行额外的记忆操作,例如调用更多工具或整合现有记忆条目。最后,它将响应返回给用户。

4. Spring AI AutoMemoryTools 应用

将所有这些整合起来,让我们看看实际效果。我们将看到三种配置 ChatClient 以使用 Spring AI AutoMemoryTools 的场景:

  • 全默认 AutoMemoryToolsAdvisor(沙箱操作)
  • 手动配置 AutoMemoryToolsAdvisor(沙箱操作)
  • FileSystemToolsShellTools(默认不进行沙箱隔离)

4.1. 默认 AutoMemoryToolsAdvisor 配置

对于第一种场景,我们使用所需的最小默认配置创建一个 AutoMemoryToolsAdvisor:

$ java
@Configuration
class ChatClientConfiguration {
    @Value("${agent.memory.dir}")
    String memoryDirectory;
    ChatClient chatClient(ChatModel chatModel) {
        return ChatClient
          .builder(chatModel)
          .defaultAdvisors(
            AutoMemoryToolsAdvisor.builder()
              .memoriesRootDirectory(memoryDirectory)
              .build(),
            MessageChatMemoryAdvisor.builder(
              MessageWindowChatMemory.builder()
                .maxMessages(100)
                .build())
            .build(),
            ToolCallingAdvisor.builder()
              .disableInternalConversationHistory()
              .build())
          .build();
    }
}

此设置使用默认的 AUTO_MEMORY_TOOLS_SYSTEM_PROMPT.md,并定义了我们之前解释过的记忆类型。我们使用 Advisor 拦截所有消息交换。memoriesRootDirectory() 方法设置记忆目录,这也是智能体的访问边界。最后,MessageChatMemoryAdvisor 是用于处理对话方面记忆的已知 Advisor。我们设置了一个随机值:100 条消息历史。

4.2. 自定义 AutoMemoryTools 配置

如果我们仍然想要沙箱化的 AutoMemoryTools,但有更多系统提示词需要包含,我们可以使用更自定义的方法:

$ java
@Configuration
class ChatClientConfiguration {
    // ...
    @Value("classpath:/prompts/AUTO_MEMORY_TOOLS_SYSTEM_PROMPT.md")
    Resource memorySystemPromptAutoMemoryTools;
    // ....
    @Bean
    ChatClient chatClientWithMoreSystemPrompt(ChatModel chatModel) {
        return ChatClient
          .builder(chatModel)
          .defaultSystem(p -> p
            .text(memorySystemPromptAutoMemoryTools)
            .param("MEMORIES_ROOT_DIERCTORY", memoryDirectory))
          .defaultTools(
            AutoMemoryTools.builder()
              .memoriesDir(memoryDirectory)
              .build(),
            TodoWriteTool.builder()
              .build())
          .defaultAdvisors(ToolCallingAdvisor.builder()
              .build())
          .build();
    }
}

在这里,我们做了与之前类似的设置,但改为使用 Tools。这样,我们可以使用提供的 .md 文件中的提示词来定义自定义 PromptSystemSpec。然而,这个提示词是 AutoMemoryTools 的核心,我们应该在其中定义记忆类型、存储方式等。因此,如果需要覆盖它,最好复制默认提示词并附加额外的系统提示词。

我们应注意,这里没有设置 ChatMemory,但使用了 TodoWriteTool。这与 Spring AI AutoMemoryTools 无关,只是为了表明我们可以根据智能体的需求决定是否添加更多工具和 Advisor。

4.3. FileSystemToolsShellTools

最后,我们可以使用 FileSystemToolsShellTools 实现不受限制的场景。例如,如果智能体已经为其他任务配备了 FileSystemTools 或 ShellTools,则不需要 AutoMemoryTools

$ java
@Configuration
class ChatClientConfiguration {
    // ...
    @Value("classpath:/prompts/AUTO_MEMORY_FILESYSTEM_TOOLS_SYSTEM_PROMPT.md")
    Resource memorySystemPromptFilesystemTools;
    // ....
    @Bean
    ChatClient chatClientWithoutAutoMemoryTools(ChatModel chatModel) {
      return ChatClient
        .builder(chatModel)
        .defaultSystem(p -> p
          .text(memorySystemPromptFilesystemTools)
          .param("MEMORIES_ROOT_DIERCTORY", memoryDirectory))   // tells the agent where to write
          .defaultTools(
            ShellTools.builder()
              .build(),         // Bash --- mkdir, ls, etc.
            FileSystemTools.builder()
              .build())    // Read, Write, Edit --- memory file operations
          .defaultAdvisors(ToolCallingAdvisor.builder()
              .build())
        .build();
    }
}

文件 AUTO_MEMORY_FILESYSTEM_TOOLS_SYSTEM_PROMPT.md 也可以在库中找到。为了演示,我们可以将其复制过来。使用这个文件时,同样的记忆约定适用:.md 文件、两步保存等。但智能体通常具有完整的文件系统访问权限,并且只在配置的目录中操作。

这两个工具是智能体执行所有文件创建、删除、编辑等操作以在文件系统中保存记忆所需的工具。

4.4. 其他项目文件

为了演示,我们将使用 spring-web-mvc,并带有一个 RestController

$ java
@PostMapping("/chat-with-memory")
ResponseEntity<String> chat(@RequestBody String question, @RequestHeader("X-Conversation-ID") String conversationId) {
    String answer = chatClient
      .prompt()
      .advisors(a -> a.param(ChatMemory.CONVERSATION_ID, conversationId))
      .user(question)
      .call()
      .content();
    return ResponseEntity.ok(answer);
}

如前所述,conversationId 是必需的,因为 Spring AI AutoMemoryTools 实现了 BaseChatMemoryAdvisor

让我们使用本地 Ollama Qwen 模型运行应用程序:

[LOADING...]

首先,我们让智能体保存一些信息。然后我们请求这些信息,但请注意使用不同的 conversationId!智能体对 session-1 一无所知。再次以 session-2 身份提问时,智能体记住了这些信息。

取决于我们的机器,智能体与文件系统的交互可能会很慢。我们还可以看到智能体创建的目录以及文件内容:

[LOADING...]

5. 结语

在本文中,我们全面了解了 Spring AI AutoMemoryTools。我们介绍了使用场景和基本定义,然后逐一讲解了六种操作以及使用它们的三种选项。最后,我们用 Spring AI 进行了实际演示。

一如既往,示例的源代码可以在 GitHub 上找到。