The current memory design is not very flexible, unless the lowest-level chatModel is used. For example, the following example

This is my ChatClient, which uses mysql for memory storage

@Bean
    public ChatClient dashScopeMemoryNoThinkingChatClient(MysqlChatMemoryRepository mysqlChatMemoryRepository){
        ChatClient.Builder builder = ChatClient.builder(dashScopeChatModel);

        MessageWindowChatMemory memory = MessageWindowChatMemory.builder()
                .chatMemoryRepository(mysqlChatMemoryRepository)
                .maxMessages(MAX_MESSAGES)
                .build();

        // mysql
        builder.defaultAdvisors(MessageChatMemoryAdvisor.builder(memory).build());

        SimpleLoggerAdvisor loggerAdvisor = SimpleLoggerAdvisor.builder().build();
        builder.defaultAdvisors(loggerAdvisor);
        return builder.build();
    }

Here is my test code. The following code can run normally and also call tools properly, but the mysql library only records user input and final output, and does not record tool information

@GetMapping(value = "/tools/chat",produces = MediaType.TEXT_EVENT_STREAM_VALUE)
    public Flux<AssistantMessage> simpleChat(HttpServletResponse  response,String message) {
        response.setCharacterEncoding("UTF-8");

        Flux<ChatResponse> chatResponseFlux = dashScopeMemoryMysqlChatClient.prompt(new Prompt(message))
                .advisors(a -> a.param(ChatMemory.CONVERSATION_ID, "123"))
                .tools(new TimeTools()) // The time tool provides a way to obtain local time
                .stream().chatResponse();

        return chatResponseFlux.map(chatResponse -> chatResponse.getResult().getOutput());
    }

This design is fine in a single simple conversation. However, problems may arise in long conversations. For instance, if A user asks "Query the delivery address information of Order A", the model calls the correct tool and returns the correct information. Since memory does not store tool information, if the user asks for the Courier information of Order A again, the tool call information will be triggered once more, resulting in repeated tool calls.

At the same time, such a memory design makes it impossible for me to conveniently obtain the information of the tools being used in the current session, unless I manually control the tool calls using the ToolCallingManager. However, this will increase the coding complexity, as I need to handle tool calls, memory, etc. simultaneously.

I think a better approach would be that when storing memories, users can choose which types of memories to store in the ChatMemory implementation. Meanwhile, during memory retrieval, they can perform filtering. Currently, the framework has almost completely blocked out tool information.

In terms of memory and tool logs, I think the langchain4j framework does a better job. Its design is very simple, and the operability of user-defined implementations is greater. At the same time, it provides tool execution hook functions, allowing real-time access to the currently used tools

Comment From: shatang123

Is there a better way for me to control my memory very flexibly?

Comment From: sunyuhan1998

Same issue: #3342 #2529 #2101