문서 이해

Gemini 모델은 기본 비전을 사용하여 전체 문서 컨텍스트를 이해함으로써 PDF 형식의 문서를 처리할 수 있습니다. 이는 단순한 텍스트 추출을 넘어 Gemini가 다음 작업을 할 수 있도록 합니다.

  • 최대 1,000페이지의 긴 문서에서도 텍스트, 이미지, 다이어그램, 차트, 표를 비롯한 콘텐츠를 분석하고 해석합니다.
  • 정보를 구조화된 출력 형식으로 추출합니다.
  • 문서의 시각적 요소와 텍스트 요소를 모두 기반으로 질문에 요약하고 답변합니다.
  • 다운스트림 애플리케이션에서 사용할 수 있도록 레이아웃과 서식을 유지하면서 문서 콘텐츠를 트랜스크립션합니다 (예: HTML로).

동일한 방식으로 PDF가 아닌 문서를 전달할 수도 있지만 Gemini는 이를 일반 텍스트로 인식하여 차트나 서식과 같은 컨텍스트를 삭제합니다.

PDF 데이터 인라인 전달

요청에서 PDF 데이터를 인라인으로 전달할 수 있습니다. 이는 후속 요청에서 파일을 참조할 필요가 없는 작은 문서 또는 임시 처리에 가장 적합합니다. 요청 지연 시간을 개선하고 대역폭 사용량을 줄이기 위해 멀티턴 상호작용에서 참조해야 하는 대용량 문서에는 Files API 를 사용하는 것이 좋습니다.

다음 예는 PDF 데이터를 인라인으로 전달하는 방법을 보여줍니다.

Python

from google import genai
import base64

client = genai.Client()

with open('path/to/document.pdf', 'rb') as f:
    pdf_bytes = f.read()

interaction = client.interactions.create(
    model="gemini-3-flash-preview",
    input=[
        {
            "type": "document",
            "data": base64.b64encode(pdf_bytes).decode('utf-8'),
            "mime_type": "application/pdf"
        },
        {"type": "text", "text": "Summarize this document"}
    ]
)

print(interaction.steps[-1].content[0].text)

JavaScript

import { GoogleGenAI } from "@google/genai";
import * as fs from "node:fs";

const ai = new GoogleGenAI({});

async function main() {
    const pdfData = fs.readFileSync("path/to/document.pdf", {
        encoding: "base64"
    });

    const interaction = await ai.interactions.create({
        model: "gemini-3-flash-preview",
        input: [
            { type: "text", text: "Summarize this document" },
            {
                type: "document",
                data: pdfData,
                mimeType: "application/pdf"
            }
        ]
    });
    console.log(interaction.steps.at(-1).content[0].text);
}

main();

REST

PDF_PATH="path/to/document.pdf"

if [[ "$(base64 --version 2>&1)" = *"FreeBSD"* ]]; then
  B64FLAGS="--input"
else
  B64FLAGS="-w0"
fi

curl -X POST "https://generativelanguage.googleapis.com/v1beta/interactions" \
  -H "x-goog-api-key: $GEMINI_API_KEY" \
  -H 'Content-Type: application/json' \
  -d '{
    "model": "gemini-3-flash-preview",
    "input": [
      {
        "type": "document",
        "data": "'$(base64 $B64FLAGS $PDF_PATH)'",
        "mimeType": "application/pdf"
      },
      {"type": "text", "text": "Summarize this document"}
    ]
  }'

처리를 위해 로컬 PDF 파일을 업로드할 수도 있습니다.

Python

from google import genai

client = genai.Client()

uploaded_file = client.files.upload(file="file.pdf")

interaction = client.interactions.create(
    model="gemini-3-flash-preview",
    input=[
        {"type": "document", "uri": uploaded_file.uri, "mime_type": uploaded_file.mime_type},
        {"type": "text", "text": "Summarize this document"}
    ]
)
print(interaction.steps[-1].content[0].text)

JavaScript

