Add Chat Memory and Session Isolation to SpringBoot AI with LangChain4j
This guide demonstrates how to integrate LangChain4j into a SpringBoot application to enable multi‑turn chat memory and per‑user session isolation using @MemoryId, configuring ChatMemoryProvider, updating the AI service interface, and testing with curl requests.
SpringBoot can be extended with LangChain4j to provide fast AI dialogue, but the initial setup lacks conversation memory and user isolation. LangChain4j solves this by using the @MemoryId parameter to distinguish separate chat histories.
AiServices in LangChain4j
AiServices allows declarative construction of AI services with annotations for memory and system prompts.
import dev.langchain4j.service.AiService;</code><code>import dev.langchain4j.service.SystemMessage;</code><code>@AiService</code><code>public interface Assistant {</code><code> @SystemMessage("你是一位知识渊博的AI助手,请用中文友好地回答用户的问题。")</code><code> String chat(String userMessage);</code><code>}The interface can be injected like a regular Spring bean.
@RestController</code><code>public class AssistantController {</code><code> private final Assistant assistant;</code><code> public AssistantController(Assistant assistant) {</code><code> this.assistant = assistant;</code><code> }</code><code> @GetMapping("/ai/assistant")</code><code> public String assistantChat(@RequestParam(value = "message") String message) {</code><code> return assistant.chat(message);</code><code> }</code><code>}ChatMemory (Conversation Memory)
To support multi‑turn dialogue, integrate a ChatMemory component. MessageWindowChatMemory provides a sliding‑window memory suitable for development and testing.
@MemoryId and Session Isolation
LangChain4j’s AiServices offers elegant session isolation: adding a method parameter annotated with @MemoryId lets the framework manage independent memories for each ID.
Implementation Steps
1. Modify the AI Service Interface
Add @MemoryId and @UserMessage to the chat method so that each user’s ID controls the memory window.
import dev.langchain4j.service.MemoryId;</code><code>import dev.langchain4j.service.SystemMessage;</code><code>import dev.langchain4j.service.UserMessage;</code><code>import dev.langchain4j.service.spring.AiService;</code><code>@AiService</code><code>public interface Assistant {</code><code> @SystemMessage("你是一位知识渊博的AI助手,请用中文友好地回答用户的问题。")</code><code> String chat(@MemoryId Long memoryId, @UserMessage String userMessage);</code><code>}The key is the @MemoryId Long memoryId parameter; different IDs (e.g., user IDs) receive independent chat windows.
2. Configure a ChatMemoryProvider Bean
Create a configuration class that supplies a ChatMemory instance for each new memoryId. The example uses a sliding window that retains the latest 10 messages.
import dev.langchain4j.memory.chat.ChatMemoryProvider;</code><code>import dev.langchain4j.memory.chat.MessageWindowChatMemory;</code><code>import org.springframework.context.annotation.Bean;</code><code>import org.springframework.context.annotation.Configuration;</code><code>@Configuration</code><code>public class AiConfig {</code><code> // Bean that provides an independent ChatMemory for each memoryId</code><code> @Bean</code><code> public ChatMemoryProvider chatMemoryProvider() {</code><code> // MessageWindowChatMemory keeps up to 10 recent messages</code><code> return memoryId -> MessageWindowChatMemory.withMaxMessages(10);</code><code> }</code><code>}This creates a MessageWindowChatMemory that stores at most ten recent messages per user.
3. Call the Service from a Controller
Inject the Assistant bean and obtain the user’s unique identifier (e.g., from the HTTP header X-User-Id) to pass as memoryId.
import com.badao.ai.service.Assistant;</code><code>import org.springframework.web.bind.annotation.*;</code><code>@RestController</code><code>public class AssistantController {</code><code> private final Assistant assistant;</code><code> public AssistantController(Assistant assistant) {</code><code> this.assistant = assistant;</code><code> }</code><code> @GetMapping("/ai/assistant")</code><code> public String chat(@RequestHeader("X-User-Id") Long userId,</code><code> @RequestParam(value = "message") String message) {</code><code> // Pass user ID as memoryId</code><code> return assistant.chat(userId, message);
</code><code> }</code><code>}The header X-User-Id supplies the unique identifier used for memory isolation.
4. Dependency Versions and Notes
Ensure langchain4j version ≥ 1.0.0‑beta3 in pom.xml; earlier versions may lack @UserMessage support. Example Maven snippet:
<parent></code><code> <groupId>org.springframework.boot</groupId></code><code> <artifactId>spring-boot-starter-parent</artifactId></code><code> <version>3.2.5</version></code><code></parent></code><code><properties></code><code> <java.version>17</java.version></code><code> <langchain4j.version>1.0.0-beta3</langchain4j.version></code><code></properties></code><code><dependencyManagement></code><code> <dependencies></code><code> <dependency></code><code> <groupId>dev.langchain4j</groupId></code><code> <artifactId>langchain4j-community-bom</artifactId></code><code> <version>${langchain4j.version}</version></code><code> </dependency></code><code> <!-- Alibaba DashScope integration starter --></code><code> <dependency></code><code> <groupId>dev.langchain4j</groupId></code><code> <artifactId>langchain4j-community-dashscope-spring-boot-starter</artifactId></code><code> </dependency></code><code> <!-- Explicit DashScope core dependency (starter may omit) --></code><code> <dependency></code><code> <groupId>dev.langchain4j</groupId></code><code> <artifactId>langchain4j-community-dashscope</artifactId></code><code> </dependency></code><code> </dependencies></code><code></dependencyManagement>Memory is stored in RAM; after a restart it is lost. For persistence, implement ChatMemoryStore and back it with MongoDB, Redis, etc.
In production, consider TokenWindowChatMemory, which evicts messages based on token count to better control costs.
5. Testing
Use an API tool (e.g., Postman) or curl to simulate two users. Example for user A (ID 1):
curl -H "X-User-Id: 1" "http://localhost:885/ai/assistant?message=你好,我叫张三。"Then ask a follow‑up:
curl -H "X-User-Id: 1" "http://localhost:885/ai/assistant?message=我叫什么名字?"The assistant should reply “张三”. For user B (ID 2), the same question should yield “I don’t know” because the memory is isolated.
Signed-in readers can open the original source through BestHub's protected redirect.
This article has been distilled and summarized from source material, then republished for learning and reference. If you believe it infringes your rights, please contactand we will review it promptly.
The Dominant Programmer
Resources and tutorials for programmers' advanced learning journey. Advanced tracks in Java, Python, and C#. Blog: https://blog.csdn.net/badao_liumang_qizhi
How this landed with the community
Was this worth your time?
0 Comments
Thoughtful readers leave field notes, pushback, and hard-won operational detail here.
