Compartir tecnología

3. Memoria de chat de LangChain4j

2024-07-12

한어Русский языкEnglishFrançaisIndonesianSanskrit日本語DeutschPortuguêsΕλληνικάespañolItalianoSuomalainenLatina

Introducción a la memoria de chat

Memoria de chatSe llama memoria de chat y almacena las conversaciones históricas entre usuarios y modelos grandes, de modo que los modelos grandes puedan usar estas conversaciones históricas para comprender lo que los usuarios dijeron recientemente y lo que quieren decir.

Sin embargo, si sigue almacenando conversaciones históricas en Chat Memory, necesitará cada vez más espacio de almacenamiento. Por lo tanto, ChatMemory también admite funciones extendidas como limitación de ventanas, mecanismo de eliminación, mecanismo de persistencia, etc.


ChatMemory es una interfaz que proporciona dos clases de implementación de forma predeterminada:

  • Ventana de mensajesChatMemoria

Según el tamaño de la colección se eliminan los mensajes antiguos.Como ventana corredera, mantengaN Las últimas novedades y desalojar noticias viejas que ya no encajan.Sin embargo, dado que cada mensaje puede contener una cantidad diferente de tokens,MessageWindowChatMemory Muy útil para la creación rápida de prototipos.

  • Ventana de tokenChatMemory

Según el tamaño del token se eliminan los mensajes antiguos.También funciona como una ventana corredera pero se centra en retenerN el token más reciente y expulsar los mensajes antiguos según sea necesario. La información es indivisible. Si el mensaje no es adecuado, será desalojado por completo. TokenWindowChatMemory requiere unaTokenizer para calcular cadaChatMessage ficha en .


La diferencia entre TokenWindowChatMemory y MessageWindowChatMemory

TokenWindowChatMemory es similar a MessageWindowChatMemory. La diferencia es que la forma de calcular la capacidad es diferente. MessageWindowChatMemory toma directamente la Lista.<ChatMessage> tamaño, y TokenWindowChatMemory utilizará el Tokenizer especificado para<ChatMessage> Se estima la cantidad correspondiente de Tokens y luego se compara con los maxTokens establecidos. Si el número excede maxTokens, también se eliminará y el ChatMessage más antiguo también se eliminará.

Tokenizer es una interfaz. La clase de implementación OpenAiTokenizer se proporciona de forma predeterminada. Se utiliza para estimar cuántos tokens corresponden a una API de ChatMessage de muchos modelos grandes en función de la cantidad de tokens utilizados, por lo que se recomienda usarlo cuando el. El costo es sensible. TokenWindowChatMemory se usa para controlar la cantidad total de tokens utilizados en una sesión.

Ambas clases de implementación tienen un atributo ChatMemoryStore en su interior. ChatMemoryStore también es una interfaz. Hay una clase de implementación InMemoryChatMemoryStore de forma predeterminada. Con el tiempo, se agregarán implementaciones listas para usar para tiendas populares como bases de datos SQL, almacenes de documentos, etc.Mientras tanto, puede implementar esta interfaz para conectarse a cualquier almacenamiento de su elección.


Práctica de caso

Caso 1: crear un maestro de nombres popular basado en ChatMemory
  1. public class NameDemo {
  2. interface NamingMaster {
  3. String talk(String desc);
  4. }
  5. public static void main(String[] args) {
  6. ChatLanguageModel chatModel = ZhipuAiChatModel.builder()
  7. .apiKey("智普apikey")
  8. .build();
  9. ChatMemory chatMemory = MessageWindowChatMemory.withMaxMessages(10);
  10. NamingMaster namingMaster = AiServices.builder(NamingMaster.class)
  11. .chatLanguageModel(chatModel)
  12. .chatMemory(chatMemory)
  13. .build();
  14. System.out.println(namingMaster.talk("我姓李,帮我取一个好听的女孩名字,就一个你觉得最好的"));
  15. System.out.println("---");
  16. System.out.println(namingMaster.talk("换一个"));
  17. }
  18. }
Caso 2: Personalice ChatMemoryStore para conservar ChatMessage en el disco

Introducir dependencias de maven

  1. <dependency>
  2. <groupId>org.mapdb</groupId>
  3. <artifactId>mapdb</artifactId>
  4. <version>3.0.9</version>
  5. <exclusions>
  6. <exclusion>
  7. <groupId>org.jetbrains.kotlin</groupId>
  8. <artifactId>kotlin-stdlib</artifactId>
  9. </exclusion>
  10. </exclusions>
  11. </dependency>

 Personalice ChatMemoryStore para lograr un almacenamiento persistente

  1. public class PersistentChatMemoryStore implements ChatMemoryStore {
  2. private final DB db = DBMaker.fileDB("chat-memory.db").transactionEnable().make();
  3. private final Map<String, String> map = db.hashMap("messages", Serializer.STRING, Serializer.STRING).createOrOpen();
  4. @Override
  5. public List<ChatMessage> getMessages(Object memoryId) {
  6. String json = map.get((String) memoryId);
  7. return ChatMessageDeserializer.messagesFromJson(json);
  8. }
  9. @Override
  10. public void updateMessages(Object memoryId, List<ChatMessage> messages) {
  11. String json = ChatMessageSerializer.messagesToJson(messages);
  12. map.put((String) memoryId, json);
  13. db.commit();
  14. }
  15. @Override
  16. public void deleteMessages(Object memoryId) {
  17. map.remove((String) memoryId);
  18. db.commit();
  19. }
  20. }

  prueba de código

  1. public class PersistentDemo {
  2. interface NamingMaster {
  3. String talk(String desc);
  4. }
  5. public static void main(String[] args) {
  6. ChatLanguageModel chatModel = ZhipuAiChatModel.builder()
  7. .apiKey("智普apikey")
  8. .build();
  9. ChatMemory chatMemory = MessageWindowChatMemory.builder()
  10. .chatMemoryStore(new PersistentChatMemoryStore())
  11. .maxMessages(10)
  12. .build();
  13. NamingMaster namingMaster = AiServices.builder(NamingMaster.class)
  14. .chatLanguageModel(chatModel)
  15. .chatMemory(chatMemory)
  16. .build();
  17. System.out.println(namingMaster.talk("我姓李,帮我取一个好听的女孩名字,就一个你觉得最好的"));
  18. System.out.println("---");
  19. System.out.println(namingMaster.talk("换一个"));
  20. }
  21. }
Caso 3: almacenar registros de chat por separado para cada usuario
  1. public class NameDemo {
  2. interface NamingMaster {
  3. String talk(@MemoryId Integer userId, @UserMessage String desc);
  4. }
  5. public static void main(String[] args) {
  6. ChatLanguageModel chatModel = ZhipuAiChatModel.builder()
  7. .apiKey("智普apikey")
  8. .build();
  9. NamingMaster namingMaster = AiServices.builder(NamingMaster.class)
  10. .chatLanguageModel(chatModel)
  11. .chatMemoryProvider(userId -> MessageWindowChatMemory.withMaxMessages(10))
  12. .build();
  13. System.out.println(namingMaster.talk(1, "我姓李,帮我取一个好听的女孩名字,就一个你觉得最好的"));
  14. System.out.println("---");
  15. System.out.println(namingMaster.talk(2, "我姓赵,帮我取一个好听的男孩名字,就一个你觉得最好的"));
  16. System.out.println("---");
  17. System.out.println(namingMaster.talk(1, "换一个"));
  18. }
  19. }