Condivisione della tecnologia

3. Memoria chat di LangChain4j

2024-07-12

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

Introduzione alla memoria di chat

Memoria di chatSi chiama memoria di chat, che memorizza le conversazioni storiche tra utenti e modelli di grandi dimensioni, in modo che i modelli di grandi dimensioni possano utilizzare queste conversazioni storiche per capire cosa hanno detto di recente gli utenti e cosa intendono.

Tuttavia, se continui a memorizzare le conversazioni storiche in Chat Memory, lo spazio di archiviazione richiesto diventerà sempre più grande. Pertanto, ChatMemory supporta anche funzioni estese come la limitazione delle finestre, il meccanismo di eliminazione, il meccanismo di persistenza, ecc.


ChatMemory è un'interfaccia che fornisce due classi di implementazione per impostazione predefinita:

  • FinestraMessaggioChatMemory

A seconda della dimensione della raccolta, i vecchi messaggi vengono eliminati.Come finestra scorrevole, mantieniN le ultime notizie e sfrattare quelle vecchie che non vanno più bene.Tuttavia, poiché ciascun messaggio può contenere un numero diverso di token,MessageWindowChatMemory Molto utile per la prototipazione rapida.

  • FinestraTokenChatMemory

A seconda della dimensione del token, i vecchi messaggi vengono eliminati.Funziona anche come una finestra scorrevole ma si concentra sulla ritenzioneN Il token più recente ed elimina i vecchi messaggi secondo necessità. Le informazioni sono indivisibili. Se il messaggio non è adatto, verrà completamente sfrattato. TokenWindowChatMemory richiede un fileTokenizer per calcolare ciascunoChatMessage gettone dentro.


La differenza tra TokenWindowChatMemory e MessageWindowChatMemory

TokenWindowChatMemory è simile a MessageWindowChatMemory. La differenza è che il modo di calcolare la capacità è diverso. MessageWindowChatMemory utilizza direttamente List.<ChatMessage> size e TokenWindowChatMemory utilizzerà il Tokenizer specificato<ChatMessage> Il numero corrispondente di Token viene stimato e poi confrontato con i maxTokens impostati. Se il numero supera i maxTokens, verrà eliminato anche il ChatMessage più vecchio.

Tokenizer è un'interfaccia. La classe di implementazione OpenAiTokenizer viene fornita per impostazione predefinita. Viene utilizzata per stimare quanti token corrispondono a un ChatMessage di molti modelli di grandi dimensioni addebitati in base al numero di token utilizzati, quindi è consigliabile utilizzarlo quando il costo è sensibile. TokenWindowChatMemory viene utilizzato per controllare il numero totale di token utilizzati in una sessione.

Entrambe le classi di implementazione hanno un attributo ChatMemoryStore al suo interno. ChatMemoryStore è anche un'interfaccia. Per impostazione predefinita è presente una classe di implementazione InMemoryChatMemoryStore. Nel corso del tempo, verranno aggiunte implementazioni pronte all'uso per archivi popolari come database SQL, archivi di documenti, ecc.Nel frattempo, puoi implementare questa interfaccia per connetterti a qualsiasi spazio di archiviazione di tua scelta


Pratica del caso

Caso 1: creare un popolare master di denominazione basato su 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: personalizzare ChatMemoryStore per rendere permanente ChatMessage su disco

Introduci le dipendenze di 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>

 Personalizza ChatMemoryStore per ottenere un'archiviazione 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. }

  test del codice

  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: archivia i record della chat separatamente per ciascun utente
  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. }