SpringBoot中集成LangChain4j实现集成阿里百炼平台进行AI对话记忆功能和对话隔离功能

场景

SpringBoot中集成LangChain4j实现集成阿里百炼平台进行AI快速对话:

https://blog.csdn.net/BADAO_LIUMANG_QIZHI/article/details/160214877

在如上快速实现AI对话后,但是对话没有记忆功能,历史对话无法记住。

且不同用户之间的对话没有隔离。

在 LangChain4j 中,要实现多轮对话的记忆和用户间的会话隔离,主要是通过 @MemoryId 参数来区分的。

LangChain4j的 AiServices

LangChain4j的 AiServices 能通过注解声明式地构建带有记忆功能、系统提示等高级能力的AI服务。

使用示例:

定义服务接口:使用 @AiService 注解定义一个接口,并通过 @SystemMessage 设置系统提示词。

复制代码
import dev.langchain4j.service.AiService;
import dev.langchain4j.service.SystemMessage;

@AiService
public interface Assistant {

    @SystemMessage("你是一位知识渊博的AI助手,请用中文友好地回答用户的问题。")
    String chat(String userMessage);
}

注入并使用服务:LangChain4j会自动创建该接口的代理实现,你可以像使用普通Spring Bean一样注入它。

复制代码
@RestController
public class AssistantController {

    private final Assistant assistant;

    public AssistantController(Assistant assistant) {
        this.assistant = assistant;
    }

    @GetMapping("/ai/assistant")
    public String assistantChat(@RequestParam(value = "message") String message) {
        return assistant.chat(message);
    }
}

对话记忆 (ChatMemory):

为了支持多轮连续对话,可以集成 ChatMemory 组件。MessageWindowChatMemory 是一个内存实现,

适合开发测试

@MemoryId 与会话隔离

LangChain4j 的 AiServices 支持一种非常优雅的会话隔离方式。

你只需要在AI服务接口的方法参数中,增加一个带有 @MemoryId 注解的参数,

框架就会自动为你管理不同ID对应的独立对话记忆。

注:

博客:
https://blog.csdn.net/badao_liumang_qizhi

实现

1. 改造 AI 服务接口

修改之前定义的 Assistant 接口,为 chat 方法增加 @MemoryId 参数和 @UserMessage 注解,

这样可以更精确地控制传给LLM的用户消息内容。

复制代码
import dev.langchain4j.service.MemoryId;
import dev.langchain4j.service.SystemMessage;
import dev.langchain4j.service.UserMessage;
import dev.langchain4j.service.spring.AiService;

@AiService
public interface Assistant {

    @SystemMessage("你是一位知识渊博的AI助手,请用中文友好地回答用户的问题。")
    String chat(@MemoryId Long memoryId, @UserMessage String userMessage);

}

这里的关键是 @MemoryId Long memoryId。

当你用不同的 memoryId(比如用户ID)调用这个方法时,LangChain4j 会自动为每个ID维护一个独立的聊天记忆窗口

2、配置 ChatMemoryProvider Bean

创建一个配置类,定义一个 ChatMemoryProvider 的 Bean。

这个 Bean 的作用是告诉 AiServices,当遇到一个新的 memoryId 时,应该如何创建对应的 ChatMemory 实例。

复制代码
import dev.langchain4j.memory.chat.ChatMemoryProvider;
import dev.langchain4j.memory.chat.MessageWindowChatMemory;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;


@Configuration
public class AiConfig {

    // 定义一个Bean,用于为每个memoryId提供独立的ChatMemory
    @Bean
    public ChatMemoryProvider chatMemoryProvider() {
        // MessageWindowChatMemory 是一个基于消息数量的滑动窗口[reference:4]
        // 这里设置最多保留最近的10条消息,超出后会从历史记录中移除最早的消息[reference:5][reference:6]
        return memoryId -> MessageWindowChatMemory.withMaxMessages(10);
    }
}

这段代码为每个 memoryId 创建了一个最多能记住 10 条 最新消息的 MessageWindowChatMemory 实例

3. 在 Controller 中调用

最后,在 Controller 里注入刚才的 Assistant Bean,

并在处理请求时从某个地方(比如HTTP请求头)获取并传入用户的唯一标识作为 memoryId。

复制代码
import com.badao.ai.service.Assistant;
import org.springframework.web.bind.annotation.*;

@RestController
public class AssistantController {

    private final Assistant assistant;

    public AssistantController(Assistant assistant) {
        this.assistant = assistant;
    }

    @GetMapping("/ai/assistant")
    public String chat(@RequestHeader("X-User-Id") Long userId,
                       @RequestParam(value = "message") String message) {
        // 将用户ID作为 memoryId 传递给AI服务
        return assistant.chat(userId, message);
    }
}

通过 HTTP 请求头 X-User-Id 来获取用户的唯一标识,并将其作为 memoryId 传入。

4、关键依赖版本与注意事项

