5️⃣Assistants API

OpenAI의 Assistant APIarrow-up-rightChat Completions APIarrow-up-right를 발전시킨 것으로, 개발자가 어시스턴트와 유사한 경험을 간편하게 만들고 코드 해석기 및 검색과 같은 강력한 도구에 액세스할 수 있도록 하기 위한 것입니다.

Assistants API Diagram

Chat Completions API vs Assistants API

**Chat Completions API의 기본 요소는 Message로, Model(gpt-3.5-turbo, gpt-4 등)을 사용하여 Completion를 수행합니다. 가볍고 강력하지만 본질적으로 상태가 없으므로 대화 상태, 도구 정의, 검색 문서 및 코드 실행을 수동으로 관리해야 합니다.

어시스턴트 API**의 기본 요소는 다음과 같습니다.

  • Assistantc기본 모델, 지침, 도구 및 (컨텍스트) 문서를 캡슐화

  • Threads: 대화의 상태를 나타냄

  • Runs: 텍스트 응답 및 다단계 도구 사용 등 '스레드'에서 '어시스턴트'의 실행을 구동

이를 사용하여 강력하고 상태 저장된 경험을 만드는 방법을 살펴보겠습니다.

Setup

Python SDK

[!note] 어시스턴트 API에 대한 지원을 추가하기 위해 Python SDKarrow-up-right를 업데이트했으므로 최신 버전(작성 시점 기준 1.2.3)으로 업데이트해야 합니다.

Version: 1.2.3

Printing Helper 함수 정의

Complete Example with Assistants API

Assistants

어시스턴트 API를 시작하는 가장 쉬운 방법은 어시스턴트 플레이그라운드arrow-up-right를 이용하는 것입니다.

Assistants Playground

어시스턴트를 만드는 것부터 시작하겠습니다! 문서arrow-up-right에서와 마찬가지로 수학 튜터를 만들겠습니다.

Creating New Assistant

생성한 어시스턴트는 어시스턴트 대시보드arrow-up-right에서 확인할 수 있습니다. Assistants Dashboard

다음과 같이 어시스턴트 API를 통해 직접 어시스턴트를 만들 수도 있습니다:

대시보드를 통해 어시스턴트를 만들든 API를 통해 만들든 관계없이 어시스턴트 ID를 추적하고 싶을 것입니다. 이렇게 하면 스레드와 런에서 어시스턴트를 참조할 수 있습니다.

다음으로 새 스레드를 만들고 여기에 메시지를 추가하겠습니다. 여기에는 대화의 상태가 유지되므로 매번 전체 메시지 기록을 다시 보낼 필요가 없습니다.

Threads

새로운 thread 만들기:

그런 다음 스레드에 메시지를 추가합니다:

[!note] 더 이상 전체 대화 내역을 매번 전송하지 않더라도, 실행할 때마다 전체 대화 내역의 토큰에 대한 요금은 계속 청구됩니다.

Runs

우리가 만든 스레드가 앞서 만든 어시스턴트와 어떻게 연결되지 않는지 주목하세요! 스레드는 어시스턴트와 독립적으로 존재하며, 이는 ChatGPT(스레드가 모델/GPT에 연결되는 방식)를 사용했을 때 예상했던 것과는 다를 수 있습니다.

특정 스레드에 대해 어시스턴트로부터 Completion를 받으려면 실행을 만들어야 합니다. 실행을 만들면 어시스턴트가 스레드의 메시지를 살펴보고 단일 응답을 추가하거나 도구를 사용하여 조치를 취해야 함을 나타냅니다.

[!note] RunsAssistants APIChat Completion API의 주요 차이점입니다. Chat Completion에서는 모델이 단일 메시지로만 응답하지만, Assistants API에서는 실행을 통해 어시스턴트가 하나 또는 여러 도구를 사용하고 잠재적으로 여러 메시지를 스레드에 추가할 수 있습니다.

어시스턴트가 사용자에게 응답하도록 하려면 실행을 만들어 보겠습니다. 앞서 언급했듯이 어시스턴트와 스레드를 둘 다 지정해야 합니다.

Chat Completions API에서 completion를 만드는 것과 달리 Run 만들기는 비동기 작업**입니다. 실행의 메타데이터와 함께 즉시 반환되며, 여기에는 처음에는 queued으로 설정되는 status가 포함됩니다. status는 어시스턴트가 작업을 수행(예: 도구 사용 및 메시지 추가)할 때 업데이트됩니다.

