LangChain4j实战之七:聊天记忆,高级API版
用LangChain4j的高级API解决聊天记忆问题,还有分用户的记忆,以及记忆内容的持久化
·
欢迎访问我的GitHub
这里分类和汇总了欣宸的全部原创(含配套源码):https://github.com/zq2599/blog_demos
LangChain4j实战全系列链接
本篇概览
- 本篇是《LangChain4j实战》系列的第七篇文章,也是前文《聊天记忆,低级API版》的续篇,前文创建了子工程memory,使用LangChain4j的低级API实现了聊天记忆功能,让大模型知道聊天的前文,可以根据之前的聊天内容来回答问题
- 本文我们会在memory子工程中继续添加代码,演示如何用LangChain4j的高级API实现聊天记忆功能,就是下图的红框部分

源码下载(觉得作者啰嗦的,直接在这里下载)
- 如果您只想快速浏览完整源码,可以在GitHub下载代码直接运行,地址和链接信息如下表所示(https://github.com/zq2599/blog_demos):
| 名称 | 链接 | 备注 |
|---|---|---|
| 项目主页 | https://github.com/zq2599/blog_demos | 该项目在GitHub上的主页 |
| git仓库地址(https) | https://github.com/zq2599/blog_demos.git | 该项目源码的仓库地址,https协议 |
| git仓库地址(ssh) | git@github.com:zq2599/blog_demos.git | 该项目源码的仓库地址,ssh协议 |
- 这个git项目中有多个文件夹,本篇的源码在langchain4j-tutorials文件夹下,如下图红色箭头所示:

编码,高级API,内存存储,全局记忆
- 本篇最先体验的是最简单的,基于高级API实现的记忆功能
- 打开配置类LangChain4jConfig.java,通过AiServices.builder方法生成了模式服务代理类的实例,通过chatMemory方法绑定ChatMemory实例,这样就能在对话时把记录存入ChatMemory中
@Bean
public Assistant assistantRamGlobal(OpenAiChatModel chatModel) {
// 创建一个ChatMemory实例,通过token数量限制记忆长度,记录在内存中
ChatMemory chatMemory = Tools.createRamChatMemoryInstance();
// 生成Assistant服务实例已经绑定了chatMemory
return AiServices.builder(Assistant.class)
.chatModel(chatModel)
.chatMemory(chatMemory)
.build();
}
- 在服务类QwenService中添加方法,使用高级API来对话,如下所示,可见只有最简单的对话功能,开发者无需关注如何处理聊天记录,都被代理类在内部处理了
@Autowired
private Assistant assistantRamGlobal;
/**
* 4. 高级API,基于内存的全局记忆
*
* @param prompt
* @return
*/
public String highLevelRamGlobal(String prompt) {
String answer = assistantRamGlobal.simpleChat(prompt);
logger.info("响应:" + answer);
return answer + "[from highLevelRamGlobal]";
}
- 在controller类QwenController中增加http接口响应以及上述服务类方法的调用
@PostMapping("/highlevel/ram/global")
public ResponseEntity<Response> highLevelRamGlobal(@RequestBody PromptRequest request) {
ResponseEntity<Response> checkRlt = check(request);
if (checkRlt != null) {
return checkRlt;
}
try {
// 使用基于内存的全局记忆功能
String response = qwenService.highLevelRamGlobal(request.getPrompt());
return ResponseEntity.ok(new Response(response));
} catch (Exception e) {
// 捕获异常并返回错误信息
return ResponseEntity.status(500).body(new Response("请求处理失败: " + e.getMessage()));
}
}
- 开发完毕,执行命令mvn spring-boot:run启动应用,然后用vscode的REST Client插件发起http请求,信息如下
POST http://localhost:8080/api/qwen/highlevel/ram/global
Content-Type: application/json
Accept: application/json
{
"prompt": "一百字介绍曹操"
}
- 收到响应
HTTP/1.1 200 OK
Content-Type: application/json
Transfer-Encoding: chunked
Date: Sat, 13 Dec 2025 08:43:18 GMT
Connection: close
{
"result": "曹操(155年-220年),字孟德,东汉末年杰出的政治家、军事家、文学家,魏国奠基者。他统一北方,推行屯田、唯才是举等政策,促进经济文化恢复。虽被传统史书称为“奸雄”,但其雄才大略与诗文成就(如《观沧海》)影响深远,是三国时代最具争议又极具魅力的历史人物。[from highLevelRamGlobal]"
}
- 再请求
POST http://localhost:8080/api/qwen/highlevel/ram/global
Content-Type: application/json
Accept: application/json
{
"prompt": "他在军事上的最高成就是什么?"
}
- 收到响应,可见聊天记忆功能正常
HTTP/1.1 200 OK
Content-Type: application/json
Transfer-Encoding: chunked
Date: Sat, 13 Dec 2025 08:43:57 GMT
Connection: close
{
"result": "曹操在军事上的最高成就是**统一中国北方**。他通过一系列关键战役,如**官渡之战(200年)以少胜多击败袁绍**,奠定了统一基础;随后平定河北、北击乌桓、收服并州与凉州,至207年基本完成对黄河流域及中原地区的整合。这一成就不仅结束了北方长期战乱,也为后来曹魏政权的建立和三国鼎立格局的形成奠定了坚实基础。[from highLevelRamGlobal]"
}
编码,高级API,内存存储,指定用户ID
- 接下来要实现的功能具有一定的实用性:假设有两个用户在使用咱们开发的这个memory应用,聊天记录应该是下面这样
用户A:介绍一下曹操
大模型:曹操是...
用户B:介绍一下刘备
大模型:刘备是...
用户A:他有那些军事成就
大模型:刘备的军事成就是...
- 显然,用户A第二次问题的答案不是他想要的,但是,从大模型的视角,它不知道有两个人在同时问他呀,对这个问题,LangChain4j给出了解决方案,就是通过不同的用户ID来分别保存聊天记忆,也就是说调用LangChain4j的高级API聊天时只要带上不同的用户ID即可
- 接下来开始编码实现分用户的聊天记忆功能
- 打开接口Assistant.java,增加一个方法声明,该方法入参除了提示词还有用户id,注意要用注解MemoryId
/**
* 带记忆的对话,返回助手的回答
*
* @param memoryId 记忆ID
* @param userMessage 用户消息
* @return 助手生成的回答
*/
String chatByMemoryId(@MemoryId int memoryId, @UserMessage String userMessage);
- 打开配置类LangChain4jConfig.java,通过AiServices.builder方法生成了模式服务代理类的实例,注意这里调用了chatMemoryProvider方法,而入参是个Lambda表达式,很明显,每个memoryId都会创建一个ChatMemory实例
@Bean
public Assistant assistantRamById(OpenAiChatModel chatModel) {
// 注意,这里通过chatMemoryProvider来指定每个id和chatMemory的对应关系,记录在内存中
return AiServices.builder(Assistant.class)
.chatModel(chatModel)
.chatMemoryProvider(memoryId -> Tools.createRamChatMemoryInstance())
.build();
}
- 然后在服务类中增加一个方法,聊天时只要使用assistantRamById就能实现按用户区分的聊天以及功能
/**
* 5. 高级API,基于内存的用户记忆
*
* @param userID
* @param prompt
* @return
*/
public String highLevelRamByUserID(int userID, String prompt) {
String secondAnswer = assistantRamById.chatByMemoryId(userID, prompt);
logger.info("响应:" + secondAnswer);
return secondAnswer + "[from highLevelRamByUserID]";
}
- 在controller类中增加一个接口响应
@PostMapping("/highlevel/ram/byuserid")
public ResponseEntity<Response> highLevelRamByUserID(@RequestBody PromptRequest request) {
System.out.println("request : " + request);
ResponseEntity<Response> checkRlt = check(request);
if (checkRlt != null) {
return checkRlt;
}
try {
// 使用基于内存的用户ID记忆功能
String response = qwenService.highLevelRamByUserID(request.getUserId(), request.getPrompt());
return ResponseEntity.ok(new Response(response));
} catch (Exception e) {
// 捕获异常并返回错误信息
return ResponseEntity.status(500).body(new Response("请求处理失败: " + e.getMessage()));
}
}
- 编码完成,来看看效果,用户1001先问曹操,注意请求body中多了userId字段
POST http://localhost:8080/api/qwen/highlevel/ram/byuserid
Content-Type: application/json
Accept: application/json
{
"userId": 1001,
"prompt": "一百字介绍曹操"
}
- 响应
HTTP/1.1 200 OK
Content-Type: application/json
Transfer-Encoding: chunked
Date: Sat, 13 Dec 2025 10:02:29 GMT
Connection: close
{
"result": "曹操(155年-220年),字孟德,东汉末年杰出的政治家、军事家、文学家,魏国奠基者。他统一北方,推行屯田、唯才是举,强化中央集权;在文学上开创建安风骨,代表作有《观沧海》《短歌行》等。虽被传统史书称为“奸雄”,但其雄才大略对结束乱世、推动历史发展影响深远。[from highLevelRamByUserID]"
}
- 然后把userId的值改一下,相当于另一个用户提问,问的是刘备的情况
POST http://localhost:8080/api/qwen/highlevel/ram/byuserid
Content-Type: application/json
Accept: application/json
{
"userId": 1002,
"prompt": "一百字介绍刘备"
}
- 响应自然是刘备的信息
HTTP/1.1 200 OK
Content-Type: application/json
Transfer-Encoding: chunked
Date: Sat, 13 Dec 2025 10:26:12 GMT
Connection: close
{
"result": "刘备(161年-223年),字玄德,东汉末年幽州涿郡人,三国时期蜀汉开国皇帝。他仁德宽厚,礼贤下士,以“兴复汉室”为志,三顾茅庐请诸葛亮出山,联合孙权于赤壁大败曹操。后占据益州,建立蜀汉政权,称帝于成都。虽屡遭挫折,却始终坚韧不拔,被后世誉为仁君典范。[from highLevelRamByUserID]"
}
- 接下来,把userId的值改回1001再提问,看看回答的是不是曹操有关的结果
POST http://localhost:8080/api/qwen/highlevel/ram/byuserid
Content-Type: application/json
Accept: application/json
{
"userId": 1001,
"prompt": "他的政治思想的根源是哪里?"
}
- 响应如下,可见聊天记忆确实已经按照id区分开了
HTTP/1.1 200 OK
Content-Type: application/json
Transfer-Encoding: chunked
Date: Sat, 13 Dec 2025 12:05:29 GMT
Connection: close
{
"result": "曹操政治思想的根源主要来自法家与儒家的融合,尤以法家为主。他身处东汉末年乱世,社会秩序崩坏,因此强调“乱世用重典”,主张严明法纪、赏罚分明,重视实效与集权,这明显承袭自商鞅、韩非等法家传统。同时,他也吸收儒家“尊王攘夷”“选贤任能”的理念,提出“唯才是举”,打破门第限制,并尊奉汉室以争取政治合法性。此外,曹操深受当时经学与现实政治环境影响,其思想体现出务实、权变与实用主义特征,形成“外儒内法”的统治策略。[from highLevelRamByUserID]"
}
- 至此,基于用户的聊天记忆功能算是已经具备了,但是还有个问题,考虑下面这两种情况:况都无法正常工作
- 应用进程出现问题后重启
- 如果前面是一个nginx,后面有多个memory进程,用户第一次请求到了一号memory进程,第二次请求到了二号memory进程
- 由于聊天记录都保存在进程的堆内存中,上述两种情况显然聊天记忆都找不到了,为了解决此问题,LangChain4j支持将聊天记录进行持久化保存,也就是保存在数据库中
编码,高级API,持久化存储,全局记忆
- 接下来要尝试的是把聊天历史保存在持久化存储的功能,先看全局聊天记录的,如下图红框

- 由于LangChain4j对持久化的支持是通过接口实现的,因此并未限制具体的方式,这里为了简单用了嵌入式数据库mapdb,您也可以按照自己的习惯选择其他数据库,例如MySQL
- 新增EmbeddedGlobalDb.java,实现了ChatMemoryStore接口,这样就可以支持聊天持久化能力了,可以看到getMessages、updateMessages、deleteMessages这些方法的具体实现可以随心所欲,这里是对dbmap数据库进行读写,您可以改为其他数据库的操作
package com.bolingcavalry.persistence;
import dev.langchain4j.data.message.ChatMessage;
import dev.langchain4j.store.memory.chat.ChatMemoryStore;
import org.mapdb.DB;
import java.util.List;
import java.util.Map;
import static dev.langchain4j.data.message.ChatMessageDeserializer.messagesFromJson;
import static dev.langchain4j.data.message.ChatMessageSerializer.messagesToJson;
public class EmbeddedGlobalDb implements ChatMemoryStore {
private DB db;
private Map<String, String> map;
/**
* 带Map参数的构造方法,使用用户提供的映射
*
* @param map 用户提供的映射实例
*/
public EmbeddedGlobalDb(DB db, Map<String, String> map) {
this.db = db;
this.map = map;
}
@Override
public List<ChatMessage> getMessages(Object memoryId) {
String json = map.get((String) memoryId);
return messagesFromJson(json);
}
@Override
public void updateMessages(Object memoryId, List<ChatMessage> messages) {
String json = messagesToJson(messages);
map.put((String) memoryId, json);
// 只有当db不为null时才提交事务
if (db != null) {
db.commit();
}
}
@Override
public void deleteMessages(Object memoryId) {
map.remove((String) memoryId);
// 只有当db不为null时才提交事务
if (db != null) {
db.commit();
}
}
}
- 再增加一个实现类EmbeddedByIdDb,这是按照用户id保存聊天记录时用到的,也就是下一个功能是才会用到
package com.bolingcavalry.persistence;
import dev.langchain4j.data.message.ChatMessage;
import dev.langchain4j.store.memory.chat.ChatMemoryStore;
import org.mapdb.DB;
import java.util.List;
import java.util.Map;
import static dev.langchain4j.data.message.ChatMessageDeserializer.messagesFromJson;
import static dev.langchain4j.data.message.ChatMessageSerializer.messagesToJson;
public class EmbeddedByIdDb implements ChatMemoryStore {
private DB db;
private Map<Integer, String> map;
/**
* 带Map参数的构造方法,使用用户提供的映射
*
* @param map 用户提供的映射实例
*/
public EmbeddedByIdDb(DB db, Map<Integer, String> map) {
this.db = db;
this.map = map;
}
@Override
public List<ChatMessage> getMessages(Object memoryId) {
String json = map.get((int) memoryId);
return messagesFromJson(json);
}
@Override
public void updateMessages(Object memoryId, List<ChatMessage> messages) {
String json = messagesToJson(messages);
map.put((int) memoryId, json);
// 只有当db不为null时才提交事务
if (db != null) {
db.commit();
}
}
@Override
public void deleteMessages(Object memoryId) {
map.remove((int) memoryId);
// 只有当db不为null时才提交事务
if (db != null) {
db.commit();
}
}
}
- 在Tools.java中增加一个静态方法createStoreInstance,用于封装ChatMemoryStore实例的创建过程
/**
* 创建一个ChatMemoryStore实例,用于存储聊天记忆,存在数据库中
*
* @return ChatMemoryStore实例
*/
public static ChatMemoryStore createStoreInstance(String dbName, boolean isById) {
ChatMemoryStore rlt = null;
// 创建一个MapDB实例,用于存储聊天记忆
DB db = DBMaker.fileDB(dbName).transactionEnable().make();
if (isById) {
Map<Integer, String> dbMap = db.hashMap("messages", INTEGER, STRING).createOrOpen();
rlt = new EmbeddedByIdDb(db, dbMap);
} else {
Map<String, String> dbMap = db.hashMap("messages", STRING, STRING).createOrOpen();
rlt = new EmbeddedGlobalDb(db, dbMap);
}
return rlt;
}
- 再在Tools.java中增加一个方法createDbChatMemoryInstance,作用是创建ChatMemory实例,在创建时通过chatMemoryStore方法把前面的ChatMemoryStore传入,这样一来,往ChatMemory传入的对话记录就会被持久化到数据库中
/**
* 创建一个ChatMemory实例,用于存储聊天记忆,存在数据库中
*
* @return ChatMemory实例
*/
public static ChatMemory createDbChatMemoryInstance(String dbName, boolean isById) {
// 创建一个MapDB实例,用于存储聊天记忆
ChatMemoryStore store = createStoreInstance(dbName, isById);
return MessageWindowChatMemory
.builder()
.maxMessages(100)
.chatMemoryStore(store)
.build();
}
-
也就是说,createDbChatMemoryInstance方法可以创建一个具有持久化能力的ChatMemory实例
-
打开配置类LangChain4jConfig.java,通过AiServices.builder方法生成了模式服务代理类的实例,通过chatMemory方法绑定ChatMemory实例,而且这个ChatMemory实例具备持久化保存对话记录的能力
@Bean
public Assistant assistantDbGlobal(OpenAiChatModel chatModel) {
// 创建一个ChatMemory实例,通过消息数量限制记忆长度,记录在数据库中
ChatMemory chatMemory = Tools.createDbChatMemoryInstance("chat-memory-global.db", false);
// 生成Assistant服务实例已经绑定了chatMemory
return AiServices.builder(Assistant.class)
.chatModel(chatModel)
.chatMemory(chatMemory)
.build();
}
- 在服务类QwenService中添加方法highLevelDbGlobal,里面使用的是前面创建的assistantDbGlobal实例,这样对话记录就会被持久化
@Autowired
private Assistant assistantDbGlobal;
/**
* 6. 高级API,基于数据库的全局记忆
*
* @param prompt
* @return
*/
public String highLevelDbGlobal(String prompt) {
String secondAnswer = assistantDbGlobal.simpleChat(prompt);
logger.info("响应:" + secondAnswer);
return secondAnswer + "[from highLevelDbGlobal]";
}
- controller中增加http响应以及对前面highLevelDbGlobal方法的调用
@PostMapping("/highlevel/db/global")
public ResponseEntity<Response> highLevelDbGlobal(@RequestBody PromptRequest request) {
ResponseEntity<Response> checkRlt = check(request);
if (checkRlt != null) {
return checkRlt;
}
try {
// 使用基于数据库的全局记忆功能
String response = qwenService.highLevelDbGlobal(request.getPrompt());
return ResponseEntity.ok(new Response(response));
} catch (Exception e) {
// 捕获异常并返回错误信息
return ResponseEntity.status(500).body(new Response("请求处理失败: " + e.getMessage()));
}
}
- 运行起来,第一次对话请求
POST http://localhost:8080/api/qwen/highlevel/db/global
Content-Type: application/json
Accept: application/json
{
"prompt": "一百字介绍曹操"
}
- 得到响应
HTTP/1.1 200 OK
Content-Type: application/json
Transfer-Encoding: chunked
Date: Sat, 13 Dec 2025 14:31:57 GMT
Connection: close
{
"result": "曹操(155年-220年),字孟德,东汉末年杰出的政治家、军事家、文学家,魏国奠基者。他统一北方,推行屯田、唯才是举等政策,稳定社会秩序;在文学上开创建安风骨。虽被传统史书视为“奸雄”,但其雄才大略对结束乱世、推动历史发展具有深远影响。[from highLevelDbGlobal]"
}
- 重启该应用,如果聊天记录持久化存储在数据库,接下来的对话大模型应该能知道是在聊曹操
- 重启后再次请求
POST http://localhost:8080/api/qwen/highlevel/db/global
Content-Type: application/json
Accept: application/json
{
"prompt": "他面临过的最大挑战是什么?"
}
- 得到响应,可见重启后大模型依旧知道问的是曹操,所以持久化功能是符合预期的
HTTP/1.1 200 OK
Content-Type: application/json
Transfer-Encoding: chunked
Date: Sat, 13 Dec 2025 14:34:31 GMT
Connection: close
{
"result": "若指曹操,他一生面临的最大挑战是**在东汉末年群雄割据、天下大乱的局势中,既要对抗强大的军事对手,又要维系内部稳定与合法性**。其中尤为关键的是:\n\n1. **官渡之战(200年)**:以弱胜强,击败兵力数倍于己的袁绍,此战决定北方霸权归属,若败则可能彻底覆灭。\n2. **赤壁之战(208年)**:意图统一全国,却遭孙刘联军火攻大败,从此形成三国鼎立格局,统一理想受挫。\n3. **政治合法性困境**:虽“挟天子以令诸侯”,但始终面临汉室忠臣与士族对其“篡汉”野心的质疑与反抗。\n\n这些挑战考验其军事、政治与战略智慧,也塑造了他复杂的历史形象。[from highLevelDbGlobal]"
}
编码,高级API,持久化存储,指定用户ID
- 最后要尝试的是既支持持久化,又支持不同用户的聊天记忆,如下图红框

- 打开配置类LangChain4jConfig.java,注意这里要先创建ChatMemoryProvider对象,也就是根据不同用户id分别生成具有持久化能力的ChatMemory对象,最后通过AiServices.builder来创建模型服务的代理类实例
@Bean
public Assistant assistantDbById(OpenAiChatModel chatModel) {
ChatMemoryStore chatMemoryStore = Tools.createStoreInstance("chat-memory-byid.db", true);
ChatMemoryProvider chatMemoryProvider = memoryId -> MessageWindowChatMemory.builder()
.id(memoryId)
.maxMessages(100)
.chatMemoryStore(chatMemoryStore)
.build();
// 生成Assistant服务实例已经绑定了chatMemory
return AiServices.builder(Assistant.class)
.chatModel(chatModel)
.chatMemoryProvider(chatMemoryProvider)
.build();
}
- 在服务类QwenService中添加方法highLevelDbGlobal,里面使用的是前面创建的assistantDbById实例,这样每个用户的对话记录就会被持久化
@Autowired
private Assistant assistantDbById;
/**
* 7. 高级API,基于数据库的用户记忆
*
* @param userID
* @param prompt
* @return
*/
public String highLevelDbByUserID(int userID, String prompt) {
String answer = assistantDbById.chatByMemoryId(userID, prompt);
logger.info("响应:" + answer);
return answer + "[from highLevelDbByUserID]";
}
- 最后是controller类增加接口响应,调用前面服务类的highLevelDbByUserID方法
@PostMapping("/highlevel/db/byuserid")
public ResponseEntity<Response> highLevelDbByUserID(@RequestBody PromptRequest request) {
ResponseEntity<Response> checkRlt = check(request);
if (checkRlt != null) {
return checkRlt;
}
try {
// 使用基于数据库的用户ID记忆功能
String response = qwenService.highLevelDbByUserID(request.getUserId(), request.getPrompt());
return ResponseEntity.ok(new Response(response));
} catch (Exception e) {
// 捕获异常并返回错误信息
return ResponseEntity.status(500).body(new Response("请求处理失败: " + e.getMessage()));
}
}
- 启动服务验证,1001用户先问,问的是曹操
POST http://localhost:8080/api/qwen/highlevel/db/byuserid
Content-Type: application/json
Accept: application/json
{
"userId": 1001,
"prompt": "一百字介绍曹操"
}
- 回答是
HTTP/1.1 200 OK
Content-Type: application/json
Transfer-Encoding: chunked
Date: Sat, 13 Dec 2025 14:58:00 GMT
Connection: close
{
"result": "曹操(155年-220年),字孟德,东汉末年杰出的政治家、军事家、文学家。他统一北方,挟天子以令诸侯,奠定曹魏基业。虽被传统史书称为“奸雄”,但其唯才是举、屯田安民、诗文慷慨,展现出复杂而卓越的才能。其子曹丕称帝后,追尊为魏武帝。[from highLevelDbByUserID]"
}
- 1002用户继续问,问的是刘备
POST http://localhost:8080/api/qwen/highlevel/db/byuserid
Content-Type: application/json
Accept: application/json
{
"userId": 1002,
"prompt": "一百字介绍刘备"
}
- 回答的自然是刘备的信息
HTTP/1.1 200 OK
Content-Type: application/json
Transfer-Encoding: chunked
Date: Sat, 13 Dec 2025 14:59:02 GMT
Connection: close
{
"result": "刘备(161年-223年),字玄德,东汉末年幽州涿郡人,三国时期蜀汉开国皇帝。他以仁德著称,礼贤下士,三顾茅庐请诸葛亮出山,联合孙权于赤壁大破曹操,后夺取益州、汉中,建立蜀汉政权。虽出身寒微,却志在匡扶汉室,一生重情重义,与关羽、张飞桃园结义传为佳话。[from highLevelDbByUserID]"
}
- 为了验证持久化能力,现在把应用重启
- 重启后以1001用户的身份继续提问
POST http://localhost:8080/api/qwen/highlevel/db/byuserid
Content-Type: application/json
Accept: application/json
{
"userId": 1001,
"prompt": "他的军事思想对后世有什么影响?"
}
- 得到响应如下,可见聊天记忆功能正常,并且准确的针对1001稳过的曹操进行了回复
HTTP/1.1 200 OK
Content-Type: application/json
Transfer-Encoding: chunked
Date: Sat, 13 Dec 2025 15:06:20 GMT
Connection: close
{
"result": "曹操的军事思想强调“兵无常势,水无常形”,主张灵活应变、因敌制胜。他重视情报侦察(“知彼知己”)、后勤保障(推行屯田以供军需)、赏罚分明与治军严整,并善于用奇兵、诈术和心理战(如官渡之战以少胜多)。其注释《孙子兵法》是中国现存最早的《孙子》注本,对后世兵学影响深远。他的实战经验与理论总结,成为历代将领研习的重要范本,推动了中国古代军事思想的发展。[from highLevelDbByUserID]"
}
- 这时候把userId改为1002,大模型应该基于刘备回答才对
POST http://localhost:8080/api/qwen/highlevel/db/byuserid
Content-Type: application/json
Accept: application/json
{
"userId": 1002,
"prompt": "他的军事思想对后世有什么影响?"
}
- 响应如下,确实是基于刘备身份的回复,可见持久化聊天记忆+按用户区分的能力同时生效了
HTTP/1.1 200 OK
Content-Type: application/json
Transfer-Encoding: chunked
Date: Sat, 13 Dec 2025 15:06:41 GMT
Connection: close
{
"result": "刘备本人并非以系统的军事理论著称,其军事思想主要体现在实践层面,对后世影响有限但具有象征意义。他强调“仁义为本、得人者昌”,重视民心向背与人才招揽(如三顾茅庐),主张联合抗强(如联吴抗曹),体现出务实灵活的战略思维。这种以道义凝聚人心、以联盟制衡强敌的策略,被后世视为乱世中弱势集团崛起的典范。更重要的是,通过《三国演义》的文学塑造,刘备“仁德之主”的形象深入人心,成为儒家理想政治领袖的代表,间接影响了后世对统帅品德与治军理念的重视,而非纯粹的军事谋略传承。[from highLevelDbByUserID]"
}
- 至此,LangChain4j的聊天记忆能力就全部实践完毕了,希望这两篇文章能给您一些参考,帮助您开发出使用的大模型对话能力
- 《LangChain4j实战》还没有结束,接下来还会继续深入学习LangChain4j,鉴于最近几篇的内容都过于庞大,接下来咱们学点简单的:体验响应流式传输
你不孤单,欣宸原创一路相伴
更多推荐


所有评论(0)