Partage de technologie

3. Mémoire de discussion de LangChain4j

2024-07-12

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

Introduction à la mémoire de discussion

Mémoire de discussionC'est ce qu'on appelle la mémoire de discussion, qui stocke les conversations historiques entre les utilisateurs et les grands modèles, afin que les grands modèles puissent utiliser ces conversations historiques pour comprendre ce que les utilisateurs ont récemment dit et ce qu'ils veulent dire.

Cependant, si vous continuez à stocker les conversations historiques dans Chat Memory, cela nécessitera de plus en plus d'espace de stockage. Par conséquent, ChatMemory prend également en charge des fonctions étendues telles que la limitation de fenêtre, le mécanisme d'élimination, le mécanisme de persistance, etc.


ChatMemory est une interface qui fournit deux classes d'implémentation par défaut :

  • Fenêtre de messageChatMémoire

Selon la taille de la collection, les anciens messages sont éliminés.En tant que fenêtre coulissante, gardezN Les dernières nouvelles et expulsez les anciennes nouvelles qui ne correspondent plus.Cependant, comme chaque message peut contenir un nombre différent de jetons,MessageWindowChatMemory Très utile pour le prototypage rapide.

  • TokenWindowChatMémoire

Selon la taille du token, les anciens messages sont éliminés.Il fonctionne également comme une fenêtre coulissante mais se concentre sur la rétentionN le dernier jeton et expulsez les anciens messages si nécessaire. Les informations sont indivisibles. Si le message ne convient pas, il sera complètement expulsé. TokenWindowChatMemory nécessite unTokenizer calculer chacunChatMessage jeton dans .


La différence entre TokenWindowChatMemory et MessageWindowChatMemory

TokenWindowChatMemory est similaire à MessageWindowChatMemory. La différence est que la façon de calculer la capacité est différente. MessageWindowChatMemory prend directement la liste.<ChatMessage> taille, et TokenWindowChatMemory utilisera le Tokenizer spécifié pour<ChatMessage> Le nombre correspondant de Tokens est estimé, puis comparé au maxTokens défini. Si le nombre dépasse maxTokens, il sera également éliminé, et le ChatMessage le plus ancien sera également éliminé.

Tokenizer est une interface. La classe d'implémentation OpenAiTokenizer est fournie par défaut. Elle est utilisée pour estimer le nombre de jetons correspondant à un ChatMessage. Les API de nombreux grands modèles sont facturés en fonction du nombre de jetons utilisés. le coût est sensible. TokenWindowChatMemory est utilisé pour contrôler le nombre total de jetons utilisés dans une session.

Les deux classes d'implémentation ont un attribut ChatMemoryStore à l'intérieur. ChatMemoryStore est également une interface par défaut. Au fil du temps, des implémentations prêtes à l'emploi seront ajoutées pour les magasins populaires tels que les bases de données SQL, les magasins de documents, etc.En attendant, vous pouvez implémenter cette interface pour vous connecter à n'importe quel stockage de votre choix


Pratique de cas

Cas 1 : Créer un maître de dénomination populaire basé sur 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. }
Cas 2 : Personnalisez ChatMemoryStore pour conserver ChatMessage sur le disque

Introduire les dépendances 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>

 Personnalisez ChatMemoryStore pour obtenir un stockage persistant

  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. }

  test de code

  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. }
Cas 3 : stocker les enregistrements de discussion séparément pour chaque utilisateur
  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. }