Add SQLite persistence to restore and continue previous conversations
This commit is contained in:
parent
a150ce37f8
commit
73f3ade0f0
4
.gitignore
vendored
4
.gitignore
vendored
@ -37,4 +37,6 @@ build/
|
||||
|
||||
*.gguf
|
||||
|
||||
*.log
|
||||
*.log
|
||||
|
||||
*.db
|
17
pom.xml
17
pom.xml
@ -42,6 +42,23 @@
|
||||
<version>4.2.0</version>
|
||||
</dependency>
|
||||
|
||||
<!-- Database -->
|
||||
<dependency>
|
||||
<groupId>org.xerial</groupId>
|
||||
<artifactId>sqlite-jdbc</artifactId>
|
||||
<version>3.45.1.0</version>
|
||||
</dependency>
|
||||
|
||||
<dependency>
|
||||
<groupId>org.hibernate.orm</groupId>
|
||||
<artifactId>hibernate-community-dialects</artifactId>
|
||||
</dependency>
|
||||
|
||||
<dependency>
|
||||
<groupId>org.springframework.boot</groupId>
|
||||
<artifactId>spring-boot-starter-data-jpa</artifactId>
|
||||
</dependency>
|
||||
|
||||
<!-- Test support -->
|
||||
<dependency>
|
||||
<groupId>org.springframework.boot</groupId>
|
||||
|
@ -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<ChatMessage> 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);
|
||||
}
|
||||
|
@ -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<ChatMessage> getMessages(HttpSession session) {
|
||||
String sessionId = session.getId();
|
||||
List<ChatMessage> messages = chatMessageStore.getMessages(sessionId);
|
||||
List<ChatMessage> 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<ChatMessage> messages) {
|
||||
messages.removeIf(m -> ObjectUtils.isEmpty(m.text()));
|
||||
chatMessageStore.saveMessages(session.getId(), messages);
|
||||
}
|
||||
}
|
@ -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;
|
||||
|
@ -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<ChatMessage> getMessages(String sessionId);
|
||||
void saveMessages(String sessionId, List<ChatMessage> messages);
|
||||
}
|
@ -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;
|
||||
}
|
||||
}
|
@ -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<ChatMessageEntity, Long> {
|
||||
List<ChatMessageEntity> findBySessionIdOrderByIdAsc(String sessionId);
|
||||
void deleteBySessionId(String sessionId);
|
||||
}
|
@ -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());
|
||||
}
|
||||
}
|
@ -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<ChatMessage> getMessages(String sessionId) {
|
||||
return repository.findBySessionIdOrderByIdAsc(sessionId)
|
||||
.stream()
|
||||
.map(ChatMessageMapper::toDomain)
|
||||
.toList();
|
||||
}
|
||||
|
||||
@Override
|
||||
@Transactional
|
||||
public void saveMessages(String sessionId, List<ChatMessage> messages) {
|
||||
repository.deleteBySessionId(sessionId);
|
||||
List<ChatMessageEntity> entities = messages.stream()
|
||||
.map(m -> ChatMessageMapper.toEntity(sessionId, m))
|
||||
.toList();
|
||||
repository.saveAll(entities);
|
||||
}
|
||||
}
|
@ -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<ChatMessage> getMessages(HttpSession session) {
|
||||
List<ChatMessage> messages = (List<ChatMessage>) 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<ChatMessage> messages) {
|
||||
session.setAttribute(ATTR_MESSAGES, messages);
|
||||
}
|
||||
}
|
||||
|
@ -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
|
||||
|
19
src/main/resources/application.yml
Normal file
19
src/main/resources/application.yml
Normal file
@ -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
|
||||
|
Loading…
x
Reference in New Issue
Block a user