ai greets first with full context
This commit is contained in:
@@ -1,9 +1,6 @@
|
|||||||
package com.petshop.backend.dto.chat;
|
package com.petshop.backend.dto.chat;
|
||||||
|
|
||||||
import jakarta.validation.constraints.NotBlank;
|
|
||||||
|
|
||||||
public class ConversationRequest {
|
public class ConversationRequest {
|
||||||
@NotBlank(message = "Initial message is required")
|
|
||||||
private String message;
|
private String message;
|
||||||
|
|
||||||
public ConversationRequest() {
|
public ConversationRequest() {
|
||||||
|
|||||||
@@ -59,14 +59,20 @@ public class ChatService {
|
|||||||
conversation.setMode(Conversation.ConversationMode.AUTOMATED);
|
conversation.setMode(Conversation.ConversationMode.AUTOMATED);
|
||||||
conversation = conversationRepository.save(conversation);
|
conversation = conversationRepository.save(conversation);
|
||||||
|
|
||||||
Message message = new Message();
|
User botUser = getBotUser();
|
||||||
message.setConversationId(conversation.getId());
|
String firstName = user.getFirstName();
|
||||||
message.setSenderId(userId);
|
String greeting = (firstName != null && !firstName.isBlank())
|
||||||
message.setContent(request.getMessage());
|
? "Hi " + firstName + "! I'm Leon's Pet Assistant. Ask me anything about pet care, adoption advice, or your pets."
|
||||||
message.setIsRead(false);
|
: "Hi! I'm Leon's Pet Assistant. Ask me anything about pet care, adoption advice, or your pets.";
|
||||||
messageRepository.save(message);
|
|
||||||
|
|
||||||
return ConversationResponse.fromEntity(conversation, request.getMessage(), userId);
|
Message greetingMsg = new Message();
|
||||||
|
greetingMsg.setConversationId(conversation.getId());
|
||||||
|
greetingMsg.setSenderId(botUser.getId());
|
||||||
|
greetingMsg.setContent(greeting);
|
||||||
|
greetingMsg.setIsRead(false);
|
||||||
|
messageRepository.save(greetingMsg);
|
||||||
|
|
||||||
|
return ConversationResponse.fromEntity(conversation, greeting, botUser.getId());
|
||||||
}
|
}
|
||||||
|
|
||||||
public List<ConversationResponse> getConversations(Long userId, User.Role role, boolean mine) {
|
public List<ConversationResponse> getConversations(Long userId, User.Role role, boolean mine) {
|
||||||
|
|||||||
@@ -5,8 +5,10 @@ import com.fasterxml.jackson.databind.ObjectMapper;
|
|||||||
import com.fasterxml.jackson.databind.json.JsonMapper;
|
import com.fasterxml.jackson.databind.json.JsonMapper;
|
||||||
import com.petshop.backend.entity.Conversation;
|
import com.petshop.backend.entity.Conversation;
|
||||||
import com.petshop.backend.entity.Message;
|
import com.petshop.backend.entity.Message;
|
||||||
|
import com.petshop.backend.entity.Pet;
|
||||||
import com.petshop.backend.entity.User;
|
import com.petshop.backend.entity.User;
|
||||||
import com.petshop.backend.repository.MessageRepository;
|
import com.petshop.backend.repository.MessageRepository;
|
||||||
|
import com.petshop.backend.repository.PetRepository;
|
||||||
import com.petshop.backend.repository.UserRepository;
|
import com.petshop.backend.repository.UserRepository;
|
||||||
import org.slf4j.Logger;
|
import org.slf4j.Logger;
|
||||||
import org.slf4j.LoggerFactory;
|
import org.slf4j.LoggerFactory;
|
||||||
@@ -39,6 +41,7 @@ public class OpenRouterAiService {
|
|||||||
private final ChatRealtimeService chatRealtimeService;
|
private final ChatRealtimeService chatRealtimeService;
|
||||||
private final MessageRepository messageRepository;
|
private final MessageRepository messageRepository;
|
||||||
private final UserRepository userRepository;
|
private final UserRepository userRepository;
|
||||||
|
private final PetRepository petRepository;
|
||||||
private final ObjectMapper objectMapper;
|
private final ObjectMapper objectMapper;
|
||||||
private final HttpClient httpClient;
|
private final HttpClient httpClient;
|
||||||
|
|
||||||
@@ -46,12 +49,14 @@ public class OpenRouterAiService {
|
|||||||
ChatService chatService,
|
ChatService chatService,
|
||||||
ChatRealtimeService chatRealtimeService,
|
ChatRealtimeService chatRealtimeService,
|
||||||
MessageRepository messageRepository,
|
MessageRepository messageRepository,
|
||||||
UserRepository userRepository
|
UserRepository userRepository,
|
||||||
|
PetRepository petRepository
|
||||||
) {
|
) {
|
||||||
this.chatService = chatService;
|
this.chatService = chatService;
|
||||||
this.chatRealtimeService = chatRealtimeService;
|
this.chatRealtimeService = chatRealtimeService;
|
||||||
this.messageRepository = messageRepository;
|
this.messageRepository = messageRepository;
|
||||||
this.userRepository = userRepository;
|
this.userRepository = userRepository;
|
||||||
|
this.petRepository = petRepository;
|
||||||
this.objectMapper = JsonMapper.builder().findAndAddModules().build();
|
this.objectMapper = JsonMapper.builder().findAndAddModules().build();
|
||||||
this.httpClient = HttpClient.newBuilder()
|
this.httpClient = HttpClient.newBuilder()
|
||||||
.connectTimeout(Duration.ofSeconds(10))
|
.connectTimeout(Duration.ofSeconds(10))
|
||||||
@@ -117,10 +122,15 @@ public class OpenRouterAiService {
|
|||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
User customer = userRepository.findById(conversation.getCustomerId()).orElse(null);
|
||||||
|
List<Pet> customerPets = customer != null
|
||||||
|
? petRepository.findAllByOwner_IdOrderByPetNameAsc(customer.getId())
|
||||||
|
: List.of();
|
||||||
|
|
||||||
List<Map<String, String>> messages = new ArrayList<>();
|
List<Map<String, String>> messages = new ArrayList<>();
|
||||||
messages.add(Map.of(
|
messages.add(Map.of(
|
||||||
"role", "system",
|
"role", "system",
|
||||||
"content", "You are a helpful pet shop assistant. Provide concise and friendly answers. Do not output markdown, just plain text."
|
"content", buildSystemPrompt(customer, customerPets)
|
||||||
));
|
));
|
||||||
|
|
||||||
for (Message message : history) {
|
for (Message message : history) {
|
||||||
@@ -177,6 +187,43 @@ public class OpenRouterAiService {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
private String buildSystemPrompt(User customer, List<Pet> pets) {
|
||||||
|
StringBuilder sb = new StringBuilder();
|
||||||
|
sb.append("You are Leon's Pet Assistant, a helpful AI for Leon's Pet Store. ");
|
||||||
|
sb.append("Be concise, friendly, and focused on pet care, adoption, products, and appointments. ");
|
||||||
|
sb.append("Do not output markdown, just plain text.\n\n");
|
||||||
|
|
||||||
|
if (customer != null) {
|
||||||
|
sb.append("Customer profile:\n");
|
||||||
|
sb.append("- Name: ").append(customer.getFirstName()).append(" ").append(customer.getLastName()).append("\n");
|
||||||
|
if (customer.getLoyaltyPoints() != null) {
|
||||||
|
sb.append("- Loyalty points: ").append(customer.getLoyaltyPoints()).append("\n");
|
||||||
|
}
|
||||||
|
if (customer.getPrimaryStore() != null && customer.getPrimaryStore().getStoreName() != null) {
|
||||||
|
sb.append("- Preferred store: ").append(customer.getPrimaryStore().getStoreName()).append("\n");
|
||||||
|
}
|
||||||
|
sb.append("\n");
|
||||||
|
}
|
||||||
|
|
||||||
|
if (pets != null && !pets.isEmpty()) {
|
||||||
|
sb.append("Their registered pets:\n");
|
||||||
|
for (Pet pet : pets) {
|
||||||
|
sb.append("- ").append(pet.getPetName()).append(" (").append(pet.getPetSpecies());
|
||||||
|
if (pet.getPetBreed() != null && !pet.getPetBreed().isBlank()) {
|
||||||
|
sb.append(", ").append(pet.getPetBreed());
|
||||||
|
}
|
||||||
|
if (pet.getPetAge() != null) {
|
||||||
|
sb.append(", ").append(pet.getPetAge()).append(" yr");
|
||||||
|
}
|
||||||
|
sb.append(")\n");
|
||||||
|
}
|
||||||
|
} else {
|
||||||
|
sb.append("They have no pets registered yet.\n");
|
||||||
|
}
|
||||||
|
|
||||||
|
return sb.toString();
|
||||||
|
}
|
||||||
|
|
||||||
private String resolveRole(Message message, Long botUserId) {
|
private String resolveRole(Message message, Long botUserId) {
|
||||||
if (message.getSenderId() != null && message.getSenderId().equals(botUserId)) {
|
if (message.getSenderId() != null && message.getSenderId().equals(botUserId)) {
|
||||||
return "assistant";
|
return "assistant";
|
||||||
|
|||||||
@@ -246,7 +246,7 @@ function AiChatPage() {
|
|||||||
"Content-Type": "application/json",
|
"Content-Type": "application/json",
|
||||||
Authorization: `Bearer ${token}`,
|
Authorization: `Bearer ${token}`,
|
||||||
},
|
},
|
||||||
body: JSON.stringify({ message: "Hello! I'd like to chat with the AI assistant." }),
|
body: JSON.stringify({}),
|
||||||
});
|
});
|
||||||
if (res.ok) {
|
if (res.ok) {
|
||||||
const conv = await res.json();
|
const conv = await res.json();
|
||||||
@@ -406,7 +406,7 @@ function AiChatPage() {
|
|||||||
"Content-Type": "application/json",
|
"Content-Type": "application/json",
|
||||||
Authorization: `Bearer ${token}`,
|
Authorization: `Bearer ${token}`,
|
||||||
},
|
},
|
||||||
body: JSON.stringify({ message: "Hello! I'd like to chat with the AI assistant." }),
|
body: JSON.stringify({}),
|
||||||
});
|
});
|
||||||
if (!res.ok) {
|
if (!res.ok) {
|
||||||
const data = await res.json().catch(() => null);
|
const data = await res.json().catch(() => null);
|
||||||
@@ -583,7 +583,7 @@ function AiChatPage() {
|
|||||||
Chat with a Real Person
|
Chat with a Real Person
|
||||||
</button>
|
</button>
|
||||||
)}
|
)}
|
||||||
{isEscalated && !isClosed && (
|
{!isClosed && (
|
||||||
<button style={s.closeConvBtn} onClick={handleCloseConversation} title="Close this conversation">
|
<button style={s.closeConvBtn} onClick={handleCloseConversation} title="Close this conversation">
|
||||||
Close Chat
|
Close Chat
|
||||||
</button>
|
</button>
|
||||||
|
|||||||
Reference in New Issue
Block a user