기억의 저장소

프로젝트 Chat gpt 사용기(feat: Spring) 본문

카테고리 없음

프로젝트 Chat gpt 사용기(feat: Spring)

JuSeong1130 2023. 8. 9. 20:16

프로젝트를 주제를 정하던 중 gpt를 이용한 답변 서비스를 만들자는 기획이 나오게 되었다. 

이 주제에 맞게 gpt를 사용해야 했으므로 gpt를 사용하는방법과 사용하면서 겪은 문제에 대해 정리해 보려한다.

gpt에는 정말 다양한 모델이 있는데 이미지를 만들기위한것 텍스트 등등이 존재합니다.

 

 

API key 발급 받기

https://platform.openai.com/account/api-keys

맨 처음은  key를 발급받아야한다 . GPT API를 사용할때 인증된 사용자인지 판별하기 위해 Key가 필요하므로 발급받아야한다. 

 

Chat gpt는 2023-08-09 현재 작성 기준으로는 5달러의 무료 크레딧을 줍니다. 그런데 만약 이미 전부터 gpt를 사용하고 있던 사용자라면 크레딧이 이미 만료되었을 확률이 아주 높습니다. GPT를 가입한날부터 바로 크레딧이 제공되어 기간이 지나가므로 만약 크레딧 기간이 만료 됬다면 카드를 등록해야지 API를 이용할 수 있습니다.

(저는 만료된지 모르고 진행하다가 retrofit2.adapter.rxjava2.HttpException: HTTP 429이런 오류가 발생하여 제가 쓴 코드가 잘못된줄알구 1시간 동안 찾아보다가 만료된걸 찾아 카드를 등록해주었네요.. 이글을 읽는 분은 이런 실수를 안했음 하는마음으로 적어봅니다. )

 

무료크레딧은 아래에서 확인이 가능합니다.

https://platform.openai.com/account/usage

 

발급 받는 방법 자세히 나와있는곳 https://www.daleseo.com/chatgpt-api-keys/

 

GPT에서 제공해주는API Erros를 확인할 수 있는곳입니다.

https://platform.openai.com/docs/guides/error-codes/api-errors

 

API 비용

내 신용카드를 등록했으니 비용에 당연히 신경써야한다. 테스트할때마다 사용료가 나가므로 비용을 생각해야되고 비용을 줄일 방법도 생각해야한다.

 

https://openai.com/pricing  해당 링크를 들어가보면 모델별 비용을 알 수 있다.

그리고 비용이 나가는것은 토큰이라는 기준인데

https://platform.openai.com/docs/guides/production-best-practices/text-generation 해당링크를 들어가보면 

OpenAI 는 1,000개 토큰(대략 750단어에 해당)이라 설명하고 있다. 

더 작은 모델로 전환하거나 필요한 토큰수를 줄이는 방법등으로 비용을 줄이라고 설명하고 있다.

또한 https://platform.openai.com/tokenizer 이것을 통해 몇개의 토큰일지 판단할 수 있는것을 제공합니다.

 

 

GPT 모델 정하기

현재 사용가능한 GPT 모델은 아래에서 확인 할 수 있습니다.

https://platform.openai.com/docs/models

 

저는 여러가지 모델이 있지만 대화형으로 진행하지 않으므로 Completion으로 진행하려 하였습니다.(text-davinci-003 모델)

그런데 postman으로 테스트 중 아래와 같은 waring이 발생하는것을 발견하게 되었고 Completion인것은 모두 Legacy이므로 Chat Completion으로 진행하는게 좋다 생각이들어 진행하게 되었습니다.

참고로 https://platform.openai.com/docs/api-reference/models 여기서 제공되는 api로 어떤 모델이 제공되는지도 확인이 가능합니다.

"warning": "This model version is deprecated. Migrate before January 4, 2024 to avoid disruption of service.
Learn more https://platform.openai.com/docs/deprecations",

 

Chat Completion 모델을 정하다가 https://platform.openai.com/docs/api-reference/chat/create 여기에 Example에 있는 gpt-3.5-turbo로 진행하기로 하였습니다. (GPT-4도 있었지만 현재 사람들이 많이 사용한다 생각된 gpt-3.5를 선택하게 되었습니다.)

현재 어떤 모델을 지원하는지 https://platform.openai.com/docs/models 여기서도 확인이 가능합니다.

 

 

의존성 주입받기

설명에 앞서 현재 사용중인 버전은 Srping boot 2.7.13으로 진행하니 참고 부탁드립니다.

 

GPT모델도 정했고 했으니 직접 프로젝트에 적용을 해봐야할거 같습니다. OpenAI에서는 Java에서 손쉽게 OpenAI 서비스를 이용할 수 있게 라이브러리를 제공합니다. (물론 라이브러리를 이용하지않고 api콜을 보내는것을 구현해도됩니다.)

 

GPT 사용 라이브러리

https://platform.openai.com/docs/libraries

