토이 프로젝트 - GPT API (1)

gigi·2023년 4월 26일
1

gpt API를 이용해서 뭔가 만들어 볼 수 없을까 찾아보다가 gpt가 문장의 긍정적 부정적인 판단이 가능하다는것에 대해 알았다. 엄청 짧은 문장이나 단어뿐만 아니라 좀 더 길고 일상적인 문법에서 전체 내용이 얼마나 긍정적인지 부정적인지 수치상으로 파악할 수 있을까 궁금했다. 테스트 해보기 좋은 음식점 리뷰를 먼저 chat gpt에 돌려봤다.

매장 굉장히 깨끗했고 좋은 분위기에서 식사했습니다. 메뉴는 조금 낯선 감은 있었지만 맛있게 잘 먹었습니다.

실제로 어느 식당의 한 이용자의 리뷰이고 그 이용자는 별점 4점을 주었다. 전체적으로 좋은평의 리뷰이지만 메뉴가 조금 낯선 감이 있었다고 하니 4점 정도의 별점이 납득이 간다.

다만, 이라는 부분부터 조금 불안하긴하지만 잘 파악한것같다. 이정도면 될거같다.

일단 gpt에 대한 사전 조사를 해본 결과

  • gpt api 무료 크레딧이 5달러밖에 안된다는 점
  • 한글이 영어보다 한글자당 token을 많이 잡아먹는다는 점
  • fine-tuning으로 좀 더 똑똑하게 만들 수 있을까라는 생각이 들었는데 fine-tuning은 1000 토큰당 가격이 상당히 나간다는 점
  • fine-tuning(davinci) > text-davinci-003 > gtp-3.5-turbo 순으로 비싸다

어느정도의 텍스트를 보냈을때 얼마만큼의 토큰이 들지 가늠하기 힘들었고, 몇번의 테스트를 거치게 될지 알 수 없었기때문에 가격이 문제였다. 일단 더 긴 문장까지는 가지말고 음식점 리뷰정도의 텍스트 길이가 좋겠다고 생각하고 리뷰를 작성하면 gpt가 자동으로 그에맞는 별점을 매겨주는 시스템으로 프로젝트를 만들어 보기로 했다.

( 아직 수정할 부분이 좀 더 있지만 현재 배포중인 주소이다 https://www.autoratingai.shop)


map API를 이용해 가게들의 리뷰 데이터를 가지고 있어야 이전에 남긴 리뷰들을 보여줄 수 있겠다 생각하고 미리 server를 간단하게 만들기로 했다.

// server/index.js
const OpenAI = require("openai");
const { Configuration, OpenAIApi } = OpenAI;
const axios = require("axios");
const express = require("express");
const bodyParser = require("body-parser");
const cors = require("cors");
const app = express();
const port = 5001;
const GPT_KEY = "my api key"

const configuration = new Configuration({
  organization: "org-N5YhVJchrFKSEZu1kn1CQPsu",
  apiKey: GPT_KEY,
});

const openai = new OpenAIApi(configuration);

app.use(bodyParser.json());
app.use(cors());


app.post("/", async (req, res) => {
  const { message } = req.body;
  const question = `너는 음식점 소비자야 너는 가게에 다음과같은 리뷰를 남겼어 ${message} 점수는 1점이상 5점이하중에 몇점을 줬을까? 점수 : 몇점, 이유: ~입니다 라고 대답해`;
  const response = await axios.post(
      "https://api.openai.com/v1/chat/completions",
      {
        model: "gpt-3.5-turbo",
        messages: [{ role: "user", content: question }],
        temperature: 0.6,
      },
      {
        headers: {
          "Content-Type": "application/json",
          Authorization: `Bearer ${GPT_KEY}`,
        },
      }
    );

    const response2 = await openai.createCompletion({
      model: "text-davinci-003",
      prompt: question,
      max_tokens: 2048,
      temperature: 0.6,
    });

    if (response2.data) {
      if (response2.data.choices) {
        res.json({
          turbo: response.data.choices[0].message.content,
          davinci: response2.data.choices[0].text,
        });
      }
    }
  } catch (error) {
    console.error(error);
  }
})


app.listen(port, () => {
  console.log("Example app port: " + port);
});
server 디렉토리에서 node index.js로 서버 실행 후 클라이언트에서 post 요청을 보냈다.

GPT API 사용하기

