4 분 소요

Assistant + tools

  • [이번 내용] code_interpreter
    • 토큰 길이에 상관 없이, 코드를 생성해서 답변할 수 있는 도구 입니다.
    • 예: 피보나치 수열을 만들어줘 -> 피보나치 수열을 생성하는 함수를 생성한 후 이것의 실행 결과로 답변을 만듦 (cf., Code Interpreter가 아니라면, text 기반의 sequence generation으로 답변을 함)
    • 함수를 생성하는 방식이기 때문에, input, output의 token length 제약을 벗어나서 활용을 할 수 있습니다.
    • 데이터와 그래프 이미지가 포함된 파일을 생성할 수 있습니다.
  • file_search
    • 우리가 업로드한 자료에서 검색한 이후 답변을 만들어 줍니다. (RAG를 활용하는 것과 비슷)
  • function
    • 우리가 직접 만든 함수를 사용할 수 있게 합니다.

기본 작업

  • Open AI 라이브러리 설치
  • Dotenv 설치
  • Google Drive 연결
  • API Key 로드
  • Open AI 클라이언트 객체 생성
# 실행을 위한 기본 설치 및 로드
!pip install --upgrade openai -q
!pip show openai | grep Version
!pip install -U python-dotenv
from dotenv import load_dotenv
import json
from openai import OpenAI
import os
from google.colab import drive
Version: 1.30.1
Requirement already satisfied: python-dotenv in /usr/local/lib/python3.10/dist-packages (1.0.1)
drive.mount('/content/drive', force_remount=True)

load_dotenv(
    dotenv_path='drive/MyDrive/AUTH/.env',
    verbose=True,
)
api_key = os.environ.get("OPEN_API_KEY")
client = OpenAI(api_key=api_key)

def show_json(obj):
  display(json.loads(obj.model_dump_json()))
Mounted at /content/drive

Code Interpreter Assistant 생성

assistant = client.beta.assistants.create(
  instructions="You are a personal math tutor. When asked a math question, write and run code to answer the question.",
  model="gpt-4o",
  tools=[{"type": "code_interpreter"}]
)
show_json(assistant)
{'id': 'asst_Y7Ndt1RKCg2Cb4mhlpgVbGbS',
 'created_at': 1716196766,
 'description': None,
 'instructions': 'You are a personal math tutor. When asked a math question, write and run code to answer the question.',
 'metadata': {},
 'model': 'gpt-4o',
 'name': None,
 'object': 'assistant',
 'tools': [{'type': 'code_interpreter'}],
 'response_format': 'auto',
 'temperature': 1.0,
 'tool_resources': {'code_interpreter': {'file_ids': []}, 'file_search': None},
 'top_p': 1.0}

Thread 생성 및 실행

  • Thread, Message, Run 차례로 생성 및 실행
thread = client.beta.threads.create()

message = client.beta.threads.messages.create(
    thread_id = thread.id,
    role = "user",
    content= "코드를 사용해서 최초 20개의 피보나치 수열을 만들어줘",
)

run = client.beta.threads.runs.create_and_poll(
    thread_id = thread.id,
    assistant_id = assistant.id,
)
show_json(run)
{'id': 'run_pqOAuhLfHIBmPXJ7ttkNF6Gw',
 'assistant_id': 'asst_Y7Ndt1RKCg2Cb4mhlpgVbGbS',
 'cancelled_at': None,
 'completed_at': 1716197343,
 'created_at': 1716197337,
 'expires_at': None,
 'failed_at': None,
 'incomplete_details': None,
 'instructions': 'You are a personal math tutor. When asked a math question, write and run code to answer the question.',
 'last_error': None,
 'max_completion_tokens': None,
 'max_prompt_tokens': None,
 'metadata': {},
 'model': 'gpt-4o',
 'object': 'thread.run',
 'required_action': None,
 'response_format': 'auto',
 'started_at': 1716197337,
 'status': 'completed',
 'thread_id': 'thread_AMQPcatbKuhqL8SMsTggLkdl',
 'tool_choice': 'auto',
 'tools': [{'type': 'code_interpreter'}],
 'truncation_strategy': {'type': 'auto', 'last_messages': None},
 'usage': {'completion_tokens': 239,
  'prompt_tokens': 486,
  'total_tokens': 725},
 'temperature': 1.0,
 'top_p': 1.0,
 'tool_resources': {}}
if run.status == 'completed':
  messages = client.beta.threads.messages.list(
    thread_id=thread.id
  )
  show_json(messages)
else:
  print(run.status)
{'data': [{'id': 'msg_ETt57jde3ZqDb0Bs0K2XEiWN',
   'assistant_id': 'asst_Y7Ndt1RKCg2Cb4mhlpgVbGbS',
   'attachments': [],
   'completed_at': None,
   'content': [{'text': {'annotations': [],
      'value': '최초 20개의 피보나치 수열은 다음과 같습니다:\n\n\\[ 0, 1, 1, 2, 3, 5, 8, 13, 21, 34, 55, 89, 144, 233, 377, 610, 987, 1597, 2584, 4181 \\]\n\n이 수열은 각 숫자가 바로 앞의 두 숫자의 합으로 구성됩니다. 예를 들어 2는 1 + 1, 3은 1 + 2, 5는 2 + 3입니다.'},
     'type': 'text'}],
   'created_at': 1716197341,
   'incomplete_at': None,
   'incomplete_details': None,
   'metadata': {},
   'object': 'thread.message',
   'role': 'assistant',
   'run_id': 'run_pqOAuhLfHIBmPXJ7ttkNF6Gw',
   'status': None,
   'thread_id': 'thread_AMQPcatbKuhqL8SMsTggLkdl'},
  {'id': 'msg_QLaWfYg2AYhFGuK6pcqDfl3Q',
   'assistant_id': None,
   'attachments': [],
   'completed_at': None,
   'content': [{'text': {'annotations': [],
      'value': '코드를 사용해서 최초 20개의 피보나치 수열을 만들어줘'},
     'type': 'text'}],
   'created_at': 1716197337,
   'incomplete_at': None,
   'incomplete_details': None,
   'metadata': {},
   'object': 'thread.message',
   'role': 'user',
   'run_id': None,
   'status': None,
   'thread_id': 'thread_AMQPcatbKuhqL8SMsTggLkdl'}],
 'object': 'list',
 'first_id': 'msg_ETt57jde3ZqDb0Bs0K2XEiWN',
 'last_id': 'msg_QLaWfYg2AYhFGuK6pcqDfl3Q',
 'has_more': False}

