Compartilhamento de tecnologia

3. Memória de bate-papo de LangChain4j

2024-07-12

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

Introdução à memória de bate-papo

Memória de bate-papoÉ chamada de memória de chat, que armazena o histórico de conversas entre usuários e grandes modelos, para que os grandes modelos possam usar essas conversas históricas para entender o que os usuários disseram recentemente e o que eles querem dizer.

No entanto, se você continuar armazenando conversas históricas na Memória do Chat, o espaço de armazenamento necessário se tornará cada vez maior. Portanto, o ChatMemory também oferece suporte a funções estendidas, como limitação de janela, mecanismo de eliminação, mecanismo de persistência, etc.


ChatMemory é uma interface que fornece duas classes de implementação por padrão:

  • MessageWindowChatMemória

De acordo com o tamanho do acervo, mensagens antigas são eliminadas.Como uma janela deslizante, mantenhaN as últimas notícias e despejar notícias antigas que não cabem mais.No entanto, como cada mensagem pode conter um número diferente de tokens,MessageWindowChatMemory Muito útil para prototipagem rápida.

  • TokenWindowChatMemória

De acordo com o tamanho do token, as mensagens antigas são eliminadas.Também funciona como uma janela deslizante, mas concentra-se em reterN O token mais recente e remova as mensagens antigas conforme necessário. A informação é indivisível. Se a mensagem não for adequada, ela será completamente removida. TokenWindowChatMemory requer umTokenizer calcular cadaChatMessage token em .


A diferença entre TokenWindowChatMemory e MessageWindowChatMemory

TokenWindowChatMemory é semelhante a MessageWindowChatMemory. A diferença é que a forma de calcular a capacidade é diferente.<ChatMessage> size, e TokenWindowChatMemory usará o Tokenizer especificado para<ChatMessage> O número correspondente de Tokens é estimado e então comparado com o conjunto maxTokens. Se o número exceder maxTokens, ele também será eliminado e o ChatMessage mais antigo também será eliminado.

Tokenizer é uma interface. A classe de implementação OpenAiTokenizer é fornecida por padrão. Ela é usada para estimar quantos Tokens correspondem a uma API ChatMessage de muitos modelos grandes, com base no número de Tokens usados. cost é sensível. TokenWindowChatMemory é usado para controlar o número total de tokens usados ​​em uma sessão.

Ambas as classes de implementação possuem um atributo ChatMemoryStore dentro. ChatMemoryStore também é uma interface. Há uma classe de implementação InMemoryChatMemoryStore por padrão. Com o tempo, implementações prontas para uso serão adicionadas para armazenamentos populares, como bancos de dados SQL, armazenamentos de documentos, etc.Enquanto isso, você pode implementar esta interface para conectar-se a qualquer armazenamento de sua escolha


Prática de caso

Caso 1: Crie um mestre de nomenclatura popular baseado em 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: Personalize o ChatMemoryStore para persistir o ChatMessage no disco

Introduzir dependências 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>

 Personalize ChatMemoryStore para obter armazenamento 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. }

  teste 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: armazene registros de bate-papo separadamente para cada usuário
  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. }