diff --git a/.gitignore b/.gitignore index d15fe9b..14d9b1b 100644 --- a/.gitignore +++ b/.gitignore @@ -37,4 +37,6 @@ build/ *.gguf -*.log \ No newline at end of file +*.log + +*.db \ No newline at end of file diff --git a/pom.xml b/pom.xml index 70f4b02..d641665 100644 --- a/pom.xml +++ b/pom.xml @@ -42,6 +42,23 @@ 4.2.0 + + + org.xerial + sqlite-jdbc + 3.45.1.0 + + + + org.hibernate.orm + hibernate-community-dialects + + + + org.springframework.boot + spring-boot-starter-data-jpa + + org.springframework.boot diff --git a/src/main/java/com/pablotj/ia/chat/boot/adapter/controller/ChatPageController.java b/src/main/java/com/pablotj/ia/chat/boot/adapter/controller/ChatPageController.java index 76bead0..bb488b9 100644 --- a/src/main/java/com/pablotj/ia/chat/boot/adapter/controller/ChatPageController.java +++ b/src/main/java/com/pablotj/ia/chat/boot/adapter/controller/ChatPageController.java @@ -1,10 +1,9 @@ package com.pablotj.ia.chat.boot.adapter.controller; +import com.pablotj.ia.chat.boot.application.session.ChatSessionManager; import com.pablotj.ia.chat.boot.application.usecase.ChatUseCase; import com.pablotj.ia.chat.boot.domain.model.ChatMessage; -import com.pablotj.ia.chat.boot.web.session.ChatSessionManager; import jakarta.servlet.http.HttpSession; -import java.util.Date; import java.util.List; import org.apache.logging.log4j.LogManager; import org.apache.logging.log4j.Logger; @@ -32,7 +31,7 @@ public class ChatPageController { List messages = chatSessionManager.getMessages(session); if (messages != null && messages.isEmpty()) { try { - chatUseCase.processUserPrompt("", session); + messages.add(chatUseCase.processUserPrompt("", session)); } catch (Exception e) { LOGGER.error(e.getMessage(), e); } diff --git a/src/main/java/com/pablotj/ia/chat/boot/application/session/ChatSessionManager.java b/src/main/java/com/pablotj/ia/chat/boot/application/session/ChatSessionManager.java new file mode 100644 index 0000000..2940748 --- /dev/null +++ b/src/main/java/com/pablotj/ia/chat/boot/application/session/ChatSessionManager.java @@ -0,0 +1,38 @@ +package com.pablotj.ia.chat.boot.application.session; + +import com.pablotj.ia.chat.boot.domain.model.ChatMessage; +import com.pablotj.ia.chat.boot.domain.port.ChatMessageStore; +import jakarta.servlet.http.HttpSession; +import java.util.ArrayList; +import org.springframework.stereotype.Component; +import org.springframework.util.ObjectUtils; + +import java.util.List; + +@Component +public class ChatSessionManager { + + private final ChatMessageStore chatMessageStore; + + public ChatSessionManager(ChatMessageStore chatMessageStore) { + this.chatMessageStore = chatMessageStore; + } + + public List getMessages(HttpSession session) { + String sessionId = session.getId(); + List messages = chatMessageStore.getMessages(sessionId); + List filteredMessages = new ArrayList<>(messages); + + if (ObjectUtils.isEmpty(filteredMessages)) { + return new ArrayList<>(); + } else { + filteredMessages.removeIf(m -> ObjectUtils.isEmpty(m.text())); + } + return filteredMessages; + } + + public void setMessages(HttpSession session, List messages) { + messages.removeIf(m -> ObjectUtils.isEmpty(m.text())); + chatMessageStore.saveMessages(session.getId(), messages); + } +} \ No newline at end of file diff --git a/src/main/java/com/pablotj/ia/chat/boot/application/usecase/ChatUseCase.java b/src/main/java/com/pablotj/ia/chat/boot/application/usecase/ChatUseCase.java index 0844620..bb33b62 100644 --- a/src/main/java/com/pablotj/ia/chat/boot/application/usecase/ChatUseCase.java +++ b/src/main/java/com/pablotj/ia/chat/boot/application/usecase/ChatUseCase.java @@ -2,10 +2,9 @@ package com.pablotj.ia.chat.boot.application.usecase; import com.pablotj.ia.chat.boot.application.prompt.PromptBuilder; import com.pablotj.ia.chat.boot.application.prompt.PromptTemplates; +import com.pablotj.ia.chat.boot.application.session.ChatSessionManager; import com.pablotj.ia.chat.boot.domain.model.ChatMessage; -import com.pablotj.ia.chat.boot.domain.service.ChatService; import com.pablotj.ia.chat.boot.infraestructure.llm.LlmModelClient; -import com.pablotj.ia.chat.boot.web.session.ChatSessionManager; import jakarta.servlet.http.HttpSession; import java.util.Date; import java.util.List; diff --git a/src/main/java/com/pablotj/ia/chat/boot/domain/port/ChatMessageStore.java b/src/main/java/com/pablotj/ia/chat/boot/domain/port/ChatMessageStore.java new file mode 100644 index 0000000..8b95e28 --- /dev/null +++ b/src/main/java/com/pablotj/ia/chat/boot/domain/port/ChatMessageStore.java @@ -0,0 +1,9 @@ +package com.pablotj.ia.chat.boot.domain.port; + +import com.pablotj.ia.chat.boot.domain.model.ChatMessage; +import java.util.List; + +public interface ChatMessageStore { + List getMessages(String sessionId); + void saveMessages(String sessionId, List messages); +} diff --git a/src/main/java/com/pablotj/ia/chat/boot/persistence/ChatMessageEntity.java b/src/main/java/com/pablotj/ia/chat/boot/persistence/ChatMessageEntity.java new file mode 100644 index 0000000..846d206 --- /dev/null +++ b/src/main/java/com/pablotj/ia/chat/boot/persistence/ChatMessageEntity.java @@ -0,0 +1,44 @@ +package com.pablotj.ia.chat.boot.persistence; + +import jakarta.persistence.*; +import java.util.Date; + +@Entity +@Table(name = "chat_messages") +public class ChatMessageEntity { + + @Id + @GeneratedValue(strategy = GenerationType.IDENTITY) + private Long id; + + private String sessionId; + + @Column(length = 4000) + private String text; + + private String role; + + private Date date; + + // Getters y Setters + + public Long getId() { return id; } + public void setId(Long id) { this.id = id; } + + public String getSessionId() { return sessionId; } + public void setSessionId(String sessionId) { this.sessionId = sessionId; } + + public String getText() { return text; } + public void setText(String text) { this.text = text; } + + public String getRole() { return role; } + public void setRole(String role) { this.role = role; } + + public Date getDate() { + return date; + } + + public void setDate(Date date) { + this.date = date; + } +} \ No newline at end of file diff --git a/src/main/java/com/pablotj/ia/chat/boot/persistence/ChatMessageJpaRepository.java b/src/main/java/com/pablotj/ia/chat/boot/persistence/ChatMessageJpaRepository.java new file mode 100644 index 0000000..39d86af --- /dev/null +++ b/src/main/java/com/pablotj/ia/chat/boot/persistence/ChatMessageJpaRepository.java @@ -0,0 +1,10 @@ +package com.pablotj.ia.chat.boot.persistence; + +import org.springframework.data.jpa.repository.JpaRepository; +import java.util.List; + + +public interface ChatMessageJpaRepository extends JpaRepository { + List findBySessionIdOrderByIdAsc(String sessionId); + void deleteBySessionId(String sessionId); +} \ No newline at end of file diff --git a/src/main/java/com/pablotj/ia/chat/boot/persistence/ChatMessageMapper.java b/src/main/java/com/pablotj/ia/chat/boot/persistence/ChatMessageMapper.java new file mode 100644 index 0000000..3300a18 --- /dev/null +++ b/src/main/java/com/pablotj/ia/chat/boot/persistence/ChatMessageMapper.java @@ -0,0 +1,19 @@ +package com.pablotj.ia.chat.boot.persistence; + +import com.pablotj.ia.chat.boot.domain.model.ChatMessage; + +public class ChatMessageMapper { + + public static ChatMessageEntity toEntity(String sessionId, ChatMessage message) { + ChatMessageEntity entity = new ChatMessageEntity(); + entity.setSessionId(sessionId); + entity.setRole(message.role()); + entity.setText(message.text()); + entity.setDate(message.date()); + return entity; + } + + public static ChatMessage toDomain(ChatMessageEntity entity) { + return new ChatMessage(entity.getRole(), entity.getText(), entity.getDate()); + } +} \ No newline at end of file diff --git a/src/main/java/com/pablotj/ia/chat/boot/persistence/SqliteChatMessageStore.java b/src/main/java/com/pablotj/ia/chat/boot/persistence/SqliteChatMessageStore.java new file mode 100644 index 0000000..36a4cbc --- /dev/null +++ b/src/main/java/com/pablotj/ia/chat/boot/persistence/SqliteChatMessageStore.java @@ -0,0 +1,35 @@ +package com.pablotj.ia.chat.boot.persistence; + +import com.pablotj.ia.chat.boot.domain.model.ChatMessage; +import com.pablotj.ia.chat.boot.domain.port.ChatMessageStore; +import org.springframework.stereotype.Repository; +import java.util.List; +import org.springframework.transaction.annotation.Transactional; + +@Repository +public class SqliteChatMessageStore implements ChatMessageStore { + + private final ChatMessageJpaRepository repository; + + public SqliteChatMessageStore(ChatMessageJpaRepository repository) { + this.repository = repository; + } + + @Override + public List getMessages(String sessionId) { + return repository.findBySessionIdOrderByIdAsc(sessionId) + .stream() + .map(ChatMessageMapper::toDomain) + .toList(); + } + + @Override + @Transactional + public void saveMessages(String sessionId, List messages) { + repository.deleteBySessionId(sessionId); + List entities = messages.stream() + .map(m -> ChatMessageMapper.toEntity(sessionId, m)) + .toList(); + repository.saveAll(entities); + } +} \ No newline at end of file diff --git a/src/main/java/com/pablotj/ia/chat/boot/web/session/ChatSessionManager.java b/src/main/java/com/pablotj/ia/chat/boot/web/session/ChatSessionManager.java deleted file mode 100644 index c853a5d..0000000 --- a/src/main/java/com/pablotj/ia/chat/boot/web/session/ChatSessionManager.java +++ /dev/null @@ -1,30 +0,0 @@ -package com.pablotj.ia.chat.boot.web.session; - -import com.pablotj.ia.chat.boot.domain.model.ChatMessage; -import jakarta.servlet.http.HttpSession; -import java.util.ArrayList; -import java.util.List; -import org.springframework.stereotype.Component; -import org.springframework.util.ObjectUtils; - -@Component -public class ChatSessionManager { - - private static final String ATTR_MESSAGES = "messages"; - - @SuppressWarnings("unchecked") - public List getMessages(HttpSession session) { - List messages = (List) session.getAttribute(ATTR_MESSAGES); - if (messages == null) { - messages = new ArrayList<>(); - session.setAttribute(ATTR_MESSAGES, messages); - } - messages.removeIf(m -> ObjectUtils.isEmpty(m.text())); - return messages; - } - - public void setMessages(HttpSession session, List messages) { - session.setAttribute(ATTR_MESSAGES, messages); - } -} - diff --git a/src/main/resources/application.properties b/src/main/resources/application.properties deleted file mode 100644 index f794079..0000000 --- a/src/main/resources/application.properties +++ /dev/null @@ -1,9 +0,0 @@ -spring.application.name = ia-chat-boot -server.port = 8080 - -! Model -llama.model.name = openchat-3.5-0106.Q4_K_M -llama.model.gpu.enabled = true -llama.model.gpu.layers = 35 -llama.model.tokens = 1024 - diff --git a/src/main/resources/application.yml b/src/main/resources/application.yml new file mode 100644 index 0000000..5affd85 --- /dev/null +++ b/src/main/resources/application.yml @@ -0,0 +1,19 @@ +server: + port: 8080 +spring: + application: + name: ia-chat-boot + datasource: + url: jdbc:sqlite:file:chat.db + jpa: + database-platform: org.hibernate.community.dialect.SQLiteDialect + hibernate: + ddl-auto: update +llama: + model: + name: openchat-3.5-0106.Q4_K_M + gpu: + enabled: true + layers: 35 + tokens: 1024 +