Java/Spring Boot
[Java] Spring Boot 환경에서 ChatGPT API 활용하기 -2 : 생태계, 레거시, 새로운 모델
adjh54
2024. 1. 21. 14:23
반응형
해당 글에서는 Spring Boot 환경에서 ChatGPT API를 사용할 때에 2023년 AI 검색도구의 추세를 확인해 보고 API를 사용하는데 필수 개념과 레거시 모델이나 신규 모델을 호출하여 사용하는 방법에 대해 알아봅니다.
💡[참고] 이전 레거시 모델만으로 호출하는 방법에 대해 궁금하시면 아래의 글을 참고하시면 도움이 됩니다.
💡 [참고] API 관련하여 주요 사이트
참고사이트 명 | 참고 사이트 링크 |
Open AI API 가격 | https://openai.com/pricing |
Open AI Key 관리 | https://platform.openai.com/api-keys |
Open AI 사용량 관리 | https://platform.openai.com/usage |
Open AI Tokenizer | https://platform.openai.com/tokenizer |
Open AI 모델 종류 | https://platform.openai.com/docs/models/overview |
Open AI API Document | https://platform.openai.com/docs/introduction |
Open AI 최신 모델 API | https://platform.openai.com/docs/api-reference/chat |
Open AI 레거시 모델 API | https://platform.openai.com/docs/api-reference/completions |
1) Trends : 2023 Stack Overflow Survey
💡 Trends : 2023 Stack Overflow Survey
- 2023년도 AI Tools와 관련되어서 조사된 내용의 일부를 확인해봅니다.
1. AI 검색 도구들(AI Search Tools)
💡 AI 검색 도구들(AI Search Tools)
- 2023년 개발자들을 대상으로 조사한 내용 중 ‘AI Search Tools’라는 주제는 어떤 AI 기반 검색도구를 가장 많이 사용하였는가? 에 대한 조사입니다.
이는 올해 새로운 섹션으로, 응답자가 AI 검색 도구로 가장 많이 선택한 것은 ChatGPT입니다. 응답자의 83%가 지난 1년 동안 ChatGPT를 사용했습니다. 이는 20%가 Bing AI를 사용한 두 번째 선택을 뛰어넘는 수치입니다. 신흥 AI 검색 기술에 대한 과대광고는 ChatGPT 경쟁업체가 사용자 기반을 늘리는 동안 성장할 여지가 있습니다. 단 4개의 도구만이 내년에 사용해 보고 싶은 사람들이 10% 이상 선택했습니다.
- 해당 부분에서 AI 검색도구로는 ChatGPT가 83.24%로 압도적으로 많이 사용하는 검색도구가 되었습니다.
2. AI 도구의 이점(Benefits of AI tools)
💡 AI 도구의 이점(Benefits of AI tools)
- 해당 조사 내용은 AI를 사용함으로 가장 큰 이점이 무엇이냐는 조사였습니다.
- 해당 내용에서는 AI 도구를 통해서 얻는 가장 큰 이점은 개발 생산성을 높이고 학습 속도 향상하는데 도움이 된다고 이야기하고 있습니다.
3. AI 도구의 정확성(Accuracy of AI tools)
💡 AI 도구의 정확성(Accuracy of AI tools)
- 해당 조사는 검색 도구를 사용하였을 때 출력되는 값의 정확도 및 신뢰가 얼마가 되는지에 대한 조사였습니다.
- 약 42%는 출력의 정확성을 신뢰한 반면은 31%는 신뢰하지 않았다고 나오고 있습니다.
2) ChatGPT
💡 ChatGPT
- OpenAI에서 개발한 인공지능 모델로 자연어 처리와 대화 기능을 갖춘 대화형 AI 모델입니다.
- 다양한 주제에 대해 대화하고 질문에 답변할 수 있으며, 일상 대화부터 정보 제공 및 문제 해결까지 다양한 용도로 사용될 수 있습니다.
1. ChatGPT 모델
💡 2024년 01월 기준의 정리한 모델들입니다.
💡 모델 리스트
1. ChatGPT-3(babbage-002, davinci-002)
2. ChatGPT-3.5 instruct(4k)
3. ChatGPT-3.5 Turbo(16k)
4. ChatGPT-4(32k)
5. ChatGPT-4 Turbo(128k)
분류 | 모델 그룹 |
레거시 모델들 (2023) | gpt-3.5-turbo-instruct, babbage-002, davinci-002 |
새로운 모델들(2023–) | gpt-4, gpt-4 turbo, gpt-3.5-turbo |
💡 [참고]
- 2024.01.04일 부로 Legacy Modols들이 Deprecated 되었습니다.
- 그리고 Updated Legacy Models이 Legacy Model로 변경되었습니다.
2. ChatGPT 모델 별 API 호출 가격
💡 2024년 01월 기준의 가장 최신으로 발표한 모델을 기준으로 하였습니다.
ChatGPT 모델 | Max Token / Context Window | 입력 가격 | 출력 가격 | 종합 가격 |
ChatGPT-3(Legacy) | 16,384 tokens(Max Token) | - | - | $ 0.0020 (약 3원) |
ChatGPT-3.5 instruct(4k) | 4,000 tokens(4K) | $ 0.0015 | $ 0.0020 | $ 0.0035 (약 5원) |
ChatGPT-3.5 Turbo (16k) | 16,000 tokens(16K) | $ 0.0010 | $ 0.0020 | $ 0.0030 (약 4원) |
ChatGPT-4 (32k) | 32,768 tokens(32K) | $ 0.03 | $ 0.06 | $ 0.09 (약 121원) |
ChatGPT-4 Turbo (128k) | 128,000 tokens(128K) | $ 0.06 | $ 0.12 | $ 0.18 (약 242원) |
💡 ChatGPT-3(Legacy)의 경우 context window가 아니라 Max Token으로 처리가 되는가?
- 대표적으로 Babbage-002 모델의 경우 입력 데이터의 길이에 제한을 두는 방식으로 작동하기에 MaxToken 값으로 사용이 된다고 합니다.
3. ChatGPT 수행과정
💡 ChatGPT 수행과정
1. 사용자는 “Hello, how are you doing?”이라는 입력 프롬프트를 입력합니다.
2. ChatGPT 모델을 통해서 수행을 합니다.
3. ChatGPT 모델에서는 입력받은 값을 토큰으로 변환합니다.
4. 입력 받은 값이 토큰으로 변환이 될 때까지 프로세스를 반복합니다.
3) ChatGPT API 주요 구성요소
1. ChatGPT Token
💡 ChatGPT Token
- 사용자가 입력한 프롬프트 메시지는 ‘토큰’ 단위로 나뉩니다. 이러한 토큰은 단어 또는 단어의 일부가 될 수 있습니다.
- 토큰에는 한도(limit)가 있습니다. 모델이 지원하는 Token에 따라서 프롬프트 값과 응답받은 값의 합에 따라 한도가 지정됩니다.
- 예를 들어 최대 4097개 토큰이 있는 경우, 프롬프트로 4000개의 토큰을 사용한 경우 최대 97개의 토큰으로 응답 값을 반환합니다.
💡 [참고] 단어 별 측정되는 토큰 정도
사용하는 단어 | 토큰 |
영어 4자 | 1 Token |
3/4 단어 | 1 Token |
75 단어 | 100 Token |
1,500단어 | 2048 Token |
1-2 문장 | 30 Token |
1 문단 | 100 Token |
What are tokens and how to count them? | OpenAI Help Center
💡 [참고] Tokenizer를 통해서 문자 별 토큰의 개수를 확인할 수 있습니다.
https://platform.openai.com/docs/introduction/tokens
Token 종류 | 설명 |
Prompt Token | 사용자가 모델에게 제공하는 ‘입력 텍스트’를 나타내는 토큰입니다. |
Completion Token | 모델이 생성하여 ‘출력하는 텍스트’를 나타내는 토큰입니다. |
Total Token | 입력(prompt) 토큰과 출력(completion) 토큰의 총합을 나타내는 토큰입니다. |
Max Token | 모델이 한 번에 처리할 수 있는 최대 토큰 수를 나타내는 토큰입니다. 해당 토큰 값은 모델이 가지고 있는 토큰 수를 넘길 수 없습니다. |
💡 [참고] API 호출 시 Prompt Token과 Completion Token, Total Token을 확인할 수 있습니다.
- prompt_tokens는 api로 request 한 프롬프트 텍스트의 토큰 수를 의미합니다.
- completion_tokens는 요청에 대한 응답으로 출력되는 텍스트의 토큰 수를 의미합니다.
- total_tokens는 요청 및 응답에 대한 토큰의 합을 의미합니다.
2. ChatGPT Context Window
💡 ChatGPT Context Window
- ChatGPT가 이전의 대화 내용을 얼마나 기억할 수 있는지를 나타내는 값을 의미합니다.
- 만약에 모델이 Context Window가 2048개의 토큰이다 하면 ChatGPT는 최근 2048개의 토큰의 대화를 기억하고 이를 기반으로 새로운 응답을 생성합니다.
- 만약 Context Window의 값을 초과하면 ‘이전의 내용은 잊어버리게 됩니다’. 이는 새로운 대화를 하는 것과 같습니다.
3. ChatGPT Temperature
💡 ChatGPT Temperature
- 생성된 텍스트의 다양성을 조절하는 매개변수입니다.
1. 값이 낮을수록 일관되고 예상 가능한 답변을 제공합니다.
2. 값이 높을수록 창의적인 답변을 제공합니다.
- 기본값은 1을 가지며 0 ~ 2 사이의 값을 가집니다. 사용자의 필요에 맞게 조정하여 사용할 수 있습니다.
💡 [참고] What is Java, a programming language?라는 질문을 해봤습니다.
- Temperature 값을 0으로 준 경우 답변Java is a high-level, object-oriented programming language that is used to develop(Java는 개발에 사용되는 고급 객체 지향 프로그래밍 언어입니다.)
💡 [참고] What is Java, a programming language? 라는 질문을 해봤습니다.
- Temperature 값을 2로 준 경우 답변
- Notably founded in 1991 by billionaire super-role sculptures internet Oracle supra(1991년 억만장자 슈퍼롤 조각가 인터넷 오라클이 설립한 것으로 유명합니다.)
4) Spring Boot 개발 환경 구성
1. 개발 환경 및 디렉터리 구조
💡 개발 환경
- 해당 개발환경은 Spring Boot 기반의 Java 언어를 이용하여 Open AI로 RestTemplate 클래스를 이용하여 호출을 하여 결과 값을 받아오는 형태의 개발환경을 구축하였습니다.
- 또한 모델은 가격적인 측면을 고려하였을 때 테스트를 위한 Legacy 모델인 ‘ChatGPT-3.5 instruct’를 이용하였습니다.
개발환경 | 버전 |
JDK | Java 17 |
spring-boot | 3.2.1 |
spring-boot-starter-web | 3.2.1 |
Lombok | - |
💡 개발환경 구조
1. User → Controller
- 사용자는 API로 Prompt를 입력하여 API Call을 수행합니다
2.Controller → Service
- Controller에서 해당 엔드포인트를 받아주고 Service를 호출합니다.
3. Serivce → ServiceImpl → ChatGPT3
- ServiceImpl에서는 RestTemplate을 이용하여 ChatGPT3로 SecretKey와 함께 주요 정보를 전달합니다.
4. ChatGPT3 → ServiceImpl → Controller → User
- 처리된 응답 결과를 반환해 줍니다.
💡 디렉터리 구조
디렉터리 | 설명 |
config | 동기식 HTTPS 통신을 위한 클래스를 관리하는 디렉터리 |
controller | 클라이언트와 통신을 하여 엔드포인트를 제공하는 디렉터리 |
dto | JSON 형태로 요청 및 전달 데이터를 객체화 시키는 모델을 관리하는 디렉터리 |
service | ChatGPT를 처리하기 위해 OpenAI로 호출 및 응답을 받아오는 처리를 수행하는 디렉터리 |
resources/config | ChatGPT의 키 값을 관리하는 환경파일이 있는 디렉터리 |
2. 라이브러리 설치
dependencies {
implementation 'org.springframework.boot:spring-boot-starter-web'
compileOnly 'org.projectlombok:lombok'
annotationProcessor 'org.projectlombok:lombok'
providedRuntime 'org.springframework.boot:spring-boot-starter-tomcat'
}
3. properties 파일 구성
💡 application.properties 구성
- 공통 사용 엔드포인트 및 소스 코드 내에 키 값 노출을 피하기 위해 properties내에 secret-key를 입력하였습니다.
openai.secret-key= xxxxxxxxxx
openai.url.model=https://api.openai.com/v1/models
openai.url.model-list=https://api.openai.com/v1/models/
openai.url.legacy-prompt=https://api.openai.com/v1/completions
openai.url.prompt=https://api.openai.com/v1/chat/completions
💡 [참고] OpenAI API 중 ‘API Keys’ 탭을 누르면 아래와 같이 키 발급이 가능합니다.
https://platform.openai.com/docs/overview
5) API 환경 구성
💡 아래와 같이 구성이 되었습니다.
💡 [참고] 아래의 소스코드는 아래 Repository에서 확인이 가능합니다.
1. ChatGPT 호출 Config : ChatGptConfig
💡 ChatGPT Config
1. RestTemplate을 사용하기 위한 객체를 구성하였습니다.
2. HttpHeader에서 JWT 토큰으로 Bearer 토큰 값을 입력하여서 전송하기 위한 공통 Header를 구성하였습니다.
package com.multiflex.multiflexchatgpt.config;
import org.springframework.beans.factory.annotation.Value;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;
import org.springframework.http.HttpHeaders;
import org.springframework.http.MediaType;
import org.springframework.web.client.RestTemplate;
/**
* ChatGPT에서 사용하는 환경 구성
*
* @author : lee
* @fileName : RestTemplate
* @since : 01/18/24
*/
@Configuration
public class ChatGPTConfig {
@Value("${openai.secret-key}")
private String secretKey;
@Bean
public RestTemplate restTemplate() {
return new RestTemplate();
}
@Bean
public HttpHeaders httpHeaders() {
HttpHeaders headers = new HttpHeaders();
headers.setBearerAuth(secretKey);
headers.setContentType(MediaType.APPLICATION_JSON);
return headers;
}
}
2. DTO 구성
💡 CompletionDto 구성
- ChatGPT Legacy 모델의 Request를 위해 CompletionDto를 구성하였습니다
- 요청 값에 대해 객체로 구성하기 위한 방법으로 우선적으로 Prompt로 호출하는 DTO와 프롬프트의 다양성을 조절하는 옵션, 최대 사용 토큰에 대한 값에 대해 멤버 변수를 추가하였습니다.
package com.multiflex.multiflexchatgpt.dto;
import lombok.*;
/**
* 프롬프트 요청 DTO : gpt-3.5-turbo-instruct, babbage-002, davinci-002
*
* @author : lee
* @fileName : CompletionDto
* @since : 12/29/23
*/
@Getter
@ToString
@NoArgsConstructor(access = AccessLevel.PROTECTED)
public class CompletionDto {
// 사용할 모델
private String model;
// 사용할 프롬프트 명령어
private String prompt;
// 프롬프트의 다양성을 조절할 명령어(default : 1)
private float temperature = 1;
// 최대 사용할 토큰(default : 16)
private int max_tokens = 16;
@Builder
public CompletionDto(String model, String prompt, float temperature, int max_tokens) {
this.model = model;
this.prompt = prompt;
this.temperature = temperature;
this.max_tokens = max_tokens;
}
}
💡 ChatRequestMsgDto
- ChatGPT 신규 모델의 Request를 위해 CompletionDto를 구성하였습니다
package com.multiflex.multiflexchatgpt.dto;
import lombok.*;
/**
* Please explain the class!!
*
* @author : lee
* @fileName : ChatRequestMsgDto
* @since : 1/18/24
*/
@Getter
@ToString
@NoArgsConstructor(access = AccessLevel.PROTECTED)
public class ChatRequestMsgDto {
private String role;
private String content;
@Builder
public ChatRequestMsgDto(String role, String content) {
this.role = role;
this.content = content;
}
}
💡 ChatCompletionDto
- ChatGPT 신규 모델의 Request를 위해 CompletionDto를 구성하였습니다
package com.multiflex.multiflexchatgpt.dto;
import lombok.*;
import java.util.List;
/**
* 새로운 모델에 대한 요청 객체를 관리합니다. : gpt-4, gpt-4 turbo, gpt-3.5-turbo
*
* @author : lee
* @fileName : ChatCompletionDto
* @since : 1/18/24
*/
@Getter
@ToString
@NoArgsConstructor(access = AccessLevel.PROTECTED)
public class ChatCompletionDto {
// 사용할 모델
private String model;
private List<ChatRequestMsgDto> messages;
@Builder
public ChatCompletionDto(String model, List<ChatRequestMsgDto> messages) {
this.model = model;
this.messages = messages;
}
}
3. ChatGPTController 구성
💡 ChatGPT Controller
- 해당 글에서는 4가지 API 테스트를 진행할 예정입니다.
API Endpoint | HTTP Methods | 설명 | Open API Endpoint |
/api/v1/chatGpt/modelList | GET | OpenAPI의 사용가능한 모델 리스트를 조회하는 API | https://api.openai.com/v1/models |
/api/v1/chatGpt/model | GET | OpenAPI에서 유효한 모델인지 체크를 하는 API | https://api.openai.com/v1/models/https://api.openai.com/v1/models/{modelName} |
/api/v1/chatGpt/legacyPrompt | POST | ChatGPT 레거시 모델을 이용하여 프롬프트를 호출하는 API | https://api.openai.com/v1/completions |
/api/v1/chatGpt/prompt | POST | ChatGPT 신규 모델을 이용하여 프롬프트를 호출하는 API | https://api.openai.com/v1/chat/completions |
package com.multiflex.multiflexchatgpt.controller;
import com.multiflex.multiflexchatgpt.dto.ChatCompletionDto;
import com.multiflex.multiflexchatgpt.dto.CompletionDto;
import com.multiflex.multiflexchatgpt.service.ChatGPTService;
import lombok.extern.slf4j.Slf4j;
import org.springframework.http.HttpStatus;
import org.springframework.http.ResponseEntity;
import org.springframework.web.bind.annotation.*;
import java.util.List;
import java.util.Map;
/**
* ChatGPT API
*
* @author : lee
* @fileName : ChatGPTController
* @since : 12/29/23
*/
@Slf4j
@RestController
@RequestMapping(value = "/api/v1/chatGpt")
public class ChatGPTController {
private final ChatGPTService chatGPTService;
public ChatGPTController(ChatGPTService chatGPTService) {
this.chatGPTService = chatGPTService;
}
/**
* [API] ChatGPT 모델 리스트를 조회합니다.
*/
@GetMapping("/modelList")
public ResponseEntity<List<Map<String, Object>>> selectModelList() {
List<Map<String, Object>> result = chatGPTService.modelList();
return new ResponseEntity<>(result, HttpStatus.OK);
}
/**
* [API] ChatGPT 유효한 모델인지 조회합니다.
*
* @param modelName
* @return
*/
@GetMapping("/model")
public ResponseEntity<Map<String, Object>> isValidModel(@RequestParam(name = "modelName") String modelName) {
Map<String, Object> result = chatGPTService.isValidModel(modelName);
return new ResponseEntity<>(result, HttpStatus.OK);
}
/**
* [API] Legacy ChatGPT 프롬프트 명령을 수행합니다. : gpt-3.5-turbo-instruct, babbage-002, davinci-002
*
* @param completionDto {}
* @return ResponseEntity<Map < String, Object>>
*/
@PostMapping("/legacyPrompt")
public ResponseEntity<Map<String, Object>> selectLegacyPrompt(@RequestBody CompletionDto completionDto) {
log.debug("param :: " + completionDto.toString());
Map<String, Object> result = chatGPTService.legacyPrompt(completionDto);
return new ResponseEntity<>(result, HttpStatus.OK);
}
/**
* [API] 최신 ChatGPT 프롬프트 명령어를 수행합니다. : gpt-4, gpt-4 turbo, gpt-3.5-turbo
*
* @param chatCompletionDto
* @return
*/
@PostMapping("/prompt")
public ResponseEntity<Map<String, Object>> selectPrompt(@RequestBody ChatCompletionDto chatCompletionDto) {
log.debug("param :: " + chatCompletionDto.toString());
Map<String, Object> result = chatGPTService.prompt(chatCompletionDto);
return new ResponseEntity<>(result, HttpStatus.OK);
}
}
4. Service 구성
package com.multiflex.multiflexchatgpt.service;
import com.multiflex.multiflexchatgpt.dto.ChatCompletionDto;
import com.multiflex.multiflexchatgpt.dto.CompletionDto;
import org.springframework.stereotype.Service;
import java.util.List;
import java.util.Map;
/**
* ChatGPT 서비스 인터페이스
*
* @author : lee
* @fileName : ChatGPTService
* @since : 12/29/23
*/
@Service
public interface ChatGPTService {
List<Map<String, Object>> modelList();
Map<String, Object> isValidModel(String modelName);
Map<String, Object> legacyPrompt(CompletionDto completionDto);
Map<String, Object> prompt(ChatCompletionDto chatCompletionDto);
}
5. Service Implement 구성
package com.multiflex.multiflexchatgpt.service.impl;
import com.fasterxml.jackson.core.JsonProcessingException;
import com.fasterxml.jackson.core.type.TypeReference;
import com.fasterxml.jackson.databind.JsonMappingException;
import com.fasterxml.jackson.databind.ObjectMapper;
import com.multiflex.multiflexchatgpt.config.ChatGPTConfig;
import com.multiflex.multiflexchatgpt.dto.ChatCompletionDto;
import com.multiflex.multiflexchatgpt.dto.CompletionDto;
import com.multiflex.multiflexchatgpt.service.ChatGPTService;
import lombok.extern.slf4j.Slf4j;
import org.springframework.beans.factory.annotation.Value;
import org.springframework.http.HttpEntity;
import org.springframework.http.HttpHeaders;
import org.springframework.http.HttpMethod;
import org.springframework.http.ResponseEntity;
import org.springframework.stereotype.Service;
import java.util.HashMap;
import java.util.List;
import java.util.Map;
/**
* ChatGPT Service 구현체
*
* @author : lee
* @fileName : ChatGPTServiceImpl
* @since : 12/29/23
*/
@Slf4j
@Service
public class ChatGPTServiceImpl implements ChatGPTService {
private final ChatGPTConfig chatGPTConfig;
public ChatGPTServiceImpl(ChatGPTConfig chatGPTConfig) {
this.chatGPTConfig = chatGPTConfig;
}
@Value("${openai.url.model}")
private String modelUrl;
@Value("${openai.url.model-list}")
private String modelListUrl;
@Value("${openai.url.prompt}")
private String promptUrl;
@Value("${openai.url.legacy-prompt}")
private String legacyPromptUrl;
/**
* 사용 가능한 모델 리스트를 조회하는 비즈니스 로직
*
* @return List<Map < String, Object>>
*/
@Override
public List<Map<String, Object>> modelList() {
log.debug("[+] 모델 리스트를 조회합니다.");
List<Map<String, Object>> resultList = null;
// [STEP1] 토큰 정보가 포함된 Header를 가져옵니다.
HttpHeaders headers = chatGPTConfig.httpHeaders();
// [STEP2] 통신을 위한 RestTemplate을 구성합니다.
ResponseEntity<String> response = chatGPTConfig
.restTemplate()
.exchange(modelUrl, HttpMethod.GET, new HttpEntity<>(headers), String.class);
try {
// [STEP3] Jackson을 기반으로 응답값을 가져옵니다.
ObjectMapper om = new ObjectMapper();
Map<String, Object> data = om.readValue(response.getBody(), new TypeReference<>() {
});
// [STEP4] 응답 값을 결과값에 넣고 출력을 해봅니다.
resultList = (List<Map<String, Object>>) data.get("data");
for (Map<String, Object> object : resultList) {
log.debug("ID: " + object.get("id"));
log.debug("Object: " + object.get("object"));
log.debug("Created: " + object.get("created"));
log.debug("Owned By: " + object.get("owned_by"));
}
} catch (JsonMappingException e) {
log.debug("JsonMappingException :: " + e.getMessage());
} catch (JsonProcessingException e) {
log.debug("JsonProcessingException :: " + e.getMessage());
} catch (RuntimeException e) {
log.debug("RuntimeException :: " + e.getMessage());
}
return resultList;
}
/**
* 모델이 유효한지 확인하는 비즈니스 로직
*
* @param modelName {}
* @return Map<String, Object>
*/
@Override
public Map<String, Object> isValidModel(String modelName) {
log.debug("[+] 모델이 유효한지 조회합니다. 모델 : " + modelName);
Map<String, Object> result = new HashMap<>();
// [STEP1] 토큰 정보가 포함된 Header를 가져옵니다.
HttpHeaders headers = chatGPTConfig.httpHeaders();
// [STEP2] 통신을 위한 RestTemplate을 구성합니다.
ResponseEntity<String> response = chatGPTConfig
.restTemplate()
.exchange(modelListUrl + "/" + modelName, HttpMethod.GET, new HttpEntity<>(headers), String.class);
try {
// [STEP3] Jackson을 기반으로 응답값을 가져옵니다.
ObjectMapper om = new ObjectMapper();
result = om.readValue(response.getBody(), new TypeReference<>() {
});
} catch (JsonProcessingException e) {
log.debug("JsonMappingException :: " + e.getMessage());
} catch (RuntimeException e) {
log.debug("RuntimeException :: " + e.getMessage());
}
return result;
}
/**
* ChatGTP 프롬프트 검색
*
* @param completionDto completionDto
* @return Map<String, Object>
*/
@Override
public Map<String, Object> legacyPrompt(CompletionDto completionDto) {
log.debug("[+] 레거시 프롬프트를 수행합니다.");
// [STEP1] 토큰 정보가 포함된 Header를 가져옵니다.
HttpHeaders headers = chatGPTConfig.httpHeaders();
// [STEP5] 통신을 위한 RestTemplate을 구성합니다.
HttpEntity<CompletionDto> requestEntity = new HttpEntity<>(completionDto, headers);
ResponseEntity<String> response = chatGPTConfig
.restTemplate()
.exchange(legacyPromptUrl, HttpMethod.POST, requestEntity, String.class);
Map<String, Object> resultMap = new HashMap<>();
try {
ObjectMapper om = new ObjectMapper();
// [STEP6] String -> HashMap 역직렬화를 구성합니다.
resultMap = om.readValue(response.getBody(), new TypeReference<>() {
});
} catch (JsonProcessingException e) {
log.debug("JsonMappingException :: " + e.getMessage());
} catch (RuntimeException e) {
log.debug("RuntimeException :: " + e.getMessage());
}
return resultMap;
}
/**
* 신규 모델에 대한 프롬프트
*
* @param chatCompletionDto {}
* @return chatCompletionDto
*/
@Override
public Map<String, Object> prompt(ChatCompletionDto chatCompletionDto) {
log.debug("[+] 신규 프롬프트를 수행합니다.");
Map<String, Object> resultMap = new HashMap<>();
// [STEP1] 토큰 정보가 포함된 Header를 가져옵니다.
HttpHeaders headers = chatGPTConfig.httpHeaders();
// [STEP5] 통신을 위한 RestTemplate을 구성합니다.
HttpEntity<ChatCompletionDto> requestEntity = new HttpEntity<>(chatCompletionDto, headers);
ResponseEntity<String> response = chatGPTConfig
.restTemplate()
.exchange(promptUrl, HttpMethod.POST, requestEntity, String.class);
try {
// [STEP6] String -> HashMap 역직렬화를 구성합니다.
ObjectMapper om = new ObjectMapper();
resultMap = om.readValue(response.getBody(), new TypeReference<>() {
});
} catch (JsonProcessingException e) {
log.debug("JsonMappingException :: " + e.getMessage());
} catch (RuntimeException e) {
log.debug("RuntimeException :: " + e.getMessage());
}
return resultMap;
}
}
6) 결과 확인하기
1. 사용 가능한 모델을 조회합니다.
💡 사용 가능한 모델을 조회합니다
- Open AI에서 제공하는 API로 사용이 가능한 모델 목록들을 확인합니다.
💡 구성한 Endpoint인 [GET] /api/v1/chatGpt/modelList 호출을 하면 호출 기준 사용이 가능한 모델을 확인할 수 있습니다.
2. 유효한 모델인지 조회합니다.
💡 유효한 모델인지 조회합니다.
- Open AI에서 제공하는 API로 입력한 모델이 유효한지 여부를 조회합니다.
💡 구성한 Endpoint인 [GET] /api/v1/chatGpt/model?modelName={modelName} 호출을 하면 호출 기준 사용이 가능한 모델을 확인할 수 있습니다.
💡 Deprecated 된 ‘text-davinci-002’를 호출하면 아래와 같은 오류로 존재하지 않는 오류로 제공해주고 있습니다.
3. 레거시 모델에게 프롬프트 명령어를 입력합니다.
4. 최신 모델에게 프롬프트 명령어를 입력합니다.
오늘도 감사합니다. 😀
반응형