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.
}
}
聊天记忆持久化
依赖:
<dependency>
<groupId>org.mapdb</groupId>
<artifactId>mapdb</artifactId>
<version>3.0.9</version>
<exclusions>
<exclusion>
<groupId>org.jetbrains.kotlin</groupId>
<artifactId>kotlin-stdlib</artifactId>
</exclusion>
</exclusions>
</dependency>
package 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<String, String> map = db.hashMap("messages", STRING, STRING).createOrOpen();
@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.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<Integer, String> map = db.hashMap("messages", INTEGER, STRING).createOrOpen();
@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.commit();
}
@Override
public void deleteMessages(Object memoryId) {
map.remove((int) memoryId);
db.commit();
}
}
}
版权归原作者 邢文凯 所有, 如有侵权,请联系我们删除。