[nest.js] openAi 연결하기

이얏호·2023년 8월 29일
0

오늘은 nest.js에서 openAi 사용에 대해서 적어보려고 한다.

우선 구조부터 말하자면
클라이언트에서 메세지 작성 -> 서버에 post요청 -> 메세지 형태 가공 -> openAi로 메세지 전송 -> 반환 받은 값 클라이언트로 전달
이 되겠다.


messages.controller.ts

import { Controller, Post, Body } from '@nestjs/common';
import { AiService } from 'src/ai/ai.service';
import { MessagesService } from './messages.service';

@Controller('messages')
export class MessagesController {
  constructor(
    private readonly aiService: AiService,
    private readonly messagesService: MessagesService,
  ) {}

  @Post()
  async createMessage(@Body() content: { message: string }) {
    const message = this.messagesService.createMessage(content);
    const msg = await this.aiService.chat(message);
    return msg;
  }
}

body 데이터로 넘어온 값을 messagesService의 createMessage() 메서드로 전달하여 메세지의 형태를 가공한다.

이후 가공된 메세지를 aiService의 chat() 메서드로 보낸 뒤, 반환 값을 클라이언트에 전송한다.


messages.service.ts

import { Injectable } from '@nestjs/common';

@Injectable()
export class MessagesService {
  createMessage(content: { message: string }) {
    const message = [{ role: 'user', content: content.message }];
    return message;
  }
}

클라이언트에서 전송받은 메세지의 형태를 가공하는데, 다음과 같이 role과 content로 분리되어져 있다.
이 부분은 openAi 학습과 관련된 내용인데, 다음에 적어보도록 할 예정이다.


ai.service.ts

import { Injectable } from '@nestjs/common';
import OpenAI from 'openai';
import { ConfigService } from '@nestjs/config';

@Injectable()
export class AiService {
  private readonly openai: OpenAI;
  constructor(private readonly configService: ConfigService) {
    this.openai = new OpenAI({
      apiKey: this.configService.get('OPENAI_API_KEY'),
    });
  }

  async chat(message: any) {
    const chatCompletion = await this.openai.chat.completions.create({
      messages: message,
      model: this.configService.get('OPENAI_API_MODEL'),
    });
    return chatCompletion.choices[0].message.content;
  }
}

OpenAI를 통해서 자신의 openAi 계정과 연결한다.
여기서 키 값은 ConfigService를 사용하여 .env로 관리하도록 한다.

추가적으로 주의 사항이 있는데,
이 코드에서 사용한 openai의 버전은 4.2.0 버전이다.

npm i openai@4.2.0

버전이 정말 중요한데,
연결을 시도하기 위해서 찾아봤던 글들의 대부분이 이 코드와 연결 방식이 달랐는데,
문제가 바로 버전에 있었다.
기존 openAi의 chat-GPT 3버전의 경우 openai 3.2.1버전으로 연동을 하니 잘 작동했었는데,
연결 방식도 좀 다르고, gpt-3.5-터보의 경우 잘 작동하지도 않았다.

그래서 버전이 매우 중요하다는 점... 기억해야한다.

(GPT-3.5 세대가 아닌 3세대를 사용하고자 한다면, 다른 글을 참조하길 바랍니다! openai 3.2.1버전으로 하니 잘 작동했었습니다. 코드는 따로 첨부하지 않습니다.)

위에서 .env 파일에 키값과 모델명을 기재해주고 연결하면 성공!

메세지 서비스에서 가공된 메세지 형식으로 openAi에 요청을 보낸 후, 해당 값을 반환한다.


자료를 찾는데에 시간이 걸렸지
(gpt-3버전 자료가 많았다. 버전 이슈로 한참 헤맸었고, 원인을 파악 한 후에는 nest.js자료는 거의 없어서 node나 js 자료를 찾아서 변형시켰다.)
코드 자체는 간단했다.

다만 여기서 ai를 자신의 입맛대로 학습을 시키는 과정이 필요하다.
(물론 gpt를 있는 그자체로 사용한다면 문제가 없다.)

다만, 팀 프로젝트에 쓰일 고객센터 겸용 챗봇을 만들어야 했기 때문에 학습에 대한 필요성이 존재했다.

찾아본 방법은 크게 두 가지로 나뉘었는데,
하나는 체인 방법, 다른 하나는 fine-tune 방법이 있었다.

체인은 기존의 대화내용들을 연결하여 전송함으로써, gpt와의 대화가 이어지는 듯한 느낌을 줄 수 있다.
(모델에 따라서 멍청하기도 하지만 실제로 이어지기도 한다.)

다만, 프로젝트에 필요한건, 고객과의 대화 누적 개념보다, 특정 키워드나 상황에 대한 ai의 페이지를 대변할 수 있는 일관적인 답변이 필요하여, fine-tune 쪽으로 시선을 돌리게 되었다.

profile
열심히 신나게 화이팅!

0개의 댓글