Решения
Эмбеддинги на GPU: батч‑планирование и хранение
Задача страницы. Дать практический рецепт вычисления эмбеддингов на облачных GPU: выбор модели и формата, батч‑планирование под VRAM, оффлайн‑ингест и онлайн‑эмбеддинг для запросов, хранение/квантизация векторных представлений и метрики производительности/стоимости.
TL;DR
- Два основных контура: оффлайн‑ингест (массовые эмбеддинги документов) и онлайн‑эмбеддинг (быстрые векторы запросов).
- Ускорение на GPU даёт максимум выигрыша при крупных батчах и политике fp16/bf16 с аккуратным планированием VRAM.
- Храните векторы в fp16 или квантуйте до int8/PQ, если нужен огромный объём и быстрый поиск (см. /solutions/rag/vector-db/).
- Ключевые метрики: T_embed (ms/запрос), QPS, recall после компрессии, цена за 1M эмбеддингов.
Связанные разделы:
/solutions/rag/ • /solutions/rag/vector-db/ • /solutions/rag/evaluation/ • /solutions/llm-inference/observability/ • /solutions/llm-inference/costs/ • /solutions/cost-planner/ • /solutions/monitoring-logging/
Модель эмбеддингов: как выбирать
Критерии:
- Языки/домены: рус/англ, код/юридический/медицинский.
- Размер и латентность: чем больше dim и модель, тем выше качество, но выше T_embed.
- Совместимость с индексом: cosine/IP‑метрика, нормировка L2.
- Стоимость: fp16 на одной GPU обычно даёт лучший баланс цена/скорость.
Практика:
- Для онлайн‑чатов и RAG — компактные энкодеры (низкая латентность), dim 384–1024.
- Для сложных доменов — средние/крупные энкодеры + rerank по необходимости (см. /solutions/rag/vector-db/).
Предобработка текста и чанкование
- Очистка HTML/PDF, нормализация пробелов, стандартные кавычки/дефисы.
- Чанкование: 256–512 токенов (чат/QA), 768–1024 (аналитика), overlap 10–20%.
- Метаданные: doc_id, section, lang, timestamp, tags.
- Дедупликация шинглами/абзацами.
Подробнее: /solutions/rag/.
Батч‑планирование под VRAM

Прикидка памяти (упрощённо):
VRAM ≈ B × (SeqLen × Hidden × bytes_per_elem × k_act) + Overhead
# B — batch size; k_act ~ 2–3 для активаций/временных буферов
# fp16/bf16: 2 байта/элемент; fp32: 4 байта/элемент
Правила:
- Используйте fp16/bf16, torch.no_grad() и автокаст.
- Включайте pinned memory и передачу non_blocking=True.
- Подберите Batch Size эмпирически по «колену» p95 и утилизации.
- Для коротких последовательностей выше throughput даёт укрупнение батча, для длинных — умное SeqLen‑ограничение.
Пример (PyTorch, mean‑pooling):
import torch, numpy as np
from transformers import AutoTokenizer, AutoModel
device = torch.device("cuda:0")
tok = AutoTokenizer.from_pretrained("./embedder")
model = AutoModel.from_pretrained("./embedder").to(device).eval()
@torch.inference_mode()
def embed_texts(texts, max_length=512, batch_size=256, dtype=torch.bfloat16):
outs = []
with torch.autocast("cuda", dtype=dtype):
for i in range(0, len(texts), batch_size):
batch = texts[i:i+batch_size]
enc = tok(batch, padding=True, truncation=True,
max_length=max_length, return_tensors="pt")
enc = {k: v.to(device, non_blocking=True) for k,v in enc.items()}
h = model(**enc).last_hidden_state # [B, T, H]
mask = enc["attention_mask"].unsqueeze(-1) # [B, T, 1]
emb = (h * mask).sum(dim=1) / mask.sum(dim=1).clamp_min(1) # mean-pool
emb = torch.nn.functional.normalize(emb, p=2, dim=1) # для cosine=IP
outs.append(emb.detach().cpu())
return torch.cat(outs, dim=0).numpy().astype(np.float16) # хранить fp16
Онлайн‑эмбеддинг запросов
Цель: p95 T_embed_q ≤ 20–40 мс при умеренной длине (≤ 256 токенов).
Практика:
- Держите модель “hot” в VRAM, прогрейте токенайзер.
- Фиксируйте/урезайте max_length для запросов.
- Считайте пачками: объединяйте параллельные запросы по 8–64 (микро‑батч) в очереди.
- Отдельный пул для длинных запросов (см. /solutions/llm-inference/multi-model/).
- Метрики и алерты: /solutions/llm-inference/observability/.
Мульти‑GPU, MIG и шардирование
- Data‑параллель для оффлайн‑ингеста: разрезайте датасет по узлам/картам, объединяйте результаты.
- MIG: выделяйте маленькие слайсы для онлайн‑эмбеддинга (низкая латентность), крупные — для оффлайн‑батчей. См. /solutions/mig/.
- Шардирование по tenant/doc_id для параллельного расчёта и обновлений.


