ReactNextCentral
Published on

버셀 AI SDK 사용을 위한 필수 배경 지식: 제공자와 모델, 프롬프트, 스트리밍, 도구와 어시스턴트

버셀 AI SDK의 제공자, 모델, 프롬프트, 스트리밍, 도구와 어시스턴트에 대한 필수 배경 지식을 소개합니다. 이 글에서는 각 요소의 정의와 사용 사례를 통해 SDK 활용 방법을 자세히 설명합니다.
버셀 AI SDK 사용을 위한 필수 배경 지식: 제공자와 모델, 프롬프트, 스트리밍, 도구와 어시스턴트
Authors
Table of Contents

이번 글에서는 버셀 AI SDK를 사용하기에 앞서 필수적인 배경 지식을 알아보겠습니다. 먼저, 버셀 AI SDK에서 대규모 언어 모델을 제공하는 다양한 제공자들에 대해 살펴보겠습니다. 또한, 프롬프트를 텍스트 프롬프트, 메시지 프롬프트, 시스템 프롬프트로 구분하여 이에 대해 알아보겠습니다. 그 후, AI SDK에서의 스트리밍과 Next.js에서의 스트리밍의 미묘한 차이를 논의하고, OpenAI에서 제공하는 도구(함수 호출)와 어시스턴트가 무엇인지 알아보겠습니다.


제공자와 모델

제공자는 AI 모델을 개발하고 이를 사용할 수 있는 API나 서비스 형태로 제공하는 회사나 플랫폼을 의미합니다. 모델은 제공자가 개발한 AI 시스템으로 특정 작업을 수행하기 위해 훈련된 대규모 언어 모델(LLM)을 말합니다.

제공자와 모델의 차이점

  • 제공자 (Providers): AI 기술과 인프라를 개발하고 배포하는 회사 또는 플랫폼

    • 예: OpenAI, Azure, Anthropic, Amazon Bedrock, Google Generative AI
    • 특징: 제공자는 다양한 모델을 지원하며 각 제공자는 고유한 기능과 특성을 가지고 있습니다. 예를 들어, OpenAI는 GPT-4와 GPT-3.5-turbo 모델을 제공하며, Amazon Bedrock은 AWS 인프라와의 통합을 통해 AI 및 머신러닝 모델을 손쉽게 배포할 수 있는 서비스를 제공합니다.
  • 모델 (Models): 제공자가 개발한 AI 시스템으로 특정 작업을 수행하기 위해 훈련된 대규모 언어 모델

    • 예: GPT-4, Claude 3, Gemini 1.5 Pro
    • 특징: 각 모델은 고유의 학습 데이터와 알고리즘을 바탕으로 특정 작업(예: 텍스트 생성, 데이터 분석 등)을 수행합니다. 예를 들어, GPT-4는 자연어 처리와 생성에서 뛰어난 성능을 보이며 Claude 3는 안전하고 윤리적인 AI 모델을 강조합니다.

