Spring & Spring Boot

[Spring&SpringBoot] ChatGPT Spring에서 사용하기

김먼저 2023. 5. 30. 15:01

일단 OpenAI Secret API Key 가 필요합니다.

 

https://firstws.tistory.com/63

 

[OpenAI] OpenAI API Key 발급 받기(feat.chatGPT)

0. OpenAI API Key OpenAI에서 개발한 인공지능 모델들을 외부에서 사용할 수 있도록 인증하는 역할을 합니다. OpenAI는 다양한 유형의 인공지능 모델을 제공하는데요, 대표적인 모델을 살펴보면 아래와

firstws.tistory.com

 

 

 

1. Postman으로 Test해보기

 

method : POST
url : https://api.openai.com/v1/chat/completions

 

Headers Setting

Content-Type : application/json
Authorization : ${OpenAI Secret API Key}

 

 

Body-JSON

{
  "model": "gpt-3.5-turbo",
  "stream" : false,
  "messages": [{"role": "user", "content": "100+200=?"}]
}

 

다양한 모델이 있지만 GPT-3.5 중에서 가장 유능한 모델인 'gpt-3.5-turbo'를 선정하였습니다.

 

 

'Send' 클릭해서 요청보내기 - 결과

 

위와 같이 나오면 성공한 겁니다.

 

choices - message - content에 답변이 담겨 있고, 우리는 그걸 꺼내 사용하면 됩니다.

 

이제 DTO - Config - Controller - Service 순서로 작성해보겠습니다.

 

2. DTO 작성하기

 

@Getter
@NoArgsConstructor
//Front단에서 요청하는 DTO
public class QuestionRequest implements Serializable {
    private String question;
}
@Getter
@NoArgsConstructor
//chatGPT에 요청할 DTO Format
public class ChatGptRequest implements Serializable {
    private String model;
    @JsonProperty("max_tokens")
    private Integer maxTokens;
    private Double temperature;
    private Boolean stream;
    private List<ChatGptMessage> messages;

    //@JsonProperty("top_p")
    //private Double topP;

    @Builder
    public ChatGptRequest(String model, Integer maxTokens, Double temperature,
                          Boolean stream, List<ChatGptMessage> messages
                          /*,Double topP*/) {
        this.model = model;
        this.maxTokens = maxTokens;
        this.temperature = temperature;
        this.stream = stream;
        this.messages = messages;
        //this.topP = topP;
    }
}
@Getter
@NoArgsConstructor
//ChatGPT 답변을 담을 DTO
public class ChatGptResponse {
    private String id;
    private String object;
    private long created;
    private String model;
    private Usage usage;
    private List<Choice> choices;

    @Getter
    @Setter
    public static class Usage {
        @JsonProperty("prompt_tokens")
        private int promptTokens;
        @JsonProperty("completion_tokens")
        private int completionTokens;
        @JsonProperty("total_tokens")
        private int totalTokens;
    }

    @Getter
    @Setter
    public static class Choice {
        private ChatGptMessage message;
        @JsonProperty("finish_reason")
        private String finishReason;
        private int index;
    }
}

 

3. Config 작성하기

@Configuration
public class ChatGptConfig {
    public static final String AUTHORIZATION = "Authorization";
    public static final String BEARER = "Bearer ";
    public static final String CHAT_MODEL = "gpt-3.5-turbo";
    public static final Integer MAX_TOKEN = 300;
    public static final Boolean STREAM = false;
    public static final String ROLE = "user";
    public static final Double TEMPERATURE = 0.6;
    //public static final Double TOP_P = 1.0;
    public static final String MEDIA_TYPE = "application/json; charset=UTF-8";
    //completions : 질답
    public static final String CHAT_URL = "https://api.openai.com/v1/chat/completions";
}

 

4. Controller 작성하기

 

@RequiredArgsConstructor
@RequestMapping("/chat-gpt")
@RestController
public class ChatGptController {
    private final APIResponse apiResponse;
    private final ChatGptService chatGptService;

    @Operation(summary = "Question to Chat-GPT")
    @PostMapping("/question")
    public ResponseEntity sendQuestion(
            Locale locale,
            HttpServletRequest request,
            HttpServletResponse response,
            @RequestBody QuestionRequest questionRequest) {
        String code = ResponseCode.CD_SUCCESS;
        ChatGptResponse chatGptResponse = null;
        try {
            chatGptResponse = chatGptService.askQuestion(questionRequest);
        } catch (Exception e) {
            apiResponse.printErrorMessage(e);
            code = e.getMessage();
        }
        //return 부분은 자유롭게 수정하시면됩니다. ex)return chatGptResponse;
        return apiResponse.getResponseEntity(locale, code,
                chatGptResponse != null ? chatGptResponse.getChoices().get(0).getMessage().getContent() : new ChatGptResponse());
    }
}

 

5. Service 작성하기

 

@Slf4j
@RequiredArgsConstructor
@Service
public class ChatGptService {
    private final RestTemplate restTemplate;

	//api key를 application.yml에 넣어두었습니다.
    @Value("${api-key.chat-gpt}")
    private String apiKey;

    public HttpEntity<ChatGptRequest> buildHttpEntity(ChatGptRequest chatGptRequest){
        HttpHeaders httpHeaders = new HttpHeaders();
        httpHeaders.setContentType(MediaType.parseMediaType(ChatGptConfig.MEDIA_TYPE));
        httpHeaders.add(ChatGptConfig.AUTHORIZATION, ChatGptConfig.BEARER + apiKey);
        return new HttpEntity<>(chatGptRequest, httpHeaders);
    }

    public ChatGptResponse getResponse(HttpEntity<ChatGptRequest> chatGptRequestHttpEntity){

        SimpleClientHttpRequestFactory requestFactory = new SimpleClientHttpRequestFactory();
        requestFactory.setConnectTimeout(60000);
        //답변이 길어질 경우 TimeOut Error가 발생하니 1분정도 설정해줍니다.
        requestFactory.setReadTimeout(60 * 1000);   //  1min = 60 sec * 1,000ms
        restTemplate.setRequestFactory(requestFactory);

        ResponseEntity<ChatGptResponse> responseEntity = restTemplate.postForEntity(
          ChatGptConfig.CHAT_URL,
          chatGptRequestHttpEntity,
          ChatGptResponse.class);

        return responseEntity.getBody();
    }
    public ChatGptResponse askQuestion(QuestionRequest questionRequest){
        List<ChatGptMessage> messages = new ArrayList<>();
        messages.add(ChatGptMessage.builder()
                .role(ChatGptConfig.ROLE)
                .content(questionRequest.getQuestion())
                .build());
        return this.getResponse(
                this.buildHttpEntity(
                        new ChatGptRequest(
                                ChatGptConfig.CHAT_MODEL,
                                ChatGptConfig.MAX_TOKEN,
                                ChatGptConfig.TEMPERATURE,
                                ChatGptConfig.STREAM,
                                messages
                                //ChatGptConfig.TOP_P
                        )
                )
        );
    }
}

 

 

실행 결과

 

 

 

 

테스트상 최소한의 parameter를 사용하였으며, 적용 가능한 parameter가 다양하므로 아래 공식문서를 참조해주세요.

 

ref : https://platform.openai.com/docs/api-reference/completions/create

 

OpenAI API

An API for accessing new AI models developed by OpenAI

platform.openai.com