Code Interpreter를 사용하는 OpenAI Assistant

OpenAI Assistant에서 기본으로 제공하는 도구에는 Retrieval 도구와 Code Interpreter가 있습니다. 원하는 도구가 없을 때는 함수 호출 기능을 이용해 도구를 추가해줄 수도 있죠. 여기서는 Code Interpreter를 사용해 데이터를 분석해 보겠습니다.

분석할 데이터

Code Interpreter를 이용해 Titanic 자료를 분석해보겠습니다. 먼저 Titanic 데이터(titanic.csv)를 받습니다. 파일을 Code Interpreter에서 사용할 수 있도록 OpenAI 서버에 올립니다.

from openai import OpenAI
client = OpenAI(api_key="sk-")

my_file = client.files.create(
    file = open("titanic.csv",'rb'),
    purpose='assistants'
)
my_file

## 출력
FileObject(id='file-zS9GLj45Ff9b2daNSQLrVPSt', bytes=60302, created_at=1699803397, filename='titanic.csv', object='file', purpose='assistants', status='processed', status_details=None)

참고로, Code Interpreter에서는 csv 파일 외에도 text, pdf, docx, pptx, xlsx, csv, jpg, png, zip 등 다양한 파일을 읽을 수 있습니다.

Code Interpreter를 사용하는 Assistant

다음으로 Assistant를 생성하며 Code Interpreter를 Tool로 사용할 수 있도록 해줍니다.

assistant = client.beta.assistants.create(
  name="데이터 분석 전문가",
  description="당신은 데이터 분석 전문가입니다.",
  model="gpt-4-1106-preview",
  tools=[{"type": "code_interpreter"}]
)

이제 Assistant에게 내릴 명령을 준비해봅시다. Thread를 생성하며 Message를 이용해 명령을 내리는데, 이 때 앞에서 올린 파일을 메시지에 첨부해줍니다.

thread = client.beta.threads.create(
  messages=[
    {
      "role": "user",
      "content": "titanic.csv 파일에서 생존률에 영향을 미친 주요 요인 세 가지를 찾고 차트로 그려서 설명해주세요.",
      "file_ids": [my_file.id]
    }
  ]
)

명령 실행

명령을 실행할 수 있도록 Run 객체를 만들고 응답을 기다립니다.

import time

def run_and_wait(client, assistant, thread):
  run = client.beta.threads.runs.create(
    thread_id=thread.id,
    assistant_id=assistant.id
  )
  while True:
    run_check = client.beta.threads.runs.retrieve(
      thread_id=thread.id,
      run_id=run.id
    )
    print(run_check.status)
    if run_check.status in ['queued','in_progress']:
      time.sleep(2)
    else:
      break
  return run

run = run_and_wait(client, assistant, thread)

Code Interpreter는 내부적으로 여러 단계를 거쳐 최종 응답을 내놓습니다. 중간 단계들을 확인하고 싶으면 Run Steps를 확인하면 됩니다.

run_steps = client.beta.threads.runs.steps.list(
    thread_id=thread.id,
    run_id=run.id
)
len(run_steps.data) ## 출력: 9

총 9단계를 거쳐 답을 내놓았습니다. 중간 과정은 run_steps 객체 내부에 저장되어 있으니 필요하면 확인할 수 있습니다.

여기서는 Thread에 저장된 메시지들을 가져와 확인해보겠습니다.

thread_messages = client.beta.threads.messages.list(thread.id)
for i,msg in enumerate(thread_messages.data):
  print(len(msg.content))

## 출력
2
2
2
1
1
1

결과를 보면 총 6개의 메시지가 있고, 세 개의 메시지는 content가 한 개, 세 개는 content가 두 개 있습니다. 이 예제에서 content가 2인 경우는 그림을 포함하고 있는 경우입니다. 메시지를 출력해보죠.

Code Interpreter의 응답

결과 확인에 사용한 코드입니다.

from IPython.display import display, Image

for i,msg in enumerate(reversed(thread_messages.data)):
  for c in msg.content:
    if c.type == 'text':
      print(i, c.text.value + '\n')

    if c.type == 'image_file':
      api_response = client.files.with_raw_response.retrieve_content(c.image_file.file_id)
      if api_response.status_code == 200:
        content = api_response.content
        fimg = f'image_{i}.png'
        with open(fimg, 'wb') as f:
          f.write(content)
        img = Image(filename=fimg)
        display(img)

결과는 다음과 같습니다.

0 titanic.csv 파일에서 생존률에 영향을 미친 주요 요인 세 가지를 찾고 차트로 그려서 설명해주세요.

1 먼저 `titanic.csv` 파일을 읽어서 데이터를 살펴본 다음, 타이타닉호의 생존률에 영향을 미칠 수 있는 주요 요소에 대한 가설을 세워볼 것입니다. 생존률에 영향을 줄 것으로 예상되는 요소로는 일반적으로 성별(Sex), 객실 등급(Pclass), 그리고 나이(Age)가 자주 언급됩니다. 이러한 요소들에 대한 데이터를 분석하고 해당 요소들이 생존률에 어떤 영향을 미쳤는지 시각화하여 설명드리겠습니다.