주요 제공자와 모델

  1. OpenAI

    • 주요 모델: GPT-4, GPT-3.5-turbo
    • 특징: 자연어 처리 및 생성에서 뛰어난 성능을 보이며, 다양한 언어 모델을 제공하여 텍스트 생성, 대화, 번역 등 다양한 용도로 활용 가능
    • 장점: 높은 정확도와 유연성, 광범위한 응용 분야 지원
  2. Azure OpenAI

    • 주요 모델: GPT-4, GPT-3.5-turbo
    • 특징: Microsoft Azure 클라우드 플랫폼과 통합되어 데이터 분석, 번역, 음성 인식 등 다양한 AI 기능을 제공
    • 장점: 높은 확장성, Azure 생태계와의 원활한 통합
  3. Anthropic

    • 주요 모델: Claude 3.5, Claude 3
    • 특징: 윤리적 AI와 안전한 AI 연구에 중점을 두고 있는 회사로, 대규모 언어 모델을 개발하여 안전하고 신뢰할 수 있는 AI 서비스를 제공
    • 장점: 안전하고 윤리적인 AI 모델 제공, 사용자 데이터 보호
  4. Amazon Bedrock

    • 주요 모델: Bedrock AI Services
    • 특징: AWS의 인프라와 통합되어 AI 및 머신러닝 모델을 손쉽게 배포하고 관리할 수 있는 플랫폼 제공
    • 장점: AWS와의 통합으로 높은 확장성과 안정성, 다양한 AI 모델 및 서비스 지원
  5. Google Generative AI

    • 주요 모델: Gemini 1.5 Pro
    • 특징: Google의 강력한 인프라와 AI 연구를 바탕으로 생성형 AI 모델을 제공하여 텍스트 생성, 대화, 데이터 분석 등 다양한 용도로 활용 가능
    • 장점: 높은 성능과 신뢰성, Google 생태계와의 원활한 통합
  6. Mistral

    • 주요 모델: Mistral Large, Mistral Small
    • 특징: 효율적인 모델 아키텍처를 제공하여 다양한 규모의 언어 모델을 지원
    • 장점: 경량 모델 제공, 다양한 애플리케이션에 유연하게 적용 가능
  7. Google Vertex AI

    • 주요 모델: Vertex AI Models
    • 특징: Google의 인프라를 활용한 고성능 AI 모델 제공, 데이터 분석과 머신러닝 워크플로우 통합 지원
    • 장점: 높은 확장성, Google의 다양한 AI 도구와 통합 가능
  8. Cohere

    • 주요 모델: Cohere Language Models
    • 특징: 텍스트 생성, 데이터 분석, 자연어 처리에 강점을 가진 AI 모델 제공
    • 장점: 고성능 자연어 처리 기능, 다양한 산업 분야에 적용 가능

프롬프트

프롬프트는 대규모 언어 모델(LLM)에게 수행할 작업을 지시하는 명령문입니다.

버셀 AI SDK에서는 프롬프트를 텍스트 프롬프트, 메시지 프롬프트, 시스템 프롬프트로 구분합니다. 아래에서 OpenAI API와 비교하여 설명하겠습니다.

Text Prompts (텍스트 프롬프트)

텍스트 프롬프트는 간단한 문자열 형태로 제공되며 동일한 프롬프트 텍스트의 변형을 반복 생성하는 데 적합합니다. OpenAI API에서는 prompt 속성을 사용하여 텍스트 프롬프트를 설정합니다.

Vercel AI SDK 예시:

const result = await generateText({
  model: 'gpt-3.5-turbo',
  prompt: 'Invent a new holiday and describe its traditions.',
});

OpenAI API 예시:

import OpenAI from "openai";

const openai = new OpenAI();

async function main() {
  const response = await openai.completions.create({
    model: "text-davinci-003",
    prompt: "Invent a new holiday and describe its traditions.",
    max_tokens: 100
  });

  console.log(response.choices[0].text);
}

main();

Vercel AI SDK 예시:

const result = await generateText({
  model: 'gpt-3.5-turbo',
  prompt: `I am planning a trip to ${destination} for ${lengthOfStay} days. Please suggest the best tourist activities for me to do.`,
});

OpenAI API 예시:

import OpenAI from "openai";

const openai = new OpenAI();
const destination = "Paris";
const lengthOfStay = 5;

async function main() {
  const response = await openai.completions.create({
    model: "text-davinci-003",
    prompt: `I am planning a trip to ${destination} for ${lengthOfStay} days. Please suggest the best tourist activities for me to do.`,
    max_tokens: 100
  });

  console.log(response.choices[0].text);
}

main();

Message Prompts (메시지 프롬프트)

메시지 프롬프트는 사용자, 어시스턴트, 도구 메시지 등의 배열로 구성됩니다. 채팅 인터페이스나 복잡한 다중 모달 프롬프트에 적합합니다. 각 메시지는 rolecontent 속성을 가지며, OpenAI API의 messages 속성과 유사합니다.

Vercel AI SDK 예시:

