原本基本对话的流程是

用户

Controller

Model

返回

而预想增加的是

用户

Controller

AiServices

找Memory

取历史记录

拼Prompt

调用DeepSeek

保存新记录

返回

真正自己写的代码其实就三处:

1. 接口加 @MemoryId

2. Controller多接收一个sessionId

3. Config把model::chat换成AiServices.builder(...)

return model::chat;

实际上等价于:


return message -> model.chat(message);

收到消息直接发给模型。

第一步改什么

先改接口

原来:


String chat(String message);

改成:


String chat(
    @MemoryId String memoryId,
    @UserMessage String message
);

这里相当于告诉 LangChain4j:


第一个参数:
用于找聊天记录

第二个参数:
真正发送给大模型

第二步改 Controller

原来:


@PostMapping("/chat")
public String chat(
        @RequestBody String message) {

    return aiChatService.chat(message);
}

改成:


@PostMapping("/chat")
public String chat(
        @RequestParam String sessionId,
        @RequestBody String message) {

    return aiChatService.chat(
            sessionId,
            message
    );
}

只是多传一个:


sessionId

而已。


流程变成:


浏览器
   ↓
session001
你好
   ↓
Controller
   ↓
aiChatService.chat(
   "session001",
   "你好"
)

第三步改配置类

原来:


@Bean
public AiChatService aiChatService(ChatModel model) {

    return model::chat;
}

这句删掉。

换成:


@Bean
public AiChatService aiChatService(ChatModel model) {

    return AiServices.builder(AiChatService.class)
            .chatModel(model)
            .chatMemoryProvider(memoryId ->
                    MessageWindowChatMemory
                            .withMaxMessages(10))
            .build();
}

这里才是真正增加记忆的地方。

最后补充一个东西,是我一直想总结的,关于在spring参数传递的注解问题

URL路径 @PathVariable /user/100
Query参数 @RequestParam ?name=tom
JSON请求体 @RequestBody {"name":"tom"}
请求头 @RequestHeader token: xxx

json其实就是什么dto来回传的时候,query就是看我们的这个接口文档怎么去写的,一看到就直接加一个还有路径主要看那个url请求头少一些,一般就是token,然后就是不需要写注解的这个就是简单的数据类型,就类似于这个分装好的这个integer它可以直接当作这个@requestparam但是dto那种东西必须得写了

Logo

Agent 垂直技术社区,欢迎活跃、内容共建。

更多推荐