import { GoogleGenAI } from "@google/genai";

const ai = new GoogleGenAI({});

async function main() {
    const uploadedFile = await ai.files.upload({
        file: "file.pdf",
        config: { mimeType: "application/pdf" }
    });

    const interaction = await ai.interactions.create({
        model: "gemini-3-flash-preview",
        input: [
            { type: "text", text: "Summarize this document" },
            {
                type: "document",
                uri: uploadedFile.uri,
                mimeType: uploadedFile.mimeType
            }
        ]
    });
    console.log(interaction.steps.at(-1).content[0].text);
}

main();

Files API를 사용하여 PDF 업로드

대용량 파일에 또는 여러 요청에서 문서를 재사용하려는 경우 Files API를 사용하는 것이 좋습니다. 이렇게 하면 파일 업로드를 모델 요청과 분리하여 요청 지연 시간이 개선되고 대역폭 사용량이 줄어듭니다.

URL의 대용량 PDF

File API를 사용하여 URL에서 대용량 PDF 파일의 업로드 및 처리를 간소화합니다.

Python

from google import genai
import io
import httpx

client = genai.Client()

long_context_pdf_path = "https://www.nasa.gov/wp-content/uploads/static/history/alsj/a17/A17_FlightPlan.pdf"

# Retrieve and upload the PDF using the File API
doc_io = io.BytesIO(httpx.get(long_context_pdf_path).content)

sample_doc = client.files.upload(
  # You can pass a path or a file-like object here
  file=doc_io,
  config=dict(
    mime_type='application/pdf')
)

prompt = "Summarize this document"

interaction = client.interactions.create(
    model="gemini-3-flash-preview",
    input=[
        {"type": "document", "uri": sample_doc.uri, "mime_type": sample_doc.mime_type},
        {"type": "text", "text": prompt}
    ]
)
print(interaction.steps[-1].content[0].text)

JavaScript

import { GoogleGenAI } from "@google/genai";

const ai = new GoogleGenAI({});

async function main() {

    const pdfBuffer = await fetch("https://www.nasa.gov/wp-content/uploads/static/history/alsj/a17/A17_FlightPlan.pdf")
        .then((response) => response.arrayBuffer());

    const fileBlob = new Blob([pdfBuffer], { type: 'application/pdf' });

    const file = await ai.files.upload({
        file: fileBlob,
        config: {
            displayName: 'A17_FlightPlan.pdf',
        },
    });

    // Wait for the file to be processed.
    let getFile = await ai.files.get({ name: file.name });
    while (getFile.state === 'PROCESSING') {
        getFile = await ai.files.get({ name: file.name });
        console.log(`current file status: ${getFile.state}`);
        console.log('File is still processing, retrying in 5 seconds');

        await new Promise((resolve) => {
            setTimeout(resolve, 5000);
        });
    }
    if (file.state === 'FAILED') {
        throw new Error('File processing failed.');
    }

    const interaction = await ai.interactions.create({
        model: 'gemini-3-flash-preview',
        input: [
            { type: "document", uri: file.uri, mimeType: file.mimeType },
            { type: "text", text: "Summarize this document" }
        ],
    });

    console.log(interaction.steps.at(-1).content[0].text);

}

main();

REST

PDF_PATH="https://www.nasa.gov/wp-content/uploads/static/history/alsj/a17/A17_FlightPlan.pdf"
DISPLAY_NAME="A17_FlightPlan"
PROMPT="Summarize this document"

# Download the PDF from the provided URL
wget -O "${DISPLAY_NAME}.pdf" "${PDF_PATH}"

MIME_TYPE=$(file -b --mime-type "${DISPLAY_NAME}.pdf")
NUM_BYTES=$(wc -c < "${DISPLAY_NAME}.pdf")

echo "MIME_TYPE: ${MIME_TYPE}"
echo "NUM_BYTES: ${NUM_BYTES}"

tmp_header_file=upload-header.tmp