axios로 호출하는 방법도 있고 openai 라이브러리를 설치해서 사용하는 방법이 있는데 이상하게 gpt-3.5-turbo 모델은 openai 라이브러리로 구현이 안돼서 axios를 이용해 통신했다.
둘다 방법은 쉽다.

text-davinci-003


const OpenAI = require("openai");
const { Configuration, OpenAIApi } = OpenAI;
const GPT_KEY = "my api key"

const configuration = new Configuration({
  organization: "org-N5YhVJchrFKSEZu1kn1CQPsu",
  apiKey: GPT_KEY,
});

const openai = new OpenAIApi(configuration);

 const response2 = await openai.createCompletion({
      model: "text-davinci-003",
      prompt: question,
      max_tokens: 2048,
      temperature: 0.6,
 });

openai 라이브러리를 설치해서 호출하는 방법이다. text-davinci-003은 model만 필수라고 나온다. prompt는 선택사항인데 일단 뭔가 답변을 받을 메세지를 보내야하기 때문에 필수항목이라고 보면 될거같다. string과 array 타입이 다 된다고 나오는데

const myArray = ["오늘은", "날씨가", "매우", "덥습니다."];
const prompt = myArray;

이 경우, prompt에 전달되는 값은 ["오늘은", "날씨가", "매우", "덥습니다."]가 아니라, 배열의 요소들이 공백으로 구분된 문자열인 "오늘은 날씨가 매우 덥습니다."가 된다고 한다.


gpt-3.5-turbo

  const response = await axios.post(
      "https://api.openai.com/v1/chat/completions",
      {
        model: "gpt-3.5-turbo",
        messages: [{ role: "user", content: question }],
        temperature: 0.6,
      },
      {
        headers: {
          "Content-Type": "application/json",
          Authorization: `Bearer ${GPT_KEY}`,
        },
      }
    );

헤더에 gpt 홈페이지에서 발급받은 api 키를 넣어주고 바디에는 model, messages, temperature 을 넣어주면 된다. model, messages는 필수 항목이고 temperature은 선택 항목이다. 그외에도 선택항목은 다양하게 있다. https://platform.openai.com/docs/api-reference/chat/create (_여기서 확인)


gpt-3.5-turbo 의 경우 대화형 모델이기 때문에 messages에는 배열 형식으로 role이 부여된다.

messages=[
        {"role": "system", "content": "You are a helpful assistant."},
        {"role": "user", "content": "Who won the world series in 2020?"},
        {"role": "assistant", "content": "The Los Angeles Dodgers won the World Series in 2020."},
        {"role": "user", "content": "Where was it played?"}
    ]

예시로는 이렇다.
일반적으로 대화는 먼저 시스템 메시지로 형식화되고 그 다음에 user 및 assistant 메시지가 번갈아 표시된다. 대화 기록을 포함하면 user의 content를 전달할때, 이전 메시지를 참조하는데 있어 도움이 된다.

위의 예에서 Where was it played? 라는 user의 마지막 질문은 2020년 월드 시리즈에 대한 이전 메시지의 맥락이 있어야 의미가 있다.

어디서 경기가 펼쳐졌는지에 대한 물음에 이전 대화 맥락을 알고있기 때문에 좌측의 gpt-3.5-turbo 모델은 월드시리즈가 어디서 경기했는지 답변을 해주고, 우측의 text-davinci-003 모델은 최초의 월드컵 이야기를 한다.

나같은경우 대화를 이어나가는것이 아닌 text-davinci-003 모델과 같은 수준의 단일 답변만 필요했기 때문에 messages에 user role만 전달한다.


[gpt-3.5-turbo] vs [text-davinci-003]

좌 : gpt-3.5-turbo ------------------ 우 : text-davinci-003

테스트1

테스트2

(두 리뷰 다 아쉬운 부분을 언급한점을 파악해 별점 1점씩 내린 부분이 신기하다)
이외에도 테스트를 많이 해봤지만 같은 요청에 답변의 퀄리티가 gpt-3.5-turbo가 대체로 마음에 들었다.

다만, gpt-3.5-turbo는 fine-tuning을 지원하지 않는다고 나와있다. fine-tuning을 하려면 davinci 모델을 기반으로 training 해야 하는데 일단은 기본 제공되는 모델도 충분히 재밌게 써먹을 수 있다고 생각해 프로젝트를 만들어보고 fine-tuning은 따로 테스트 해보는 방식으로 프로젝트를 진행했다.

0개의 댓글