const result = await streamUI({
  model: 'gpt-3.5-turbo',
  messages: [
    { role: 'user', content: 'Hi!' },
    { role: 'assistant', content: 'Hello, how can I help?' },
    { role: 'user', content: 'Where can I buy the best Currywurst in Berlin?' },
  ],
});

OpenAI API 예시:

import OpenAI from "openai";

const openai = new OpenAI();

async function main() {
  const response = await openai.chat.completions.create({
    model: "gpt-3.5-turbo",
    messages: [
      { role: "user", content: "Hi!" },
      { role: "assistant", content: "Hello, how can I help?" },
      { role: "user", content: "Where can I buy the best Currywurst in Berlin?" }
    ]
  });

  console.log(response.choices[0].message.content);
}

main();

System Prompts (시스템 프롬프트)

시스템 메시지는 모델에게 초기 지시 사항을 제공하여 모델의 동작과 응답을 안내합니다. OpenAI API의 system 속성과 유사합니다.

Vercel AI SDK 예시:

const result = await generateText({
  model: 'gpt-3.5-turbo',
  system: 'You help planning travel itineraries. Respond to the users\' request with a list of the best stops to make in their destination.',
  prompt: `I am planning a trip to ${destination} for ${length_of_stay} days. Please suggest the best tourist activities for me to do.`,
});

OpenAI API 예시:

import OpenAI from "openai";

const openai = new OpenAI();
const destination = "Paris";
const lengthOfStay = 5;

async function main() {
  const response = await openai.chat.completions.create({
    model: "gpt-3.5-turbo",
    messages: [
      { role: "system", content: "You help planning travel itineraries. Respond to the users' request with a list of the best stops to make in their destination." },
      { role: "user", content: `I am planning a trip to ${destination} for ${lengthOfStay} days. Please suggest the best tourist activities for me to do.` }
    ]
  });

  console.log(response.choices[0].message.content);
}

main();

Multi-modal Messages

다중 모달 메시지는 텍스트, 이미지, 오디오 등 다양한 데이터 유형을 포함하여 모델과 상호 작용합니다. OpenAI API에서는 content 속성에 텍스트 외에 다른 데이터 유형을 배열 형태로 포함시킬 수 있습니다.

Vercel AI SDK 예시:

const result = await generateText({
  model: 'gpt-3.5-turbo',
  messages: [
    {
      role: 'user',
      content: [
        { type: 'text', text: 'Describe the image in detail.' },
        { type: 'image', image: fs.readFileSync('./data/comic-cat.png') },
      ],
    },
  ],
});

OpenAI API 예시:

import OpenAI from "openai";
import fs from "fs";
import path from "path";

const openai = new OpenAI();
const imagePath = path.resolve('./data/comic-cat.png');
const imageBase64 = fs.readFileSync(imagePath).toString('base64');

async function main() {
  const response = await openai.chat.completions.create({
    model: "gpt-3.5-turbo",
    messages: [
      {
        role: "user",
        content: [
          { type: "text", text: "Describe the image in detail." },
          { type: "image", image: imageBase64 }
        ]
      }
    ]
  });

  console.log(response.choices[0].message.content);
}

main();

Tool Messages

도구 메시지는 모델의 내장 기능을 확장하기 위해 외부 API 호출이나 UI 내 함수를 사용할 수 있도록 합니다. OpenAI API에서는 tooltool-result 타입의 메시지로 도구 호출을 처리합니다.

Vercel AI SDK 예시:

const result = await generateText({
  model: 'gpt-3.5-turbo',
  messages: [
    {
      role: 'user',
      content: [
        { type: 'text', text: 'How many calories are in this block of cheese?' },
        { type: 'image', image: fs.readFileSync('./data/roquefort.jpg') },
      ],
    },
    {
      role: 'assistant',
      content: [
        {
          type: 'tool-call',
          toolCallId: '12345',
          toolName: 'get-nutrition-data',
          args: { cheese: 'Roquefort' },
        },
      ],
    },
    {
      role: 'tool',
      content: [
        {
          type: 'tool-result',
          toolCallId: '12345', // needs to match the tool call id
          toolName: 'get-nutrition-data',
          result: {
            name: 'Cheese, roquefort',
            calories: 369,
            fat: 31,
            protein: 22,
          },
        },
      ],
    },
  ],
});