어시스턴트가 언제 처리를 완료 했는지 알기 위해 Run을 반복적으로 폴링할 수 있습니다. 여기서는 queued 또는 in_progress 상태만 확인하지만, 실제로는 Run다양한 상태 변경arrow-up-right을 겪을 수 있으며, 이를 사용자에게 표시하도록 선택할 수 있습니다. (이를 Steps고 하며 나중에 다룰 예정입니다.

Messages

이제 실행이 완료되었으므로 스레드에 메시지를 나열하여 어시스턴트가 추가한 내용을 확인할 수 있습니다.

As you can see, Messages are ordered in reverse-chronological order – this was done so the most recent results are always on the first page (since results can be paginated). Do keep a look out for this, since this is the opposite order to messages in the Chat Completions API.

Let's ask our Assistant to explain the result a bit further!

보시다시피 메시지는 시간 역순으로 정렬되며, 이는 가장 최근의 결과가 항상 첫 번째 page에 표시되도록 하기 위함입니다. (결과 페이지 매김이 가능하기 때문에). 이는 Chat Completions API의 메시지와 반대 순서이므로 이 점에 유의하세요.

어시스턴트에게 결과에 대해 좀 더 자세히 설명해 달라고 요청해 보겠습니다!

특히 이 간단한 예제에서는 응답을 받기 위해 많은 단계를 거쳐야 하는 것처럼 느껴질 수 있습니다. 하지만 곧 코드를 전혀 변경하지 않고도 어시스턴트에 매우 강력한 기능을 추가할 수 있는 방법을 알게 될 것입니다!

Example

이 모든 것을 어떻게 조합할 수 있는지 살펴봅시다. 다음은 직접 만든 어시스턴트를 사용하는 데 필요한 모든 코드입니다.

이미 Math Assistants를 만들었으므로 그 ID를 MATH_ASSISTANT_ID에 저장했습니다. 그런 다음 두 개의 함수를 정의했습니다:

  • submit_message: 스레드에 메시지를 만든 다음 새 실행을 Run(및 returns)합니다.

  • get_response: 스레드 내 메시지 목록을 반환합니다.

또한 재사용할 수 있는 create_thread_and_run 함수도 정의했습니다(실제로는 API의 client.beta.threads.create_and_runarrow-up-right 복합 함수와 거의 동일합니다). 마지막으로 모의 사용자 요청을 각각 새 스레드에 제출할 수 있습니다.

이 모든 API 호출이 비동기 작업이라는 점에 주목하세요. 즉, 비동기 라이브러리를 사용하지 않고도 코드에서 실제로 비동기 동작을 얻을 수 있습니다! (예: asyncio)

모든 Runs이 진행되면 각 실행을 기다렸다가 응답을 받을 수 있습니다.

이 코드는 실제로 수학 어시스턴트에만 국한된 것이 아니라, Assistants ID만 변경하면 새 Assistants를 생성할 때 모두 사용할 수 있습니다! 이것이 바로 Assistants API의 힘입니다.

Tools

어시스턴트 API의 핵심 기능은 어시스턴트에 Code Interpreter, Retrieval, 사용자 지정 함수 등의 도구를 장착할 수 있는 기능입니다. 각각에 대해 살펴보겠습니다.

Code Interpreter

Let's equip our Math Tutor with the Code Interpreterarrow-up-right tool, which we can do from the Dashboard...

만들어진 수학 튜터에게 대시보드에서 사용할 수 있는 Code Interpreterarrow-up-right 도구를 장착해 봅시다...

Enabling code interpreter

...또는 Assistant ID를 사용하여 API에 접속합니다.

이제 어시스턴트에게 새 도구를 사용하도록 요청해 보겠습니다.

Steps

A Run is composed of one or more Steps. Like a Run, each Step has a status that you can query. This is useful for surfacing the progress of a Step to a user (e.g. a spinner while the Assistant is writing code or performing retrieval).

Run은 하나 이상의 스텝으로 구성됩니다. Run과 마찬가지로 각 단계에는 쿼리할 수 있는 status가 있습니다. 이는 사용자에게 Step의 진행 상황을 표시하는 데 유용합니다(예: 어시스턴트가 코드를 작성하거나 retrieval을 수행하는 동안 스피너가 작동하는 경우).

각 단계의 내용을 살펴보자면 step_details메서드를 사용

두 단계에 대한 step_details를 볼 수 있습니다:

  1. tool_calls (단일 스텝에 둘 이상 있을 수 있으므로 복수형)

  2. message_creation

첫 번째 단계는 tool_calls이며, 특히 code_interpreter를 사용합니다:

  • input: 도구가 호출되기 전에 생성된 파이썬 코드

  • output: 코드 인터프리터를 실행한 결과를 포함

두 번째 단계는 결과를 사용자에게 전달하기 위해 스레드에 추가한 message를 포함하는 message_creation입니다.

Retrieval

어시스턴트 API의 또 다른 강력한 도구는 Retrievalarrow-up-right으로, 어시스턴트가 질문에 답변할 때 지식창고로 사용할 파일을 업로드할 수 있는 기능입니다. 이 기능은 대시보드 또는 API에서 사용하려는 파일을 업로드할 수 있습니다.

Enabling retrieval

[!note] Retrieval에는 Annotationsarrow-up-right과 같은 더 복잡한 기능이 있으며, 이는 다른 설명서에서 다룰 수 있습니다.

Functions

As a final powerful tool for your Assistant, you can specify custom Functionsarrow-up-right (much like the Function Callingarrow-up-right in the Chat Completions API). During a Run, the Assistant can then indicate it wants to call one or more functions you specified. You are then responsible for calling the Function, and providing the output back to the Assistant.

Let's take a look at an example by defining a display_quiz() Function for our Math Tutor.

This function will take a title and an array of questions, display the quiz, and get input from the user for each:

어시스턴트를 위한 마지막 강력한 도구로 사용자 지정 Functionsarrow-up-right를 지정할 수 있습니다(Chat Completions API의 Function Calling, 함수 호출arrow-up-right과 매우 유사). 그러면 실행 중에 어시스턴트가 사용자가 지정한 하나 이상의 함수를 호출하고 싶다고 표시할 수 있습니다. 그러면 사용자는 함수를 호출하고 그 결과를 다시 어시스턴트에게 제공할 책임이 있습니다.

수학 튜터에 대한 display_quiz() 함수를 정의하여 예를 살펴 보겠습니다.

이 함수는 titlequestions'의 배열을 받아 퀴즈를 표시하고 각각에 대해 사용자로부터 입력을 받습니다:

  • title

  • questions

    • question_text

    • question_type: [MULTIPLE_CHOICE, FREE_RESPONSE]

    • choices: ["choice 1", "choice 2", ...]

안타깝게도 파이썬 노트북 내에서 사용자 입력을 가져오는 방법을 모르기 때문에 get_mock_response...로 응답을 모의해 보겠습니다. 여기에서 사용자의 실제 입력을 얻을 수 있습니다.

다음은 샘플 퀴즈의 모습입니다:

이제 어시스턴트가 호출할 수 있도록 이 함수의 인터페이스를 JSON 형식으로 정의해 보겠습니다:

다시 한 번 대시보드 또는 API를 통해 어시스턴트를 업데이트해 보겠습니다.

Enabling custom function

[!note] 함수 JSON을 대시보드에 붙여넣는 것은 들여쓰기 등으로 인해 약간 까다로웠습니다. 저는 대시보드에 있는 예제 중 하나와 동일하게 함수의 형식을 지정해 달라고 ChatGPT에 요청했습니다.

이제 퀴즈를 출제합니다.

하지만 이제 실행의 상태를 확인하면 requires_action이 표시됩니다! 자세히 살펴봅시다.

required_action 필드는 Tool이 실행되고 그 출력을 다시 어시스턴트에게 제출하기를 기다리고 있음을 나타냅니다. 구체적으로는 display_quiz 함수입니다! namearguments를 파싱하는 것부터 시작해 보겠습니다.

[!note] 이 경우에는 Tool 호출이 하나만 있지만, 실제로는 어시스턴트가 여러 도구를 호출하도록 선택할 수 있습니다.

이제 어시스턴트가 제공한 인수를 사용하여 display_quiz 함수를 실제로 호출해 보겠습니다:

이 응답은 앞서 mocked respones라는 것을 기억하세요. 실제로는 이 함수 호출을 통해 뒤쪽에서 입력을 받을 것입니다).

이제 응답을 얻었으니 어시스턴트에게 다시 제출해 봅시다. 여기에는 앞서 파싱한 tool_call에서 찾은 tool_call ID가 필요합니다. 또한 응답의 liststr으로 인코딩해야 합니다.

이제 다시 한 번 Run이 완료되기를 기다렸다가 스레드를 확인할 수 있습니다!

Last updated