# Initial resumable request defining metadata.
# The upload url is in the response headers dump them to a file.
curl "https://generativelanguage.googleapis.com/upload/v1beta/files?key=${GOOGLE_API_KEY}" \
  -D upload-header.tmp \
  -H "X-Goog-Upload-Protocol: resumable" \
  -H "X-Goog-Upload-Command: start" \
  -H "X-Goog-Upload-Header-Content-Length: ${NUM_BYTES}" \
  -H "X-Goog-Upload-Header-Content-Type: ${MIME_TYPE}" \
  -H "Content-Type: application/json" \
  -d "{'file': {'display_name': '${DISPLAY_NAME}'}}" 2> /dev/null

upload_url=$(grep -i "x-goog-upload-url: " "${tmp_header_file}" | cut -d" " -f2 | tr -d "\r")
rm "${tmp_header_file}"

# Upload the actual bytes.
curl "${upload_url}" \
  -H "Content-Length: ${NUM_BYTES}" \
  -H "X-Goog-Upload-Offset: 0" \
  -H "X-Goog-Upload-Command: upload, finalize" \
  --data-binary "@${DISPLAY_NAME}.pdf" 2> /dev/null > file_info.json

file_uri=$(jq ".file.uri" file_info.json)
echo "file_uri: ${file_uri}"

# Now create an interaction using that file
curl "https://generativelanguage.googleapis.com/v1beta/interactions" \
    -H "x-goog-api-key: $GOOGLE_API_KEY" \
    -H 'Content-Type: application/json' \
    -X POST \
    -d '{
      "model": "gemini-3-flash-preview",
      "input": [
        {"type": "text", "text": "'$PROMPT'"},
        {"type": "document", "uri": '$file_uri', "mimeType": "application/pdf"}
      ]
    }' 2> /dev/null > response.json

cat response.json
echo

jq ".steps[-1].content[0].text" response.json

# Clean up the downloaded PDF
rm "${DISPLAY_NAME}.pdf"

로컬에 저장된 대용량 PDF

Python

from google import genai
import pathlib

client = genai.Client()

# Upload the PDF using the File API
file_path = pathlib.Path('large_file.pdf')
sample_file = client.files.upload(
    file=file_path,
)

interaction = client.interactions.create(
    model="gemini-3-flash-preview",
    input=[
        {"type": "document", "uri": sample_file.uri, "mime_type": sample_file.mime_type},
        {"type": "text", "text": "Summarize this document"}
    ]
)
print(interaction.steps[-1].content[0].text)

JavaScript

import { GoogleGenAI } from "@google/genai";

const ai = new GoogleGenAI({});

async function main() {
    const file = await ai.files.upload({
        file: 'path-to-localfile.pdf',
        config: {
            displayName: 'A17_FlightPlan.pdf',
        },
    });

    // Wait for the file to be processed.
    let getFile = await ai.files.get({ name: file.name });
    while (getFile.state === 'PROCESSING') {
        getFile = await ai.files.get({ name: file.name });
        console.log(`current file status: ${getFile.state}`);
        console.log('File is still processing, retrying in 5 seconds');

        await new Promise((resolve) => {
            setTimeout(resolve, 5000);
        });
    }
    if (file.state === 'FAILED') {
        throw new Error('File processing failed.');
    }

    const interaction = await ai.interactions.create({
        model: 'gemini-3-flash-preview',
        input: [
            { type: "document", uri: file.uri, mimeType: file.mimeType },
            { type: "text", text: "Summarize this document" }
        ],
    });

    console.log(interaction.steps.at(-1).content[0].text);

}

main();

REST

PDF_PATH="path/to/large_file.pdf"
NUM_BYTES=$(wc -c < "${PDF_PATH}")
DISPLAY_NAME=TEXT
tmp_header_file=upload-header.tmp

