The Challenge of Stateless LLMs

Large Language Models (LLMs) like Google Gemini are inherently stateless. Each interaction with the API is an isolated event. If a user provides information in one turn, like "My name is Alex," and then asks a question in the next, "What is my name?", the model has no memory of the previous statement. This fundamental limitation prevents the creation of natural, flowing chatbot experiences that users expect. To overcome this, developers must build mechanisms to retain and manage conversational history, effectively giving the LLM a memory.

Architecting a Context-Aware Chat Microservice

Building a truly conversational AI requires more than just sending prompts to an LLM. It demands an architecture that can manage the state of the conversation across multiple user interactions. This involves several key components working in concert:

Google Gemini API: The Conversational Engine

At its core, the system relies on the Google Gemini API for its powerful natural language processing capabilities. Gemini handles the complex task of understanding user input, generating relevant responses, and performing the underlying language understanding and generation.

Spring AI: Bridging the Gap

Spring AI acts as the crucial middleware, simplifying the integration with LLMs and providing essential features for building AI-powered applications. For context-aware applications, Spring AI's ChatMemory Advisor is particularly vital. This component is designed to manage the conversational history, ensuring that previous turns are included in subsequent API calls to the LLM. This allows the model to understand the ongoing dialogue and respond appropriately based on prior interactions.

H2 Database: Persistent Memory

While Spring AI's ChatMemory Advisor handles in-memory conversation management for the current session, true persistence requires a database. The article proposes using an H2 database. H2 is an in-memory or disk-based relational database that is lightweight and easy to embed within a Spring Boot application. By mapping conversation history to unique user sessions and storing it in H2, the microservice can ensure that conversations are not lost even if the application restarts. This provides a robust solution for maintaining context over longer periods and across different user sessions.

Implementation Details: Spring Boot and H2

The proposed solution leverages Spring Boot, a popular framework for building Java-based microservices, known for its convention-over-configuration approach and ease of development. The integration involves configuring Spring AI to utilize the Gemini API and setting up the H2 database for persistence.

Spring AI's ChatClient and related components are used to interact with the Gemini API. The key to statefulness lies in configuring the ChatMemoryAdvisor. This advisor intercepts requests and responses, accumulating the conversation history. When a new user message arrives, the advisor retrieves the relevant past messages from its memory (which can be backed by the H2 database) and includes them in the prompt sent to Gemini.

Diagram illustrating the flow from user input through Spring AI to Gemini API and H2 storage

For persistence, the H2 database is configured as a data source within the Spring Boot application. Entities representing user sessions and their corresponding conversation turns are defined. When the ChatMemoryAdvisor needs to persist or retrieve history, it interacts with these entities via Spring Data JPA or a similar mechanism, ensuring that the conversation context is reliably stored and retrievable.

The User Session as the Context Key

The concept of a "user session" is central to managing context in a multi-user microservice. Each unique user initiating a conversation is assigned a session ID. This ID acts as the key to retrieve and store their specific conversation history in the H2 database. When a request comes in, the microservice identifies the user session and loads the associated history. This ensures that User A's conversation does not interfere with User B's, maintaining privacy and accuracy. Without this session management, all conversations would be merged, leading to nonsensical interactions.

Benefits of this Approach

This architecture offers several advantages:

  • Enhanced User Experience: By remembering previous interactions, the chatbot provides a more natural and engaging conversational flow.
  • Scalability: Spring Boot microservices are designed for scalability, and integrating with an embedded H2 database simplifies deployment.
  • Robustness: Persistent storage ensures that conversation history is not lost, providing a more reliable service.
  • Developer Productivity: Spring AI abstracts away much of the complexity of LLM integration and memory management, allowing developers to focus on application logic.

The surprising detail here is not the use of Gemini or Spring AI, which are becoming standard tools, but the specific implementation of persistent, session-aware memory using an embedded H2 database. This combination offers a straightforward yet effective way to achieve statefulness without the overhead of more complex distributed caching systems for many common use cases.

Future Considerations

While this approach provides a solid foundation, several areas could be explored for further enhancement. These might include more sophisticated memory management strategies, such as summarizing past conversations to reduce token usage, implementing different database solutions for higher scalability needs (e.g., PostgreSQL, Redis), or integrating advanced techniques for managing long-term user profiles and preferences.