위 주소를 들어가보면 OpenAI에서 공식적으로 JAVA라이브러리 주소를 올려놨습니다.

해당 주소는 https://github.com/TheoKanning/openai-java  여기입니다.

 

프로젝트에 적용할때는 release 버전을 보고 적용하면되는데 github에 들어가 오른쪽에 보다보면 아래와 같은 현재의 최신버전을 볼 수있습니다.

프로젝트에는 아래와 같이 의존성을 추가해주면 됩니다. 

implementation 'com.theokanning.openai-gpt3-java:service:0.15.0'
implementation 'com.squareup.retrofit2:retrofit:2.7.2'

(1번째 api, service,client가 있었지만 service를 택한것은 부록 1번 설명에 있습니다. 2번쨰 추가해준것은 부록 2번 설명에 있습니다.)

 

이렇게 의존성을 추가해주게되면 OpenAiService를 이용하여 간편하게 GPT에게 API콜을 할 수 있게됩니다.

import com.theokanning.openai.service.OpenAiService;

 

 

구현하기

의존성 주입이 완료된다면 아래와 같은 클래스를 사용할 수 있게됩니다. 이를 이용해 간단하고 간편하게 구현이 가능합니다.

public class OpenAiService

 

첫번째로 OpenAiService객체를 만들어야합니다. 생성자를 통해 생성하며 token은 발급받은 API key를 말합니다.

public OpenAiService(final String token) {
        this(token, DEFAULT_TIMEOUT);
    }

https://platform.openai.com/docs/api-reference이곳에 접속하게되면 사용할 수 있는 api들이 있습니다.

 

제가사용할것은 Chat Completion입니다. https://platform.openai.com/docs/api-reference/chat/create

위의 주소로가면 아래와 같은 모습을 볼 수 있습니다.  API 요청을 보낼때 model,messages등의 파라미터가 있으며 Required는 꼭 파라미터 값에 추가해서 보내야합니다. 값을 넣지 않으면 404에러등이 나게됩니다.(Chat모델인데 text-davinci-003을 썻다가 404에러가 났다 이후 gpt-3.5-turbo로 바꾸니 제대로 작동했다.)

 

curl https://api.openai.com/v1/chat/completions

그럼 위 해당 주소로 필요한 파라미터를 가지고 요청을 보내면될텐데 어떻게 하면될까요?

물론 직접 restTemplate등을 이용해서 구현해도 가능합니다. 하지만 OpenAiService라는 객체에 제공되는 api들을 간편하게 사용할 수있도록 아래와 같은 메서드를 생성해 놓았습니다. 저는 OpenAiService 이용하여 간편하게 구현하였습니다.

 public ChatCompletionResult createChatCompletion(ChatCompletionRequest request) {
        return execute(api.createChatCompletion(request));
    }
    
 public Flowable<ChatCompletionChunk> streamChatCompletion(ChatCompletionRequest request) {
        request.setStream(true);

        return stream(api.createChatCompletionStream(request), ChatCompletionChunk.class);
    }
 
image 관련
public ImageResult createImage(CreateImageRequest request) {
        return execute(api.createImage(request));
    }

 

요청을 보내기 위해 아래와 같은 메서드를 만들어 ChatCompletionRequest객체를 생성하였고 이후 createChatCompletion메서드에 파라미터로 넘겨주기만 하면 ChatCompletionResult라는 결과를 손쉽게 얻을 수 있게 됩니다. 

public ChatCompletionRequest getStreamCompletionRequest(RequestCompletionMessageDto completionMessageDto) {
		return ChatCompletionRequest.builder()
				.model(model)
				.messages(createChatMessage(completionMessageDto.getPrompt()))
				.maxTokens(1000)
				.stream(true)
				.build();
	}
	public List<ChatMessage> createChatMessage(String content) {
		List<ChatMessage> chatMessages = new ArrayList<>();
		chatMessages.add(new ChatMessage("user",content));
		return chatMessages;
	}

 

 

동작 

ChatCompletionResult라는결과를 손쉽게 얻어냈지만 어떻게 동작되는지 궁금해져 동작되는방식을 정리해보고자합니다.

RxJava 이용해서 구현함..

 

 

 

 

 

 

여기서부터는 chat으로 바꾸고 streaming까지 해보고 정리하기

 

 

참고

라이브러리 안쓰고 RestTemplate 써서 직접 구현한것

https://firstws.tistory.com/64

https://www.baeldung.com/spring-boot-chatgpt-api-openai

 

요금줄이기 

https://velog.io/@noh0907/ChatGPT-API-Token-Limit-%ED%95%B4%EA%B2%B0%ED%95%98%EA%B8%B0-%EC%9A%94%EA%B8%88-%EC%A4%84%EC%9D%B4%EA%B8%B0

 

그냥 참고

https://akku-dev.tistory.com/52

 

다른라이브써서 구현한거