# Initial resumable request defining metadata.
# The upload url is in the response headers dump them to a file.
curl "https://generativelanguage.googleapis.com/upload/v1beta/files?key=${GEMINI_API_KEY}" \
  -D upload-header.tmp \
  -H "X-Goog-Upload-Protocol: resumable" \
  -H "X-Goog-Upload-Command: start" \
  -H "X-Goog-Upload-Header-Content-Length: ${NUM_BYTES}" \
  -H "X-Goog-Upload-Header-Content-Type: application/pdf" \
  -H "Content-Type: application/json" \
  -d "{'file': {'display_name': '${DISPLAY_NAME}'}}" 2> /dev/null

upload_url=$(grep -i "x-goog-upload-url: " "${tmp_header_file}" | cut -d" " -f2 | tr -d "\r")
rm "${tmp_header_file}"

# Upload the actual bytes.
curl "${upload_url}" \
  -H "Content-Length: ${NUM_BYTES}" \
  -H "X-Goog-Upload-Offset: 0" \
  -H "X-Goog-Upload-Command: upload, finalize" \
  --data-binary "@${PDF_PATH}" 2> /dev/null > file_info.json

file_uri=$(jq ".file.uri" file_info.json)
echo file_uri=$file_uri

# Now create an interaction using that file
curl "https://generativelanguage.googleapis.com/v1beta/interactions" \
    -H "x-goog-api-key: $GEMINI_API_KEY" \
    -H 'Content-Type: application/json' \
    -X POST \
    -d '{
      "model": "gemini-3-flash-preview",
      "input": [
        {"type": "document", "uri": '$file_uri', "mimeType": "application/pdf"},
        {"type": "text", "text": "Can you add a few more lines to this poem?"}
      ]
    }' 2> /dev/null > response.json

cat response.json
echo

jq ".steps[-1].content[0].text" response.json

`files.get`을 호출하여 API가 업로드된 파일을 성공적으로 저장했는지 확인하고 메타데이터를 가져올 수 있습니다. name(및 확장 프로그램 uri)만 고유합니다.

Python

from google import genai
import pathlib

client = genai.Client()

fpath = pathlib.Path('example.pdf')
fpath.write_text('hello')

file = client.files.upload(file='example.pdf')

file_info = client.files.get(name=file.name)
print(file_info.model_dump_json(indent=4))

REST

name=$(jq ".file.name" file_info.json)
# Get the file of interest to check state
curl https://generativelanguage.googleapis.com/v1beta/files/$name?key=$GEMINI_API_KEY > file_info.json
# Print some information about the file you got
name=$(jq ".file.name" file_info.json)
echo name=$name
file_uri=$(jq ".file.uri" file_info.json)
echo file_uri=$file_uri

여러 PDF 전달

Gemini API는 문서와 텍스트 프롬프트의 결합된 크기가 모델의 컨텍스트 윈도우 내에 있는 한 단일 요청에서 여러 PDF 문서 (최대 1, 000페이지)를 처리할 수 있습니다.

Python

from google import genai
import io
import httpx

client = genai.Client()

doc_url_1 = "https://arxiv.org/pdf/2312.11805"
doc_url_2 = "https://arxiv.org/pdf/2403.05530"

# Retrieve and upload both PDFs using the File API
doc_data_1 = io.BytesIO(httpx.get(doc_url_1).content)
doc_data_2 = io.BytesIO(httpx.get(doc_url_2).content)

sample_pdf_1 = client.files.upload(
  file=doc_data_1,
  config=dict(mime_type='application/pdf')
)
sample_pdf_2 = client.files.upload(
  file=doc_data_2,
  config=dict(mime_type='application/pdf')
)

prompt = "What is the difference between each of the main benchmarks between these two papers? Output these in a table."

interaction = client.interactions.create(
    model="gemini-3-flash-preview",
    input=[
        {"type": "document", "uri": sample_pdf_1.uri, "mime_type": sample_pdf_1.mime_type},
        {"type": "document", "uri": sample_pdf_2.uri, "mime_type": sample_pdf_2.mime_type},
        {"type": "text", "text": prompt}
    ]
)

print(interaction.steps[-1].content[0].text)

