-
Notifications
You must be signed in to change notification settings - Fork 0
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
[Feat] 챗봇 기능 구현 #38
Merged
Merged
[Feat] 챗봇 기능 구현 #38
Changes from 12 commits
Commits
Show all changes
14 commits
Select commit
Hold shift + click to select a range
52dd8da
Feat : 의존성 추가 (#24)
chaen-ing bf85185
Feat : 의존성 추가 및 키 설정 (#24)
chaen-ing a37c434
Feat : 도메인 필드 수정 (#24)
chaen-ing 5cf6aa5
Feat : DTO 생성 (#24)
chaen-ing fb004df
Feat : 컨트롤러 추가 (#24)
chaen-ing 3500b8b
Feat : 그래들 설정 추가 (#24)
chaen-ing cc09ab6
Feat : 챗봇 대화 기능 구현 및 저장 완료 (#24)
chaen-ing f6a5cc5
Feat : yml 파일 변경 (#24)
chaen-ing 464d0c7
Feat : 서비스로직 변경 (#24)
chaen-ing e07ce12
Feat : 조회 로직 추가 (#24)
chaen-ing e112bd7
Feat : 조회 로직에 페이징과 시간 추가 (#24)
chaen-ing b58e8a4
Feat : 초기화 기능 추가 (#24)
chaen-ing 56b0e8c
Debug : 변수명 등 수정 (#24)
chaen-ing 8b38f2b
Merge branch 'develop' into feat/chat-bot-#24
chaen-ing File filter
Filter by extension
Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
There are no files selected for viewing
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
68 changes: 68 additions & 0 deletions
68
src/main/java/com/ripple/BE/chatbot/controller/ChatbotController.java
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,68 @@ | ||
package com.ripple.BE.chatbot.controller; | ||
|
||
import com.ripple.BE.chatbot.dto.ChatDTO; | ||
import com.ripple.BE.chatbot.dto.ChatListDTO; | ||
import com.ripple.BE.chatbot.dto.request.ChatRequest; | ||
import com.ripple.BE.chatbot.dto.response.ChatListResponse; | ||
import com.ripple.BE.chatbot.dto.response.ChatResponse; | ||
import com.ripple.BE.chatbot.service.ChatbotService; | ||
import com.ripple.BE.global.dto.response.ApiResponse; | ||
import com.ripple.BE.user.domain.CustomUserDetails; | ||
import io.swagger.v3.oas.annotations.Operation; | ||
import io.swagger.v3.oas.annotations.tags.Tag; | ||
import jakarta.validation.Valid; | ||
import jakarta.validation.constraints.PositiveOrZero; | ||
import lombok.RequiredArgsConstructor; | ||
import org.springframework.http.HttpStatus; | ||
import org.springframework.http.ResponseEntity; | ||
import org.springframework.security.core.annotation.AuthenticationPrincipal; | ||
import org.springframework.web.bind.annotation.GetMapping; | ||
import org.springframework.web.bind.annotation.PostMapping; | ||
import org.springframework.web.bind.annotation.RequestMapping; | ||
import org.springframework.web.bind.annotation.RequestParam; | ||
import org.springframework.web.bind.annotation.RestController; | ||
|
||
@RequiredArgsConstructor | ||
@RestController | ||
@RequestMapping("/api/v1/chatbot") | ||
@Tag(name = "Chatbot", description = "챗봇 API") | ||
public class ChatbotController { | ||
|
||
private final ChatbotService chatbotService; | ||
|
||
@Operation(summary = "챗봇에게 메세지 보내기", description = "챗봇에게 메세지를 보내고 응답을 받습니다. 대화 내용을 저장합니다.") | ||
@PostMapping | ||
public ResponseEntity<ApiResponse<Object>> sendMessage( | ||
final @AuthenticationPrincipal CustomUserDetails currentUser, | ||
final @Valid ChatRequest request) { | ||
|
||
ChatResponse chatResponse = | ||
chatbotService.sendMessage(ChatDTO.tochatDTO(request), currentUser.getId()); | ||
|
||
return ResponseEntity.status(HttpStatus.OK).body(ApiResponse.from(chatResponse)); | ||
} | ||
|
||
@Operation( | ||
summary = "대화 내역 조회", | ||
description = "챗봇과의 대화 내역을 조회합니다. 페이지네이션을 지원합니다. 페이지당 10개의 대화 내역을 반환합니다.") | ||
@GetMapping("/list") | ||
public ResponseEntity<ApiResponse<Object>> getMessages( | ||
final @AuthenticationPrincipal CustomUserDetails currentUser, | ||
final @RequestParam(defaultValue = "0") @PositiveOrZero int page) { | ||
|
||
ChatListDTO chatList = chatbotService.getChatList(currentUser.getId(), page); | ||
|
||
return ResponseEntity.status(HttpStatus.OK) | ||
.body(ApiResponse.from(ChatListResponse.toChatListResponse(chatList))); | ||
} | ||
|
||
@Operation(summary = "대화 내역 초기화", description = "챗봇과의 대화 내역을 초기화합니다.") | ||
@PostMapping("/clear") | ||
public ResponseEntity<ApiResponse<Object>> clearMessages( | ||
final @AuthenticationPrincipal CustomUserDetails currentUser) { | ||
|
||
chatbotService.clearChat(currentUser.getId()); | ||
|
||
return ResponseEntity.status(HttpStatus.OK).body(ApiResponse.from(ApiResponse.EMPTY_RESPONSE)); | ||
} | ||
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
43 changes: 0 additions & 43 deletions
43
src/main/java/com/ripple/BE/chatbot/domain/ChatSession.java
This file was deleted.
Oops, something went wrong.
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,17 @@ | ||
package com.ripple.BE.chatbot.dto; | ||
|
||
import com.ripple.BE.chatbot.domain.ChatMessage; | ||
import com.ripple.BE.chatbot.domain.type.Sender; | ||
import com.ripple.BE.chatbot.dto.request.ChatRequest; | ||
|
||
public record ChatDTO(String message, Sender sender, String createdAt) { | ||
|
||
public static ChatDTO toChatDTO(final ChatMessage chatMessage) { | ||
return new ChatDTO( | ||
chatMessage.getMessage(), chatMessage.getSender(), chatMessage.getCreatedDate().toString()); | ||
} | ||
|
||
public static ChatDTO tochatDTO(final ChatRequest request) { | ||
return new ChatDTO(request.message(), Sender.USER, null); | ||
} | ||
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,16 @@ | ||
package com.ripple.BE.chatbot.dto; | ||
|
||
import com.ripple.BE.chatbot.domain.ChatMessage; | ||
import java.util.List; | ||
import lombok.Builder; | ||
import org.springframework.data.domain.Page; | ||
|
||
@Builder | ||
public record ChatListDTO(List<ChatDTO> chatDTOList, int totalPage, int currentPage) { | ||
public static ChatListDTO toChatListDTO(Page<ChatMessage> chatMessagePage) { | ||
return new ChatListDTO( | ||
chatMessagePage.getContent().stream().map(ChatDTO::toChatDTO).toList(), | ||
chatMessagePage.getTotalPages(), | ||
chatMessagePage.getNumber()); | ||
} | ||
} |
5 changes: 5 additions & 0 deletions
5
src/main/java/com/ripple/BE/chatbot/dto/request/ChatRequest.java
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,5 @@ | ||
package com.ripple.BE.chatbot.dto.request; | ||
|
||
import jakarta.validation.constraints.NotBlank; | ||
|
||
public record ChatRequest(@NotBlank String message) {} |
14 changes: 14 additions & 0 deletions
14
src/main/java/com/ripple/BE/chatbot/dto/response/ChatListResponse.java
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,14 @@ | ||
package com.ripple.BE.chatbot.dto.response; | ||
|
||
import com.ripple.BE.chatbot.dto.ChatListDTO; | ||
import java.util.List; | ||
|
||
public record ChatListResponse(List<ChatResponse> postList, int totalPage, int currentPage) { | ||
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. 여기 변수명 변경이 필요할거 같아요 There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. 앗 그러네요 수정해서 올렸습니다ㅎㅎ |
||
|
||
public static ChatListResponse toChatListResponse(ChatListDTO chatListDTO) { | ||
return new ChatListResponse( | ||
chatListDTO.chatDTOList().stream().map(ChatResponse::toChatResponse).toList(), | ||
chatListDTO.totalPage(), | ||
chatListDTO.currentPage()); | ||
} | ||
} |
19 changes: 19 additions & 0 deletions
19
src/main/java/com/ripple/BE/chatbot/dto/response/ChatResponse.java
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,19 @@ | ||
package com.ripple.BE.chatbot.dto.response; | ||
|
||
import com.ripple.BE.chatbot.domain.ChatMessage; | ||
import com.ripple.BE.chatbot.dto.ChatDTO; | ||
|
||
public record ChatResponse(String message, String sender, String createdAt) { | ||
|
||
public static ChatResponse toChatResponse(ChatDTO chatDTO) { | ||
return new ChatResponse( | ||
chatDTO.message(), chatDTO.sender().toString(), chatDTO.createdAt().toString()); | ||
} | ||
|
||
public static ChatResponse toChatResponse(ChatMessage chatMessage) { | ||
return new ChatResponse( | ||
chatMessage.getMessage(), | ||
chatMessage.getSender().toString(), | ||
chatMessage.getCreatedDate().toString()); | ||
} | ||
} |
12 changes: 12 additions & 0 deletions
12
src/main/java/com/ripple/BE/chatbot/repository/ChatbotRepository.java
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,12 @@ | ||
package com.ripple.BE.chatbot.repository; | ||
|
||
import com.ripple.BE.chatbot.domain.ChatMessage; | ||
import org.springframework.data.domain.Page; | ||
import org.springframework.data.domain.Pageable; | ||
import org.springframework.data.jpa.repository.JpaRepository; | ||
|
||
public interface ChatbotRepository extends JpaRepository<ChatMessage, Long> { | ||
Page<ChatMessage> findAllByUserIdOrderByCreatedDate(Long userId, Pageable pageable); | ||
|
||
void deleteAllByUserId(Long userId); | ||
} |
93 changes: 93 additions & 0 deletions
93
src/main/java/com/ripple/BE/chatbot/service/ChatbotService.java
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,93 @@ | ||
package com.ripple.BE.chatbot.service; | ||
|
||
import static com.ripple.BE.user.exception.errorcode.UserErrorCode.*; | ||
|
||
import com.ripple.BE.chatbot.domain.ChatMessage; | ||
import com.ripple.BE.chatbot.domain.type.Sender; | ||
import com.ripple.BE.chatbot.dto.ChatDTO; | ||
import com.ripple.BE.chatbot.dto.ChatListDTO; | ||
import com.ripple.BE.chatbot.dto.response.ChatListResponse; | ||
import com.ripple.BE.chatbot.dto.response.ChatResponse; | ||
import com.ripple.BE.chatbot.repository.ChatbotRepository; | ||
import com.ripple.BE.user.domain.User; | ||
import com.ripple.BE.user.exception.UserException; | ||
import com.ripple.BE.user.repository.UserRepository; | ||
|
||
import lombok.RequiredArgsConstructor; | ||
import lombok.extern.slf4j.Slf4j; | ||
|
||
import org.springframework.ai.openai.OpenAiChatClient; | ||
import org.springframework.data.domain.Page; | ||
import org.springframework.data.domain.PageRequest; | ||
import org.springframework.data.domain.Pageable; | ||
import org.springframework.stereotype.Service; | ||
import org.springframework.transaction.annotation.Transactional; | ||
|
||
@Service | ||
@RequiredArgsConstructor | ||
@Slf4j | ||
@Transactional(readOnly = true) | ||
public class ChatbotService { | ||
private final OpenAiChatClient openAiChatClient; | ||
|
||
private final UserRepository userRepository; | ||
private final ChatbotRepository chatbotRepository; | ||
|
||
private static final int PAGE_SIZE = 10; | ||
|
||
@Transactional | ||
public ChatResponse sendMessage(final ChatDTO chatDTO, final Long userId) { | ||
User user = userRepository.findById(userId) | ||
.orElseThrow(() -> new UserException(USER_NOT_FOUND)); | ||
|
||
// 프롬프트 포함하여 OpenAI API 호출 | ||
String prompt = """ | ||
당신은 경제학습 서비스를 위한 AI 챗봇입니다. | ||
오직 경제와 관련된 질문에만 답변해야 하며, 경제와 무관한 질문에는 답변하지 않습니다. | ||
모든 답변은 반드시 한국어로 제공해야 합니다. | ||
경제 이외의 주제에 대한 질문에는 다음과 같이 답변하세요: | ||
"죄송합니다. 저는 경제 관련 질문에만 답변할 수 있습니다." | ||
"""; | ||
|
||
// OpenAI API 호출 | ||
String response = openAiChatClient.call(prompt + "\n사용자 질문: " + chatDTO.message()); | ||
|
||
// 유저의 메세지 저장 | ||
chatbotRepository.save( | ||
ChatMessage.builder() | ||
.user(user) | ||
.message(chatDTO.message()) | ||
.sender(Sender.USER) | ||
.build()); | ||
|
||
// 챗봇의 응답 저장 | ||
ChatMessage saved = chatbotRepository.save( | ||
ChatMessage.builder() | ||
.user(user) | ||
.message(response) | ||
.sender(Sender.CHATBOT) | ||
.build()); | ||
|
||
return ChatResponse.toChatResponse(saved); | ||
} | ||
|
||
public ChatListDTO getChatList(final Long userId, final int page) { | ||
Pageable pageable = PageRequest.of(page, PAGE_SIZE); | ||
|
||
User user = userRepository.findById(userId) | ||
.orElseThrow(() -> new UserException(USER_NOT_FOUND)); | ||
|
||
Page<ChatMessage> chatMessagePage = chatbotRepository.findAllByUserIdOrderByCreatedDate( | ||
user.getId(), pageable); | ||
|
||
return ChatListDTO.toChatListDTO(chatMessagePage); | ||
} | ||
|
||
@Transactional | ||
public void clearChat(final Long userId) { | ||
User user = userRepository.findById(userId) | ||
.orElseThrow(() -> new UserException(USER_NOT_FOUND)); | ||
|
||
chatbotRepository.deleteAllByUserId(user.getId()); | ||
} | ||
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Add this suggestion to a batch that can be applied as a single commit.
This suggestion is invalid because no changes were made to the code.
Suggestions cannot be applied while the pull request is closed.
Suggestions cannot be applied while viewing a subset of changes.
Only one suggestion per line can be applied in a batch.
Add this suggestion to a batch that can be applied as a single commit.
Applying suggestions on deleted lines is not supported.
You must change the existing code in this line in order to create a valid suggestion.
Outdated suggestions cannot be applied.
This suggestion has been applied or marked resolved.
Suggestions cannot be applied from pending reviews.
Suggestions cannot be applied on multi-line comments.
Suggestions cannot be applied while the pull request is queued to merge.
Suggestion cannot be applied right now. Please check back later.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
@DeleteMapping으로 변경해도 좋을거 같네요