Для получения чистого Markdown любой страницы добавьте .md к URL страницы.
Для полного индекса документации см. https://api.vega.chat/docs/llms.txt.
Для полного содержания документации см. https://api.vega.chat/docs/llms-full.txt.
Для интеграции AI‑клиентов (Claude Code, Cursor и др.) подключитесь к MCP‑серверу по адресу https://api.vega.chat/docs/_mcp/server.
PDF‑вводы
VEGA поддерживает обработку PDF через API /api/v1/chat/completions. PDF можно отправлять как прямые URL или base64‑закодированные data URL в массиве messages, используя тип содержимого file. Эта функция работает с любой моделью в VEGA.
Поддержка URL: отправляйте публично доступные PDF‑файлы напрямую без скачивания или кодирования.
Поддержка Base64: требуется для локальных файлов или закрытых документов, которые недоступны публично.
PDF‑файлы также работают в чат‑комнате для интерактивного тестирования.
Когда модель поддерживает ввод файлов нативно, PDF передаётся напрямую модели. Когда модель не поддерживает ввод файлов нативно, VEGA будет разбирать файл и передавать результаты разбора запрошенной модели.
Вы можете отправлять как PDF, так и другие типы файлов в одном запросе.
Конфигурация плагина
Для настройки обработки PDF используйте параметр plugins в вашем запросе. VEGA предоставляет несколько движков обработки PDF с разными возможностями и ценой:
{
plugins: [
{
id: 'file-parser',
pdf: {
engine: 'cloudflare-ai', // или 'mistral-ocr' или 'native'
},
},
],
}Ценообразование
VEGA предоставляет несколько движков обработки PDF:
- <code>"{PDFParserEngine.MistralOCR}"</code>: лучший вариант для отсканированных документов или PDF с изображениями (${MISTRAL_OCR_COST.toString()} за 1 000 страниц).
- <code>"{PDFParserEngine.CloudflareAI}"</code>: преобразует PDF в markdown с помощью Cloudflare Workers AI (Бесплатно).
- <code>"{PDFParserEngine.Native}"</code>: доступен только для моделей, которые поддерживают ввод файлов нативно (оплачивается как токены ввода).
Движок "pdf-text" устарел и автоматически перенаправляется на "cloudflare-ai". Существующие запросы, использующие "pdf-text", продолжат работать.
Стоимость OCR применяется ко всем запросам, включая BYOK. VEGA использует собственный ключ Mistral для OCR (не ваш BYOK‑ключ), поэтому плата за страницу всегда списывается с вашего аккаунта VEGA.
Если вы явно не указываете движок, VEGA сначала будет использовать нативные возможности модели по обработке файлов, а если их нет — применит движок <code>"{DEFAULT_PDF_ENGINE}"</code>.
Ограничения изображений OCR
Когда движок <code>"{PDFParserEngine.MistralOCR}"</code> извлекает изображения из PDF, VEGA запрашивает не более 8 изображений на PDF у Mistral через параметр image_limit OCR‑API и передаёт не более 8 изображений за запрос downstream‑модели. Избыточные изображения отбрасываются, при этом весь извлечённый текст сохраняется полностью.
Это ограничение существует потому, что лимиты изображений в запросе сильно различаются у провайдеров — некоторые отклоняют запросы с более чем 8 изображениями, а даже у провайдеров с более высокими лимитами часто возникают ошибки длины контекста, когда длинный PDF генерирует по одному изображению на страницу. Ограничение в 8 изображений сохраняет запросы в пределах лимитов всех поддерживаемых провайдеров.
Если ваша downstream‑модель не принимает изображения вообще, извлечённые OCR‑изображения полностью удаляются, и передаётся только разобранный текст.
Использование URL PDF
Для публично доступных PDF‑файлов вы можете отправлять URL напрямую без необходимости скачивать и кодировать файл:
import { OpenRouter } from '@openrouter/sdk';
const client = new OpenRouter({
apiKey: '{{API_KEY_REF}}',
});
const result = await client.chat.send({
model: '{{MODEL}}',
messages: [
{
role: 'user',
content: [
{
type: 'text',
text: 'What are the main points in this document?',
},
{
type: 'file',
file: {
filename: 'document.pdf',
fileData: 'https://bitcoin.org/bitcoin.pdf',
},
},
],
},
],
// Optional: Configure PDF processing engine
plugins: [
{
id: 'file-parser',
pdf: {
engine: '{{ENGINE}}',
},
},
],
stream: false,
});
console.log(result);import requests
import json
url = "https://api.vega.chat/api/v1/chat/completions"
headers = {
"Authorization": f"Bearer {API_KEY_REF}",
"Content-Type": "application/json"
}
messages = [
{
"role": "user",
"content": [
{
"type": "text",
"text": "What are the main points in this document?"
},
{
"type": "file",
"file": {
"filename": "document.pdf",
"file_data": "https://bitcoin.org/bitcoin.pdf"
}
},
]
}
]
# Optional: Configure PDF processing engine
plugins = [
{
"id": "file-parser",
"pdf": {
"engine": "{{ENGINE}}"
}
}
]
payload = {
"model": "{{MODEL}}",
"messages": messages,
"plugins": plugins
}
response = requests.post(url, headers=headers, json=payload)
print(response.json())const response = await fetch('https://api.vega.chat/api/v1/chat/completions', {
method: 'POST',
headers: {
Authorization: `Bearer ${API_KEY_REF}`,
'Content-Type': 'application/json',
},
body: JSON.stringify({
model: '{{MODEL}}',
messages: [
{
role: 'user',
content: [
{
type: 'text',
text: 'What are the main points in this document?',
},
{
type: 'file',
file: {
filename: 'document.pdf',
file_data: 'https://bitcoin.org/bitcoin.pdf',
},
},
],
},
],
// Optional: Configure PDF processing engine
plugins: [
{
id: 'file-parser',
pdf: {
engine: '{{ENGINE}}',
},
},
],
}),
});
const data = await response.json();
console.log(data);URL‑адреса PDF работают со всеми движками обработки. Для Mistral OCR URL передаётся напрямую в сервис. Для остальных движков VEGA скачивает PDF и обрабатывает его внутренне.
Использование PDF, закодированных в Base64
Для локальных PDF‑файлов или когда необходимо отправить содержимое PDF напрямую, вы можете закодировать файл в base64:
import requests
import json
import base64
from pathlib import Path
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.vega.chat/api/v1/chat/completions"
headers = {
"Authorization": f"Bearer {API_KEY_REF}",
"Content-Type": "application/json"
}
# Read and encode the PDF
pdf_path = "path/to/your/document.pdf"
base64_pdf = encode_pdf_to_base64(pdf_path)
data_url = f"data:application/pdf;base64,{base64_pdf}"
messages = [
{
"role": "user",
"content": [
{
"type": "text",
"text": "What are the main points in this document?"
},
{
"type": "file",
"file": {
"filename": "document.pdf",
"file_data": data_url
}
},
]
}
]
# Optional: Configure PDF processing engine
# PDF parsing will still work even if the plugin is not explicitly set
plugins = [
{
"id": "file-parser",
"pdf": {
"engine": "{{ENGINE}}" # defaults to "{{DEFAULT_PDF_ENGINE}}". See Pricing above
}
}
]
payload = {
"model": "{{MODEL}}",
"messages": messages,
"plugins": plugins
}
response = requests.post(url, headers=headers, json=payload)
print(response.json())async function encodePDFToBase64(pdfPath: string): Promise<string> {
const pdfBuffer = await fs.promises.readFile(pdfPath);
const base64PDF = pdfBuffer.toString('base64');
return `data:application/pdf;base64,${base64PDF}`;
}
// Read and encode the PDF
const pdfPath = 'path/to/your/document.pdf';
const base64PDF = await encodePDFToBase64(pdfPath);
const response = await fetch('https://api.vega.chat/api/v1/chat/completions', {
method: 'POST',
headers: {
Authorization: `Bearer ${API_KEY_REF}`,
'Content-Type': 'application/json',
},
body: JSON.stringify({
model: '{{MODEL}}',
messages: [
{
role: 'user',
content: [
{
type: 'text',
text: 'What are the main points in this document?',
},
{
type: 'file',
file: {
filename: 'document.pdf',
file_data: base64PDF,
},
},
],
},
],
// Optional: Configure PDF processing engine
// PDF parsing will still work even if the plugin is not explicitly set
plugins: [
{
id: 'file-parser',
pdf: {
engine: '{{ENGINE}}', // defaults to "{{DEFAULT_PDF_ENGINE}}". See Pricing above
},
},
],
}),
});
const data = await response.json();
console.log(data);Пропуск расходов на повторный разбор
Когда вы отправляете PDF в API, ответ может включать аннотации файла в сообщении ассистента. Эти аннотации содержат структурированную информацию о разобранном PDF‑документе. Отправляя эти аннотации обратно в последующих запросах, вы можете избежать повторного разбора того же PDF‑документа, что экономит как время обработки, так и затраты.
Как переиспользовать аннотации файла:
import requests
import json
import base64
from pathlib import Path
# First, encode and send the PDF
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.vega.chat/api/v1/chat/completions"
headers = {
"Authorization": f"Bearer {API_KEY_REF}",
"Content-Type": "application/json"
}
# Read and encode the PDF
pdf_path = "path/to/your/document.pdf"
base64_pdf = encode_pdf_to_base64(pdf_path)
data_url = f"data:application/pdf;base64,{base64_pdf}"
# Initial request with the PDF
messages = [
{
"role": "user",
"content": [
{
"type": "text",
"text": "What are the main points in this document?"
},
{
"type": "file",
"file": {
"filename": "document.pdf",
"file_data": data_url
}
},
]
}
]
payload = {
"model": "{{MODEL}}",
"messages": messages
}
response = requests.post(url, headers=headers, json=payload)
response_data = response.json()
# Store the annotations from the response
file_annotations = None
if response_data.get("choices") and len(response_data["choices"]) > 0:
if "annotations" in response_data["choices"][0]["message"]:
file_annotations = response_data["choices"][0]["message"]["annotations"]
# Follow-up request using the annotations (without sending the PDF again)
if file_annotations:
follow_up_messages = [
{
"role": "user",
"content": [
{
"type": "text",
"text": "What are the main points in this document?"
},
{
"type": "file",
"file": {
"filename": "document.pdf",
"file_data": data_url
}
}
]
},
{
"role": "assistant",
"content": "The document contains information about...",
"annotations": file_annotations
},
{
"role": "user",
"content": "Can you elaborate on the second point?"
}
]
follow_up_payload = {
"model": "{{MODEL}}",
"messages": follow_up_messages
}
follow_up_response = requests.post(url, headers=headers, json=follow_up_payload)
print(follow_up_response.json())import fs from 'fs/promises';
async function encodePDFToBase64(pdfPath: string): Promise<string> {
const pdfBuffer = await fs.readFile(pdfPath);
const base64PDF = pdfBuffer.toString('base64');
return `data:application/pdf;base64,${base64PDF}`;
}
// Initial request with the PDF
async function processDocument() {
// Read and encode the PDF
const pdfPath = 'path/to/your/document.pdf';
const base64PDF = await encodePDFToBase64(pdfPath);
const initialResponse = await fetch(
'https://api.vega.chat/api/v1/chat/completions',
{
method: 'POST',
headers: {
Authorization: `Bearer ${API_KEY_REF}`,
'Content-Type': 'application/json',
},
body: JSON.stringify({
model: '{{MODEL}}',
messages: [
{
role: 'user',
content: [
{
type: 'text',
text: 'What are the main points in this document?',
},
{
type: 'file',
file: {
filename: 'document.pdf',
file_data: base64PDF,
},
},
],
},
],
}),
},
);
const initialData = await initialResponse.json();
// Store the annotations from the response
let fileAnnotations = null;
if (initialData.choices && initialData.choices.length > 0) {
if (initialData.choices[0].message.annotations) {
fileAnnotations = initialData.choices[0].message.annotations;
}
}
// Follow-up request using the annotations (without sending the PDF again)
if (fileAnnotations) {
const followUpResponse = await fetch(
'https://api.vega.chat/api/v1/chat/completions',
{
method: 'POST',
headers: {
Authorization: `Bearer ${API_KEY_REF}`,
'Content-Type': 'application/json',
},
body: JSON.stringify({
model: '{{MODEL}}',
messages: [
{
role: 'user',
content: [
{
type: 'text',
text: 'What are the main points in this document?',
},
{
type: 'file',
file: {
filename: 'document.pdf',
file_data: base64PDF,
},
},
],
},
{
role: 'assistant',
content: 'The document contains information about...',
annotations: fileAnnotations,
},
{
role: 'user',
content: 'Can you elaborate on the second point?',
},
],
}),
},
);
const followUpData = await followUpResponse.json();
console.log(followUpData);
}
}
processDocument();Когда вы включаете аннотации файла из предыдущего ответа в последующие запросы, VEGA будет использовать эту предварительно разобранную информацию вместо повторного разбора PDF, что экономит время обработки и затраты. Это особенно полезно для больших документов или при использовании движка mistral-ocr, который влечёт дополнительные расходы.
Схема аннотаций файла
Когда VEGA разбирает PDF, ответ включает аннотации файла в сообщении ассистента. Ниже приведён тип TypeScript для схемы аннотации:
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 содержит разобранное содержимое PDF, которое может включать текстовые блоки и изображения (в виде base64 data URL). Поле hash уникально идентифицирует содержимое разобранного файла и используется для пропуска повторного разбора, когда вы включаете аннотацию в последующие запросы.
Формат ответа
API вернёт ответ в следующем формате:
{
"id": "gen-1234567890",
"provider": "DeepInfra",
"model": "google/gemma-3-27b-it",
"object": "chat.completion",
"created": 1234567890,
"choices": [
{
"message": {
"role": "assistant",
"content": "The document discusses...",
"annotations": [
{
"type": "file",
"file": {
"hash": "abc123...",
"name": "document.pdf",
"content": [
{ "type": "text", "text": "Parsed text content..." },
{ "type": "image_url", "image_url": { "url": "data:image/png;base64,..." } }
]
}
}
]
}
}
],
"usage": {
"prompt_tokens": 1000,
"completion_tokens": 100,
"total_tokens": 1100
}
}Ошибочные ответы с разобранными аннотациями
Если VEGA успешно разбирает ваш PDF, но каждый провайдер вывода затем не может сгенерировать завершение, ответ с ошибкой всё равно будет включать разобранные аннотации в error.metadata.file_annotations. Структура совпадает с FileAnnotation, описанным выше, поэтому вы можете передать тот же массив обратно в VEGA при повторной попытке, чтобы пропустить повторный разбор.
Это относится к движкам <code>"{PDFParserEngine.MistralOCR}"</code> и <code>"{PDFParserEngine.CloudflareAI}"</code>, которые разбирают PDF перед отправкой модели. Движок <code>"{PDFParserEngine.Native}"</code> не создаёт аннотаций, потому что файл передаётся напрямую модели.
{
"error": {
"code": 502,
"message": "Provider returned an error",
"metadata": {
"file_annotations": [
{
"type": "file",
"file": {
"hash": "abc123...",
"name": "document.pdf",
"content": [
{ "type": "text", "text": "Parsed text content..." }
]
}
}
]
}
}
}Когда вы читаете аннотации как из успешного, так и из ошибочного пути, удаляйте дубликаты по file.hash — хеш стабилен для обеих форм для одного и того же разобранного файла:
function isFileAnnotation(value: unknown): value is FileAnnotation {
if (typeof value !== 'object' || value === null) return false;
const candidate = value as { type?: unknown; file?: { hash?: unknown } };
return (
candidate.type === 'file' &&
typeof candidate.file?.hash === 'string'
);
}
function extractFileAnnotations(response: unknown): FileAnnotation[] {
if (typeof response !== 'object' || response === null) return [];
const root = response as {
choices?: Array<{ message?: { annotations?: unknown[] } }>;
error?: { metadata?: { file_annotations?: unknown[] } };
};
const fromMessage = root.choices?.[0]?.message?.annotations ?? [];
const fromError = root.error?.metadata?.file_annotations ?? [];
const seen = new Set<string>();
const out: FileAnnotation[] = [];
for (const a of [...fromMessage, ...fromError]) {
if (isFileAnnotation(a) && !seen.has(a.file.hash)) {
seen.add(a.file.hash);
out.push(a);
}
}
return out;
}