파일 업로드

파일 업로드 (File Uploads)

모델에 이미지나 PDF 같은 파일을 넘겨야 할 때가 있어요. AI SDK는 uploadFile 함수로 파일을 제공자에 업로드하고, 이후 API 호출에 쓸 수 있는 ProviderReference를 돌려받게 해 줍니다. 업로드된 파일은 ProviderReference로 식별되는데, 이건 제공자 이름을 제공자별 식별자로 매핑하는 Record<string, string>이에요. 이 개념은 업로드한 스킬(skill)처럼 제공자별 자산 참조를 다룰 때도 함께 쓰입니다.

출처: 공식문서

본문

import { uploadFile, generateText } from 'ai';
import { openai } from '@ai-sdk/openai';
import fs from 'node:fs';

const { providerReference } = await uploadFile({
  api: openai.files(),
  data: fs.readFileSync('./photo.png'),
  filename: 'photo.png',
});

const { text } = await generateText({
  model: openai.responses('gpt-4o-mini'),
  messages: [
    {
      role: 'user',
      content: [
        { type: 'text', text: 'Describe what you see in this image.' },
        { type: 'file', mediaType: 'image', data: providerReference },
      ],
    },
  ],
});

api에 제공자 인스턴스를 그대로 넘기는 축약형도 쓸 수 있어요. SDK가 알아서 .files()를 호출해 줍니다.

const { providerReference } = await uploadFile({
  api: openai, // shorthand for openai.files()
  data: fs.readFileSync('./photo.png'),
  filename: 'photo.png',
});

지원 파일 유형

제공자에 따라 이미지·PDF·텍스트 파일·기타 문서를 업로드할 수 있어요. 미디어 타입은 명시하지 않으면 파일 바이트에서 자동으로 감지됩니다.

const { providerReference } = await uploadFile({
  api: anthropic.files(),
  data: fs.readFileSync('./document.pdf'),
  mediaType: 'application/pdf', // optional, auto-detected if omitted
  filename: 'document.pdf',
});

providerReference를 파일 콘텐츠 파트에 미디어 타입과 함께 넣어 사용합니다.

{
  role: 'user',
  content: [
    { type: 'text', text: 'Summarize this document.' },
    { type: 'file', data: providerReference, mediaType: 'application/pdf' },
  ],
}

제공자별 옵션

일부 제공자는 providerOptions로 추가 옵션을 받아요. 예를 들어 OpenAI는 purpose 필드를 요구합니다.

import { openai, type OpenAIFilesOptions } from '@ai-sdk/openai';

const { providerReference } = await uploadFile({
  api: openai.files(),
  data: fs.readFileSync('./photo.png'),
  providerOptions: {
    openai: {
      purpose: 'assistants',
    } satisfies OpenAIFilesOptions,
  },
});

스트리밍 업로드

스트리밍 업로드를 지원하는 제공자(예: OpenAI, xAI)는 태그가 붙은 { type: 'stream', stream } 형태를 받아요. 파일 전체를 메모리에 버퍼링하지 않고 바이트를 보냅니다. 스트리밍을 지원하지 않는 제공자는 UnsupportedFunctionalityError로 스트림 데이터를 거부합니다.

const { providerReference } = await uploadFile({
  api: openai.files(),
  data: { type: 'stream', stream: fileStream },
  mediaType: 'application/jsonl',
  filename: 'batch.jsonl',
});

제공자가 스트림을 소비해요. 요청 전 검증 실패를 포함해 실패한 업로드는 스트림을 취소하고, 재사용해서는 안 됩니다. 스트림 데이터는 스니핑할 수 없어서 mediaType을 생략하면 application/octet-stream으로 기본값이 정해지고, multipart 기반 제공자는 파일명을 기본값 "blob"으로 둡니다.

업로드는 abortSignal로 취소할 수 있고 요청별 headers를 실을 수 있어요. 결과에는 제공자가 보고할 때 byteSize·createdAt·expiresAt(제공자가 적용한 보존 만료)가 포함됩니다.

제공자 참조(Provider References)

ProviderReference는 제공자 이름을 제공자별 파일 식별자로 매핑하는 Record<string, string>이에요.

// Example ProviderReference
{
  openai: 'file-abc123',
}

메시지 콘텐츠 파트의 dataimage 필드에 ProviderReference를 넘기면, 제공자가 참조에서 자기 파일 ID를 찾아요. 참조에 현재 제공자 항목이 없으면 오류가 던져집니다.

다중 제공자 사용

대화 중간에 제공자를 바꾸는 경우(예: OpenAI로 시작한 채팅을 Anthropic으로 이어가기)에는 파일을 두 제공자 모두에 업로드하고 참조를 병합해야 해요.

const openaiResult = await uploadFile({
  api: openai.files(),
  data: imageBytes,
  filename: 'photo.png',
});
const anthropicResult = await uploadFile({
  api: anthropic.files(),
  data: imageBytes,
  filename: 'photo.png',
});
const mergedReference = {
  ...openaiResult.providerReference,
  ...anthropicResult.providerReference,
};
// mergedReference: { openai: 'file-abc123', anthropic: 'file-xyz789' }

병합된 참조는 어떤 제공자가 요청을 처리하든 그대로 메시지에 쓸 수 있어요. 각 제공자가 자기 파일 ID를 찾아내니까요.

지원 제공자

files()와 파일 업로드를 지원하는 제공자는 다음과 같습니다: Anthropic(anthropic.files()), Google(google.files()), OpenAI(openai.files()), xAI(xai.files()). 파일 업로드를 지원하지 않는 제공자는 메시지에서 제공자 참조를 만나면 UnsupportedFunctionalityError를 던져요.

더 알아보기

  • 멀티모달 프롬프트에서 파일 파트 구성
  • 텍스트 생성(Generating Text)에서 파일 참조 활용
  • 파일 업로드 API 레퍼런스(uploadFile)