OpenAI API 예시:

import OpenAI from "openai";
import fs from "fs";
import path from "path";

const openai = new OpenAI();
const imagePath = path.resolve('./data/roquefort.jpg');
const imageBase64 = fs.readFileSync(imagePath).toString('base64');

async function main() {
  const response = await openai.chat.completions.create({
    model: "gpt-3.5-turbo",
    messages: [
      {
        role: "user",
        content: [
          { type: "text", text: "How many calories are in this block of cheese?" },
          { type: "image", image: imageBase64 }
        ]
      },
      {
        role: "assistant",
        content: [
          {
            type: "tool-call",
            toolCallId: "12345",
            toolName: "get-nutrition-data",
            args: { cheese: "Roquefort" }
          }
        ]
      },
      {
        role: "tool",
        content: [
          {
            type: "tool-result",
            toolCallId: "12345",
            toolName: "get-nutrition-data",
            result: {
              name: "Cheese, roquefort",
              calories: 369,
              fat: 31,
              protein: 22,
            },
          },
        ]
      }
    ]
  });

  console.log(response.choices[0].message.content);
}

main();

웹 개발에서의 스트리밍, 버셀 AI SDK 스트리밍, 그리고 Next.js 스트리밍 정의와 차이점

웹 개발에서의 스트리밍

정의: 웹 개발에서 스트리밍은 데이터를 작은 청크(chunk)로 나누어 전송하여 전체 데이터가 모두 전송되기 전에 일부 데이터를 먼저 사용할 수 있게 하는 기술입니다.

주요 특징:

  • 지연 시간 감소: 전체 데이터가 전송될 때까지 기다리지 않고, 빠르게 데이터 일부를 처리할 수 있습니다.
  • 사용자 경험 개선: 로딩 시간을 줄이고, 빠른 피드백을 제공하여 사용자 경험을 향상시킵니다.

버셀 AI SDK에서의 스트리밍

정의: 버셀 AI SDK에서의 스트리밍은 대규모 언어 모델(LLM)로부터 생성된 텍스트를 청크 단위로 스트리밍하여 실시간으로 사용자에게 전달하는 방식입니다.

주요 특징:

  • 실시간 텍스트 전송: 긴 응답 시간을 피하고 텍스트의 일부가 생성될 때마다 즉시 사용자에게 전달합니다.
  • 대화형 애플리케이션에 최적: 챗봇 등 실시간 상호작용이 필요한 애플리케이션에서 유용합니다.

예제:

import { openai } from '@ai-sdk/openai';
import { streamText } from 'ai';

const { textStream } = await streamText({
  model: openai('gpt-4-turbo'),
  prompt: 'Write a poem about embedding models.',
});

for await (const textPart of textStream) {
  console.log(textPart);
}

OpenAI API:

import OpenAI from "openai";

const openai = new OpenAI();

async function main() {
  const completion = await openai.chat.completions.create({
    messages: [{ role: "system", content: "You are a helpful assistant." }],
    model: "gpt-4-turbo",
    stream: true,
  });

  for await (const part of completion.choices) {
    console.log(part.text);
  }
}

main();

Next.js에서의 스트리밍

정의: Next.js에서의 스트리밍은 서버 사이드 렌더링(SSR) 중에 HTML 콘텐츠를 청크 단위로 클라이언트에 전송하여 모든 데이터가 준비되기 전에 페이지 일부를 먼저 렌더링하는 방식입니다.

