Berbagi teknologi

3. Memori Obrolan LangChain4j

2024-07-12

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

Pengantar Memori Obrolan

Memori ObrolanIni disebut memori obrolan, yang menyimpan riwayat percakapan antara pengguna dan model besar, sehingga model besar dapat menggunakan percakapan historis tersebut untuk memahami apa yang baru-baru ini dikatakan pengguna dan apa maksudnya.

Namun, jika Anda terus menyimpan percakapan historis di Memori Obrolan, maka akan memerlukan lebih banyak ruang penyimpanan. Oleh karena itu, ChatMemory juga mendukung fungsi tambahan seperti batasan jendela, mekanisme eliminasi, mekanisme persistensi, dll.


ChatMemory adalah antarmuka yang menyediakan dua kelas implementasi secara default:

  • PesanJendelaObrolanMemori

Berdasarkan ukuran koleksinya, pesan-pesan lama dihilangkan.Sebagai jendela geser, simpanN Berita terkini dan usir berita lama yang sudah tidak muat lagi.Namun, karena setiap pesan dapat berisi jumlah token yang berbeda,MessageWindowChatMemory Sangat berguna untuk pembuatan prototipe cepat.

  • Jendela TokenObrolanMemori

Berdasarkan ukuran tokennya, pesan-pesan lama akan dihilangkan.Ini juga berfungsi sebagai jendela geser tetapi berfokus pada penahanN token terbaru dan hapus pesan lama sesuai kebutuhan. Informasi tidak dapat dipisahkan. Jika pesannya tidak sesuai maka akan diusir seluruhnya. TokenWindowChatMemory memerlukan aTokenizer untuk menghitung masing-masingChatMessage tanda masuk.


Perbedaan antara TokenWindowChatMemory dan MessageWindowChatMemory

TokenWindowChatMemory mirip dengan MessageWindowChatMemory. Bedanya cara menghitung kapasitasnya berbeda. MessageWindowChatMemory langsung mengambil List.<ChatMessage> ukuran, dan TokenWindowChatMemory akan menggunakan Tokenizer yang ditentukan untuk<ChatMessage> Jumlah Token yang sesuai diperkirakan, dan kemudian dibandingkan dengan maxTokens yang ditetapkan. Jika jumlahnya melebihi maxTokens, maka ChatMessage terlama juga akan dihilangkan.

Tokenizer adalah sebuah antarmuka. Kelas implementasi OpenAiTokenizer disediakan secara default. Ini digunakan untuk memperkirakan berapa banyak Token yang sesuai dengan ChatMessage. API dari banyak model besar mengenakan biaya berdasarkan jumlah Token yang digunakan, jadi disarankan untuk menggunakannya saat biayanya sensitif. TokenWindowChatMemory digunakan untuk mengontrol jumlah total Token yang digunakan dalam satu sesi.

Kedua kelas implementasi memiliki atribut ChatMemoryStore di dalamnya. ChatMemoryStore juga merupakan antarmuka. Ada kelas implementasi InMemoryChatMemoryStore secara default. Seiring waktu, implementasi out-of-the-box akan ditambahkan untuk penyimpanan populer seperti database SQL, penyimpanan dokumen, dll.Sementara itu, Anda dapat mengimplementasikan antarmuka ini untuk terhubung ke penyimpanan apa pun pilihan Anda


Praktek kasus

Kasus 1: Buat master penamaan populer berdasarkan 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. }
Kasus 2: Sesuaikan ChatMemoryStore untuk mempertahankan ChatMessage ke disk

Perkenalkan dependensi pakar

  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>

 Sesuaikan ChatMemoryStore untuk mencapai penyimpanan persisten

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

  pengujian kode

  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. }
Kasus 3: Simpan rekaman obrolan secara terpisah untuk setiap pengguna
  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. }