View Javadoc
1   package fr.paris.lutece.plugins.knowledge.service;
2   
3   import dev.langchain4j.data.message.ChatMessage;
4   import dev.langchain4j.store.memory.chat.ChatMemoryStore;
5   import fr.paris.lutece.plugins.knowledge.business.Bot;
6   import fr.paris.lutece.plugins.knowledge.business.BotSession;
7   import fr.paris.lutece.plugins.knowledge.business.BotSessionHome;
8   import fr.paris.lutece.plugins.knowledge.rs.RequestData;
9   import fr.paris.lutece.portal.service.security.LuteceUser;
10  import fr.paris.lutece.portal.service.security.SecurityService;
11  import org.apache.commons.lang3.tuple.Pair;
12  import org.apache.commons.lang3.tuple.ImmutablePair;
13  
14  
15  
16  import static dev.langchain4j.data.message.ChatMessageDeserializer.messagesFromJson;
17  import static dev.langchain4j.data.message.ChatMessageSerializer.messagesToJson;
18  
19  import javax.servlet.http.HttpServletRequest;
20  import javax.servlet.http.HttpSession;
21  import java.util.HashMap;
22  import java.util.List;
23  import java.util.Map;
24  
25  public class ChatMemoryService
26  {
27      private static final String ATTRIBUTE_CHAT_MEMORY_MAP = "CHAT_MEMORY_MAP";
28      
29      /**
30       * Retrieves a chat memory associated with the given project ID from the provided session. If no chat memory exists for the given project ID, a new one is
31       * created.
32       * 
33       * @param session
34       *            The current HTTP session.
35       * @param projectId
36       *            The ID of the project for which the chat memory is to be fetched.
37       * @return The associated MessageWindowChatMemory object or a new one if none exists.
38       */
39      @SuppressWarnings( "unchecked" )
40      public static Pair<PersistentChatMemoryStore, String> getChatMemory(HttpServletRequest request, RequestData data, Bot bot, String sessionId ) {
41          LuteceUser luteceUser = SecurityService.getInstance().getRegisteredUser(request);
42          HttpSession session = request.getSession();
43           PersistentChatMemoryStore chatMemoryStore = null;
44      
45          Map<String, PersistentChatMemoryStore> chatMemoryStoreMap = (Map<String, PersistentChatMemoryStore>) session.getAttribute(ATTRIBUTE_CHAT_MEMORY_MAP);
46      
47          if (chatMemoryStoreMap == null) {
48              chatMemoryStoreMap = new HashMap<>();
49              session.setAttribute(ATTRIBUTE_CHAT_MEMORY_MAP, chatMemoryStoreMap);
50          }
51  
52  
53          if( data.getBotSessionId() != null ) {
54              chatMemoryStore = chatMemoryStoreMap.get( data.getBotSessionId() );
55          }
56  
57          String botSessionId;
58  
59          if (chatMemoryStore == null) {
60              if (data.getBotSessionId() != null) {
61                  BotSession botSession = BotSessionHome.findByAccessCode( luteceUser.getAccessCode(), data.getBotSessionId() ).get();
62                  chatMemoryStore = new PersistentChatMemoryStore();
63                  chatMemoryStore.updateMessages(botSession.getSessionId(), messagesFromJson(botSession.getContent()));
64                  chatMemoryStoreMap.put( botSession.getSessionId() , chatMemoryStore);
65                  botSessionId = botSession.getSessionId();
66              } else {
67                  BotSession botSession = createNewBotSession(bot, sessionId, luteceUser );
68                  chatMemoryStore = new PersistentChatMemoryStore();
69                  chatMemoryStoreMap.put(sessionId, chatMemoryStore);
70                  botSessionId = botSession.getSessionId();
71              }
72          } else {
73              botSessionId = data.getBotSessionId();
74          }
75      
76          return new ImmutablePair<>(chatMemoryStore, botSessionId);
77      }
78  
79      private static BotSession createNewBotSession(Bot bot, String sessionId, LuteceUser luteceUser ) {
80          long timestamp = System.currentTimeMillis();
81          BotSessiondge/business/BotSession.html#BotSession">BotSession botSession = new BotSession();
82          botSession.setCreationDate(new java.sql.Date(timestamp));
83          botSession.setBotId(bot.getId());
84          botSession.setAccessCode( luteceUser.getAccessCode( ) );
85          botSession.setSessionId( sessionId );
86          return BotSessionHome.create(botSession);
87      }
88  
89        static class PersistentChatMemoryStore implements ChatMemoryStore {
90          @Override
91          public List<ChatMessage> getMessages(Object memoryId) {
92  
93          BotSession botSession = BotSessionHome.findBySessionId( (String) memoryId ).get( );
94          return messagesFromJson( botSession.getContent( ) );
95          }
96  
97          @Override
98          public void updateMessages(Object memoryId, List<ChatMessage> messages) {
99  
100             BotSession botSession = BotSessionHome.findBySessionId( (String) memoryId ).get( );
101             botSession.setContent( messagesToJson( messages ) );
102             BotSessionHome.update( botSession );
103         }
104 
105         @Override
106         public void deleteMessages(Object memoryId) {
107             BotSessionHome.remove( (int) memoryId );
108         }
109     }
110 
111 }