Мультимодальность

PDF

Как передавать PDF-документы в AllTokens через /api/v1/chat/completions.

PDF-документы можно отправлять через POST /api/v1/chat/completions. PDF передаётся внутри массива messages через элемент file. Документ можно передать как по прямой ссылке, так и в виде base64-строки.

Для большинства сценариев удобнее использовать URL для публичных документов и base64 для локальных или закрытых файлов.

Если выбранная модель умеет принимать файлы напрямую, PDF будет обработан как файловый ввод. Если нет, платформа постарается передать модели содержимое документа в совместимом формате.

В одном запросе можно сочетать PDF, текст и другие поддерживаемые типы входа.

Как найти подходящую модель

Ищите модели в каталоге AllTokens, которые поддерживают файловый ввод. В первую очередь смотрите на:

  • architecture.input_modalities
  • supported_parameters
  • context_length

В примерах ниже используется модель anthropic/claude-sonnet-4.

PDF по URL

Для публично доступных документов можно передать ссылку напрямую, без скачивания и кодирования файла.

import requests

url = "https://api.alltokens.ru/api/v1/chat/completions"
headers = {
    "Authorization": "Bearer YOUR_API_KEY",
    "Content-Type": "application/json"
}

payload = {
    "model": "anthropic/claude-sonnet-4",
    "messages": [
        {
            "role": "user",
            "content": [
                {
                    "type": "text",
                    "text": "Кратко перечисли главные мысли из этого документа."
                },
                {
                    "type": "file",
                    "file": {
                        "filename": "bitcoin.pdf",
                        "file_data": "https://bitcoin.org/bitcoin.pdf"
                    }
                }
            ]
        }
    ]
}

response = requests.post(url, headers=headers, json=payload)
print(response.json())

PDF в base64

Если PDF лежит локально или его нельзя отдать по публичной ссылке, передайте его как data:application/pdf;base64,....

import base64
import requests

def encode_pdf_to_base64(pdf_path):
    with open(pdf_path, "rb") as pdf_file:
        return base64.b64encode(pdf_file.read()).decode("utf-8")

base64_pdf = encode_pdf_to_base64("path/to/your/document.pdf")
data_url = f"data:application/pdf;base64,{base64_pdf}"

url = "https://api.alltokens.ru/api/v1/chat/completions"
headers = {
    "Authorization": "Bearer YOUR_API_KEY",
    "Content-Type": "application/json"
}

payload = {
    "model": "anthropic/claude-sonnet-4",
    "messages": [
        {
            "role": "user",
            "content": [
                {
                    "type": "text",
                    "text": "О чем этот документ и какие у него ключевые выводы?"
                },
                {
                    "type": "file",
                    "file": {
                        "filename": "document.pdf",
                        "file_data": data_url
                    }
                }
            ]
        }
    ]
}

response = requests.post(url, headers=headers, json=payload)
print(response.json())

Повторное использование разбора документа

После первого запроса ответ может содержать annotations внутри сообщения ассистента. Если передать эти данные в следующем запросе, платформе не придётся заново разбирать тот же документ.

Это полезно, если вы:

  • задаёте несколько вопросов по одному и тому же PDF
  • работаете с длинными документами
  • строите чат поверх одного документа

Пример повторного использования annotations

import base64
import requests

def encode_pdf_to_base64(pdf_path):
    with open(pdf_path, "rb") as pdf_file:
        return base64.b64encode(pdf_file.read()).decode("utf-8")

url = "https://api.alltokens.ru/api/v1/chat/completions"
headers = {
    "Authorization": "Bearer YOUR_API_KEY",
    "Content-Type": "application/json"
}

base64_pdf = encode_pdf_to_base64("path/to/your/document.pdf")
data_url = f"data:application/pdf;base64,{base64_pdf}"

first_payload = {
    "model": "anthropic/claude-sonnet-4",
    "messages": [
        {
            "role": "user",
            "content": [
                {
                    "type": "text",
                    "text": "Сделай краткое резюме документа."
                },
                {
                    "type": "file",
                    "file": {
                        "filename": "document.pdf",
                        "file_data": data_url
                    }
                }
            ]
        }
    ]
}

first_response = requests.post(url, headers=headers, json=first_payload)
first_data = first_response.json()

annotations = None
if first_data.get("choices"):
    annotations = first_data["choices"][0]["message"].get("annotations")

if annotations:
    follow_up_payload = {
        "model": "anthropic/claude-sonnet-4",
        "messages": [
            {
                "role": "user",
                "content": [
                    {
                        "type": "text",
                        "text": "Сделай краткое резюме документа."
                    },
                    {
                        "type": "file",
                        "file": {
                            "filename": "document.pdf",
                            "file_data": data_url
                        }
                    }
                ]
            },
            {
                "role": "assistant",
                "content": "Вот краткое резюме документа.",
                "annotations": annotations
            },
            {
                "role": "user",
                "content": "Теперь отдельно перечисли риски и ограничения."
            }
        ]
    }

    follow_up_response = requests.post(url, headers=headers, json=follow_up_payload)
    print(follow_up_response.json())

Если вы передаёте annotations из предыдущего ответа, платформа может использовать уже подготовленный разбор документа вместо повторной обработки PDF.

Формат annotations

Если PDF был разобран, в ответе может появиться структура примерно такого вида:

type FileAnnotation = {
  type: 'file';
  file: {
    hash: string;
    name?: string;
    content: ContentPart[];
  };
};

type ContentPart =
  | { type: 'text'; text: string }
  | { type: 'image_url'; image_url: { url: string } };

Поле content содержит разобранное содержимое документа: текстовые блоки, а в некоторых случаях и изображения.

Пример ответа

{
  "id": "gen-1234567890",
  "model": "anthropic/claude-sonnet-4",
  "object": "chat.completion",
  "created": 1234567890,
  "choices": [
    {
      "message": {
        "role": "assistant",
        "content": "Документ посвящён...",
        "annotations": [
          {
            "type": "file",
            "file": {
              "hash": "abc123...",
              "name": "document.pdf",
              "content": [
                { "type": "text", "text": "Разобранный текст..." },
                { "type": "image_url", "image_url": { "url": "data:image/png;base64,..." } }
              ]
            }
          }
        ]
      }
    }
  ],
  "usage": {
    "prompt_tokens": 1000,
    "completion_tokens": 100,
    "total_tokens": 1100
  }
}

Частые вопросы

Для публичных PDF обычно удобнее URL: запрос короче и не нужно кодировать файл. Для локальных и закрытых документов нужен base64.

Да. Для этого удобно использовать annotations из предыдущего ответа, чтобы не разбирать документ заново.

Да. Текстовая инструкция и PDF обычно передаются вместе в одном массиве content.