diff --git a/src/main/java/tenten/blooming/domain/goal/config/OpenAIRestTemplateConfig.java b/src/main/java/tenten/blooming/domain/goal/config/OpenAIRestTemplateConfig.java new file mode 100644 index 0000000..c7d3117 --- /dev/null +++ b/src/main/java/tenten/blooming/domain/goal/config/OpenAIRestTemplateConfig.java @@ -0,0 +1,25 @@ +package tenten.blooming.domain.goal.config; + +import org.springframework.beans.factory.annotation.Qualifier; +import org.springframework.beans.factory.annotation.Value; +import org.springframework.context.annotation.Bean; +import org.springframework.context.annotation.Configuration; +import org.springframework.web.client.RestTemplate; + +@Configuration +public class OpenAIRestTemplateConfig { + + @Value("${openai.api.key}") + private String openaiApiKey; + + @Bean + @Qualifier("openaiRestTemplate") + public RestTemplate openaiRestTemplate() { + RestTemplate restTemplate = new RestTemplate(); + restTemplate.getInterceptors().add((request, body, execution) -> { + request.getHeaders().add("Authorization", "Bearer " + openaiApiKey); + return execution.execute(request, body); + }); + return restTemplate; + } +} \ No newline at end of file diff --git a/src/main/java/tenten/blooming/domain/goal/controller/GoalController.java b/src/main/java/tenten/blooming/domain/goal/controller/GoalController.java new file mode 100644 index 0000000..4e08529 --- /dev/null +++ b/src/main/java/tenten/blooming/domain/goal/controller/GoalController.java @@ -0,0 +1,63 @@ +package tenten.blooming.domain.goal.controller; +import jakarta.persistence.Basic; +import org.springframework.beans.factory.annotation.Autowired; +import org.springframework.beans.factory.annotation.Qualifier; +import org.springframework.http.HttpStatus; +import org.springframework.http.ResponseEntity; +import org.springframework.web.bind.annotation.*; +import org.springframework.beans.factory.annotation.Value; +import org.springframework.web.client.RestTemplate; +import tenten.blooming.domain.goal.dto.ChatRequest; +import tenten.blooming.domain.goal.dto.ChatResponse; +import tenten.blooming.domain.goal.dto.GoalDto; +import tenten.blooming.domain.goal.entity.Goal; +import tenten.blooming.domain.goal.service.GoalService; +import tenten.blooming.global.common.BasicResponse; + +@RestController +public class GoalController { + + @Qualifier("openaiRestTemplate") + @Autowired + private RestTemplate restTemplate; + + @Autowired + private GoalService goalService; + + @Value("${openai.model}") + private String model; + + @Value("${openai.api.url}") + private String apiUrl; + + @PostMapping("/goal") + public ResponseEntity createGoal(@RequestBody GoalDto dto) { + Goal created = goalService.create(dto); + BasicResponse basicResponse = new BasicResponse(); + + if (created != null) { + basicResponse = BasicResponse.builder() + .code(HttpStatus.OK.value()) + .message("목표 등록에 성공했습니다.") + .result(created) + .build(); + + } + + return new ResponseEntity<>(basicResponse, HttpStatus.OK); + + } + + @GetMapping("/goal") + public String getSubGoal(@RequestParam String goalName) { + ChatRequest request = new ChatRequest(model, goalName); + + ChatResponse response = restTemplate.postForObject(apiUrl, request, ChatResponse.class); + + if (response == null || response.getChoices() == null || response.getChoices().isEmpty()) { + return "No response"; + } + + return response.getChoices().get(0).getMessage().getContent(); + } +} \ No newline at end of file diff --git a/src/main/java/tenten/blooming/domain/goal/dto/ChatRequest.java b/src/main/java/tenten/blooming/domain/goal/dto/ChatRequest.java new file mode 100644 index 0000000..99470ef --- /dev/null +++ b/src/main/java/tenten/blooming/domain/goal/dto/ChatRequest.java @@ -0,0 +1,25 @@ +package tenten.blooming.domain.goal.dto; + +import lombok.*; + +import java.util.ArrayList; +import java.util.List; + +@Data +@Getter @Setter +@NoArgsConstructor +@AllArgsConstructor +public class ChatRequest { + private String model; + private List messages; + private final int n = 1; + private double temperature; + + public ChatRequest(String model, String goalName) { + this.model = model; + this.messages = new ArrayList<>(); + this.messages.add(new Message("system", "입력 받은 큰 목표 G를 달성하기 위한 구체적인 6가지 세부 목표 g1, g2, g3, g4, g5, g6 을 알려 주는 assistant bot. 6가지 세부 목표는 10일동안 매일매일 꾸준히 실천하여 10일 뒤에 G를 달성할 수 있는 목표여야 함.")); + this.messages.add(new Message("user", "G: " + goalName)); + } + +} diff --git a/src/main/java/tenten/blooming/domain/goal/dto/ChatResponse.java b/src/main/java/tenten/blooming/domain/goal/dto/ChatResponse.java new file mode 100644 index 0000000..4f1a90b --- /dev/null +++ b/src/main/java/tenten/blooming/domain/goal/dto/ChatResponse.java @@ -0,0 +1,23 @@ +package tenten.blooming.domain.goal.dto; + + +import lombok.Data; +import lombok.Getter; +import lombok.NoArgsConstructor; +import lombok.Setter; + +import java.util.List; + +@Data +@NoArgsConstructor +@Getter @Setter +public class ChatResponse { + private List choices; + + @Data + @NoArgsConstructor + public static class Choice { + private int idx; + private Message message; + } +} diff --git a/src/main/java/tenten/blooming/domain/goal/dto/GoalDto.java b/src/main/java/tenten/blooming/domain/goal/dto/GoalDto.java new file mode 100644 index 0000000..a21af44 --- /dev/null +++ b/src/main/java/tenten/blooming/domain/goal/dto/GoalDto.java @@ -0,0 +1,27 @@ +package tenten.blooming.domain.goal.dto; + +import lombok.AllArgsConstructor; +import lombok.Builder; +import lombok.Data; +import lombok.ToString; +import tenten.blooming.domain.goal.entity.Goal; + +import java.time.LocalDate; + +@Data +@AllArgsConstructor +@Builder +public class GoalDto { + private Long userId; + private String goalName; + + public Goal toEntity() { + Goal goal = new Goal(); + + goal.setGoalName(goalName); + goal.setCreatedAt(LocalDate.now()); + goal.setIsActivate(true); + + return goal; + } +} diff --git a/src/main/java/tenten/blooming/domain/goal/dto/Message.java b/src/main/java/tenten/blooming/domain/goal/dto/Message.java new file mode 100644 index 0000000..56d120d --- /dev/null +++ b/src/main/java/tenten/blooming/domain/goal/dto/Message.java @@ -0,0 +1,12 @@ +package tenten.blooming.domain.goal.dto; + +import lombok.*; + +@Data +@NoArgsConstructor +@AllArgsConstructor +@Getter @Setter +public class Message { + private String role; + private String content; +} diff --git a/src/main/java/tenten/blooming/domain/goal/entity/Goal.java b/src/main/java/tenten/blooming/domain/goal/entity/Goal.java new file mode 100644 index 0000000..903c046 --- /dev/null +++ b/src/main/java/tenten/blooming/domain/goal/entity/Goal.java @@ -0,0 +1,46 @@ +package tenten.blooming.domain.goal.entity; + +import jakarta.persistence.*; +import lombok.AllArgsConstructor; +import lombok.Getter; +import lombok.NoArgsConstructor; +import lombok.Setter; +import org.springframework.data.annotation.CreatedDate; +import tenten.blooming.domain.subgoal.entity.Subgoal; +import tenten.blooming.domain.user.entity.User; + +import java.time.LocalDate; +import java.util.ArrayList; +import java.util.List; + +@AllArgsConstructor +@NoArgsConstructor +@Entity +@Getter +@Setter +@Table(name = "goal") +public class Goal { + + @Id + @GeneratedValue(strategy = GenerationType.IDENTITY) + @Column(name = "goal_id", nullable = false) + private Long goalId; // 기본키 + + @Column(name = "goal_name", nullable = false) + private String goalName; + + @CreatedDate + @Column(name = "created_at", nullable = false, updatable = false) + private LocalDate createdAt; + + @Column(name = "is_activate") + private Boolean isActivate; + + @ManyToOne + @JoinColumn(name = "user_id") + private User user; + + @OneToMany(mappedBy = "goal") + private List subgoals = new ArrayList<>(); + +} diff --git a/src/main/java/tenten/blooming/domain/goal/repository/GoalRepository.java b/src/main/java/tenten/blooming/domain/goal/repository/GoalRepository.java new file mode 100644 index 0000000..0c42e67 --- /dev/null +++ b/src/main/java/tenten/blooming/domain/goal/repository/GoalRepository.java @@ -0,0 +1,10 @@ +package tenten.blooming.domain.goal.repository; + +import org.springframework.data.jpa.repository.JpaRepository; +import tenten.blooming.domain.goal.entity.Goal; + +public interface GoalRepository extends JpaRepository { + + +} + diff --git a/src/main/java/tenten/blooming/domain/goal/service/GoalService.java b/src/main/java/tenten/blooming/domain/goal/service/GoalService.java new file mode 100644 index 0000000..2566aa6 --- /dev/null +++ b/src/main/java/tenten/blooming/domain/goal/service/GoalService.java @@ -0,0 +1,19 @@ +package tenten.blooming.domain.goal.service; + +import org.springframework.beans.factory.annotation.Autowired; +import org.springframework.stereotype.Service; +import tenten.blooming.domain.goal.dto.GoalDto; +import tenten.blooming.domain.goal.entity.Goal; +import tenten.blooming.domain.goal.repository.GoalRepository; + +@Service +public class GoalService { + @Autowired + private GoalRepository goalRepository; + + public Goal create(GoalDto dto) { + Goal goal = dto.toEntity(); + + return goalRepository.save(goal); + } +} diff --git a/src/main/java/tenten/blooming/domain/subgoal/entity/Subgoal.java b/src/main/java/tenten/blooming/domain/subgoal/entity/Subgoal.java new file mode 100644 index 0000000..fa59462 --- /dev/null +++ b/src/main/java/tenten/blooming/domain/subgoal/entity/Subgoal.java @@ -0,0 +1,42 @@ +package tenten.blooming.domain.subgoal.entity; + +import jakarta.persistence.*; +import lombok.AllArgsConstructor; +import lombok.Getter; +import lombok.NoArgsConstructor; +import lombok.Setter; +import tenten.blooming.domain.goal.entity.Goal; + +import java.time.LocalDate; + +@AllArgsConstructor +@NoArgsConstructor +@Entity +@Getter +@Setter +@Table(name = "subgoal") +public class Subgoal { + @Id + @GeneratedValue(strategy = GenerationType.IDENTITY) + @Column(name = "subgoal_id", nullable = false) + private Long subgoalId; // 기본키 + + @Column(name = "subgoal_name", nullable = false) + private String subgoalName; + + private LocalDate doneDate1; + private LocalDate doneDate2; + private LocalDate doneDate3; + private LocalDate doneDate4; + private LocalDate doneDate5; + private LocalDate doneDate6; + private LocalDate doneDate7; + private LocalDate doneDate8; + private LocalDate doneDate9; + private LocalDate doneDate10; + + @ManyToOne + @JoinColumn(name = "goal_id") + private Goal goal; + +} diff --git a/src/main/java/tenten/blooming/domain/user/entity/User.java b/src/main/java/tenten/blooming/domain/user/entity/User.java index 8b3241b..d28d364 100644 --- a/src/main/java/tenten/blooming/domain/user/entity/User.java +++ b/src/main/java/tenten/blooming/domain/user/entity/User.java @@ -3,8 +3,11 @@ import jakarta.persistence.*; import lombok.*; import org.hibernate.annotations.CreationTimestamp; +import tenten.blooming.domain.goal.entity.Goal; import java.sql.Timestamp; +import java.util.ArrayList; +import java.util.List; @AllArgsConstructor @NoArgsConstructor @@ -33,4 +36,6 @@ public class User { @Column(name = "created_at", nullable = false, updatable = false) private Timestamp createdAt; + @OneToMany(mappedBy = "user") + private List goals = new ArrayList<>(); } diff --git a/src/main/resources/application.yml b/src/main/resources/application.yml index 9a03a39..ac1d265 100644 --- a/src/main/resources/application.yml +++ b/src/main/resources/application.yml @@ -15,4 +15,8 @@ spring: properties: hibernate: format_sql: true - +openai: + model: ${OPENAI_MODEL} + api: + url: https://api.openai.com/v1/chat/completions + key: ${OPENAI_KEY} \ No newline at end of file