Logo

터미널에서 curl로 ChatGPT API 호출 해보기

이번 포스팅에서는 터미널에서 curl을 이용하여 ChatGPT API 직접 호출해보면서 ChatGPT와 어떻게 메시지를 주고 받을 수 있는지 알아보겠습니다.

터미널에서 간단한 명령어를 입력하여 웹 페이지나 API 데이터를 요청하고 받을 수 있는 HTTP 클라이언트 도구인 curl에 대한 자세한 설명은 관련 포스팅을 참고 바랍니다.

ChatGPT API 키 발급

ChatGPT API를 사용하려면 반드시 OpenAI의 API 키가 있어야 합니다. API키가 없으신 분들은 이전 글을 따라서 OpenAI 웹사이트에 가입을 하시고 API 키를 발급받으시길 바랍니다.

환경 변수로 API Key 설정

터미널을 열고 우선 OPENAI_API_KEY라는 환경 변수에 OpenAI의 API 키를 저장해놓고 시작하겠습니다.

$ export OPENAI_API_KEY=sk-...mn1a
$ echo $OPENAI_API_KEY
sk-...mn1a

이렇게 API 키를 환경 변수로 설정해놓으면 curl 명령어를 날릴 때 마다 매번 긴 문자열의 API 키를 명시할 필요가 없어서 편리합니다. 환경 변수는 터미널 창을 닫으면 소멸되므로 실습을 진행되는 동안에는 같은 터미널 창을 사용하도록 주의하세요.

401 Unauthorized

ChatGPT API의 주소(URL)는 https://api.openai.com/v1/chat/completions 인데요.

우선 맛보기로 ChatGPT API를 -i 옵션만 줘서 curl로 그냥 찔러볼까요? -i 옵션을 사용하면 응답 헤더도 함께 출력해주기 때문에 유용합니다.

명령
$ curl https://api.openai.com/v1/chat/completions -i

401 상태 코드와 함께 API 키를 제공하지 않았다는 오류 메시지가 응답이 되는데요. OpenAI의 API 키를 넘기지 않았으니 당연한 인증에 실패하는 거 겠죠?

결과
HTTP/2 401
date: Wed, 12 Apr 2023 02:43:09 GMT
content-type: application/json; charset=utf-8
content-length: 496
vary: Origin
x-request-id: 6a95db70a1686a0bff8d160526276948
strict-transport-security: max-age=15724800; includeSubDomains
cf-cache-status: DYNAMIC
server: cloudflare
cf-ray: 7b681ebfac6ea24c-YYZ
alt-svc: h3=":443"; ma=86400, h3-29=":443"; ma=86400

{
    "error": {
        "message": "You didn't provide an API key. You need to provide your API key in an Authorization header using Bearer auth (i.e. Authorization: Bearer YOUR_KEY), or as the password field (with blank username) if you're accessing the API from your browser and are prompted for a username and password. You can obtain an API key from https://platform.openai.com/account/api-keys.",
        "type": "invalid_request_error",
        "param": null,
        "code": null
    }
}

400 Bad Request

이번에는 ChatGPT API를 호출할 때 OpenAI의 API 키도 함께 실어서 보내볼까요? curl 명령어의 -H 옵션을 통해서 Authorization 헤더에 Bearer <API 키>의 형태로 지정해주면 됩니다.

명령
$ curl https://api.openai.com/v1/chat/completions -i \
  -H "Authorization: Bearer $OPENAI_API_KEY"

그러면 400 상태 코드와 함께 모델을 입력으로 보내지 않았다는 오류 메시지가 응답이 되네요.

결과
HTTP/2 400
date: Wed, 12 Apr 2023 02:48:33 GMT
content-type: application/json; charset=utf-8
content-length: 167
vary: Origin
x-request-id: 6a892c4ca7886678871a9ba16530d7db
strict-transport-security: max-age=15724800; includeSubDomains
cf-cache-status: DYNAMIC
server: cloudflare
cf-ray: 7b6826a5e8afa1f3-YYZ
alt-svc: h3=":443"; ma=86400, h3-29=":443"; ma=86400

{
    "error": {
        "message": "you must provide a model parameter",
        "type": "invalid_request_error",
        "param": null,
        "code": null
    }
}

OpenAI는 gpt-3.5-turbo, gpt-4 등 여러가지 인공지능 모델을 제공하기 때문에 모델 종류를 필수적으로 명시해줘야 하는데요. 저처럼 무료 크레딧으로 체험하시는데는 gpt-3.5-turbo 모델이면 충분할 것입니다.

200 OK

자, 이제 curl 명령어의 -d 옵션을 통해서 gpt-3.5-turbo라는 인공지능 모델을 사용하고 싶다고 명시해주고, 야!라는 메시지도 입력해보겠습니다.

명령
$ curl https://api.openai.com/v1/chat/completions -i \
  -H "Authorization: Bearer $OPENAI_API_KEY" \
  -H "Content-Type: application/json" \
  -d '{
     "model": "gpt-3.5-turbo",
     "messages": [{"role": "user", "content": "야!"}]
   }'