주요 특징:

  • 빠른 첫 화면 표시: 전체 페이지가 로드되기 전에 일부 UI를 먼저 표시하여 사용자에게 빠른 피드백을 제공합니다.
  • 서버와 클라이언트의 효율적인 협력: 데이터 로드가 완료되기 전에 부분적으로 UI를 렌더링하고 리액트의 선택적 하이드레이션을 통해 필요한 컴포넌트부터 상호작용을 가능하게 합니다.

예제:

import { Suspense } from 'react';

function Posts() {
  return (
    <section>
      <Suspense fallback={<p>Loading feed...</p>}>
        <PostFeed />
      </Suspense>
      <Suspense fallback={<p>Loading weather...</p>}>
        <Weather />
      </Suspense>
    </section>
  );
}

export default Posts;

요약:

  • 웹 개발에서의 스트리밍: 일반적인 데이터 스트리밍 기술로, 데이터를 작은 청크로 나누어 빠르게 전송
  • 버셀 AI SDK에서의 스트리밍: LLM의 텍스트를 실시간으로 스트리밍하여 사용자에게 즉시 제공
  • Next.js에서의 스트리밍: SSR 중 HTML 콘텐츠를 청크 단위로 전송하여 빠른 첫 화면 표시 및 선택적 하이드레이션 지원

각각의 스트리밍 방식은 특정 용도에 맞게 설계되어 있으며 사용자가 요구하는 빠른 응답성과 실시간 상호작용을 제공하는 데 큰 장점을 가지고 있습니다.


도구와 어시스턴트

도구(함수 호출)

정의: 도구(함수 호출)는 대규모 언어 모델(LLM)이 수행하기 어려운 특정 작업을 처리하기 위해 호출할 수 있는 프로그램입니다. 도구는 모델이 필요할 때 실행되며 외부 API와 상호작용하거나 특정 기능을 수행할 수 있습니다.

사용 시나리오:

  1. 날씨 정보 제공:

    • 상황: 사용자가 챗봇에게 특정 도시의 날씨를 물어봅니다.
    • 동작: 챗봇은 OpenWeatherMap API를 호출하여 해당 도시의 실시간 날씨 정보를 가져옵니다.
    • 코드 예시 (Vercel AI SDK):
    import { z } from 'zod';
    import { generateText, tool } from 'ai';
    
    const result = await generateText({
      model: yourModel,
      tools: {
        weather: tool({
          description: 'Get the weather in a location',
          parameters: z.object({
            location: z.string().describe('The location to get the weather for'),
          }),
          execute: async ({ location }) => ({
            location,
            temperature: 72 + Math.floor(Math.random() * 21) - 10,
          }),
        }),
      },
      toolChoice: 'required', // force the model to call a tool
      prompt: 'What is the weather in San Francisco and what attractions should I visit?',
    });
    
    • 코드 예시 (OpenAI API):
    import OpenAI from "openai";
    import fs from "fs";
    import path from "path";
    
    const openai = new OpenAI();
    const imagePath = path.resolve('./data/roquefort.jpg');
    const imageBase64 = fs.readFileSync(imagePath).toString('base64');
    
    async function main() {
      const response = await openai.chat.completions.create({
        model: "gpt-3.5-turbo",
        messages: [
          {
            role: "user",
            content: [
              { type: "text", text: "How many calories are in this block of cheese?" },
              { type: "image", image: imageBase64 }
            ]
          },
          {
            role: "assistant",
            content: [
              {
                type: "tool-call",
                toolCallId: "12345",
                toolName: "get-nutrition-data",
                args: { cheese: "Roquefort" }
              }
            ]
          },
          {
            role: "tool",
            content: [
              {
                type: "tool-result",
                toolCallId: "12345",
                toolName: "get-nutrition-data",
                result: {
                  name: 'Cheese, roquefort',
                  calories: 369,
                  fat: 31,
                  protein: 22,
                },
              }
            ]
          }
        ],
      });
    
      console.log(response);
    }
    
    main();
    

어시스턴트

정의: 어시스턴트는 AI 모델과의 상호작용을 관리하고 사용자가 요청한 작업을 수행하며 결과를 제공하는 기능입니다. 이를 통해 복잡한 작업을 처리하고 사용자에게 보다 풍부한 상호작용을 제공할 수 있습니다.