먼저 데이터를 로드하고 초기 분석을 수행해 보겠습니다.

2 데이터셋에는 여러 컬럼들이 있는데, 여기서 생존률에 영향을 미쳤을 것으로 추정되는 주요 요인인 성별(`Sex`), 객실 등급(`Pclass`), 나이(`Age`)를 중점으로 살펴보겠습니다. 생존 여부는 `Survived` 컬럼에 표시되어 있으며, 생존한 경우 1, 그렇지 않은 경우 0의 값을 가지고 있습니다.

세 가지 요인에 대해 생존률을 비교하기 위해 다음과 같은 단계로 진행하겠습니다:

1. `Sex`: 성별에 따른 생존률 비교
2. `Pclass`: 객실 등급에 따른 생존률 비교
3. `Age`: 나이 범주(어린이, 성인, 노인 등)에 따른 생존률 비교

각각의 요인 별로 생존률을 계산하고 시각화하여 차트를 그리겠습니다. 차트는 각 요인에 따른 생존자 수 및 생존률을 보여줄 것입니다.

우선 성별에 따른 생존률을 분석해 보겠습니다.
3 성별에 따른 생존률 차트를 보면 여성의 생존률이 약 74.2%로, 남성의 생존률인 약 18.9%보다 훨씬 높다는 것을 알 수 있습니다. 이는 성별이 타이타닉호 생존률에 큰 영향을 미쳤음을 시사합니다.

그 다음으로는 객실 등급(`Pclass`)에 따른 생존률을 분석해 보겠습니다.
4 객실 등급(`Pclass`)별 생존률 차트에 따르면 1등급 객실 승객의 생존률이 약 62.96%로 가장 높고, 2등급은 약 47.28%, 3등급은 약 24.24%로 나타나고 있습니다. 이는 객실 등급이 생존률에 중요한 요인으로 작용했음을 보여줍니다. 1등급 객실 승객이 생존 가능성이 가장 높았고, 객실 등급이 낮을수록 생존 확률이 감소하는 경향을 볼 수 있습니다.

마지막으로 나이(`Age`) 범주별 생존률을 분석해 보겠습니다. `Age` 데이터에는 결측치가 있을 수 있으므로 이를 처리한 후 나이를 어린이(0-17), 성인(18-65), 노인(65+)의 세 범주로 나누어 생존률을 비교해 보겠습니다.
5 나이 범주별 생존률 차트를 보면 어린이(17세 이하)의 생존률이 약 53.98%로 가장 높고, 성인(18-65세)의 생존률은 약 38.45%, 노인(65세 이상)은 12.5%로 나타나고 있습니다. 나이를 알 수 없는 승객들(Unkown)의 생존률은 약 29.38%입니다. 이는 나이도 생존에 영향을 미친 요인이라 할 수 있으며, 특히 어린이의 생존률이 높게 나타나고 있습니다.

이상의 분석 결과를 종합해보면 타이타닉호에서의 생존률에 가장 큰 영향을 미친 요인 세 가지는 성별(`Sex`), 객실 등급(`Pclass`), 그리고 나이(`Age`)라는 결론이 도출됩니다.

- **성별**: 여성의 생존률이 남성에 비해 훨씬 높으며, 이는 당시 사회적인 구조와 구명 보트에 대한 여성과 어린이 우선 정책의 영향일 것으로 보입니다.
- **객실 등급**: 1등급 객실 승객의 생존률이 가장 높고, 객실 등급이 낮아질수록 생존률이 감소하는 경향을 보여줍니다. 구명 보트에 접근하는 데 있어서 1등급 승객이 더 우선적이었기 때문일 수 있습니다.
- **나이**: 어린이의 생존률이 가장 높고, 성인과 노인 순으로 낮아짐을 보여줍니다. 이는 어린이를 보호하려는 경향과 구명 보트 배정에 어린이를 우선시한 결과로 볼 수 있습니다.

각 요인의 차트는 상기 데이터와 결론을 시각적으로 보여주며, 이러한 요인들이 생존률에 영향을 미친 방식을 직관적으로 이해하는 데 도움을 줍니다.

저는 데이터에서 생존률에 영향을 미친 주요 요인 세 가지를 찾으라고 했는데, Code Interpreter는 이미 알고 있는 정보를 바탕으로 분석 결과를 보여줬네요. 데이터 분석은 잘 해서 보여줬습니다.

Assistant, Thread, File은 더 이상 사용하지 않으면 삭제해줍니다.

response = client.beta.threads.delete(thread.id)

response = client.beta.assistants.delete(assistant.id)

response = client.files.delete(my_file.id)

Code Interpreter 사용료

Code Interpreter는 세션당 $0.03 씩 과금합니다. 세션은 한 번 시작하면 한 시간동안 유효하고, 질문 횟수와는 무관합니다. 물론, 질문과 응답에 따르는 토큰 사용료는 별도입니다.

댓글 남기기