OpenAI Assistants API 사용해보기

개요

Workflow

  • OpenAI의 Assistants API는 OpenAI의 model, tool, file을 이용하여 대화형 AI시스템을 구축할 수 있는 API이다.
  • 기존 OpenAI Chat Completion과 Assistant API의 차이점은
    • Chat Completion은 각 질문이 독립적으로 수행되어 대화의 context를 고려한 답변을 제시하지 않는다.
    • Assistants API는 Thread 를 통해 사용자와 assistant간의 대화 맥락을 유지하며 답변을 제공한다.
  • 현재 openai api (v1.54.4) 에서는 code interpreter, file search, custom function calling tool을 제공하고 있다.
Assistant API에서는
  1. 하나의 thread에서 사용자와 assistant간의 대화 기록이 저장되어 Assistant는 대화 문맥을 기반으로 답변을 제공하고 (= session)
  1. 사용자가 질문 (message)를 입력하면 run을 통해 assistant에게 전달되어
  1. Tool 사용, 답변 생성의 step을 통해 assistant가 적절한 답변을 제공한다.
Assistant API에서는
  1. 하나의 thread에서 사용자와 assistant간의 대화 기록이 저장되어 Assistant는 대화 문맥을 기반으로 답변을 제공하고 (= session)
  1. 사용자가 질문 (message)를 입력하면 run을 통해 assistant에게 전달되어
  1. Tool 사용, 답변 생성의 step을 통해 assistant가 적절한 답변을 제공한다.

주요 용어 정리

  • Assistant: Task 수행에 필요한 구성 요소를 정의
    • Instruction (= system message), OpenAI model, 사용할 tool 등
  • Thread: 사용자-assistant간의 대화 session
  • Message: 대화 참여자 (사용자/assistant)가 생성하는 message
  • Run: 사용자의 질문을 assistant의 답변으로 변환하는 단계
  • Run step: run을 실행 시 수반되는 단계
    • Function call, file search, code interpreter, message creation 등

2. 세부 사항

Assistant

  • Assistant는 task를 수행하는 요소들(instruction, OpenAI model, 사용할 tool 등)로 정의된다.
  • Instruction은 각 assistant가 작동해야 하는 방식(rule, persona, tone 등)을 설정한다.
    • Assistant에 설정한 instruction은 모든 run에서 동일하게 적용된다(system message와 유사한 역할 수행).
    • 각 run마다 다른 task를 수행하기 위해서는 개별 run에서 instruction을 수정하거나 추가할 수 있다(Run 참조).
  • Generation parameter(temperature, top_p)를 설정하여 모델의 무작위성을 조절할 수 있다.
  • 어떤 tool을 사용할지 설정할 수 있다.
  • TODO: response_format
Code
from openai import OpenAI client = OpenAI() assistant = client.beta.assistants.create( description="DESCRIPTION OF ASSISTANT" # assistant에 관한 설명. 실제 response 생성 과정에서는 영향이 없는 것으로 파악됨. instructions="SYSTEM MESSAGE", # system prompt와 비슷함. 한번 설정되면 name="NAME OF THE CLIENT", model="gpt-4o", # GPT 계열의 모델 설정 가능 https://platform.openai.com/docs/models tools=[{"type": "code_interpreter"}, {"type": "file_search"}], tool_resources={ "file_search": { "vector_store_ids": [vector_store_id] }, "code_interpreter": { "file_ids": [file_id] }, }, temperature=1.0, top_p=1.0 )

Thread

  • Thread는 사용자와 assistant 간의 대화 상호작용이 이루어지는 세션을 의미한다.
  • 일반적인 OpenAI의 Chat Completion과 달리, Thread에서는 대화 기록이 유지된다. 이로 인해 새로운 run이 실행될 때마다 이전 맥락을 고려하여 답변을 제공할 수 있다.
    • ChatGPT의 세션과 유사한 개념이다.
  • 동일한 세션에서 대화를 이어가려면 해당 thread의 ID만 정확히 전달하면 된다.
  • 새로운 thread를 생성할 때 (1) 대화 내용이 없는 빈 thread를 만들거나, (2) 사용자의 질문이 포함된 thread를 만들 수 있다.
    • (1) 빈 thread를 만들 때는 추가로 사용자나 assistant의 message를 넣어야 한다.
    • (2) (1)의 과정을 한 번에 수행하여 사용자의 message가 포함된 thread를 생성한다.
Code
from openai import OpenAI client = OpenAI() # Thread without user messages and add message empty_thread = client.beta.threads.create() thread_message = client.beta.threads.message.create( thread_id=empty_thread.id, role="user" OR "assistant", content="MESSAGE" ) # Thread with user message message_thread = client.beta.threads.create( messages=[{"role": "user" OR "assistant", "content": "MESSAGE" }] )

Messages

  • Message는 thread에 사용자나 assistant의 메시지를 전달한다.
  • 사용자 message는 run을 통해 assistant에게 전달될 메시지를 의미한다.
    • TODO: assistant message의 동작법
  • Message는 단순한 입력이므로, 실제 출력을 얻기 위해서는 run을 실행해야 한다.
Code
from openai import OpenAI client = OpenAI() thread = client.beta.threads.create() thread_message = client.beta.threads.message.create( thread_id=thread.id, role="user" OR "assistant", content="MESSAGE" )
 

Run

  • Run은 thread에서 assistant를 실행하여 (tool을 사용하거나 generation config에 맞춰) 답변을 생성한다.
    • ChatGPT의 한 번의 질문과 답변 pair와 유사함
  • Run은 비동기적으로 실행되며, 종료되어야 response를 받을 수 있다.
    • Run이 완료되기를 확인해야 한다 (status == “completed”)
    • threads.runs.create_and_poll()을 사용하면 run 생성과 종료 시 polling을 한 번에 수행한다.
  • 매 run마다 instruction을 수정(override)하거나 추가할 수 있으며, message 생성과 run을 동시에 진행할 수 있다.
  • File search tool을 사용하는 경우, include=[step_details.tool_calls[*].file_search.results[*].content]를 추가하여 file search 결과를 불러올 수 있다.
    • 각 file search 결과는 run step 참조
Code
from openai import OpenAI client = OpenAI() # Create a run run = client.beta.threads.runs.create( thread_id=thread.id, assistant_id=assistant.id ) # Create a thread and execute run = client.beta.threads.create_and_run( assistant_id=assistant.id, thread={ "messages": [ {"role": "user" OR "assistant", "content": "MESSAGE"} ] } # Create a run and poll when completed run = client.beta.threads.runs.create_and_poll( assistant_id=assistant.id, thread_id=thread.id, instructions="INSTRUCTION TO OVERRIDE", additional_instructions="INSTRUCTION TO APPEND AT ASSISTANT'S INSTRUCTION", additional_messages=[ { "role": "user" OR "assistant", "content": "A MESSAGE FOR NEW RUN" } ], include=[step_details.tool_calls[*].file_search.results[*].content] )

Run steps

  • Run step은 run이 실행되는 동안의 모델 작업과 도구 호출에 대한 단계를 나타낸다.
  • Run이 실행되면 자동으로 생성되므로 thread와 run ID를 통해 각 단계별 출력을 확인할 수 있다.
Code
from openai import OpenAI client = OpenAI() # Get the run steps run_steps = client.beta.threads.runs.steps.list( thread_id=thread.id, run_id=run.id ) # Retrieve the specific step output run_step = client.beta.threads.runs.steps.retrieve( thread_id=thread.id, run_id=run.id, step_id=step.id, # To include the search file results, please add the line below include=["step_details.tool_calls[*].file_search.results[*].content"], )