팀프로젝트에서 서술형 정답 체크 부분에 대해서 이야기를 나누다가 키워드 매칭으로 단순하게 하는 것보단 ai채점까지 추가해서 하는게 좋을 거 같다는 의견을 받고 gpt api를 적용해보았다.
GPT API를 처음 사용하게되면서 처음에 방법에 대해 이해하는데 꽤 걸렸는데 다른 분이 사용한 것을 보고나니 많이 이해됬습니다.
https://waveofmymind.github.io/posts/springboot+chatgpt/ (설명을 잘 적어주셔서 따라하시면 금방 이해 될거라고 생각합니다.)
gpt 3.5버전부터는 chat Completion만 제공해줍니다.(Completions에서 향상된 버전)
gptService 생성
import com.fasterxml.jackson.core.JsonProcessingException;
import com.fasterxml.jackson.databind.JsonNode;
import com.fasterxml.jackson.databind.ObjectMapper;
import com.theokanning.openai.completion.chat.ChatCompletionRequest;
import com.theokanning.openai.completion.chat.ChatCompletionResult;
import com.theokanning.openai.completion.chat.ChatMessage;
import com.theokanning.openai.completion.chat.ChatMessageRole;
import com.theokanning.openai.service.OpenAiService;
import com.twenty.inhub.base.appConfig.GptConfig;
import com.twenty.inhub.boundedContext.answer.controller.dto.AnswerDto;
import com.twenty.inhub.boundedContext.answer.controller.dto.QuestionAnswerDto;
import com.twenty.inhub.boundedContext.gpt.dto.GptResponseDto;
import io.micrometer.core.annotation.Timed;
import lombok.RequiredArgsConstructor;
import lombok.extern.slf4j.Slf4j;
import org.springframework.stereotype.Service;
import org.springframework.web.client.RestTemplate;
import java.util.Collections;
import java.util.HashMap;
import java.util.List;
import java.util.Map;
@Slf4j
@Service
@RequiredArgsConstructor
@Timed(value = "gpt.service")
public class GptService {
private final OpenAiService openAiService;
private final ObjectMapper objectMapper;
public ChatCompletionResult generated(List<ChatMessage> chatMessages) {
//기본적으로 라이브러리에서 제공해주는 틀
ChatCompletionRequest build = ChatCompletionRequest.builder()
.messages(chatMessages)
.maxTokens(GptConfig.MAX_TOKEN)
.temperature(GptConfig.TEMPERATURE)
.topP(GptConfig.TOP_P)
.model(GptConfig.MODEL)
.build();
return openAiService.createChatCompletion(build);
}
//gpt에게 물어볼 메세지 생성
public List<ChatMessage> generatedQuestionAndAnswerMessage(QuestionAnswerDto questionAnswerDto) {
String prompt = Prompt.generateQuestionPrompt(questionAnswerDto.getContent(), questionAnswerDto.getAnswer());
log.info("생성된 프롬프트 : {}", prompt);
ChatMessage userMessage = new ChatMessage(ChatMessageRole.USER.value(), prompt);
return List.of(userMessage);
}
//메세지를 물어보고 답변을 위한 툴
//GptResponseDto는 gpt에게 받은 데이터를 json으로 파싱한 값을 받아서 전달하기위해서 만들었습니다.
public GptResponseDto askQuestion(QuestionAnswerDto questionAnswerDto) {
List<ChatMessage> chatMessages = generatedQuestionAndAnswerMessage(questionAnswerDto);
ChatCompletionResult result = generated(chatMessages);
String gptAnswer = result.getChoices().get(0).getMessage().getContent();
log.info("GPT 답변: {}", gptAnswer);
// JSON 문자열을 파싱하여 결과 값을 추출
try {
JsonNode jsonNode = objectMapper.readTree(gptAnswer);
String score = jsonNode.get("score").asText();
String feedback = jsonNode.get("feedback").asText();
log.info("점수 : {}",score);
log.info("피드백 : {}",feedback);
// 결과를 담을 GptResponseDto 객체 생성
GptResponseDto response = new GptResponseDto();
response.setScore(Double.parseDouble(score));
response.setFeedBack(feedback);
return response;
} catch (JsonProcessingException e) {
log.error("Error parsing GPT response JSON: {}", e.getMessage());
return null;
}
}
}
Prompt 생성
package com.twenty.inhub.boundedContext.gpt;
public class Prompt {
//학습 시킬 형식
public static String generateQuestionPrompt(String Question,String Answer){
String prompt= """
I'll give you questions and answers.
question : %s
answer : %s
Now, please grade the answers to the questions on a 100-point scale.
If you want to give feedback, please keep it in korean as short as possible (3 lines or less).
Also, if the answer doesn't make much sense, give it a 0.
Finally, when you respond to me, respond in JSON format below.
{
"score" : "",
"feedback" : ""
}
""";
return String.format(prompt,Question,Answer);
}
}
이렇게 만들어 두면 Controller에서 gptService를 생성자로 받아두면 사용이 가능해집니다.
외부 라이브러리를 사용하기 때문에 속도가 살짝 느리긴합니다.
안녕하세요! 글 너무 잘 읽었습니다 🙌
GPT API 기반 자동 채점 로직과 프롬프트 설계까지 직접 구현하신 과정이 정말 인상 깊네요.
저희도 현재 AI 기반 기술 튜토리얼 플랫폼 Insty를 만들고 있는데,
러너의 설치 흐름을 돕는 GPT 챗봇, 영상 추천, 자동 태깅 등 다양한 AI 기능을 API 기반으로 직접 설계/연동하고 있습니다.
작성하신 경험이 저희 팀에서 고민하고 있는 방향과 정말 잘 맞는다고 느꼈고,
혹시 괜찮으시다면 편하게 커피챗 한 번 나눌 수 있을까요?
사이드 프로젝트이지만 진심으로 재미있게 달리고 있어요 :)
holaworld 게시글 링크: https://holaworld.io/study/67f30444f675c05ce9c28316
궁금하시다면 instyhelp@gmail.com 이나
오픈채팅 https://open.kakao.com/o/siI0EBoh 통해 편하게 연락 주세요!
감사합니다!
잘 읽었습니다. 좋은 정보 감사드립니다.