AI项目博客
记录 AI 工程实践与大模型应用

Spring AI Alibaba 21|Memory 短期记忆 · 访问记忆

你可以通过多种方式访问和修改 Agent 的短期记忆(状态):

工具

在工具中读取短期记忆

使用 ToolContext 参数在工具中访问短期记忆(状态)。

toolContext 参数从工具签名中隐藏(因此模型看不到它),但工具可以通过它访问状态。

import com.alibaba.cloud.ai.graph.RunnableConfig;
import org.springframework.ai.tool.ToolCallback;
import org.springframework.ai.tool.function.FunctionToolCallback;
import org.springframework.ai.chat.model.ToolContext;
import org.springframework.ai.chat.messages.AssistantMessage;
import com.alibaba.cloud.ai.graph.checkpoint.savers.MemorySaver;
import java.util.function.BiFunction;

public class UserInfoTool implements BiFunction<String, ToolContext, String> {

  @Override
  public String apply(String query, ToolContext toolContext) {
      // 从上下文中获取用户信息
      RunnableConfig config = (RunnableConfig) toolContext.getContext().get("config");
      String userId = (String) config.metadata("user_id").orElse("");

      if ("user_123".equals(userId)) {
          return "用户是 John Smith";
      } else {
          return "未知用户";
      }
  }
}

// 创建工具
ToolCallback getUserInfoTool = FunctionToolCallback
  .builder("get_user_info", new UserInfoTool())
  .description("查找用户信息")
  .inputType(String.class)
  .build();

// 使用
ReactAgent agent = ReactAgent.builder()
  .name("my_agent")
  .model(chatModel)
  .tools(getUserInfoTool)
  .saver(new MemorySaver())
  .build();

RunnableConfig config = RunnableConfig.builder()
  .threadId("1")
  .addMetadata("user_id", "user_123")
  .build();

AssistantMessage response = agent.call("获取用户信息", config);
System.out.println(response.getText());

从工具写入短期记忆

要在执行期间修改 Agent 的短期记忆(状态),你可以在 Hook 中更新状态,或者使用工具返回的信息更新状态。

这对于持久化中间结果或使信息对后续工具或提示可访问很有用。

提示

在 Hook 中访问短期记忆(状态)以基于对话历史或自定义状态字段创建动态提示。

import com.alibaba.cloud.ai.graph.agent.interceptor.ModelInterceptor;
import com.alibaba.cloud.ai.graph.agent.interceptor.ModelRequest;
import com.alibaba.cloud.ai.graph.agent.interceptor.ModelResponse;
import com.alibaba.cloud.ai.graph.agent.interceptor.ModelCallHandler;

public class DynamicPromptInterceptor extends ModelInterceptor {

  @Override
  public ModelResponse interceptModel(ModelRequest request, ModelCallHandler handler) {
      // 从上下文中获取用户名
      Map<String, Object> context = request.getContext();
      String userName = (String) context.get("user_name");

      // 创建动态系统提示
      String systemPrompt = "你是一个有帮助的助手。称呼用户为 " + userName + "。";

      // 创建修改后的请求(示例),实际使用中需要根据具体 API 进行调整
	SystemMessage enhancedSystemMessage;
	if (request.getSystemMessage() == null) {
		enhancedSystemMessage = new SystemMessage(systemPrompt);
	} else {
		enhancedSystemMessage = new SystemMessage(request.getSystemMessage().getText() + "

" + systemPrompt);
	}

	// Create enhanced request
	ModelRequest enhancedRequest = ModelRequest.builder(request)
			.systemMessage(enhancedSystemMessage)
			.build();

      return handler.call(enhancedRequest);
  }

  @Override
  public String getName() {
      return "DynamicPromptInterceptor";
  }
}

ReactAgent agent = ReactAgent.builder()
  .name("my_agent")
  .model(chatModel)
  .tools(getWeatherTool)
  .interceptors(new DynamicPromptInterceptor())
  .build();

// 使用时传递上下文
Map<String, Object> context = Map.of("user_name", "John Smith");

Before Model

在 beforeModel Hook 中访问短期记忆(状态)以在模型调用之前处理消息。

import com.alibaba.cloud.ai.graph.agent.hook.HookPosition;
import com.alibaba.cloud.ai.graph.agent.hook.HookPositions;
import com.alibaba.cloud.ai.graph.agent.hook.messages.MessagesModelHook;
import com.alibaba.cloud.ai.graph.agent.hook.messages.AgentCommand;
import com.alibaba.cloud.ai.graph.agent.hook.messages.UpdatePolicy;
import com.alibaba.cloud.ai.graph.RunnableConfig;
import org.springframework.ai.chat.messages.Message;
import java.util.ArrayList;
import java.util.List;

@HookPositions({HookPosition.BEFORE_MODEL})
public class TrimMessagesHook extends MessagesModelHook {

