이미지 여러 개를 처리할 때 높은 메모리 사용

이미지 여러 개를 처리할 때 높은 메모리 사용

이미지를 여러 개 처리할 때 메모리가 계속 늘어나는 문제를 해결하는 문서예요. include 옵션으로 요청/응답 본문 포함을 조절하면 돼요.

출처: 문서

본문

문제

generateText나 streamText를 이미지 여러 개와 함께 사용할 때(예: 루프나 배치 처리) 다음과 같은 현상이 생길 수 있어요:

  • 메모리 사용량이 계속 늘어나고 줄어들지 않아요
  • 애플리케이션이 결국 메모리 부족으로 죽어요
  • 가비지 컬렉션 후에도 메모리가 회수되지 않아요

특히 experimental_download로 URL의 이미지를 처리하거나, base64로 인코딩된 이미지를 프롬프트로 보낼 때 이런 현상이 두드러져요.

배경

기본적으로 AI SDK는 단계(steps) 결과에 전체 요청 메시지와 요청/응답 본문을 포함해요. 이미지를 처리할 때 요청 메시지와 요청 본문에는 base64로 인코딩된 이미지 데이터가 들어갈 수 있는데, 이 데이터는 매우 클 수 있어요(이미지 하나를 base64로 인코딩하면 1MB 이상 될 수 있어요). 이미지 여러 개를 처리하면서 결과에 대한 참조를 계속 유지하면 이 데이터가 메모리에 쌓이게 돼요.

예를 들어 500KB 크기의 이미지 100개를 처리하면 요청 본문 데이터만 메모리에 약 50MB 이상 쌓일 수 있어요.

해결 방법

include 옵션을 사용해 요청 메시지 또는 요청/응답 본문 포함을 끌 수 있어요:

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

const result = await generateText({
  model: openai('gpt-6-astra'),
  messages: [
    {
      role: 'user',
      content: [
        { type: 'text', text: 'Describe this image' },
        { type: 'file', mediaType: 'image', data: imageUrl },
      ],
    },
  ],
  // Request and response bodies are excluded by default.
  include: {
    requestBody: false,
    responseBody: false,
  },
});

옵션

include 옵션은 다음을 받아요:

  • requestBody: true로 설정하면 요청 본문을 단계 결과에 포함해요. base64 인코딩된 이미지가 주로 저장되는 곳이 요청 본문이에요. 기본값: false. generateText와 streamText 둘 다에서 사용 가능해요.
  • requestMessages: true로 설정하면 요청 메시지를 단계 결과에 포함해요. 요청 메시지에는 이미지, 파일 같은 큰 메시지 콘텐츠가 담길 수 있어요. 기본값: false. generateText와 streamText 둘 다에서 사용 가능해요.
  • rawChunks: true로 설정하면 스트림에 원본 프로바이더 청크를 포함해요. 기본값: false. streamText에서만 사용 가능해요.
  • responseBody: true로 설정하면 응답 본문을 단계 결과에 포함해요. 기본값: false. generateText에서만 사용 가능해요.

언제 사용할까요

  • 배치 이미지 처리: 루프에서 이미지 여러 개를 처리할 때
  • 오래 실행되는 에이전트: 에이전트가 수명 동안 이미지를 많이 처리할 수 있을 때
  • 메모리가 제한된 환경: 메모리가 부족한 환경에서 실행할 때

트레이드오프

본문 포함을 끄면:

  • result.request.body나 result.response.body에 접근할 수 없어요
  • requestMessages를 활성화하지 않는 한 result.request.messages에 접근할 수 없어요
  • 원본 요청/응답을 검사할 수 없어 디버깅이 어려워질 수 있어요
  • 로깅이나 디버깅을 위해 본문이 필요하다면, 다음 반복 전에 필요한 데이터를 미리 추출해 두는 걸 고려해 보세요

예시: 이미지 여러 개 처리하기

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

const imageUrls = [
  /* array of image URLs */
];
const results = [];

for (const imageUrl of imageUrls) {
  const result = await generateText({
    model: openai('gpt-6-astra'),
    messages: [
      {
        role: 'user',
        content: [
          { type: 'text', text: 'Describe this image' },
          { type: 'file', mediaType: 'image', data: imageUrl },
        ],
      },
    ],
    include: {
      requestBody: false,
    },
  });

  // Only store the text result, not the full result object
  results.push(result.text);
}

더 배우기

더 알아보기 (Learn more)

전체 사이트맵