依赖版本:

需要确保你的 pom.xml 中 LangChain4j 的版本是 1.0.0-beta3 或更高,

因为之前的版本在 @UserMessage 注解的支持上可能存在差异。你之前使用的 1.0.0-beta1 可能无法正常工作,建议进行升级。

记忆存储:

MessageWindowChatMemory 的对话记录是存储在内存中的,一旦应用重启就会丢失。

如果需要持久化保存,可以实现 ChatMemoryStore 接口,将数据存入数据库(如MongoDB)或Redis等外部存储中。

生产环境:

在生产环境中,建议使用更精确的 TokenWindowChatMemory,它基于Token数量进行淘汰,能更好地控制成本

附示例中的pom文件:

复制代码
    <parent>
        <groupId>org.springframework.boot</groupId>
        <artifactId>spring-boot-starter-parent</artifactId>
        <version>3.2.5</version>
    </parent>

    <groupId>com.example</groupId>
    <artifactId>spring-langchain4j-bailian</artifactId>
    <version>1.0</version>

    <properties>
        <java.version>17</java.version>
        <langchain4j.version>1.0.0-beta3</langchain4j.version>
    </properties>

    <dependencyManagement>
        <dependencies>
            <dependency>
                <groupId>dev.langchain4j</groupId>
                <artifactId>langchain4j-community-bom</artifactId>
                <version>${langchain4j.version}</version>
                <type>pom</type>
                <scope>import</scope>
            </dependency>
        </dependencies>
    </dependencyManagement>

    <dependencies>
        <dependency>
            <groupId>org.springframework.boot</groupId>
            <artifactId>spring-boot-starter-web</artifactId>
        </dependency>

        <!-- LangChain4j 核心 Spring Boot Starter -->
        <dependency>
            <groupId>dev.langchain4j</groupId>
            <artifactId>langchain4j-spring-boot-starter</artifactId>
             <version>${langchain4j.version}</version>
        </dependency>

        <!-- 阿里百炼 DashScope 集成 Starter -->
        <dependency>
            <groupId>dev.langchain4j</groupId>
            <artifactId>langchain4j-community-dashscope-spring-boot-starter</artifactId>
        </dependency>

        <!-- 显式添加 DashScope 核心依赖(Starter 有时不会传递) -->
        <dependency>
            <groupId>dev.langchain4j</groupId>
            <artifactId>langchain4j-community-dashscope</artifactId>
        </dependency>
    </dependencies>

5、测试

使用API工具(如Postman),模拟两个不同用户的请求进行测试:

模拟用户A(用户ID为 1):

curl -H "X-User-Id: 1" "http://localhost:885/ai/assistant?message=你好,我叫张三。"

模拟用户A(用户ID为 1):

curl -H "X-User-Id: 1" "http://localhost:885/ai/assistant?message=我叫什么名字?"

预期AI助手能够回答出"张三"。

模拟用户B(用户ID为 2):

curl -H "X-User-Id: 2" "http://localhost:885/ai/assistant?message=我叫什么名字?"

预期AI助手因为缺乏上下文,会表示不知道或需要用户告知。

相关推荐
蓝瑟12 分钟前
代码越写越乱? 从 Vibe Coding 到 Spec + Harness
人工智能·ai编程·代码规范
ACP广源盛1392462567315 分钟前
GSV6155@ACP# 搭配 AI 服务器、AI PC 完整适配方案
大数据·服务器·人工智能·分布式·单片机·嵌入式硬件
阿里云大数据AI技术40 分钟前
Agent时代“Token炼金术”,阿里云 PAI 推出 TokenWorks:重塑企业专属的高保障SLO推理服务
人工智能·agent
饼饼学习空间智能1 小时前
2026数字孪生选型避坑指南:如何避免项目沦为3D大屏展示
人工智能·深度学习
tellmewhoisi1 小时前
多版本共用redis的token有效期校验(过期重新登录)
java·redis·缓存
疯狂打码的少年1 小时前
【软件工程】结构化设计:模块独立性与耦合内聚
java·开发语言·笔记·软件工程
乐观的Terry1 小时前
3、数据库设计与领域实体
java·数据库·spring boot·spring cloud·ai编程
SEONIB_Explorer1 小时前
新手冷启动:如何用 SEONIB + VEONIB 搞定独立站图文与短视频基础产能
人工智能·shopify·seonib·veonib·低成本测试·钩子生成·冷启动 30 天执行计划表
Inhand陈工1 小时前
数据中心UPS无功补偿与智能化监控方案:基于IG502的Modbus RTU转IEC61850实战
运维·人工智能·物联网·信息与通信
Saniffer_SH1 小时前
NAND技术(二):从 Channel、Die/LUN、P/E Cycle 到 LDPC,一次讲透 NAND 里那些最容易误解的概念
人工智能·驱动开发·嵌入式硬件·测试工具·fpga开发·计算机外设·压力测试