https://velog.io/@msung99/ChatGPT-SpringBoot-%EC%8A%A4%ED%94%84%EB%A7%81%EB%B6%80%ED%8A%B8-%EC%95%A0%ED%94%8C%EB%A6%AC%EC%BC%80%EC%9D%B4%EC%85%98%EC%97%90%EC%84%9C-OpenAI-%EB%A5%BC-%EC%A0%81%EC%9A%A9%ED%95%B4-AI-%EC%B1%84%ED%8C%85-%EC%84%9C%EB%B9%84%EC%8A%A4-%EA%B0%9C%EB%B0%9C%ED%95%98%EA%B8%B0

 

gpt가 할 수 있는일,모델

https://effortguy.tistory.com/237

https://brunch.co.kr/@amirjung/99

부록

1. api service client

github에 들어가보면 아래와 같이 의존성을 추가하도록 되어있다.
implementation 'com.theokanning.openai-gpt3-java:<api|client|service>:<version>'

GPT에게 물어보니 아래와 같은 답변을 얻게되었다.  설명을 들어봐도 잘 모르겠어 가장 간단한 방법이라는 Service를 택하게 되었다
api: 이 부분은 OpenAI의 GPT 모델을 사용하는 데 필요한 API 요청 및 응답을 다루기 위한 클래스들을 포함합니다. POJOs(Plain Old Java Objects)는 간단한 자바 객체를 말하며, 이 부분에서는 API 요청과 응답을 표현하는데 사용됩니다.

client: GPT 엔드포인트를 호출하기 위한 기본적인 Retrofit 클라이언트가 포함되어 있습니다. Retrofit은 HTTP API 호출을 관리하고 처리하는 라이브러리입니다. 이 모듈은 api 모듈을 포함하고 있어, GPT API를 호출하는 데 필요한 데이터 모델과 요청을 생성하고 응답을 처리합니다.

service: 이 부분은 클라이언트를 생성하고 사용하는 기본적인 서비스 클래스입니다. 이 클래스는 GPT API 클라이언트를 생성하고 호출하는 역할을 합니다. 이는 GPT 모델을 사용하는 가장 간단한 방법 중 하나입니다.

이렇게 구성된 모듈들은 OpenAI의 GPT API를 쉽게 활용하기 위한 코드 및 구조를 제공합니다. 이러한 구성 요소들을 사용하여 OpenAI GPT 모델과 상호 작용할 수 있습니다.

API (Application Programming Interface):
API는 다른 소프트웨어 컴포넌트가 특정 서비스 또는 기능을 사용하기 위해 사용할 수 있는 인터페이스를 제공하는 것을 의미합니다. OpenAI GPT의 경우, "API" 모듈은 GPT 모델과 상호 작용하기 위한 요청(request)과 응답(response)을 정의하는 자바 클래스들로 구성됩니다. 이 클래스들은 GPT 모델을 호출하는 데 필요한 데이터 구조를 정의하고, 요청을 생성하며, 응답을 처리하는 역할을 합니다.

클라이언트 (Client):
클라이언트는 서버나 원격 서비스에 연결하여 해당 서비스를 사용할 수 있도록 도와주는 소프트웨어입니다. OpenAI GPT의 "클라이언트" 모듈은 GPT API 엔드포인트에 HTTP 요청을 보내고, 응답을 받아오는 역할을 담당합니다. 주로 HTTP 통신을 추상화하고, 요청 및 응답을 처리하는 로직을 포함하고 있습니다. 클라이언트는 API 모듈을 활용하여 실제 API 요청을 만들어내고 처리합니다.

서비스 (Service):
서비스는 특정 기능이나 업무를 수행하기 위한 코드 블록 또는 모듈을 나타냅니다. OpenAI GPT의 "서비스" 모듈은 일반적으로 클라이언트를 생성하고 API를 호출하는 역할을 수행합니다. 이는 보다 높은 추상화 수준에서 API를 사용하는 방법을 제공합니다. 즉, 서비스 클래스는 클라이언트를 사용하여 실제 API 호출을 처리하고, 이를 더 편리하게 사용할 수 있는 인터페이스를 제공합니다.

요약하자면, API 모듈은 데이터의 형식과 통신 규약을 정의하며, 클라이언트 모듈은 HTTP 통신 및 데이터 처리 로직을 담당하며, 서비스 모듈은 클라이언트를 더 편리하게 사용할 수 있는 인터페이스를 제공하는 역할을 합니다.

 

2. Retrofit waring

두번째에있는것은 원래 추가안해줘도되지만 아래와 같은 waring이 떠서 넣어주게되었다.

https://stackoverflow.com/questions/60915381/retrofit2-maven-project-illegal-reflective-access-warning

 

이유를 찾다보니 자바 9버전부터 생긴 모듈 시스템에서는 자바의 핵심 클래스에 대한 접근 제어를 막도록 제어하는데,해당 라이브러리가 이 부분을 고려하지 않아서 발생한 경고문이라고 한다.

https://pgmjun.tistory.com/86