Technologieaustausch

3. Chat-Speicher von LangChain4j

2024-07-12

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

Einführung in das Chat-Memory

Chat-SpeicherEs wird als Chat-Speicher bezeichnet, der die historischen Gespräche zwischen Benutzern und großen Modellen speichert, sodass die großen Modelle diese historischen Gespräche nutzen können, um zu verstehen, was die Benutzer kürzlich gesagt haben und was sie meinen.

Wenn Sie jedoch weiterhin historische Konversationen im Chat Memory speichern, wird immer mehr Speicherplatz benötigt. Daher unterstützt ChatMemory auch erweiterte Funktionen wie Fensterbegrenzung, Eliminierungsmechanismus, Persistenzmechanismus usw.


ChatMemory ist eine Schnittstelle, die standardmäßig zwei Implementierungsklassen bereitstellt:

  • NachrichtFensterChatSpeicher

Je nach Umfang der Sammlung werden alte Nachrichten gelöscht.B. ein Schiebefenster, haltenN die neuesten Nachrichten und entfernen Sie alte Nachrichten, die nicht mehr passen.Da jedoch jede Nachricht eine unterschiedliche Anzahl an Token enthalten kann,MessageWindowChatMemory Sehr nützlich für Rapid Prototyping.

  • TokenFensterChatSpeicher

Je nach Größe des Tokens werden alte Nachrichten gelöscht.Es läuft auch als Schiebefenster, konzentriert sich aber auf das BeibehaltenN Das neueste Token und alte Nachrichten nach Bedarf entfernen. Informationen sind untrennbar miteinander verbunden. Wenn die Nachricht nicht geeignet ist, wird sie vollständig entfernt. TokenWindowChatMemory erfordert aTokenizer jeweils zu berechnenChatMessage Token in .


Der Unterschied zwischen TokenWindowChatMemory und MessageWindowChatMemory

TokenWindowChatMemory ähnelt MessageWindowChatMemory. Der Unterschied besteht darin, dass MessageWindowChatMemory direkt eine andere Methode zur Berechnung der Kapazität verwendet.<ChatMessage> Größe, und TokenWindowChatMemory verwendet den angegebenen Tokenizer, um<ChatMessage> Die entsprechende Anzahl an Token wird geschätzt und dann mit den festgelegten maxTokens verglichen. Wenn die Anzahl maxTokens überschreitet, wird sie ebenfalls eliminiert, und die älteste ChatMessage wird ebenfalls eliminiert.

Tokenizer ist eine Schnittstelle, die standardmäßig bereitgestellt wird. Sie wird verwendet, um anhand der Anzahl der verwendeten Token abzuschätzen, wie viele Tokens einer ChatMessage-API entsprechen Die Kosten sind empfindlich. TokenWindowChatMemory wird verwendet, um die Gesamtzahl der in einer Sitzung verwendeten Token zu steuern.

Beide Implementierungsklassen verfügen über ein ChatMemoryStore-Attribut. ChatMemoryStore ist ebenfalls eine Schnittstelle. Es gibt standardmäßig eine InMemoryChatMemoryStore-Implementierungsklasse. Im Laufe der Zeit werden vorkonfigurierte Implementierungen für beliebte Speicher wie SQL-Datenbanken, Dokumentenspeicher usw. hinzugefügt.Mittlerweile können Sie diese Schnittstelle implementieren, um eine Verbindung zu jedem Speicher Ihrer Wahl herzustellen


Fallpraxis

Fall 1: Erstellen Sie einen beliebten Namensmaster basierend auf 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. }
Fall 2: Passen Sie ChatMemoryStore an, um ChatMessage auf der Festplatte beizubehalten

Führen Sie Maven-Abhängigkeiten ein

  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>

 Passen Sie ChatMemoryStore an, um dauerhaften Speicher zu erreichen

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

  Code-Tests

  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. }
Fall 3: Chat-Aufzeichnungen für jeden Benutzer separat speichern
  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. }