Welcome back! In the previous lesson, you learned how to send a simple message to DeepSeek's language model and receive a response. Now, we will take a step further by exploring how to maintain conversation context, enabling your AI tutor to remember previous exchanges and provide more natural, interactive responses. This ability is crucial for tailoring the tutor's behavior to meet specific educational needs and for building a truly helpful and engaging educational assistant.
One of the most powerful aspects of an AI tutor is its ability to remember what you’ve said before—making the conversation feel more natural, interactive, and helpful. But how do you achieve this in code? In this lesson, you’ll learn how to enable memory for your tutor using Spring AI’s ChatMemory system, making your Java application just as context-aware as a real chatbot.
Let’s see how this works and how you can easily integrate context handling into your own project.
Large Language Models (LLMs) like DeepSeek or ChatGPT are stateless by nature. That means every time you send a prompt to the model, it has no built-in knowledge of earlier exchanges—unless you include those exchanges in the current prompt. On most web chatbots, this “memory” is handled for you behind the scenes: the system collects all your previous messages and sends the entire history to the model on every turn, creating the illusion of a continuous conversation.
When you build applications using LLM APIs, you need to implement this behavior yourself. If you want your tutor to remember previous questions and answers, you must gather up the conversation history and send it along with each request. Doing this manually gets tedious fast. Thankfully, Spring AI provides an elegant solution with its ChatMemory abstraction.
ChatMemory is an interface that manages the storage and retrieval of past messages so the model can reference earlier context. You can use various implementations of this interface to control how much history is retained and how it’s managed. For most scenarios, MessageWindowChatMemory is a great choice. This class maintains a “window” of the most recent messages—ensuring that prompts remain short enough for efficient processing, while still containing enough history for context.
Let’s see how you can build your chat service step by step, taking full advantage of these powerful features.
The first step is to configure a chat memory store that keeps track of recent conversation turns. Here, we use MessageWindowChatMemory, which is designed to keep a fixed number of messages (by default, 20). This class works with an internal in-memory repository and automatically trims older messages as new ones are added.
MessageWindowChatMemory is responsible for storing just the most recent exchanges, which helps you balance between maintaining context and keeping your requests efficient. If you want a different window size, simply change the maxMessages
parameter.
To make sure your chat memory is used on every model call, you’ll use a MessageChatMemoryAdvisor. This advisor acts as a bridge between your ChatClient
and the ChatMemory
, automatically injecting recent history into the prompt before each request and updating the memory after each response.
MessageChatMemoryAdvisor ensures your model always receives the right context—without you having to manage any lists or manual history handling in your own code.
Now it’s time to build your ChatClient
and wire in the advisor. This setup enables fully automated context management for your tutor.
After this, every time you send a prompt using this chatClient
, the advisor will take care of adding all relevant previous messages and updating the memory after the AI responds.
With your memory infrastructure in place, your askQuestion
method becomes beautifully simple. You just send a new prompt and get the answer—the rest is handled automatically.
Here, the combination of MessageWindowChatMemory and MessageChatMemoryAdvisor means your tutor is always up-to-date with the latest context, making your application much easier to maintain and extend.
Let’s encapsulate everything we’ve discussed so far into a reusable ChatService
class. This service will handle chat memory, advisor setup, and message sending, making it easy to use conversational context throughout your application.
With this ChatService
, you can easily send questions and have the conversation context managed automatically behind the scenes. Next, let’s see how to test this service in your application.
Let’s put everything together by testing the service in a CommandLineRunner
. This example shows the tutor remembering a number from the first message and using it in a follow-up question.
When you run this code, you should see output like:
Notice how the AI remembers and uses context, just like a real tutor would!
In this lesson, you learned how to give your AI tutor memory using Spring AI’s ChatMemory
and the MessageChatMemoryAdvisor
. With these tools, your Java applications can finally offer stateful, conversational interactions—making your tutor more helpful and engaging.
As you move on to the practice exercises, experiment with different follow-up questions and see how your tutor maintains context across turns. This hands-on work will help you understand the power of conversational memory and set you up for the next unit, where you’ll further customize your tutor’s behavior and session management. Keep exploring—each improvement brings you closer to building a truly interactive AI tutor with DeepSeek!