  @Override
  public String getName() {
      return "trim_messages";
  }

  @Override
  public AgentCommand beforeModel(List<Message> previousMessages, RunnableConfig config) {
      if (previousMessages.size() <= 3) {
          return new AgentCommand(previousMessages); // 无需更改
      }

      // 保留第一条和最后几条消息
      Message firstMsg = previousMessages.get(0);
      List<Message> recentMessages = previousMessages.subList(
          previousMessages.size() - 3,
          previousMessages.size()
      );

      List<Message> trimmedMessages = new ArrayList<>();
      trimmedMessages.add(firstMsg);
      trimmedMessages.addAll(recentMessages);

      // 使用 REPLACE 策略替换消息列表,只保留需要的消息
      return new AgentCommand(trimmedMessages, UpdatePolicy.REPLACE);
  }
}

ReactAgent agent = ReactAgent.builder()
  .name("my_agent")
  .model(chatModel)
  .tools(tools)
  .hooks(new TrimMessagesHook())
  .saver(new MemorySaver())
  .build();

After Model

在 afterModel Hook 中访问短期记忆(状态)以在模型调用之后处理消息。

import com.alibaba.cloud.ai.graph.agent.hook.HookPosition;
import com.alibaba.cloud.ai.graph.agent.hook.HookPositions;
import com.alibaba.cloud.ai.graph.agent.hook.messages.MessagesModelHook;
import com.alibaba.cloud.ai.graph.agent.hook.messages.AgentCommand;
import com.alibaba.cloud.ai.graph.agent.hook.messages.UpdatePolicy;
import com.alibaba.cloud.ai.graph.RunnableConfig;
import org.springframework.ai.chat.messages.AssistantMessage;
import org.springframework.ai.chat.messages.Message;
import java.util.ArrayList;
import java.util.List;

@HookPositions({HookPosition.AFTER_MODEL})
public class ValidateResponseHook extends MessagesModelHook {

  private static final List<String> STOP_WORDS =
      List.of("password", "secret", "api_key");

  @Override
  public String getName() {
      return "validate_response";
  }

  @Override
  public AgentCommand afterModel(List<Message> previousMessages, RunnableConfig config) {
      if (previousMessages.isEmpty()) {
          return new AgentCommand(previousMessages);
      }

      Message lastMessage = previousMessages.get(previousMessages.size() - 1);
      String content = lastMessage.getText();

      // 检查是否包含敏感词
      for (String stopWord : STOP_WORDS) {
          if (content.toLowerCase().contains(stopWord)) {
              // 移除包含敏感词的消息,替换为安全消息
              List<Message> filtered = new ArrayList<>(
                  previousMessages.subList(0, previousMessages.size() - 1)
              );
              filtered.add(new AssistantMessage("抱歉,我无法提供该信息。"));
              return new AgentCommand(filtered, UpdatePolicy.REPLACE);
          }
      }

      return new AgentCommand(previousMessages);
  }
}

ReactAgent agent = ReactAgent.builder()
  .name("secure_agent")
  .model(chatModel)
  .hooks(new ValidateResponseHook())
  .saver(new MemorySaver())
  .build();
  • Agents 文档 – 了解 ReactAgent 的核心概念
  • Hooks 和 Interceptors – 了解如何扩展 Agent 功能
  • Messages 文档 – 了解消息类型和使用

本文整理自 Spring AI Alibaba 官方文档《Memory 短期记忆》:https://java2ai.com/docs/frameworks/agent-framework/tutorials/memory

赞(0)
未经允许不得转载:AI项目博客 » Spring AI Alibaba 21|Memory 短期记忆 · 访问记忆

评论 抢沙发

AI项目博客

专注 AI 工程化落地 —— 覆盖智能体、大模型、Java AI 与 Python 的学习笔记,以及 AI 平台的项目实战记录。

关于本站文章归档

登录

找回密码

注册