Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
2 changes: 1 addition & 1 deletion Backend_Config
Original file line number Diff line number Diff line change
Expand Up @@ -20,7 +20,6 @@
public class ChatbotController {
private final ChatbotService chatbotService;

// 지금 챗봇 생성 컨트롤러 만드는 중이었음
@PostMapping("/{graphId}")
@Operation(summary = "[챗봇 화면] 챗봇 응답 생성", description = "챗봇 화면에서 사용자의 질문에 응답을 생성합니다.")
@ApiResponses(
Expand Down
Original file line number Diff line number Diff line change
@@ -0,0 +1,22 @@
package com.going.server.domain.openai.dto;

import lombok.AllArgsConstructor;
import lombok.Getter;
import lombok.NoArgsConstructor;
import lombok.Setter;

@Getter
@Setter
@NoArgsConstructor
@AllArgsConstructor
public class ImageCreateRequestDto {
private String prompt;
private String model = "dall-e-3";
private String style = "vivid";
private String size = "1024x1024";
private int n = 1;

public ImageCreateRequestDto(String prompt) {
this.prompt = prompt;
}
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,22 @@
package com.going.server.domain.openai.dto;

import lombok.AllArgsConstructor;
import lombok.Getter;
import lombok.NoArgsConstructor;

import java.util.List;

@Getter
@NoArgsConstructor
@AllArgsConstructor
public class ImageCreateResponseDto {
private List<Data> data;

@Getter
@NoArgsConstructor
@AllArgsConstructor
public static class Data {
private String url;
private String revised_prompt;
}
}
Original file line number Diff line number Diff line change
@@ -1,26 +1,42 @@
package com.going.server.domain.openai.service;

import com.theokanning.openai.image.CreateImageRequest;
import com.theokanning.openai.OpenAiService;
import jakarta.annotation.Resource;
import com.going.server.domain.openai.dto.ImageCreateRequestDto;
import com.going.server.domain.openai.dto.ImageCreateResponseDto;
import lombok.RequiredArgsConstructor;
import org.springframework.beans.factory.annotation.Qualifier;
import org.springframework.http.*;
import org.springframework.stereotype.Service;
import org.springframework.web.client.RestTemplate;

@Service
@RequiredArgsConstructor
public class ImageCreateService {

@Resource(name = "getOpenAIService")
private final OpenAiService openAiService;
private final RestTemplate restTemplate = new RestTemplate();
private final String openAIImageUrl;
private final String apiKey;

public String generatePicture(String prompt) {
CreateImageRequest createImageRequest = CreateImageRequest.builder()
.prompt(prompt)
.size("512x512") //사이즈
.n(1)
.build();
public ImageCreateService(
@Qualifier("openAIImageUrl") String openAIImageUrl,
@Qualifier("openAIKey") String apiKey
) {
this.openAIImageUrl = openAIImageUrl;
this.apiKey = apiKey;
}

public String generatePicture(ImageCreateRequestDto requestDto) {
HttpHeaders headers = new HttpHeaders();
headers.setBearerAuth(apiKey);
headers.setContentType(MediaType.APPLICATION_JSON);

HttpEntity<ImageCreateRequestDto> entity = new HttpEntity<>(requestDto, headers);

ResponseEntity<ImageCreateResponseDto> response = restTemplate.exchange(
openAIImageUrl,
HttpMethod.POST,
entity,
ImageCreateResponseDto.class
);

//URL로 리턴 (1시간 후 만료)
return openAiService.createImage(createImageRequest).getData().get(0).getUrl();
return response.getBody().getData().get(0).getUrl();
}
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -2,6 +2,7 @@

import com.going.server.domain.graph.entity.Graph;
import com.going.server.domain.graph.entity.GraphNode;
import com.going.server.domain.openai.dto.ImageCreateRequestDto;
import com.going.server.domain.openai.service.ImageCreateService;
import com.going.server.domain.quiz.dto.PictureQuizDto;
import lombok.AllArgsConstructor;
Expand Down Expand Up @@ -58,8 +59,9 @@ public PictureQuizDto generate(Graph graph) {
int answerIndex = random.nextInt(shuffledListSize);
String answer = new ArrayList<>(selectedSentences).get(answerIndex);

String prompt = buildImagePrompt(answer);
String imageUrl = imageCreateService.generatePicture(prompt);
String prompt = buildQuizImagePrompt(answer);
ImageCreateRequestDto requestDto = new ImageCreateRequestDto(prompt);
String imageUrl = imageCreateService.generatePicture(requestDto);

return PictureQuizDto.builder()
.imageUrl(imageUrl)
Expand All @@ -69,9 +71,54 @@ public PictureQuizDto generate(Graph graph) {
}

// 이미지 생성 프롬프트 생성 메서드
private String buildImagePrompt(String answer) {
return "아래 설명을 이미지로 표현해주세요.\n\n"
+ "[설명]\n" + answer;

// 버전1
// private String buildQuizImagePrompt(String answer) {
// return "You are given an educational description in natural language.\n\n" +
// "1. First, analyze the sentence to determine what kind of relationship it contains, such as:\n" +
// "- Cause and effect\n" +
// "- Inclusion or category\n" +
// "- Example and concept\n" +
// "- Behavioral actions\n" +
// "- General explanation\n\n" +
// "2. Then, generate a **cute, warm, and educational diagram-style illustration** that reflects the structure and meaning of the sentence.\n\n" +
// "Use **flat vector illustrations inspired by iOS emojis**, with **bright and soft colors**.\n" +
// "If the sentence includes multiple ideas, arrange the illustration using diagrams, arrows, or symbolic layouts that match the logical structure.\n" +
// "Do **not include any text or labels** in the image. Use only visuals.\n\n" +
// "[Description]\n" + answer;
// }

// 버전2
// public String buildQuizImagePrompt(String answer) {
// return "You are given an educational description in natural language.\n\n" +
// "1. First, analyze the sentence to determine what kind of relationship it contains, such as:\n" +
// "- Cause and effect\n" +
// "- Inclusion or category\n" +
// "- Example and concept\n" +
// "- Behavioral actions\n" +
// "- General explanation\n\n" +
// "2. Then, generate a cute, warm, and educational diagram-style illustration that reflects the structure and meaning of the sentence.\n\n" +
// "Use flat vector illustrations inspired by iOS emojis, with bright and soft colors.\n" +
// "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" +
// "Do not include any text or labels in the image. Use only visuals.\n\n" +
// "[Description]\n" + answer;
// }

// 버전3
public static String buildQuizImagePrompt(String answer) {
return "You are given an educational description in natural language.\n\n" +
"1. First, analyze the sentence to determine what kind of relationship it contains, such as:\n" +
"- Cause and effect\n" +
"- Inclusion or category\n" +
"- Example and concept\n" +
"- Behavioral actions\n" +
"- General explanation\n\n" +
"2. Then, generate a cute, warm, and educational diagram-style illustration that reflects the structure and meaning of the sentence.\n\n" +
"Use flat vector illustrations inspired by iOS emojis, with bright and soft colors.\n\n" +
"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" +
"Do **not overuse symbols**—use them only when they help express meaning clearly.\n\n" +
"Do not include any text or labels in the image. Use only visuals.\n\n" +
"[Description]\n" + answer;
}

}
21 changes: 19 additions & 2 deletions src/main/java/com/going/server/global/config/OpenAIConfig.java
Original file line number Diff line number Diff line change
@@ -1,19 +1,36 @@
package com.going.server.global.config;

import org.springframework.context.annotation.Configuration;
import com.theokanning.openai.OpenAiService;
import org.springframework.beans.factory.annotation.Value;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;

import java.time.Duration;

@Configuration
public class OpenAIConfig {

@Value("${openai.key}")
private String apiKey;

@Value("${openai.image-url}")
private String imageUrl;

@Value("${openai.timeout:30}")
private int timeout;

@Bean
public OpenAiService getOpenAIService() {
return new OpenAiService(apiKey, Duration.ofSeconds(30));
return new OpenAiService(apiKey, Duration.ofSeconds(timeout));
}

@Bean(name = "openAIImageUrl")
public String openAIImageUrl() {
return imageUrl;
}

@Bean(name = "openAIKey")
public String openAIKey() {
return apiKey;
}
}