사용 시나리오:

  1. 여행 계획 지원:

    • 상황: 사용자가 챗봇에게 여행 계획을 세우는 데 도움을 요청합니다.
    • 동작: 챗봇은 사용자의 요청에 따라 여행 경로를 추천하고, 관련 정보를 제공합니다.
    • 코드 예시 (Vercel AI SDK):
    'use client';
    
    import { Message, useAssistant } from 'ai/react';
    
    export default function Chat() {
      const { status, messages, input, submitMessage, handleInputChange } = useAssistant({ api: '/api/assistant' });
    
      return (
        <div>
          {messages.map((m: Message) => (
            <div key={m.id}>
              <strong>{`${m.role}: `}</strong>
              {m.role !== 'data' && m.content}
              {m.role === 'data' && (
                <>
                  {(m.data as any).description}
                  <br />
                  <pre className={'bg-gray-200'}>
                    {JSON.stringify(m.data, null, 2)}
                  </pre>
                </>
              )}
            </div>
          ))}
    
          {status === 'in_progress' && <div />}
    
          <form onSubmit={submitMessage}>
            <input
              disabled={status !== 'awaiting_message'}
              value={input}
              placeholder="What is the temperature in the living room?"
              onChange={handleInputChange}
            />
          </form>
        </div>
      );
    }
    
    • 코드 예시 (OpenAI API):
    import OpenAI from 'openai';
    
    const openai = new OpenAI({
      apiKey: process.env.OPENAI_API_KEY || '',
    });
    
    export async function POST(req: Request) {
      const input: { threadId: string | null; message: string; } = await req.json();
      const threadId = input.threadId ?? (await openai.beta.threads.create({})).id;
      const createdMessage = await openai.beta.threads.messages.create(threadId, {
        role: 'user',
        content: input.message,
      });
    
      return AssistantResponse(
        { threadId, messageId: createdMessage.id },
        async ({ forwardStream, sendDataMessage }) => {
          const runStream = openai.beta.threads.runs.stream(threadId, {
            assistant_id: process.env.ASSISTANT_ID ?? (() => {
              throw new Error('ASSISTANT_ID is not set');
            })(),
          });
    
          let runResult = await forwardStream(runStream);
    
          while (runResult?.status === 'requires_action' && runResult.required_action?.type === 'submit_tool_outputs') {
            const tool_outputs = runResult.required_action.submit_tool_outputs.tool_calls.map(
              (toolCall: any) => {
                const parameters = JSON.parse(toolCall.function.arguments);
    
                switch (toolCall.function.name) {
                  default:
                    throw new Error(`Unknown tool call function: ${toolCall.function.name}`);
                }
              },
            );
    
            runResult = await forwardStream(
              openai.beta.threads.runs.submitToolOutputsStream(threadId, runResult.id, { tool_outputs }),
            );
          }
        },
      );
    }
    

도구(함수 호출)와 어시스턴트: 차이점과 사용 사례

도구(함수 호출)

도구(함수 호출)는 대규모 언어 모델(LLM)이 수행하기 어려운 특정 작업을 처리하기 위해 호출할 수 있는 프로그램입니다. 예를 들어, 복잡한 계산이나 외부 API와의 상호작용이 필요한 작업에서 도구를 사용합니다.

주요 사용 사례:

  1. 날씨 정보 제공:

    • 사용자가 챗봇에게 특정 도시의 날씨를 물어보면, 챗봇은 OpenWeatherMap API를 호출하여 해당 도시의 실시간 날씨 정보를 가져옵니다.
    • 코드 예시 (Vercel AI SDK):
    import { z } from 'zod';
    import { generateText, tool } from 'ai';
    
    const result = await generateText({
      model: yourModel,
      tools: {
        weather: tool({
          description: 'Get the weather in a location',
          parameters: z.object({
            location: z.string().describe('The location to get the weather for'),
          }),
          execute: async ({ location }) => ({
            location,
            temperature: 72 + Math.floor(Math.random() * 21) - 10,
          }),
        }),
      },
      toolChoice: 'required', // force the model to call a tool
      prompt: 'What is the weather in San Francisco and what attractions should I visit?',
    });
    

