ChatMemory
上次说到ChatMessage手动的维护和管理是比较麻烦的,因此LangChain4j提出了ChatMemory的概念。它的本质是ChatMessage的容器。
可以看下ChatMemory这个接口的方法,它内部封装了一个List的ChatMessage。
要注意的是:
- LLM的上下文窗口都是有一定限制的,针对不同的LLM可能限制的令牌数量有所不同,这意味着他们在任何给定时间可以处理的令牌数量都有上限,这可能会导致整个窗口对话超出限制。
- 每个令牌都有成本,所以每次调用LLM的成本会逐渐增加。
通过ChatMemory可以结合ApiServices组件可以实现聊天记忆功能。
以下是官方提供的几个示例:
简单的聊天记忆
package com.chatglm.demo; import dev.langchain4j.memory.ChatMemory; import dev.langchain4j.memory.chat.MessageWindowChatMemory; import dev.langchain4j.model.openai.OpenAiChatModel; import dev.langchain4j.service.AiServices; /** * 聊天记忆 */ public class ServiceWithMemoryExample { /** * 定义一个带有单个方法的接口 */ interface Assistant { String chat(String message); } public static void main(String[] args) { // 创建ChatLanguageModel组件作为AiServices的基础组件 OpenAiChatModel openAiChatModel = OpenAiChatModel.withApiKey("demo"); // 创建MessageWindowChatMemory充当滑动窗口 ChatMemory chatMemory = MessageWindowChatMemory.withMaxMessages(10); // 利用Apiservices组件实现Assistant接口并接入chatMemory Assistant assistant = AiServices.builder(Assistant.class) .chatLanguageModel(openAiChatModel) .chatMemory(chatMemory) .build(); String answer = assistant.chat("你好,我叫小A."); System.out.println(answer); String answerWithName = assistant.chat("我叫什么名字?"); System.out.println(answerWithName); } }
AI回答:
多用户聊天记忆
package com.chatglm.demo; import dev.langchain4j.memory.chat.MessageWindowChatMemory; import dev.langchain4j.model.openai.OpenAiChatModel; import dev.langchain4j.service.AiServices; import dev.langchain4j.service.MemoryId; import dev.langchain4j.service.UserMessage; /** * 每个用户单独的聊天内存 */ public class ServiceWithMemoryForEachUserExample { interface Assistant { String chat(@MemoryId int memoryId, @UserMessage String userMessage); } public static void main(String[] args) { Assistant assistant = AiServices.builder(Assistant.class) .chatLanguageModel(OpenAiChatModel.withApiKey("")) .chatMemoryProvider(memoryId -> MessageWindowChatMemory.withMaxMessages(10)) .build(); System.out.println(assistant.chat(1, "Hello, my name is Klaus")); // Hi Klaus! How can I assist you today? System.out.println(assistant.chat(2, "Hello, my name is Francine")); // Hello Francine! How can I assist you today? System.out.println(assistant.chat(1, "What is my name?")); // Your name is Klaus. System.out.println(assistant.chat(2, "What is my name?")); // Your name is Francine. } }
聊天记忆持久化
依赖:
org.mapdb mapdb3.0.9 org.jetbrains.kotlin kotlin-stdlibpackage com.chatglm.demo; import dev.langchain4j.data.message.ChatMessage; import dev.langchain4j.memory.ChatMemory; import dev.langchain4j.memory.chat.MessageWindowChatMemory; import dev.langchain4j.model.openai.OpenAiChatModel; import dev.langchain4j.service.AiServices; import dev.langchain4j.store.memory.chat.ChatMemoryStore; import org.mapdb.DB; import org.mapdb.DBMaker; import java.util.List; import java.util.Map; import static dev.langchain4j.data.message.ChatMessageDeserializer.messagesFromJson; import static dev.langchain4j.data.message.ChatMessageSerializer.messagesToJson; import static org.mapdb.Serializer.STRING; /** * 持久的聊天记忆 */ public class ServiceWithPersistentMemoryExample { interface Assistant { String chat(String message); } public static void main(String[] args) { ChatMemory chatMemory = MessageWindowChatMemory.builder() .maxMessages(10) .chatMemoryStore(new PersistentChatMemoryStore()) .build(); Assistant assistant = AiServices.builder(Assistant.class) .chatLanguageModel(OpenAiChatModel.withApiKey("demo")) .chatMemory(chatMemory) .build(); String answer = assistant.chat("你是什么智能"); System.out.println(answer); // Hello Klaus! How can I assist you today? // Now, comment out the two lines above, uncomment the two lines below, and run again. // String answerWithName = assistant.chat("What is my name?"); // System.out.println(answerWithName); // Your name is Klaus. } // You can create your own implementation of ChatMemoryStore and store chat memory whenever you'd like static class PersistentChatMemoryStore implements ChatMemoryStore { private final DB db = DBMaker.fileDB("chat-memory.db").transactionEnable().make(); private final Map
map = db.hashMap("messages", STRING, STRING).createOrOpen(); @Override public List getMessages(Object memoryId) { String json = map.get((String) memoryId); return messagesFromJson(json); } @Override public void updateMessages(Object memoryId, List messages) { String json = messagesToJson(messages); map.put((String) memoryId, json); db.commit(); } @Override public void deleteMessages(Object memoryId) { map.remove((String) memoryId); db.commit(); } } } 多用户聊天记忆持久化
package com.chatglm.demo; import dev.langchain4j.data.message.ChatMessage; import dev.langchain4j.memory.chat.ChatMemoryProvider; import dev.langchain4j.memory.chat.MessageWindowChatMemory; import dev.langchain4j.model.openai.OpenAiChatModel; import dev.langchain4j.service.AiServices; import dev.langchain4j.service.MemoryId; import dev.langchain4j.service.UserMessage; import dev.langchain4j.store.memory.chat.ChatMemoryStore; import org.mapdb.DB; import org.mapdb.DBMaker; import java.util.List; import java.util.Map; import static dev.langchain4j.data.message.ChatMessageDeserializer.messagesFromJson; import static dev.langchain4j.data.message.ChatMessageSerializer.messagesToJson; import static org.mapdb.Serializer.INTEGER; import static org.mapdb.Serializer.STRING; /** * 每个用户持久的聊天记忆 */ public class ServiceWithPersistentMemoryForEachUserExample { interface Assistant { String chat(@MemoryId int memoryId, @UserMessage String userMessage); } public static void main(String[] args) { PersistentChatMemoryStore store = new PersistentChatMemoryStore(); ChatMemoryProvider chatMemoryProvider = memoryId -> MessageWindowChatMemory.builder() .id(memoryId) .maxMessages(10) .chatMemoryStore(store) .build(); Assistant assistant = AiServices.builder(Assistant.class) .chatLanguageModel(OpenAiChatModel.withApiKey("demo")) .chatMemoryProvider(chatMemoryProvider) .build(); System.out.println(assistant.chat(1, "Hello, my name is Klaus")); System.out.println(assistant.chat(2, "Hi, my name is Francine")); // Now, comment out the two lines above, uncomment the two lines below, and run again. // System.out.println(assistant.chat(1, "What is my name?")); // System.out.println(assistant.chat(2, "What is my name?")); } // You can create your own implementation of ChatMemoryStore and store chat memory whenever you'd like static class PersistentChatMemoryStore implements ChatMemoryStore { private final DB db = DBMaker.fileDB("multi-user-chat-memory.db").transactionEnable().make(); private final Map
map = db.hashMap("messages", INTEGER, STRING).createOrOpen(); @Override public List getMessages(Object memoryId) { String json = map.get((int) memoryId); return messagesFromJson(json); } @Override public void updateMessages(Object memoryId, List messages) { String json = messagesToJson(messages); map.put((int) memoryId, json); db.commit(); } @Override public void deleteMessages(Object memoryId) { map.remove((int) memoryId); db.commit(); } } }