JavaScript

import { GoogleGenAI } from "@google/genai";

const ai = new GoogleGenAI({});

async function uploadRemotePDF(url, displayName) {
    const pdfBuffer = await fetch(url)
        .then((response) => response.arrayBuffer());

    const fileBlob = new Blob([pdfBuffer], { type: 'application/pdf' });

    const file = await ai.files.upload({
        file: fileBlob,
        config: {
            displayName: displayName,
        },
    });

    // Wait for the file to be processed.
    let getFile = await ai.files.get({ name: file.name });
    while (getFile.state === 'PROCESSING') {
        getFile = await ai.files.get({ name: file.name });
        console.log(`current file status: ${getFile.state}`);
        console.log('File is still processing, retrying in 5 seconds');

        await new Promise((resolve) => {
            setTimeout(resolve, 5000);
        });
    }
    if (file.state === 'FAILED') {
        throw new Error('File processing failed.');
    }

    return file;
}

async function main() {
    const file1 = await uploadRemotePDF("https://arxiv.org/pdf/2312.11805", "PDF 1");
    const file2 = await uploadRemotePDF("https://arxiv.org/pdf/2403.05530", "PDF 2");

    const interaction = await ai.interactions.create({
        model: 'gemini-3-flash-preview',
        input: [
            { type: "document", uri: file1.uri, mimeType: file1.mimeType },
            { type: "document", uri: file2.uri, mimeType: file2.mimeType },
            { type: "text", text: "What is the difference between each of the main benchmarks between these two papers? Output these in a table." }
        ],
    });

    console.log(interaction.steps.at(-1).content[0].text);
}

main();

REST

DOC_URL_1="https://arxiv.org/pdf/2312.11805"
DOC_URL_2="https://arxiv.org/pdf/2403.05530"
DISPLAY_NAME_1="Gemini_paper"
DISPLAY_NAME_2="Gemini_1.5_paper"
PROMPT="What is the difference between each of the main benchmarks between these two papers? Output these in a table."

# Function to download and upload a PDF
upload_pdf() {
  local doc_url="$1"
  local display_name="$2"

  # Download the PDF
  wget -O "${display_name}.pdf" "${doc_url}"

  local MIME_TYPE=$(file -b --mime-type "${display_name}.pdf")
  local NUM_BYTES=$(wc -c < "${display_name}.pdf")

  echo "MIME_TYPE: ${MIME_TYPE}"
  echo "NUM_BYTES: ${NUM_BYTES}"

  local tmp_header_file=upload-header.tmp

  # Initial resumable request
  curl "https://generativelanguage.googleapis.com/upload/v1beta/files?key=${GOOGLE_API_KEY}" \
    -D "${tmp_header_file}" \
    -H "X-Goog-Upload-Protocol: resumable" \
    -H "X-Goog-Upload-Command: start" \
    -H "X-Goog-Upload-Header-Content-Length: ${NUM_BYTES}" \
    -H "X-Goog-Upload-Header-Content-Type: ${MIME_TYPE}" \
    -H "Content-Type: application/json" \
    -d "{'file': {'display_name': '${display_name}'}}" 2> /dev/null

  local upload_url=$(grep -i "x-goog-upload-url: " "${tmp_header_file}" | cut -d" " -f2 | tr -d "\r")
  rm "${tmp_header_file}"

  # Upload the PDF
  curl "${upload_url}" \
    -H "Content-Length: ${NUM_BYTES}" \
    -H "X-Goog-Upload-Offset: 0" \
    -H "X-Goog-Upload-Command: upload, finalize" \
    --data-binary "@${display_name}.pdf" 2> /dev/null > "file_info_${display_name}.json"

  local file_uri=$(jq ".file.uri" "file_info_${display_name}.json")
  echo "file_uri for ${display_name}: ${file_uri}"

  # Clean up the downloaded PDF
  rm "${display_name}.pdf"

  echo "${file_uri}"
}

