Skip to content

Commit 08fd672

Browse files
authored
Merge pull request #179 from capgoing/perf/#176
⚡️ [perf] 이미지 생성 모델 변경(dall-e-3) 및 picture 퀴즈 이미지 생성 결과 개선
2 parents 8ba355d + e61a166 commit 08fd672

File tree

7 files changed

+147
-24
lines changed

7 files changed

+147
-24
lines changed

Backend_Config

src/main/java/com/going/server/domain/chatbot/controller/ChatbotController.java

Lines changed: 0 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -20,7 +20,6 @@
2020
public class ChatbotController {
2121
private final ChatbotService chatbotService;
2222

23-
// 지금 챗봇 생성 컨트롤러 만드는 중이었음
2423
@PostMapping("/{graphId}")
2524
@Operation(summary = "[챗봇 화면] 챗봇 응답 생성", description = "챗봇 화면에서 사용자의 질문에 응답을 생성합니다.")
2625
@ApiResponses(
Lines changed: 22 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,22 @@
1+
package com.going.server.domain.openai.dto;
2+
3+
import lombok.AllArgsConstructor;
4+
import lombok.Getter;
5+
import lombok.NoArgsConstructor;
6+
import lombok.Setter;
7+
8+
@Getter
9+
@Setter
10+
@NoArgsConstructor
11+
@AllArgsConstructor
12+
public class ImageCreateRequestDto {
13+
private String prompt;
14+
private String model = "dall-e-3";
15+
private String style = "vivid";
16+
private String size = "1024x1024";
17+
private int n = 1;
18+
19+
public ImageCreateRequestDto(String prompt) {
20+
this.prompt = prompt;
21+
}
22+
}
Lines changed: 22 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,22 @@
1+
package com.going.server.domain.openai.dto;
2+
3+
import lombok.AllArgsConstructor;
4+
import lombok.Getter;
5+
import lombok.NoArgsConstructor;
6+
7+
import java.util.List;
8+
9+
@Getter
10+
@NoArgsConstructor
11+
@AllArgsConstructor
12+
public class ImageCreateResponseDto {
13+
private List<Data> data;
14+
15+
@Getter
16+
@NoArgsConstructor
17+
@AllArgsConstructor
18+
public static class Data {
19+
private String url;
20+
private String revised_prompt;
21+
}
22+
}
Lines changed: 31 additions & 15 deletions
Original file line numberDiff line numberDiff line change
@@ -1,26 +1,42 @@
11
package com.going.server.domain.openai.service;
22

3-
import com.theokanning.openai.image.CreateImageRequest;
4-
import com.theokanning.openai.OpenAiService;
5-
import jakarta.annotation.Resource;
3+
import com.going.server.domain.openai.dto.ImageCreateRequestDto;
4+
import com.going.server.domain.openai.dto.ImageCreateResponseDto;
65
import lombok.RequiredArgsConstructor;
6+
import org.springframework.beans.factory.annotation.Qualifier;
7+
import org.springframework.http.*;
78
import org.springframework.stereotype.Service;
9+
import org.springframework.web.client.RestTemplate;
810

911
@Service
10-
@RequiredArgsConstructor
1112
public class ImageCreateService {
1213

13-
@Resource(name = "getOpenAIService")
14-
private final OpenAiService openAiService;
14+
private final RestTemplate restTemplate = new RestTemplate();
15+
private final String openAIImageUrl;
16+
private final String apiKey;
1517

16-
public String generatePicture(String prompt) {
17-
CreateImageRequest createImageRequest = CreateImageRequest.builder()
18-
.prompt(prompt)
19-
.size("512x512") //사이즈
20-
.n(1)
21-
.build();
18+
public ImageCreateService(
19+
@Qualifier("openAIImageUrl") String openAIImageUrl,
20+
@Qualifier("openAIKey") String apiKey
21+
) {
22+
this.openAIImageUrl = openAIImageUrl;
23+
this.apiKey = apiKey;
24+
}
25+
26+
public String generatePicture(ImageCreateRequestDto requestDto) {
27+
HttpHeaders headers = new HttpHeaders();
28+
headers.setBearerAuth(apiKey);
29+
headers.setContentType(MediaType.APPLICATION_JSON);
30+
31+
HttpEntity<ImageCreateRequestDto> entity = new HttpEntity<>(requestDto, headers);
32+
33+
ResponseEntity<ImageCreateResponseDto> response = restTemplate.exchange(
34+
openAIImageUrl,
35+
HttpMethod.POST,
36+
entity,
37+
ImageCreateResponseDto.class
38+
);
2239

23-
//URL로 리턴 (1시간 후 만료)
24-
return openAiService.createImage(createImageRequest).getData().get(0).getUrl();
40+
return response.getBody().getData().get(0).getUrl();
2541
}
26-
}
42+
}

src/main/java/com/going/server/domain/quiz/generate/PictureQuizGenerator.java

Lines changed: 52 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -2,6 +2,7 @@
22

33
import com.going.server.domain.graph.entity.Graph;
44
import com.going.server.domain.graph.entity.GraphNode;
5+
import com.going.server.domain.openai.dto.ImageCreateRequestDto;
56
import com.going.server.domain.openai.service.ImageCreateService;
67
import com.going.server.domain.quiz.dto.PictureQuizDto;
78
import lombok.AllArgsConstructor;
@@ -58,8 +59,9 @@ public PictureQuizDto generate(Graph graph) {
5859
int answerIndex = random.nextInt(shuffledListSize);
5960
String answer = new ArrayList<>(selectedSentences).get(answerIndex);
6061

61-
String prompt = buildImagePrompt(answer);
62-
String imageUrl = imageCreateService.generatePicture(prompt);
62+
String prompt = buildQuizImagePrompt(answer);
63+
ImageCreateRequestDto requestDto = new ImageCreateRequestDto(prompt);
64+
String imageUrl = imageCreateService.generatePicture(requestDto);
6365

6466
return PictureQuizDto.builder()
6567
.imageUrl(imageUrl)
@@ -69,9 +71,54 @@ public PictureQuizDto generate(Graph graph) {
6971
}
7072

7173
// 이미지 생성 프롬프트 생성 메서드
72-
private String buildImagePrompt(String answer) {
73-
return "아래 설명을 이미지로 표현해주세요.\n\n"
74-
+ "[설명]\n" + answer;
74+
75+
// 버전1
76+
// private String buildQuizImagePrompt(String answer) {
77+
// return "You are given an educational description in natural language.\n\n" +
78+
// "1. First, analyze the sentence to determine what kind of relationship it contains, such as:\n" +
79+
// "- Cause and effect\n" +
80+
// "- Inclusion or category\n" +
81+
// "- Example and concept\n" +
82+
// "- Behavioral actions\n" +
83+
// "- General explanation\n\n" +
84+
// "2. Then, generate a **cute, warm, and educational diagram-style illustration** that reflects the structure and meaning of the sentence.\n\n" +
85+
// "Use **flat vector illustrations inspired by iOS emojis**, with **bright and soft colors**.\n" +
86+
// "If the sentence includes multiple ideas, arrange the illustration using diagrams, arrows, or symbolic layouts that match the logical structure.\n" +
87+
// "Do **not include any text or labels** in the image. Use only visuals.\n\n" +
88+
// "[Description]\n" + answer;
89+
// }
90+
91+
// 버전2
92+
// public String buildQuizImagePrompt(String answer) {
93+
// return "You are given an educational description in natural language.\n\n" +
94+
// "1. First, analyze the sentence to determine what kind of relationship it contains, such as:\n" +
95+
// "- Cause and effect\n" +
96+
// "- Inclusion or category\n" +
97+
// "- Example and concept\n" +
98+
// "- Behavioral actions\n" +
99+
// "- General explanation\n\n" +
100+
// "2. Then, generate a cute, warm, and educational diagram-style illustration that reflects the structure and meaning of the sentence.\n\n" +
101+
// "Use flat vector illustrations inspired by iOS emojis, with bright and soft colors.\n" +
102+
// "If the sentence includes multiple ideas, arrange the illustration using symbols or visual layouts like arrows, sets, or diagrams **only when necessary to express the logical relationship**.\n" +
103+
// "Do not include any text or labels in the image. Use only visuals.\n\n" +
104+
// "[Description]\n" + answer;
105+
// }
106+
107+
// 버전3
108+
public static String buildQuizImagePrompt(String answer) {
109+
return "You are given an educational description in natural language.\n\n" +
110+
"1. First, analyze the sentence to determine what kind of relationship it contains, such as:\n" +
111+
"- Cause and effect\n" +
112+
"- Inclusion or category\n" +
113+
"- Example and concept\n" +
114+
"- Behavioral actions\n" +
115+
"- General explanation\n\n" +
116+
"2. Then, generate a cute, warm, and educational diagram-style illustration that reflects the structure and meaning of the sentence.\n\n" +
117+
"Use flat vector illustrations inspired by iOS emojis, with bright and soft colors.\n\n" +
118+
"If the sentence includes multiple ideas or relationships, use simple visual symbols like arrows or grouping layouts to represent those relationships **only when necessary**.\n" +
119+
"Do **not overuse symbols**—use them only when they help express meaning clearly.\n\n" +
120+
"Do not include any text or labels in the image. Use only visuals.\n\n" +
121+
"[Description]\n" + answer;
75122
}
76123

77124
}
Lines changed: 19 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -1,19 +1,36 @@
11
package com.going.server.global.config;
22

3-
import org.springframework.context.annotation.Configuration;
43
import com.theokanning.openai.OpenAiService;
54
import org.springframework.beans.factory.annotation.Value;
65
import org.springframework.context.annotation.Bean;
6+
import org.springframework.context.annotation.Configuration;
77

88
import java.time.Duration;
99

1010
@Configuration
1111
public class OpenAIConfig {
12+
1213
@Value("${openai.key}")
1314
private String apiKey;
1415

16+
@Value("${openai.image-url}")
17+
private String imageUrl;
18+
19+
@Value("${openai.timeout:30}")
20+
private int timeout;
21+
1522
@Bean
1623
public OpenAiService getOpenAIService() {
17-
return new OpenAiService(apiKey, Duration.ofSeconds(30));
24+
return new OpenAiService(apiKey, Duration.ofSeconds(timeout));
25+
}
26+
27+
@Bean(name = "openAIImageUrl")
28+
public String openAIImageUrl() {
29+
return imageUrl;
30+
}
31+
32+
@Bean(name = "openAIKey")
33+
public String openAIKey() {
34+
return apiKey;
1835
}
1936
}

0 commit comments

Comments
 (0)