Хранение и форматы
Размер (прикидка):
Mem ≈ N × dim × bytes_per_elem
# Пример: 2M × 768 × 2 байта(fp16) ≈ ~2.95 ГБ (без оверхеда индекса)
Рекомендации:
- fp16 как базовый формат хранения; для экономии — int8/PQ (см. ниже).
- Храните рядом метаданные (Parquet/JSONL): doc_id, chunk_id, offset, lang, ts.
- Версионируйте «корпус@версия, модель@версия, предобработка@хэш».
- Держите «горячие» коллекции на NVMe, индексы — в VRAM/памяти сервера поиска.
- Интеграция с поиском: /solutions/rag/vector-db/.
Квантизация эмбеддингов: int8 и PQ
Зачем: снизить хранение и ускорить поиск на больших N.
A) Простая row‑wise int8 (симметричная)
- Один масштаб на вектор (или per‑dim).
- Храните scale и zero_point (для симметричной — zero_point=0).
import numpy as np
def quantize_int8_rowwise(x: np.ndarray):
# x: [N, dim] float16/32, L2-нормализован (желательно)
norms = np.max(np.abs(x), axis=1, keepdims=True) + 1e-8
scale = norms / 127.0
q = np.clip(np.round(x / scale), -127, 127).astype(np.int8)
return q, scale.astype(np.float32)
def dequantize_int8_rowwise(q: np.ndarray, scale: np.ndarray):
return (q.astype(np.float32) * scale).astype(np.float32)
- Плюсы: простота, ×2–×4 экономия; Минусы: небольшой спад качества косинусной близости.
- Для сравнения cosine/IP лучше хранить нормированные векторы и пересчитывать норму после де‑кванта.
B) Product Quantization (PQ)
- Делит вектор на m субвекторов и кодирует каждый кодом bits (4/6/8).
- Существенно сокращает память (см. /solutions/rag/vector-db/), небольшой спад recall → компенсируйте nprobe/rerank.
Качество эмбеддингов
- Нормируйте L2, используйте cosine как IP c нормировкой.
- Проверяйте двуязычность/мультиязычность вашего энкодера.
- Оффлайн‑оценка: Recall@K/MRR на валид‑запросах; онлайновая — CSAT/deflection.
Подробнее: /solutions/rag/evaluation/.
Ингест‑пайплайн (офлайн): от текстов к индексу
[Scrape/Docs] → Clean → Chunk → Embed (GPU, batched) → Store (fp16/int8) → Build Index (GPU) → Persist
Псевдокод:
def ingest(docs, embedder, vecdb, batch=2048):
# 1) Clean & chunk
chunks = list(generate_chunks(docs, size=512, overlap=64)) # см. /solutions/rag/
# 2) Embed on GPU
vecs = embedder(chunks, batch_size=batch, max_length=512)
# 3) (Опц.) Quantize & persist
# q, scale = quantize_int8_rowwise(vecs)
save_vectors(vecs, meta=chunks.meta) # fp16 обычно достаточно
# 4) Build index on GPU
vecdb.build(vecs, kind="IVF-PQ", nlist=4096, m=32, bits=8)
vecdb.persist()
Детали индексов и параметров: /solutions/rag/vector-db/.
Онлайн‑поиск (RAG): latency‑бюджет
Разложение задержки:
T_total ≈ T_embed_q + T_search + T_rerank + T_LLM
- Минимизируйте T_embed_q батчированием запросов и фиксированным max_length.
- Держите индексы на GPU, T_search ≤ 50–150 мс (p95), смотрите /solutions/rag/vector-db/.
- Стримьте ответ LLM (см. /solutions/llm-inference/streaming/).
Наблюдаемость и стоимость
Метрики:
- embed_latency_ms p50/p95, embed_qps, размер батча, seq_len.
- GPU: util/HBM, PCIe/NVLink, загрузка токенизатора (CPU).
- Ингест: время на 1M токенов/доков; онлайн: T_embed_q и ошибки.
Экономика (оценка цены за 1M эмбеддингов):
Embeddings_per_hour ≈ QPS × 3600
Cost_per_1M_embed ≈ (GPU_hour_price × Num_GPU) / (Embeddings_per_hour / 1e6)
Для токен‑экономики и сравнения со стоимостью LLM‑ответов см. /solutions/llm-inference/costs/ и планировщик /solutions/cost-planner/.
Безопасность и приватность
- Маскируйте PII до эмбеддинга, храните маппинг токенов‑замен отдельно.
- Логируйте метаданные событий (без сырого текста), см. /solutions/llm-inference/guardrails/ и /solutions/security/.
Как это запустить в cloudcompute.ru
- Шаблоны в /solutions/templates/:
– “Embeddings‑Batcher”: оффлайн‑ингест с fp16, pin‑memory, профилем VRAM;
– “Embeddings‑API”: онлайн‑эмбеддинг с микро‑батчами, фикс. max_length, метрики и алерты;
– “RAG‑VectorDB (GPU)”: сборка индекса IVF‑Flat/IVF‑PQ. - Планирование цены/режимов: /solutions/cost-planner/.
- Наблюдаемость: /solutions/llm-inference/observability/, логи — /solutions/monitoring-logging/.
Чек‑лист перед продом
- Выбрана модель эмбеддингов (языки/домен/latency).
- Настроены батчи и dtype (fp16/bf16), подтверждён VRAM‑бюджет.
- Определены размеры чанков и метаданные; включён дедуп.
- Решена схема хранения: fp16 или int8/PQ; зафиксированы версии.
- Собраны индексы и подтверждён recall/latency (валидация).
- Включены метрики/алерты; рассчитана цена за 1M эмбеддингов.
- Настроены guardrails и маскирование PII.