java / / 2023. 4. 6. 14:07

java로 chatgpt api 만들어보기

java를 사용하여 chatgpt api를 사용하는 방법을 알아보자.

chatgpt api 사용하는 방법은 생각보다 어렵지 않다. 다른 외부 api 사용하는 것과 동일하며 특정 api에 요청을 보내고 응답을 받으면 된다. 물론 api를 사용하기 전에 필요한 api key를 발급을 받아야 한다.

이런 과정을 차례대로 아주 단순한 방법으로 한번 해보도록 하자.

인증 키 발급

우선 chatgpt api를 사용하기 위해서는 인증키가 있어야 한다.
아래 URL로 접속해서 인증키를 발급받자. (로그인 필요)

여기서 발급 받은 인증키를 복사해두자.

프로젝트 구성

java로 api를 사용하기 위한 프로젝트 구성은 아래와 같이 진행한다.

  • http tool: intellij http
  • Java version : 17
  • build tool: maven

API 사전 테스트

우선 위에서 발급받은 인증키로 api가 잘 동작하는 지 확인하자.
여기서는 intellij의 http를 사용하였는데, 다른 툴을 사용해도 무관하다. (Postman 등)

chatgpt의 질의를 하려면 completion api를 사용해서 응답을 받을 수 있다. Completion API에 대한 설명은 아래 링크를 참고하자.

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


아래에서 <인증키> 부분을 위에서 발급받은 api key로 변경하고 실행해보자.

POST https://api.openai.com/v1/completions
Content-Type: application/json
Authorization: Bearer <인증키>

{
  "model": "text-davinci-001",
  "prompt": "1+1은 몇이야?",
  "temperature": 1,
  "max_tokens": 10
}
GPT-3 model

여기서 model은 GPT-3를 실행할 때 어떤 모델을 사용할 것인가를 선택하는 것인데 여기서는 davinci를 사용하였다.

  • text-davinci-001: 가장 유능한 GPT-3 모델. 다른 모델이 할 수 있는 모든 작업을 종종 더 높은 품질로 수행할 수 있습니다.
  • text-curie-001: Davinci보다 매우 유능하고 빠르며 비용이 저렴합니다.
  • text-babbage-001: 매우 간단한 작업이 가능하며 일반적으로 GPT-3 시리즈에서 가장 빠른 모델이며 가장 저렴합니다.
  • text-ada-001 : 매우 간단한 작업이 가능하고, GPT-3 시리즈에서 가장 빠른 모델이며 cost가 가장 낮다.

위의 코드를 실행하면 다음과 같은 결과가 나타나면 정상적으로 실행이 된 것이다.

응답결과
{
  "id": "cmpl-72BsQ5QCg9qW1lL36EtQq8baJhkPt",
  "object": "text_completion",
  "created": 1680756666,
  "model": "text-davinci-001",
  "choices": [
    {
      "text": "\n\n2",
      "index": 0,
      "logprobs": null,
      "finish_reason": "stop"
    }
  ],
  "usage": {
    "prompt_tokens": 14,
    "completion_tokens": 3,
    "total_tokens": 17
  }
}

API 개발

이제 maven으로 API를 개발해보자.

아래와 같이 api에 필요한 의존성을 추가하자. (데이터 바인딩이 필요하므로 jackson을 추가)

pom.xml
<properties>
    <jackson.version>2.14.2</jackson.version>
</properties>

<dependencies>
    <dependency>
        <groupId>com.fasterxml.jackson.core</groupId>
        <artifactId>jackson-core</artifactId>
        <version>${jackson.version}</version>
    </dependency>
    <dependency>
        <groupId>com.fasterxml.jackson.core</groupId>
        <artifactId>jackson-annotations</artifactId>
        <version>${jackson.version}</version>
    </dependency>
    <dependency>
        <groupId>com.fasterxml.jackson.core</groupId>
        <artifactId>jackson-databind</artifactId>
        <version>${jackson.version}</version>
    </dependency>
</dependencies>

다음은 간단하게 command line으로 실행할 수 있도록 클래스를 하나 만들었다.

특정 URL을 HttpRequest로 요청하고 응답결과를 출력하는 로직이다.

GptTest
public class GptTest {

    public static void main(String[] args) throws IOException, InterruptedException {
        String prompt;
        if (args.length > 0) {
            prompt = args[0];
        } else {
            Scanner scanner = new Scanner(System.in);
            System.out.println("Enter a string to search for: ");
            prompt = scanner.nextLine();
        }

        ObjectMapper mapper = new ObjectMapper();
        ChatGptRequest chatGptRequest = new ChatGptRequest("text-davinci-001", prompt, 1, 100);
        String input = mapper.writeValueAsString(chatGptRequest);

        HttpRequest request = HttpRequest.newBuilder()
            .uri(URI.create("https://api.openai.com/v1/completions"))
            .header("Content-Type", "application/json")
            .header("Authorization", "Bearer <API Key>")
            .POST(HttpRequest.BodyPublishers.ofString(input))
            .build();

        HttpClient client = HttpClient.newHttpClient();
        var response = client.send(request, HttpResponse.BodyHandlers.ofString());

        if (response.statusCode() == 200) {
            ChatGptResponse chatGptResponse = mapper.readValue(response.body(), ChatGptResponse.class);
            String answer = chatGptResponse.choices()[chatGptResponse.choices().length-1].text();
            if (!answer.isEmpty()) {
                System.out.println(answer.replace("\n", "").trim());
            }
        } else {
            System.out.println(response.statusCode());
            System.out.println(response.body());
        }
    }
}

여기서는 ChatGptRequest, ChatGptResponse 등은 java 14에서 지원하는 레코드(record)를 사용하였다. record를 사용하게 되면 getter, setter와 같은 불필요한 보일러플레이트 코드는 필요하지 않다.

물론 java 8, 11 등을 사용할 때는 record 대신 class로 만들어서 사용하면 된다. 단, getter, setter가 필요할 수 있으니 참고하자.

public record ChatGptRequest(String model, String prompt, int temperature, int max_tokens) {
}
public record ChatGptResponse(
    String id,
    String object,
    int created,
    String model,
    ChatGptResponseChoice[] choices,
    ChatGptResponseUsage usage
) {
}
public record ChatGptResponseChoice(
    String text,
    int index,
    Object logprobs,
    String finish_reason
) {
}
public record ChatGptResponseUsage(
    int prompt_tokens,
    int completion_tokens,
    int total_tokens
) {
}
실행결과

위의 코드를 실행하면 아래와 같은 결과가 출력된다. 물론 다른 응답 결과가 나올 수 있다. chatgpt는 질의할 때마다 다른 결과를 출력할 수 있다는 것을 염두에 둬야 한다.

Enter a string to search for: 
1:1은 몇이야?
One to one is equal to two.

위와 같이 별로 어렵지 않게 chatgpt java api 코드를 작성할 수 있는 것 같다. chatgpt api를 사용하는 방법은 간단하지만 chatgpt가 상황에 맞는 응답을 적절하게 하는 원리는 엄청 복잡할 것 같다. 나중에 시간되면 좀 더 많은 기능을 활용해봐야겠다.

반응형
  • 네이버 블로그 공유
  • 네이버 밴드 공유
  • 페이스북 공유
  • 카카오스토리 공유