# Upload the first PDF
file_uri_1=$(upload_pdf "${DOC_URL_1}" "${DISPLAY_NAME_1}")

# Upload the second PDF
file_uri_2=$(upload_pdf "${DOC_URL_2}" "${DISPLAY_NAME_2}")

# Now create an interaction using both files
curl "https://generativelanguage.googleapis.com/v1beta/interactions" \
    -H "x-goog-api-key: $GOOGLE_API_KEY" \
    -H 'Content-Type: application/json' \
    -X POST \
    -d '{
      "model": "gemini-3-flash-preview",
      "input": [
        {"type": "document", "uri": '$file_uri_1', "mimeType": "application/pdf"},
        {"type": "document", "uri": '$file_uri_2', "mimeType": "application/pdf"},
        {"type": "text", "text": "'$PROMPT'"}
      ]
    }' 2> /dev/null > response.json

cat response.json
echo

jq ".steps[-1].content[0].text" response.json

기술 세부정보

Gemini는 최대 50MB 또는 1,000페이지의 PDF 파일을 지원합니다. 이 한도는 인라인 데이터와 Files API 업로드 모두에 적용됩니다. 각 문서 페이지는 258개의 토큰과 같습니다.

모델의 컨텍스트 창 외에 문서의 픽셀 수에 대한 구체적인 제한은 없지만, 큰 페이지는 원래 가로세로 비율을 유지하면서 최대 해상도인 3072 x 3072로 축소되고 작은 페이지는 768 x 768픽셀로 확대됩니다. 대역폭 외에 크기가 작은 페이지의 비용 절감이나 해상도가 높은 페이지의 성능 개선은 없습니다.

Gemini 3 모델

Gemini 3는 media_resolution 파라미터를 통해 멀티모달 비전 처리에 대한 세밀한 제어 기능을 제공합니다. 이제 개별 미디어 파트별로 해상도를 낮음, 중간 또는 높음으로 설정할 수 있습니다. 이 추가로 PDF 문서 처리가 업데이트되었습니다.

  1. 기본 텍스트 포함: PDF에 기본적으로 삽입된 텍스트가 추출되어 모델에 제공됩니다.
  2. 결제 및 토큰 보고:
    • PDF에서 추출된 기본 텍스트 에서 발생한 토큰에 대해서는 요금이 청구되지 않습니다.
    • API 응답의 usage_metadata 섹션에서 PDF 페이지 (이미지) 처리로 생성된 토큰은 이제 이전 버전과 달리 별도의 DOCUMENT 모드가 아닌 IMAGE 모드에서 집계됩니다.

문서 유형

기술적으로는 TXT, Markdown, HTML, XML 등과 같은 문서 이해를 위한 다른 MIME 유형을 전달할 수 있습니다. 하지만 문서 비전은 PDF만 의미 있게 이해합니다. 다른 유형은 순수 텍스트로 추출되며 모델은 이러한 파일의 렌더링에서 보이는 내용을 해석할 수 없습니다. 차트, 다이어그램, HTML 태그, Markdown 서식 등과 같은 파일 유형 관련 세부정보는 손실됩니다.

다른 파일 입력 방법에 대한 자세한 내용은 파일 입력 방법 가이드를 참고하세요.

권장사항

최상의 결과를 얻는 방법

  • 업로드하기 전에 페이지를 올바른 방향으로 회전합니다.
  • 흐릿한 페이지는 사용하지 마세요.
  • 단일 페이지를 사용하는 경우 페이지 뒤에 텍스트 프롬프트를 배치합니다.

다음 단계

자세한 내용은 다음 리소스를 참조하세요.

  • 파일 프롬프트 전략: Gemini API는 멀티모달 프롬프트 사용이라고도 하는 텍스트, 이미지, 오디오, 동영상 데이터로 프롬프트를 지원합니다.
  • 시스템 안내: 시스템 안내를 사용하면 특정 요구사항 및 사용 사례에 따라 모델의 동작을 조정할 수 있습니다.