본문 바로가기

NestJS

NestJS에서 openAI API 연동으로 ChatGPT 활용하기

 해커톤을 하며 서비스에 ChatGPT를 활용해 보기로 결정하였다. 검색 교육 프로그램이기 때문에 다양한 답을 정답으로 인정해줘야 했기 때문이다. 언어 모델을 직접 만들어 사용하는 방법도 있었지만, 인공지능에 대해선 아는 게 없었기 때문에 ChatGPT를 활용하기로 했다.

 

 

 

 ChatGPT를 사용하려면 먼저 KEY를 발급받아야 한다

https://platform.openai.com/overview

 

OpenAI Platform

Explore developer resources, tutorials, API docs, and dynamic examples to get the most out of OpenAI's platform.

platform.openai.com

 

 

여기에 들어가서 API KEY를 발급받으면 된다. 우측 상단에 프로필을 누르고 View API keys에 들어가 Create new secret key를 누르고 발급받으면 된다. 추가로, Settings에 들어가 organization key도 가지고 있어야 한다. KEY를 확인했다면, Billing 수단을 등록하면 된다. 카드 등록을 하지 않고 API Key를 발급받으면 사용할 수 없다는 것을 알아두자. 필자가 겪은 문제이다.

 

이제 사용 준비는 끝났다.

 

 NestJS에서 openAI를 사용하려면 openai를 설치해야 한다.

 

yarn add openai

 

 

설치가 잘 되었다면, openAI를 사용할 service를 만들면 된다.

 

 

 

필자는 API키를 .env로 관리했다. 

 

openaiService 파일을 만들었다. 다음은 예시 코드이다.

// openaiService
.
.
.
.
@Injectable()
export class OpenaiService {
  constructor(
    @Inject(openaiConfig.KEY) private config: ConfigType<typeof openaiConfig>,
  ) {}

  openai: OpenAIApi = new OpenAIApi(
    new Configuration({
      organization: this.config.organization,
      apiKey: this.config.apiKey,
    }),
  );

  async scoreProblem() {
    /*
    .
    .
    .
     */
  }
}

 

 

 

위 코드처럼 openAIApi 인스턴스를 만들어 주어야 한다. 생성 시 처음에 발급받았던 키들을 넣어 주면 된다.

 

 

이제 요청을 보내기 위한 작업을 하면 된다. 아까 만든 openai 변수에서 createChatCompletion() 함수를 이용하면 요청을 보낼 수 있다. 요청을 보내기 전에 매개변수로 넣어야 하는 것들이 있다. openAI의 API reference에 들어가면 어떤 값들을 넣을 수 있는지 알 수 있다. 

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

 

OpenAI Platform

Explore developer resources, tutorials, API docs, and dynamic examples to get the most out of OpenAI's platform.

platform.openai.com

 

 

 이 중에서 필자가 사용한 것들을 표로 나타내면 다음과 같다.

model: string ChatGPT 모델 ID
messages: [] 전송할 메시지 정보
role: string 역할(user: 사용자, system: 시스템)
만약 system의 content를 teacher 라고 설정한다면, 선생님처럼 응답한다.
content: string role이 user일 때는 질문의 내용이 들어갈 수 있고, system 일 때는 역할이 들어갈 수 있다.
temperature: number 온도, 0과 2 사이로 0.8과 같은 높은 값은 응답을 더 무작위로 만들고, 0.2와 같은 낮은 값은 응답을 보다 집중적이고 결정론적으로 만든다

 

그림으로 그려 보면 다음과 같다.

openAIApi 변수의 createChatCompention() 함수를 통해 요청을 보내는 것이고, 그 안에 매개변수로 openAiChatComplentionRequest가 들어간다.

 

openAi 요청 구조

 

 

 

 

 필자는 이 옵션들을 하나하나 설정하는 게 매우 귀찮은 작업이라고 생각했고, Builder 패턴을 통해 이를 해결했다.

Builder를 통해 모든 옵션들을 set 하고 build() 함수를 통해 openAiChatComplentionRequest를 리턴 받아 요청을 보내는 방식을 택했다. 이렇게 하면 하나의 클래스만 만들고 그때그때 다른 설정을 해줄 수 있다. 코드로 보면 아래와 같다. 

 

 

CreateChatCompletionRequest Builder를 위한 클래스를 하나 만들었다.

// openAiChatCompletionRequestBuilder.ts
import { CreateChatCompletionRequest } from 'openai';

export class OpenAiChatCompletionRequestBuilder {
  private readonly openAiChatCompletionRequest: CreateChatCompletionRequest;

  constructor() {
    this.openAiChatCompletionRequest = {
      model: 'gpt-3.5-turbo',
      messages: [],
      temperature: 0.2,
    };
  }

  public setModel(model: string) {
    this.openAiChatCompletionRequest.model = model;
  }

  public setUserRole(content: string) {
    this.openAiChatCompletionRequest.messages.push({
      role: 'user',
      content: content,
    });
  }

  public setSystemRole(content: string) {
    this.openAiChatCompletionRequest.messages.push({
      role: 'system',
      content: content,
    });
  }

  public setTemperature(temperature: number) {
    this.openAiChatCompletionRequest.temperature = temperature;
  }

  public build(): CreateChatCompletionRequest {
    return this.openAiChatCompletionRequest;
  }
}

 

 set 함수를 통해 옵션을 정할 수 있고, build를 하면 정해진 옵션을 반환한다.

 

 

 

 

이제 요청을 보내면 된다. 다시 openAIService로 돌아가 보자

 

// openaiService
@Injectable()
export class OpenaiService {
  constructor(
    @Inject(openaiConfig.KEY) private config: ConfigType<typeof openaiConfig>,
  ) {}

  openai: OpenAIApi = new OpenAIApi(
    new Configuration({
      organization: this.config.organization,
      apiKey: this.config.apiKey,
    }),
  );

  async testRequest() {
    const openAiChatCompletionRequestBuilder: OpenAiChatCompletionRequestBuilder =
      new OpenAiChatCompletionRequestBuilder();
    openAiChatCompletionRequestBuilder.setUserRole('hello?');
    openAiChatCompletionRequestBuilder.setSystemRole('you are a teacher');
    const response = await this.openai.createChatCompletion(
      openAiChatCompletionRequestBuilder.build(),
    );
    console.log(response.data.choices[0].message.content);
  }
}

 

 

방금 만든 Builder를 통해 손쉽게 요청을 보내 보았다.

 

'NestJS' 카테고리의 다른 글

Role을 통한 User 인가  (0) 2023.09.24
CORS, credentials  (0) 2023.08.30
Throttler를 사용한 Rate Limiting  (0) 2023.08.24
Provider  (0) 2023.07.24
Controller  (0) 2023.07.20