어시스턴트

어시스턴트는 도구(함수 호출)보다 더 복잡하고 다양한 작업을 수행할 수 있는 AI입니다. 어시스턴트는 여러 모델과 도구를 병렬로 사용할 수 있으며 지속적인 대화의 맥락을 유지하고 파일을 처리하는 등의 기능을 제공합니다.

주요 기능:

  1. 모델 호출: 특정 지침을 통해 모델의 성격과 기능을 조정할 수 있습니다.
  2. 병렬 도구 사용: 여러 도구를 동시에 호출하여 복잡한 작업을 수행할 수 있습니다.
  3. 지속적인 대화 맥락 유지: 대화의 맥락을 유지하고 메시지 기록을 저장하여 긴 대화에서도 일관성을 유지합니다.
  4. 파일 접근 및 생성: 다양한 형식의 파일을 읽고 생성할 수 있습니다.

주요 사용 사례:

  1. 코드 해석 및 파일 검색:

    • 사용자가 챗봇에게 코드 문제를 물어보면, 어시스턴트는 코드 해석 도구를 사용하여 문제를 분석하고 파일 검색 도구를 통해 관련 파일을 찾아 제공합니다.
    • 코드 예시 (OpenAI API):
    import OpenAI from 'openai';
    
    const openai = new OpenAI({
      apiKey: process.env.OPENAI_API_KEY || '',
    });
    
    export async function POST(req: Request) {
      const input: { threadId: string | null; message: string; } = await req.json();
      const threadId = input.threadId ?? (await openai.beta.threads.create({})).id;
      const createdMessage = await openai.beta.threads.messages.create(threadId, {
        role: 'user',
        content: input.message,
      });
    
      return AssistantResponse(
        { threadId, messageId: createdMessage.id },
        async ({ forwardStream, sendDataMessage }) => {
          const runStream = openai.beta.threads.runs.stream(threadId, {
            assistant_id: process.env.ASSISTANT_ID ?? (() => {
              throw new Error('ASSISTANT_ID is not set');
            })(),
          });
    
          let runResult = await forwardStream(runStream);
    
          while (runResult?.status === 'requires_action' && runResult.required_action?.type === 'submit_tool_outputs') {
            const tool_outputs = runResult.required_action.submit_tool_outputs.tool_calls.map(
              (toolCall: any) => {
                const parameters = JSON.parse(toolCall.function.arguments);
    
                switch (toolCall.function.name) {
                  default:
                    throw new Error(`Unknown tool call function: ${toolCall.function.name}`);
                }
              },
            );
    
            runResult = await forwardStream(
              openai.beta.threads.runs.submitToolOutputsStream(threadId, runResult.id, { tool_outputs }),
            );
          }
        },
      );
    }
    
  2. 복잡한 질문 응답:

    • 사용자가 챗봇에게 복잡한 질문을 하면, 어시스턴트는 여러 도구를 사용하여 질문에 대한 종합적인 응답을 제공합니다. 예를 들어, 여행 계획을 세우는 데 필요한 정보와 관련 이미지를 함께 제공합니다.
  3. 파일 생성 및 관리:

    • 어시스턴트는 대화 중에 이미지, 스프레드시트 등의 파일을 생성하고 관리할 수 있습니다. 사용자가 요청한 정보에 따라 새로운 파일을 생성하고 이를 대화에 참조할 수 있습니다.

도구(함수 호출)와 어시스턴트는 AI 모델의 기능을 확장하여 사용자가 더 복잡하고 다양한 작업을 수행할 수 있게 합니다. Vercel AI SDK와 OpenAI API를 통해 이러한 기능을 쉽게 구현할 수 있으며 사용자 경험을 향상시킬 수 있습니다.