마침내 ChatGPT API가 200 상태 코드와 함께 정상적인 메시지를 응답하는 것을 보실 수 있으실 것입니다. (응답 메시지가 저랑 살짝 다를 수 있어요.)

HTTP/2 200
date: Wed, 12 Apr 2023 03:00:04 GMT
content-type: application/json
access-control-allow-origin: *
cache-control: no-cache, must-revalidate
openai-model: gpt-3.5-turbo-0301
openai-organization: user-c0dbvszubcin3xsvakpwxd9n
openai-processing-ms: 4079
openai-version: 2020-10-01
strict-transport-security: max-age=15724800; includeSubDomains
x-ratelimit-limit-requests: 20
x-ratelimit-remaining-requests: 19
x-ratelimit-reset-requests: 3s
x-request-id: 779c3612f7b428450cd286fc9f985d75
cf-cache-status: DYNAMIC
server: cloudflare
cf-ray: 7b68376ead9e3ffd-YYZ
alt-svc: h3=":443"; ma=86400, h3-29=":443"; ma=86400

{
  "id":"chatcmpl-74L0C0jSUWQN1zQU3jS46xgGUyMJq",
  "object":"chat.completion",
  "created":1681268400,
  "model":"gpt-3.5-turbo-0301",
  "usage":{
    "prompt_tokens":10,
    "completion_tokens":26,
    "total_tokens":36
  },
  "choices":[
    {
      "message":{
        "role":"assistant",
        "content":"예, 부르셨나요? 무엇을 도와드릴까요?"
      },
      "finish_reason":"stop",
      "index":0
    }
  ]
}

메시지 형식

ChatGPT API와 메시지를 주고 받을 때는 정해진 형식을 따라야하는데요. 우선 송수신 메시지 모두 배열의 형태이며 요청 전문의 messages 속성에 메시지를 담아서 보내면, 응답 전문의 choices 속성에 메시지가 담겨서 돌아옵니다.

각 메시지는 role 속성과 content 속성으로 이루어지는데요. role 속성의 값은 user, assistant, system 역할 중 하나가 되며, content 속성에는 메시지 내용이 담깁니다. user는 우리 사용자를 나타내고, assistant 역할은 ChatGPT가 맡으며, system은 주로 대화 상황을 가정하는 특수한 용도로 쓰입니다.

이렇게 한 번에 여러 메시지를 주고 받도록 설계된 이유는 ChatGPT API와 연속적인 대화를 하기 위함인데요. ChatGPT API가 기존에 나누었던 대화의 맥락을 고려하기를 원한다면 ChatGPT API의 응답까지 포함해서 다시 ChatGPT API로 재전송할 수 있습니다.

예를 들어, 서울의 인구를 물어볼 때 쌩뚱맞게 바로 거기에서 가장 높은 건물이 뭐야?라는 요청을 보내면 ChatGPT API는 구체적으로 질문을 달라고 응답할 것입니다. 하지만, 다음과 같이 바로 전에 나누었던 질문과 대답을 함께 보내면 ChatGPT API는 좀 더 도움이 되는 응답을 보내줄 것입니다.

{
  "model": "gpt-3.5-turbo",
  "messages": [
    {
      "role": "user",
      "content": "한국의 수도가 어디야?"
    },
    {
      "role": "assistant",
      "content": "한국의 수도는 서울입니다."
    },
    {
      "role": "user",
      "content": "거기에서 가장 높은 건물이 뭐야?"
    }
  ]
}

토큰 사용량

ChatGPT API의 응답 전문에서 자세히 보시면 choices 말고도 usage라는 속성이 보일텐데요. 이 속성은 요청과 응답의 토큰 사용량과 둘은 합친 총 토큰 사용량을 알려주며 과금에 있어서 중요한 정보입니다.

호출수에 따라 과금하는 기존 API들과 다르게 ChatGPT API는 이 토큰 사용량을 기준으로 과금을 합니다. 예를 들어, 총 36 토큰을 사용한 요청은 36 * 0.0002 = 0.0072 달러가 과금되고, 총 360 토큰을 사용한 요청은 360 * 0.0002 = 0.072 달러가 과금됩니다.

마치면서

이상으로 터미널에서 curl을 이용하여 실제로 ChatGPT API의 요청과 응답이 어떻게 생겼는지 살펴보았습니다. 이렇게 curl을 잘 활용하면 간편하게 ChatGPT API를 찔러볼 수 있으므로 테스트 및 디버깅에 유용하게 활용할 수 있습니다.

실제로 애플리케이션을 개발할 때는 OpenAI에서 제공하는 라이브러리를 사용하게 될텐데요. 이 부분에 대해서는 다음 포스팅에서 다뤄보도록 하겠습니다.

ChatGPT에 대한 포스팅은 관련 태그를 통해서 쉽게 만나보세요!