Эмбеддинги и мультимодальность
POST /v1/embeddings совместим с OpenAI: каждый элемент input → один
вектор в ответе. Поверх стандарта шлюз добавляет мультимодальное
расширение — элемент input может быть не строкой, а массивом «частей»
(text/image/audio/video/pdf), которые агрегируются в один вектор.
Обычный текстовый ввод
from openai import OpenAI
client = OpenAI(
base_url="https://api.aigateway.andrewdev.ru/v1",
api_key="sk-tn-ВАШ_КЛЮЧ",
)
response = client.embeddings.create(
model="gemini-embedding-2",
input=["первый текст", "второй текст"],
)
for item in response.data:
print(item.index, len(item.embedding))input принимает строку или массив; каждый элемент массива — это либо
строка (обычный текст), либо массив частей (см. ниже). Несколько
элементов input уходят апстриму одним батч-запросом.
Мультимодальное расширение
Вместо строки элемент input может быть массивом частей. Все части
одного элемента объединяются в один запрос эмбеддинга и дают один
вектор на выходе (не по вектору на часть):
{
"model": "gemini-embedding-2",
"input": [
[
{ "type": "text", "text": "Подпись к товару" },
{
"type": "image_url",
"image_url": { "url": "data:image/png;base64,iVBORw0KGgo..." }
}
]
]
}Поддерживаемые типы частей:
type | Форма | Ограничение (400, если превышено) |
|---|---|---|
text | {"type": "text", "text": string} | — |
image_url | {"type": "image_url", "image_url": {"url": "data:image/png|image/jpeg;base64,..."}} | не более 6 изображений на элемент input; только PNG/JPEG base64 data-URI |
input_audio | {"type": "input_audio", "input_audio": {"data": string, "format": "mp3" | "wav"}} | см. практический лимит Gemini ниже |
input_video | {"type": "input_video", "input_video": {"data": string, "format": "mp4" | "mov"}} | см. практический лимит Gemini ниже |
input_file | {"type": "input_file", "input_file": {"data": string, "mime_type": "application/pdf"}} | не более 1 PDF на элемент input |
data во всех случаях — содержимое файла в base64 (без data: префикса
для audio/video/file — в отличие от image_url, где нужен полный
data-URI).
Изображения и PDF шлюз проверяет до обращения к апстриму — превышение
лимита возвращает наш собственный 400 invalid_request с понятным
сообщением, апстрим не вызывается.
Только для Gemini-моделей эмбеддингов
Части (image_url/input_audio/input_video/input_file) принимает
только модель на маршруте Google (например, gemini-embedding-2). Если
такой элемент input отправить модели на OpenAI-совместимом маршруте,
шлюз вернёт 400: "This model does not support multimodal embeddings".
Обычная строка в input работает с любой моделью эмбеддингов.
Практические лимиты Gemini Embedding 2
Помимо проверок count (6 изображений, 1 PDF), сама модель
gemini-embedding-2 на стороне Google ограничивает содержимое так:
| Медиа | Лимит |
|---|---|
| Аудио (MP3/WAV) | до 180 с |
| Видео (MP4/MOV) | до 120 с (32 кадра) |
| 1 файл, до 6 страниц (~258 токенов/страница) | |
| Суммарно на запрос | 8192 токена |
Эти лимиты — не наша локальная валидация (шлюз их не пересчитывает
заранее), а ограничение самой модели: превышение вернёт ошибку от
апстрима, транслированную в наш стандартный 502/400. Планируйте
контент в этих рамках, чтобы не терять запрос на середине пайплайна.
Пример полного запроса на Python
import base64
with open("product.png", "rb") as f:
image_b64 = base64.b64encode(f.read()).decode()
response = client.embeddings.create(
model="gemini-embedding-2",
input=[
"обычный текстовый запрос",
[
{"type": "text", "text": "Фото товара с описанием"},
{
"type": "image_url",
"image_url": {"url": f"data:image/png;base64,{image_b64}"},
},
],
],
)
print(len(response.data)) # 2 вектора: один на строку, один на элемент-массивОтвет
{
"object": "list",
"model": "gemini-embedding-2",
"data": [
{ "object": "embedding", "index": 0, "embedding": [0.0123, -0.0456, "..."] },
{ "object": "embedding", "index": 1, "embedding": [0.0031, 0.0789, "..."] }
],
"usage": { "prompt_tokens": 342, "total_tokens": 342 }
}usage для Gemini-эмбеддингов — всегда оценка
Gemini не возвращает точное число токенов для embedContent/
batchEmbedContents — для моделей на маршруте Google usage всегда
оценивается шлюзом по документированным правилам Google (символы
текста / 4, ~258 токенов на изображение, ~1000 на аудио, ~1500 на
видео, ~1548 на PDF) и помечен как оценочный. Для эмбеддинг-моделей на
OpenAI-совместимом маршруте usage берётся из ответа апстрима, если он
его вернул.