-
Notifications
You must be signed in to change notification settings - Fork 1
AI 프롬프트 DB로 관리 #34
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
base: dev
Are you sure you want to change the base?
AI 프롬프트 DB로 관리 #34
Changes from 26 commits
8ffbbb4
1cc9f2c
fd264a4
e19c802
f347036
e950acd
d1e4f26
2be5b51
e063f64
2206c4a
63465b0
90e0bef
f45f44a
35d39c2
790de6a
4bddd94
fa5e5f6
3b99bc2
cf247a6
147afa4
edfbd61
7364f0d
558d468
f758c24
d018219
939094b
da3c804
053fed4
File filter
Filter by extension
Conversations
Jump to
Diff view
Diff view
There are no files selected for viewing
| Original file line number | Diff line number | Diff line change |
|---|---|---|
| @@ -0,0 +1,9 @@ | ||
| { | ||
| "permissions": { | ||
| "allow": [ | ||
| "Bash(./gradlew test:*)", | ||
| "Bash(./gradlew:*)" | ||
| ], | ||
| "deny": [] | ||
| } | ||
| } |
| Original file line number | Diff line number | Diff line change |
|---|---|---|
| @@ -0,0 +1,25 @@ | ||
| package kr.swyp.backend.chatbot.client; | ||
|
|
||
| import kr.swyp.backend.chatbot.client.dto.ChatDto.ChatRequest; | ||
| import kr.swyp.backend.chatbot.client.dto.ChatDto.ChatResponse; | ||
| import org.springframework.cloud.openfeign.FeignClient; | ||
| import org.springframework.http.MediaType; | ||
| import org.springframework.web.bind.annotation.PostMapping; | ||
| import org.springframework.web.bind.annotation.RequestBody; | ||
| import org.springframework.web.bind.annotation.RequestHeader; | ||
|
|
||
| @FeignClient( | ||
| name = "openai-client", | ||
| url = "https://api.openai.com" | ||
| ) | ||
| public interface ChatClient { | ||
|
|
||
| @PostMapping(value = "/v1/chat/completions", | ||
| consumes = MediaType.APPLICATION_JSON_VALUE, // Content-Type 고정 | ||
| produces = MediaType.APPLICATION_JSON_VALUE) | ||
| ChatResponse createChatCompletion( | ||
| @RequestHeader("Authorization") String authorization, | ||
| @RequestBody ChatRequest request | ||
| ); | ||
|
|
||
| } | ||
| Original file line number | Diff line number | Diff line change |
|---|---|---|
| @@ -0,0 +1,65 @@ | ||
| package kr.swyp.backend.chatbot.client.dto; | ||
|
|
||
| import com.fasterxml.jackson.annotation.JsonIgnoreProperties; | ||
| import java.util.List; | ||
| import lombok.AllArgsConstructor; | ||
| import lombok.Builder; | ||
| import lombok.Getter; | ||
| import lombok.NoArgsConstructor; | ||
|
|
||
| public class ChatDto { | ||
|
|
||
| @Getter | ||
| @Builder | ||
| @NoArgsConstructor | ||
| @AllArgsConstructor | ||
| public static class ChatRequest { | ||
|
|
||
| private String model; | ||
| private List<Message> messages; | ||
| private Double temperature; | ||
|
|
||
| @Getter | ||
| @Builder | ||
| @NoArgsConstructor | ||
| @AllArgsConstructor | ||
| public static class Message { | ||
|
|
||
| private String role; | ||
| private String content; | ||
| } | ||
| } | ||
|
|
||
| @Getter | ||
| @NoArgsConstructor | ||
| @AllArgsConstructor | ||
| @JsonIgnoreProperties(ignoreUnknown = true) | ||
| @Builder | ||
| public static class ChatResponse { | ||
|
|
||
| private String id; | ||
| private List<Choice> choices; | ||
|
|
||
| @Getter | ||
| @NoArgsConstructor | ||
| @AllArgsConstructor | ||
| @Builder | ||
| @JsonIgnoreProperties(ignoreUnknown = true) | ||
| public static class Choice { | ||
|
|
||
| private Message message; | ||
|
|
||
| @Getter | ||
| @NoArgsConstructor | ||
| @AllArgsConstructor | ||
| @Builder | ||
| @JsonIgnoreProperties(ignoreUnknown = true) | ||
| public static class Message { | ||
|
|
||
| private String role; | ||
| private String content; | ||
| } | ||
| } | ||
| } | ||
|
|
||
| } |
| Original file line number | Diff line number | Diff line change |
|---|---|---|
| @@ -0,0 +1,72 @@ | ||
| package kr.swyp.backend.chatbot.controller; | ||
|
|
||
| import jakarta.validation.constraints.NotBlank; | ||
| import java.util.List; | ||
| import kr.swyp.backend.chatbot.dto.ChatDto.ChatHistoryDto; | ||
| import kr.swyp.backend.chatbot.dto.ChatDto.ChatRequestDto; | ||
| import kr.swyp.backend.chatbot.dto.ChatDto.ChatResponseDto; | ||
| import kr.swyp.backend.chatbot.dto.ChatDto.ChatSessionDto; | ||
| import kr.swyp.backend.chatbot.dto.ChatDto.ConversationRequestDto; | ||
| import kr.swyp.backend.chatbot.dto.ChatDto.ConversationResponseDto; | ||
| import kr.swyp.backend.chatbot.service.ChatService; | ||
| import kr.swyp.backend.member.dto.MemberDetails; | ||
| import lombok.RequiredArgsConstructor; | ||
| import org.springframework.security.core.annotation.AuthenticationPrincipal; | ||
| import org.springframework.web.bind.annotation.GetMapping; | ||
| import org.springframework.web.bind.annotation.PathVariable; | ||
| import org.springframework.web.bind.annotation.PostMapping; | ||
| import org.springframework.web.bind.annotation.RequestBody; | ||
| import org.springframework.web.bind.annotation.RequestMapping; | ||
| import org.springframework.web.bind.annotation.RequestParam; | ||
| import org.springframework.web.bind.annotation.RestController; | ||
|
|
||
| @RestController | ||
| @RequiredArgsConstructor | ||
| @RequestMapping("/chat") | ||
| public class ChatController { | ||
|
|
||
| private final ChatService chatService; | ||
|
|
||
| @PostMapping("/ask") | ||
| public ChatResponseDto ask(@RequestBody ChatRequestDto question, | ||
| @AuthenticationPrincipal MemberDetails memberDetails) { | ||
| return chatService.ask(memberDetails.getMemberId(), question); | ||
| } | ||
|
|
||
| @GetMapping("/history") | ||
| public List<ChatHistoryDto> getChatHistory( | ||
| @AuthenticationPrincipal MemberDetails memberDetails) { | ||
| return chatService.getChatHistory(memberDetails.getMemberId()); | ||
| } | ||
|
|
||
| // 새로운 채팅 세션 시작 | ||
| @PostMapping("/sessions/start") | ||
| public ChatSessionDto startNewSession( | ||
| @RequestParam @NotBlank String initialMessage, | ||
| @AuthenticationPrincipal MemberDetails memberDetails) { | ||
| return chatService.startNewSession(memberDetails.getMemberId(), initialMessage); | ||
| } | ||
|
|
||
| // 기존 세션에서 대화 계속 | ||
| @PostMapping("/sessions/continue") | ||
| public ConversationResponseDto continueConversation( | ||
| @RequestBody ConversationRequestDto request, | ||
| @AuthenticationPrincipal MemberDetails memberDetails) { | ||
| return chatService.continueConversation(memberDetails.getMemberId(), request); | ||
| } | ||
|
|
||
| // 사용자의 채팅 세션 목록 조회 | ||
| @GetMapping("/sessions") | ||
| public List<ChatSessionDto> getUserSessions( | ||
| @AuthenticationPrincipal MemberDetails memberDetails) { | ||
| return chatService.getUserSessions(memberDetails.getMemberId()); | ||
| } | ||
|
|
||
| // 특정 세션의 대화 기록 조회 | ||
| @GetMapping("/sessions/{sessionId}/history") | ||
| public List<ConversationResponseDto> getSessionHistory( | ||
| @PathVariable String sessionId, | ||
| @AuthenticationPrincipal MemberDetails memberDetails) { | ||
| return chatService.getSessionHistory(memberDetails.getMemberId(), sessionId); | ||
| } | ||
| } |
| Original file line number | Diff line number | Diff line change |
|---|---|---|
| @@ -0,0 +1,58 @@ | ||
| package kr.swyp.backend.chatbot.domain; | ||
|
|
||
| import jakarta.persistence.Column; | ||
| import jakarta.persistence.Entity; | ||
| import jakarta.persistence.GeneratedValue; | ||
| import jakarta.persistence.GenerationType; | ||
| import jakarta.persistence.Id; | ||
| import jakarta.persistence.Table; | ||
| import java.util.UUID; | ||
| import kr.swyp.backend.common.domain.BaseEntity; | ||
| import lombok.AccessLevel; | ||
| import lombok.AllArgsConstructor; | ||
| import lombok.Builder; | ||
| import lombok.Getter; | ||
| import lombok.NoArgsConstructor; | ||
| import org.hibernate.annotations.Comment; | ||
|
|
||
| @Entity | ||
| @Getter | ||
| @Builder | ||
| @AllArgsConstructor(access = AccessLevel.PROTECTED) | ||
| @NoArgsConstructor(access = AccessLevel.PROTECTED) | ||
| @Table(name = "CHAT_HISTORY") | ||
| public class ChatHistory extends BaseEntity { | ||
|
|
||
| @Id | ||
| @GeneratedValue(strategy = GenerationType.IDENTITY) | ||
| @Column(name = "ID") | ||
| private Long id; | ||
|
|
||
| @Column(name = "MEMBER_ID") | ||
| @Comment("유저 아이디") | ||
| private UUID memberId; | ||
|
|
||
| @Column(name = "TARGET") | ||
| @Comment("대상") | ||
| private String target; | ||
|
|
||
| @Column(name = "TOPIC") | ||
| @Comment("주제") | ||
| private String topic; | ||
|
|
||
| @Column(name = "QUESTION", columnDefinition = "TEXT") | ||
| @Comment("질문") | ||
| private String question; | ||
|
|
||
| @Column(name = "RESPONSE", columnDefinition = "TEXT") | ||
| @Comment("AI 응답") | ||
| private String response; | ||
|
|
||
| @Column(name = "SESSION_ID") | ||
| @Comment("채팅 세션 ID") | ||
| private String sessionId; | ||
|
|
||
| @Column(name = "MESSAGE_TYPE") | ||
| @Comment("메시지 타입 (USER/BOT)") | ||
| private String messageType; | ||
|
Comment on lines
+55
to
+57
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.
@Enumerated(EnumType.STRING)
@Column(name = "MESSAGE_TYPE")
@Comment("메시지 타입 (USER/BOT)")
private MessageType messageType;이렇게 변경하면 |
||
| } | ||
| Original file line number | Diff line number | Diff line change |
|---|---|---|
| @@ -0,0 +1,41 @@ | ||
| package kr.swyp.backend.chatbot.domain; | ||
|
|
||
| import jakarta.persistence.Column; | ||
| import jakarta.persistence.Entity; | ||
| import jakarta.persistence.GeneratedValue; | ||
| import jakarta.persistence.GenerationType; | ||
| import jakarta.persistence.Id; | ||
| import jakarta.persistence.Table; | ||
| import kr.swyp.backend.common.domain.BaseEntity; | ||
| import lombok.AccessLevel; | ||
| import lombok.AllArgsConstructor; | ||
| import lombok.Builder; | ||
| import lombok.Getter; | ||
| import lombok.NoArgsConstructor; | ||
| import org.hibernate.annotations.Comment; | ||
|
|
||
| @Entity | ||
| @Table(name = "CHAT_PROMPT") | ||
| @Getter | ||
| @Builder | ||
| @AllArgsConstructor(access = AccessLevel.PROTECTED) | ||
| @NoArgsConstructor(access = AccessLevel.PROTECTED) | ||
| public class ChatPrompt extends BaseEntity { | ||
|
|
||
| @Id | ||
| @GeneratedValue(strategy = GenerationType.IDENTITY) | ||
| private Long id; | ||
|
|
||
| @Column(name = "prompt_key", nullable = false, unique = true) | ||
| @Comment("프롬프트 식별자") | ||
| private String promptKey; | ||
|
|
||
| @Column(name = "prompt_content", nullable = false, columnDefinition = "TEXT") | ||
| @Comment("프롬프트 텍스트") | ||
| private String promptContent; | ||
|
|
||
| @Column(name = "is_active", nullable = false) | ||
| @Comment("활성 상태") | ||
| private Boolean isActive = true; | ||
|
|
||
| } |
| Original file line number | Diff line number | Diff line change |
|---|---|---|
| @@ -0,0 +1,47 @@ | ||
| package kr.swyp.backend.chatbot.domain; | ||
|
|
||
| import jakarta.persistence.Column; | ||
| import jakarta.persistence.Entity; | ||
| import jakarta.persistence.GeneratedValue; | ||
| import jakarta.persistence.GenerationType; | ||
| import jakarta.persistence.Id; | ||
| import jakarta.persistence.Table; | ||
| import java.util.UUID; | ||
| import kr.swyp.backend.common.domain.BaseEntity; | ||
| import lombok.AccessLevel; | ||
| import lombok.AllArgsConstructor; | ||
| import lombok.Builder; | ||
| import lombok.Getter; | ||
| import lombok.NoArgsConstructor; | ||
| import org.hibernate.annotations.Comment; | ||
|
|
||
| @Entity | ||
| @Getter | ||
| @Builder | ||
| @AllArgsConstructor(access = AccessLevel.PROTECTED) | ||
| @NoArgsConstructor(access = AccessLevel.PROTECTED) | ||
| @Table(name = "CHAT_SESSION") | ||
| public class ChatSession extends BaseEntity { | ||
|
|
||
| @Id | ||
| @GeneratedValue(strategy = GenerationType.IDENTITY) | ||
| @Column(name = "ID") | ||
| private Long id; | ||
|
|
||
| @Column(name = "SESSION_ID", unique = true) | ||
| @Comment("세션 고유 식별자") | ||
| private String sessionId; | ||
|
|
||
| @Column(name = "MEMBER_ID") | ||
| @Comment("사용자 아이디") | ||
| private UUID memberId; | ||
|
|
||
| @Column(name = "TITLE") | ||
| @Comment("채팅 세션 제목") | ||
| private String title; | ||
|
|
||
| @Column(name = "IS_ACTIVE") | ||
| @Comment("활성 상태") | ||
| @Builder.Default | ||
| private Boolean isActive = true; | ||
| } |
Uh oh!
There was an error while loading. Please reload this page.