실행 단계를 살펴보기 위해 Steps 활용

  • 질문에 대해 답을 만들 때 실제 함수를 생성하는 것을 확인 할 수 있음
run_steps = client.beta.threads.runs.steps.list(
    thread_id = thread.id, run_id = run.id, order="asc",
)
show_json(run_steps)
{'data': [{'id': 'step_9I2fBWyMtivKvaLauynEph6j',
   'assistant_id': 'asst_Y7Ndt1RKCg2Cb4mhlpgVbGbS',
   'cancelled_at': None,
   'completed_at': 1716197341,
   'created_at': 1716197338,
   'expired_at': None,
   'failed_at': None,
   'last_error': None,
   'metadata': None,
   'object': 'thread.run.step',
   'run_id': 'run_pqOAuhLfHIBmPXJ7ttkNF6Gw',
   'status': 'completed',
   'step_details': {'tool_calls': [{'id': 'call_rVAbMWt9OhKznoszzP9VBYVS',
      'code_interpreter': {'input': '# 피보나치 수열의 최초 20개 숫자를 생성하는 함수\ndef generate_fibonacci(n):\n    fibonacci_sequence = [0, 1]\n    while len(fibonacci_sequence) < n:\n        next_value = fibonacci_sequence[-1] + fibonacci_sequence[-2]\n        fibonacci_sequence.append(next_value)\n    return fibonacci_sequence\n\n# 최초 20개의 피보나치 수열 생성\nfirst_20_fibonacci = generate_fibonacci(20)\nfirst_20_fibonacci',
       'outputs': [{'logs': '[0,\n 1,\n 1,\n 2,\n 3,\n 5,\n 8,\n 13,\n 21,\n 34,\n 55,\n 89,\n 144,\n 233,\n 377,\n 610,\n 987,\n 1597,\n 2584,\n 4181]',
         'type': 'logs'}]},
      'type': 'code_interpreter'}],
    'type': 'tool_calls'},
   'thread_id': 'thread_AMQPcatbKuhqL8SMsTggLkdl',
   'type': 'tool_calls',
   'usage': {'completion_tokens': 107,
    'prompt_tokens': 154,
    'total_tokens': 261},
   'expires_at': None},
  {'id': 'step_vWH14ewi199t8aTMBx7GLEoV',
   'assistant_id': 'asst_Y7Ndt1RKCg2Cb4mhlpgVbGbS',
   'cancelled_at': None,
   'completed_at': 1716197343,
   'created_at': 1716197341,
   'expired_at': None,
   'failed_at': None,
   'last_error': None,
   'metadata': None,
   'object': 'thread.run.step',
   'run_id': 'run_pqOAuhLfHIBmPXJ7ttkNF6Gw',
   'status': 'completed',
   'step_details': {'message_creation': {'message_id': 'msg_ETt57jde3ZqDb0Bs0K2XEiWN'},
    'type': 'message_creation'},
   'thread_id': 'thread_AMQPcatbKuhqL8SMsTggLkdl',
   'type': 'message_creation',
   'usage': {'completion_tokens': 132,
    'prompt_tokens': 332,
    'total_tokens': 464},
   'expires_at': None}],
 'object': 'list',
 'first_id': 'step_9I2fBWyMtivKvaLauynEph6j',
 'last_id': 'step_vWH14ewi199t8aTMBx7GLEoV',
 'has_more': False}

Steps 내용 중 input에 있는 code_interpreter가 생성한 코드 copy and paste

  • print 구문과 함께 써 보면 개행 문자 포함 출력됨
print(run_steps.data[0].step_details.tool_calls[0].code_interpreter.input)
# 피보나치 수열의 최초 20개 숫자를 생성하는 함수
def generate_fibonacci(n):
    fibonacci_sequence = [0, 1]
    while len(fibonacci_sequence) < n:
        next_value = fibonacci_sequence[-1] + fibonacci_sequence[-2]
        fibonacci_sequence.append(next_value)
    return fibonacci_sequence

# 최초 20개의 피보나치 수열 생성
first_20_fibonacci = generate_fibonacci(20)
first_20_fibonacci
def generate_fibonacci(n):
    fibonacci_sequence = [0, 1]
    while len(fibonacci_sequence) < n:
        next_value = fibonacci_sequence[-1] + fibonacci_sequence[-2]
        fibonacci_sequence.append(next_value)
    return fibonacci_sequence

# 최초 20개의 피보나치 수열 생성
first_20_fibonacci = generate_fibonacci(20)
first_20_fibonacci
[0,
 1,
 1,
 2,
 3,
 5,
 8,
 13,
 21,
 34,
 55,
 89,
 144,
 233,
 377,
 610,
 987,
 1597,
 2584,
 4181]

Reference