들어가며
이미 많은 개발자들이 알고, 사용해보고 있을 ChatGPT. Open AI에서 만든 ChatGPT는 API로도 사용이 가능하다.
모델마다 토큰 당 가격에 일부 차이가 있지만 단순한 프로젝트에 적용하기에는 부담되는 비용이 아니기 때문에 사이드프로젝트에 도입을 해보면 좋을 것 같다는 생각이 들어 간단하게 사용법을 작성해보고자 한다.
자세한 내용은 OpenAI의 ChatGPT API Docs를 참고하도록 하자
OpenAI Platform
Explore developer resources, tutorials, API docs, and dynamic examples to get the most out of OpenAI's platform.
platform.openai.com
ChatGPT API
사전준비
1. OpenAI 회원가입
회원가입은 어렵지 않다. 이미 ChatGPT를 사용해본 사람이라면 로그인을 하고, 사용해본 적 없는 사람이라면 회원가입을 진행하자.
OpenAI Platform
Explore developer resources, tutorials, API docs, and dynamic examples to get the most out of OpenAI's platform.
platform.openai.com
2. 무료 크레딧 확인
OpenAI에서는 신규회원가입 시 3개월 동안 사용할 수 있는 $5 무료크레딧을 제공해준다.
프로필 클릭 > Manage account > Billing
해당 화면으로 이동 시 현재까지 남은 크레딧을 확인할 수 있다.
만약 Playground에서 아래와 같은 문구가 뜬다면 무료 크레딧이 만료된 것이므로 카드 정보 등록 후 크레딧을 구매해주자.
토큰량이 많지 않은 프로젝트라면 $5로도 충분하다고 생각되므로, 최소한의 금액 씩 구매하는걸 추천한다.
3. API Key 등록
크레딧까지 확인했다면 API를 사용하기 위해 API Key를 등록해주어야한다.
프로필 클릭 > USER > API key > Create new secret key
Secret key의 Name은 자유롭게 설정해도 된다. 필자는 [GPT secret key]라고 입력해주었다.
Name을 입력하고 나면 다음과 같이 Secret key가 생성된다. Secret key는 해당 화면에서 딱 한번만 확인가능하기 때문에 안전한 곳에 저장해두고 관리해야한다.
만약 Secret key를 분실했다면 기존 Key를 삭제한 후 새롭게 발급받아야 한다.
4. Playground
OpenAI가 제공하는 Playgound에서 ChatGPT API를 간편하게 테스트해볼 수 있다.
오른쪽 탭에서는 GPT의 Model, Temperature, Maximum Token(Length) 등등을 설정할 수있고, 좌측 탭에서는 SYSTEM과 USER를 설정할 수 있다.
뒤에서 자세히 설명하겠지만 SYSTEM은 GPT의 역할을 정해주는 부분이고, USER는 발화(질문) 내용을 입력하는 부분으로 이해하면 된다.
간단하게 Playground에서 테스트를 해보면 다음과 같이 ChatGPT와 동일하게 응답이 온다.
ASSISTANT 부분은 GPT에 대한 답변인데, API를 이용할 때 이 ASSISTANT를 함께 Request로 보내주면 마치 대화의 맥락을 기억하는 듯이 구현이 가능하다.
이 SYSTEM 부분에 적절한 역할을 부여해주면 해줄 수록 GPT는 개발자가 의도한 바를 명확하게 파악하고 대답을 하게 되고, 이 부분을 작성하는 과정이 바로 프롬프트 엔지니어링이다.
이제 간단히 ChatGPT의 사전준비가 끝났으니 본격적으로 ChatGPT API를 사용해보자.
알아보기
라이브러리
OpenAI의 ChatGPT API 공식문서에서는 Node.js와 Python를 사용하여 가이드를 진행하고, 공식적으로 이 두가지 언어의 라이브러리만을 지원해준다. 하지만 수많은 기업과 개발자들이 각각의 언어로 된 라이브러리를 배포 및 유지보수하고 있으므로 너무 걱정하지는 말자!
라이브러리가 지원되는 언어들은 다음과 같다.
이정도면 거의 모든 언어가 지원되는게 아닌가 할 정도로 많은 언어로 된 라이브러리가 배포되어있다.
라이브러리 언어 목록
C# / .NET
C++
Clojure
Crystal
Dart/Flutter
Delphi
Elixir
Go
Java
Julia
Kotlin
Node.js
- openai-api by Njerschow
- openai-api-node by erlapso
- gpt-x by ceifa
- gpt3 by poteat
- gpts by thencc
- @dalenguyen/openai by dalenguyen
- tectalic/openai by tectalic
PHP
Python
R
Ruby
Rust
- async-openai by 64bit
- fieri by lbkolev
Scala
Swift
- OpenAIKit by dylanshine
- OpenAI by MacPaw
Unity
Unreal Engine
이 예제에서는 OpenAI가 기본으로 라이브러리를 제공해주는 Python 을 사용해서 구현해볼 것이다.
파라미터 요소
https://platform.openai.com/docs/api-reference/chat/create
OpenAI Platform
Explore developer resources, tutorials, API docs, and dynamic examples to get the most out of OpenAI's platform.
platform.openai.com
우리가 사용하게 될 Chat Completion API의 파라미터들 중 주로 사용하는 인자들은 다음과 같다.
model(필수)
사용하게 될 GPT의 모델이다. 사용 가능한 모델은 다음과 같다.
GPT 모델 목록
MODELS | DESCRIPTION |
GPT-4 | GPT-3.5 업그레이드 버전 |
GPT-3.5 | GPT-3 업그레이드 버전 |
GPT base | 현재 사용하지 않는 베이스 모델 |
DALL·E | 이미지를 생성하고 편집할 수 있는 모델 |
Whisper | 오디오를 텍스트로 변환할 수 있는 모델 |
Embeddings | 임베딩이 가능한 모델 |
Moderation | 민감한 내용이나 안전하지 않은 지 여부를 감지할 수 있는 미세조정 모델 |
GPT-3
Legacy
|
가장 기본 모델. 3.5나 4로 대체되었지만 미세조정이 가능한 유일한 모델이다. |
Deprecated | deprecated된 모델 목록 |
messages(필수)
GPT와의 대화를 구성하는 메시지 목록이다. JSON형태로 제공하며 필수 구성요소는 다음과 같다.
- role: 메시지 작성자의 역할을 정의한다. 가능한 인자로는
system
,user
,assistant
,function
이 있다.- system: GPT의 동작을 미리 설정할 수 있다. 예를 들어, GPT의 성격을 정한다거나 응답 형태를 지정하는 방식으로 사용할 수 있다.
- user: 사용자가 입력하는 내용이다.
- assistant: GPT가 답변한 내용이다. GPT는 기본적으로 이전 대화내용을 기억하지 못하기 때문에, 이전 내용을 바탕으로 대화를 이어나가기 위해 사용한다.
- content: 메시지의 내용을 작성한다.
max_tokens(옵션)
GPT가 응답으로 만들어내는 토큰의 최대 개수이다. 기본값은 inf
로 model에 따라 기본값이 달라진다.
temperature(옵션)
답변의 다양성을 설정한다. 0부터 2사이로 설정하도록 권장되며 소수점 첫째자리까지 입력가능하다.
값이 낮을 수록 더 정확하고 일관된 답변을 제공하고, 값이 높을 수록 더 다양한 답변을 제공하게 된다.
일반적으로 가장 안정적인 숫자는 0.5 ~ 1.0 사이라고 하지만 유저의 요구사항에 따라 적절한 temperature를 찾아야한다.
stream(옵션)
ChatGPT처럼 한글자씩 응답이 출력되는 방식을 사용하고 싶다면 true
로 지정하면 된다. GPT를 Front end에서 구현한다면 느린 응답에 대한 대안이 될 수 있다.
구현하기
이 예제에서는 개발 면접을 도와주는 AI 멘토를 주제로 간단하게 구현한 코드와 프롬프트이다.
GPT는 영어에 대해 더 정확한 응답을 해주지만 이번 예제에서는 한국어로 구현하기로 한다.
사용한 언어는 OpenAI가 공식적으로 지원하는 라이브러리를 사용하기 위해 Python으로 선택하였다.
최종 코드
import json
import os
from dotenv import load_dotenv
import openai
load_dotenv()
# key와 organization을 환경변수로 관리
openai.organization = os.getenv('OPENAI_ORGANIZATION')
openai.api_key = os.getenv('OPENAI_API_KEY')
lang = "Java"
user_content = "Java는 객체지향 언어이다."
messages = [
{"role": "system", "content": "너는 개발 면접자야. 오직 " + lang + "에 대해서만 질문을 물어봐."},
{"role": "system", "content": "유저가 말하는 내용을 1점에서 100점까지 점수로 판단해야해. 문장 가장 처음은 무조건 점수부터 출력해."},
{"role": "system", "content": "유저가 말하는 내용에 대한 점수는 데이터의 정확도로 판단해. 공백이거나 \"모르겠음\"이라는 의미가 포함되면 0점이야."},
{"role": "system",
"content": "유저가 말한 내용에 대해 '답변'과 '키워드'와 '꼬리질문'을 말해. 답변은 틀린 이유에 대해 설명해줘.\n점수 : {점수}점\n답변 : {답변}\n키워드: {키워드}\n꼬리질문: {꼬리질문}"},
{"role": "system", "content": "어조: 친절하게, 전문적이게"},
{"role": "assistant", "content": "꼬리질문: JAVA의 특징은 무엇이 있나요?"}, # 첫번째 질문을 미리 세팅해두었다.
{"role": "user", "content": user_content}
]
# assistant를 저장하는 jsonl 파일을 읽고, message에 추가
with open('gpt_msg_assistant.jsonl', 'r') as file:
for line in file:
assistant = json.loads(line)
messages.append(assistant)
# GPT 호출
completion = openai.ChatCompletion.create(model="gpt-4", messages=messages, temperature=0.2, max_tokens=2048)
# GPT 응답에서 필요한 부분만 추출
assistant_message = completion["choices"][0]["message"].encode("UTF-8").decode()
# 결과값을 확인하기 위해 출력
print(assistant_message)
# user의 답변을 jsonl 파일에 저장하기 위해 변수에 저장
user_message = {"role": "user", "content": user_content}
# 파일에 쓰기
data_path = "gpt_msg_assistant.jsonl"
with open(data_path, 'a', encoding='utf-8') as f:
json.dump(user_message, f, ensure_ascii=False)
f.write('\n')
with open(data_path, 'a', encoding='utf-8') as f:
json.dump(assistant_message, f, ensure_ascii=False)
f.write('\n')
이번 포스팅에서는 세세한 코드에 대한 설명보다는 GPT 라이브러리를 사용하는 부분에 대해서만 설명하도록 하겠다.
1. key 세팅
import os
from dotenv import load_dotenv
import openai
load_dotenv()
# key와 organization을 환경변수로 관리
openai.organization = os.getenv('OPENAI_ORGANIZATION')
openai.api_key = os.getenv('OPENAI_API_KEY')
openai 라이브러리를 호출하기 위한 기본 key값 설정이다. 여기서는 .env 파일로 관리하고 있다.
여기서 api_key는 위에서 등록해준 secret key를 입력하면 되며,
organization은 프로필 클릭 > ORGANIZATION > Settings > Organization ID
에 적혀있는 값을 사용하면 된다.
2. messages 세팅
lang = "Java"
message = "Java는 객체지향 언어이다."
messages = [
{"role": "system", "content": "너는 개발 면접자야. 오직 " + lang + "에 대해서만 질문을 물어봐."},
{"role": "system", "content": "유저가 말하는 내용을 1점에서 100점까지 점수로 판단해야해. 문장 가장 처음은 무조건 점수부터 출력해."},
{"role": "system", "content": "유저가 말하는 내용에 대한 점수는 데이터의 정확도로 판단해. 공백이거나 \"모르겠음\"이라는 의미가 포함되면 0점이야."},
{"role": "system",
"content": "유저가 말한 내용에 대해 '답변'과 '키워드'와 '꼬리질문'을 말해. 답변은 틀린 이유에 대해 설명해줘.\n점수 : {점수}점\n답변 : {답변}\n키워드: {키워드}\n꼬리질문: {꼬리질문}"},
{"role": "system", "content": "어조: 친절하게, 전문적이게"},
{"role": "assistant", "content": "꼬리질문: JAVA의 특징은 무엇이 있나요?"}, # 첫번째 질문을 미리 세팅해두었다.
{"role": "user", "content": message}
]
# assistant를 저장하는 jsonl 파일을 읽고, message에 추가
with open('gpt_msg_assistant.jsonl', 'r') as file:
for line in file:
assistant = json.loads(line)
messages.append(assistant)
본격적으로 프롬프트를 작성한다.
코드를 보면 role을 system으로 설정하고 GPT의 역할, 어조, 응답 형태 등등을 지정해주고 있다.
여기서는 assistant를 직접 입력해주어 첫번째 질문을 미리 세팅해두었다.
또, GPT를 호출할 때마다 응답(assistant)을 jsonl(Json line)파일에 저장해둔다음 GPT호출 전에 미리 messages에 그 내용을 append하여 이전 대화 내용을 기억할 수 있도록 해주었다.
3. GPT 호출
# GPT 호출
completion = openai.ChatCompletion.create(model="gpt-4", messages=messages, temperature=0.2, max_tokens=2048)
# GPT 응답에서 필요한 부분만 추출
assistant_message = completion["choices"][0]["message"].encode("UTF-8").decode()
# 결과값을 확인하기 위해 출력
print(assistant_message)
위에서 생성한 messages를 사용하여 GPT를 호출해준다.
예제에서는 가장 최신 모델인 gpt-4를 사용하였고, temperature는 다양한 질문을 받기 위해 0.2로, max_token은 2048으로 설정해주었다.
이 코드를 호출해보면 출력되는 응답값은 다음과 같다.
{
"id": "chatcmpl-8C1VQeMNq3vFfbCriutG5CC3YvK4i",
"object": "chat.completion",
"created": 1697876416,
"model": "gpt-4-0613",
"choices": [
{
"index": 0,
"message": {
"role": "assistant",
"content": "\uc810\uc218 : 70\uc810\n\ub2f5\ubcc0 : \ub9de\uc2b5\ub2c8\ub2e4. Java\ub294 \uac1d\uccb4\uc9c0\ud5a5 \uc5b8\uc5b4\uc785\ub2c8\ub2e4. \ud558\uc9c0\ub9cc Java\uc758 \ud2b9\uc9d5\uc740 \uadf8\uac83\ub9cc\uc774 \uc544\ub2d9\ub2c8\ub2e4. Java\ub294 \ud50c\ub7ab\ud3fc \ub3c5\ub9bd\uc801\uc774\uba70, \uba40\ud2f0\uc2a4\ub808\ub4dc\uc640 \ubd84\uc0b0\ud658\uacbd \uc9c0\uc6d0, \uac04\ub2e8\ud55c \uba54\ubaa8\ub9ac \uad00\ub9ac \ub4f1\uc758 \ud2b9\uc9d5\ub3c4 \uc788\uc2b5\ub2c8\ub2e4.\n\ud0a4\uc6cc\ub4dc: \uac1d\uccb4\uc9c0\ud5a5 \uc5b8\uc5b4, \ud50c\ub7ab\ud3fc \ub3c5\ub9bd\uc801, \uba40\ud2f0\uc2a4\ub808\ub4dc, \ubd84\uc0b0\ud658\uacbd \uc9c0\uc6d0, \uba54\ubaa8\ub9ac \uad00\ub9ac\n\uaf2c\ub9ac\uc9c8\ubb38: Java\uc758 \uba54\ubaa8\ub9ac \uad00\ub9ac\uc5d0 \ub300\ud574 \uc880 \ub354 \uc790\uc138\ud788 \uc124\uba85\ud574\uc8fc\uc2e4 \uc218 \uc788\ub098\uc694?"
},
"finish_reason": "stop"
}
],
"usage": {
"prompt_tokens": 353,
"completion_tokens": 204,
"total_tokens": 557
}
}
이 중에서 우리는 message의 value를 가져와서 파일에 저장하기만 하면 되는데, content부분이 Unicode로 인코딩되어 출력되기 때문에 디코딩을 하는 과정이 필수이다.
결과값을 디코딩해보면 다음과 같이 출력된다.
점수 : 70점\n답변 : 맞습니다. Java는 객체지향 언어입니다. 하지만 Java의 특징은 그것만이 아닙니다. Java는 플랫폼 독립적이며, 멀티스레드와 분산환경 지원, 간단한 메모리 관리 등의 특징도 있습니다.\n키워드: 객체지향 언어, 플랫폼 독립적, 멀티스레드, 분산환경 지원, 메모리 관리\n꼬리질문: Java의 메모리 관리에 대해 좀 더 자세히 설명해주실 수 있나요?
4. 응답값 jsonl 파일에 쓰기
# 파일에 쓰기
data_path = "gpt_msg_assistant.jsonl"
with open(data_path, 'a', encoding='utf-8') as f:
json.dump(user_message, f, ensure_ascii=False)
f.write('\n')
with open(data_path, 'a', encoding='utf-8') as f:
json.dump(assistant_message, f, ensure_ascii=False)
f.write('\n')
GPT가 대화 맥락을 기억할 수 있도록 하기 위해 위에서 jsonl파일을 읽어 messages에 추가해주었다.
이 마지막 부분에서 사용자의 메시지와 GPT의 응답을 파일에 쓰게 된다.
마치며
간단하게 OpenAI의 라이브러리를 사용하는 과정에 대해 적어보았다.
GPT API에는 이렇게 간단한 대화 뿐만 아니라 직접 학습을 시키거나, 오디오를 인식하거나, 이미지를 만드는 등등의 파워풀한 기능이 굉장히 많아서 어떻게 사용하느냐에 따라 ChatGPT보다 더 좋은 서비스를 개발할 수 있을 것 같다.
앞으로는 이 예제 코드에 여러가지 기능을 추가해서 직접 화면을 띄워놓고 면접을 보는 서비스를 개발해 볼 예정이다.
'Study > etc' 카테고리의 다른 글
[Intellij] 인텔리제이 TODO 코드태그(Code Tag) 커스텀 (0) | 2023.01.24 |
---|---|
[Postman] postman에서 cookie 설정 (1) | 2022.07.25 |
[mac] 맥북 한영키 윈도우처럼 쓰자 (0) | 2022.01.26 |
[Eclipse] 이클립스 자동완성을 ctrl + space 입력없이 사용하기 (0) | 2022.01.10 |
[Spring boot] macOS Spring boot 설치 (0) | 2022.01.10 |