파일 업로드
파일 업로드 (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',
}
메시지 콘텐츠 파트의 data나 image 필드에 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)