
手动维护和管理ChatMessage比较繁琐。因此,LangChain4j 提供了ChatMemory抽象以及多个开箱即用的实现:
ChatMemory可以作为一个独立的底层组件使用ChatMemory作为ChatMessage的容器(基于List),并提供以下附加功能:
SystemMessage的特殊处理“内存”和“历史记录”相似但有区别:
LangChain4j 当前仅提供“内存”,而非“历史记录”。如果您需要保留整个历史记录,请手动进行保存。
LLM 能一次处理的 token 数是有限。在某些情况下,对话可能会超出这个限制,此时需要驱逐部分消息。 通常,最早的消息会被驱逐,但如果需要,也可以实现更复杂的算法。
每个 token 都有成本,因此每次调用 LLM 的成本会逐渐增加。驱逐不必要的消息可以降低成本。
发送给 LLM 的 token 越多,处理时间越长。
目前,LangChain4j 提供两种开箱即用的
MessageWindowChatMemory作为滑动窗口保留最近的N条消息,并驱逐不再符合条件的较旧消息。 由于每条消息包含的 token 数可能不同,MessageWindowChatMemory 主要用于快速原型开发。
TokenWindowChatMemory也是滑动窗口,但重点是保留最近的N个token,并根据需要驱逐较旧的消息。 消息是不可分割的。如果某条消息不符合条件,它将被完全驱逐。 TokenWindowChatMemory 需要一个Tokenizer来统计每条ChatMessage中的 token 数。
默认情况下,ChatMemory的实现将ChatMessage存储在内存中。如需持久化,可以实现自定义的ChatMemoryStore, 将ChatMessage存储在您选择的任何持久存储中:
class PersistentChatMemoryStore implements ChatMemoryStore {
@Override
public List<ChatMessage> getMessages(Object memoryId) {
// TODO: 实现通过内存 ID 从持久存储中获取所有消息的功能。
// 可以使用 ChatMessageDeserializer.messageFromJson(String) 和
// ChatMessageDeserializer.messagesFromJson(String) 来轻松从 JSON 反序列化聊天消息。
}
@Override
public void updateMessages(Object memoryId, List<ChatMessage> messages) {
// TODO: 实现通过内存 ID 更新持久存储中的所有消息。
// 可以使用 ChatMessageSerializer.messageToJson(ChatMessage) 和
// ChatMessageSerializer.messagesToJson(List<ChatMessage>) 来轻松将聊天消息序列化为 JSON。
}
@Override
public void deleteMessages(Object memoryId) {
// TODO: 实现通过内存 ID 删除持久存储中所有消息的功能。
}
}
ChatMemory chatMemory = MessageWindowChatMemory.builder()
.id("12345")
.maxMessages(10)
.chatMemoryStore(new PersistentChatMemoryStore())
.build();每当新的ChatMessage添加到ChatMemory中时,updateMessages()方法就会被调用。 通常在每次与 LLM 交互的过程中,这个方法会被调用两次:
UserMessage时AiMessage时。 updateMessages()方法需要更新与给定内存 ID 相关联的所有消息。 可以将ChatMessage分别存储(例如,每条消息一个记录/行/对象), 也可以将其一起存储(例如,整个ChatMemory作为一个记录/行/对象)。
从
ChatMemory中驱逐的消息也将从ChatMemoryStore中驱逐。 当某条消息被驱逐时,updateMessages()方法将被调用, 并且传递的消息列表不包含已驱逐的消息。
每当ChatMemory的用户请求所有消息时,都会调用getMessages()方法。 通常在每次与 LLM 交互时调用一次。 Object memoryId参数的值对应于创建ChatMemory时指定的id,
它可以用于区分多个用户和/或对话。 getMessages()方法应该返回与给定内存 ID 相关联的所有消息。
每当调用ChatMemory.clear()时,都会调用deleteMessages()方法。 如果不使用此功能,可以将此方法留空。
特殊的消息类型:
SystemMessage将始终保留SystemMessageSystemMessage,则会被忽略SystemMessage,它将替换之前的消息如果包含ToolExecutionRequest的AiMessage被驱逐, 后续的孤立ToolExecutionResultMessage也会自动被驱逐, 以避免某些 LLM 提供商(如 OpenAI)不允许在请求中发送孤立的ToolExecutionResultMessage的问题。
原创声明:本文系作者授权腾讯云开发者社区发表,未经许可,不得转载。
如有侵权,请联系 cloudcommunity@tencent.com 删除。
原创声明:本文系作者授权腾讯云开发者社区发表,未经许可,不得转载。
如有侵权,请联系 cloudcommunity@tencent.com 删除。