Искусственный интеллект и машинное обучение

Сервер для корпоративного RAG: Как рассчитать требования

~15 минут15 сентября 2026 г.

Сервер для RAG нельзя корректно выбрать только по объёму базы знаний, числу сотрудников или размеру LLM.

Сначала нужно описать две разные нагрузки. Первая — ingestion и indexing: сколько документов меняется, сколько chunks и embeddings требуется создать и через какое время новая версия должна стать доступна в поиске. Вторая — online serving: сколько запросов приходит одновременно, как работает filtered retrieval, сколько кандидатов обрабатывает reranker и какой token profile получает LLM.

Только после этого требования переводятся в CPU, RAM, storage, GPU и количество узлов.

CORPUS + CHANGE RATE

        ↓

extraction

        ↓

chunking

        ↓

embedding

        ↓

index update

        ↓

freshness SLA


        +


QUERY LOAD

        ↓

query embedding

        ↓

filtered retrieval

        ↓

reranking

        ↓

context

        ↓

LLM

        ↓

latency SLA


        ↓

combined-load test


        ↓

shared

/

isolated

/

independently scaled

Главный принцип:

Актуальная NVIDIA Enterprise RAG architecture также рассматривает retrieval pipeline как несколько компонентов — RAG server, embedding, vector database, reranker и LLM — которые могут становиться отдельными bottlenecks и масштабироваться независимо. Конкретные размеры NVIDIA reference architecture при этом относятся к её моделям и software stack и не являются универсальной нормой.

Разделите RAG на ingestion и online serving

1
Разделите RAG на ingestion и online serving

Ingestion / indexing plane

source

  ↓

extraction

  ↓

chunking

  ↓

embedding

  ↓

DB write

  ↓

index update

  ↓

searchable

Полезные единицы нагрузки:

documents/s

pages/s

chunks/s

embeddings/s

vectors/s

Например, NVIDIA в своей ingestion methodology использует documents per second или pages per second в зависимости от типа данных и способа обработки. Это хороший пример того, почему единицу нагрузки нужно выбирать по реальному pipeline, а не по объёму диска.

Online serving plane

query

  ↓

query embedding

  ↓

filtered retrieval

  ↓

reranking

  ↓

context construction

  ↓

LLM prefill

  ↓

generation

Здесь нужны другие inputs:

QPS

concurrency

retrieval Top-K

rerank candidates/request

input tokens

output tokens

TTFT

ITL

E2E latency

Одна строка:

RAG load = high

не является входными данными для инженерного расчёта.

Почему 500 GB документов не определяют сервер

Исходный corpus проходит несколько преобразований:

raw documents

≠

parsed content

≠

chunks

≠

vectors

≠

vector database footprint

На итог влияют:

document formats

parser

tokenizer

chunking strategy

chunk size

overlap

embedding dimension

datatype

dense/sparse representation

metadata

filter indexes

ANN index

replication

Минимальный corpus record:

Input

Значение

Documents / objects

Pages

Raw bytes

Рост в месяц

PDF / DOCX / HTML

Scans / images

Tables

Parser + version

Chunker + version

Embedding model + version

Число chunks лучше измерить на representative sample

Надёжный путь:

representative corpus

        ↓

production parser

        ↓

production chunker

        ↓

measured chunk count

        ↓

project estimate

Не следует использовать универсальное:

1 PDF = 40 chunks

или:

1 GB = N vectors

Если конкретный pipeline действительно использует обычное overlapping-window splitting, для предварительной оценки можно использовать:

Nchunks=1+⌈max⁡(0,T−C)C−O⌉N_{chunks} = 1+ \left\lceil \frac{\max(0,T-C)} {C-O} \right\rceil

при C > O, где T — длина документа в токенах, C — размер chunk, O — overlap.

Raw vector payload можно рассчитать

Для N dense vectors размерности D при B bytes на один элемент:

RawVectorBytes=N×D×BRawVectorBytes=N\times D\times B

Если физическая replication равна R:

RawVectorBytesreplicated=N×R×D×BRawVectorBytes_{replicated} = N\times R\times D\times B

Это именно базовый payload vectors.

Qdrant в текущей capacity-planning documentation использует такую же основу: число points, replication, dimensions и datatype; при нескольких named vectors каждое представление считается отдельно.

Обязательные inputs:

Vector count:

Dimensions:

Datatype:

Replication:

Datatype нельзя предполагать

Нельзя автоматически считать каждый embedding как FP32.

Возможны, например:

float32

float16

uint8

и другие поддерживаемые выбранным stack representation.

Следовательно:

Dimensions:

Datatype:

должны фиксироваться вместе.

Quantization тоже не означает, что весь disk footprint сокращается в ту же пропорцию. В Qdrant, например, quantized representation хранится наряду с original vectors; конфигурация может уменьшать RAM working set, не удаляя исходные vectors с диска. Сам Qdrant рекомендует отдельно проверять качество поиска после quantization.

Raw vectors — не размер vector DB

Полный storage/RAM footprint может дополнительно включать:

ANN index


sparse-vector index

if used


payload / metadata


payload indexes


IDs


quantized copies


WAL


temporary optimization data


snapshots


replicas

Qdrant, например, рассчитывает dense vectors, HNSW, payload, payload indexes и ID tracker как самостоятельные structures. Их placement между RAM и disk также настраивается отдельно.

Поэтому нельзя использовать vendor-neutral shortcut:

Vector DB size =

raw vectors × 1.2

Корректнее:

Слой

Как получать

Dense raw vectors

CALCULATED

Sparse vectors, если есть

CALCULATED / STACK-SPECIFIC

ANN/vector index

STACK-SPECIFIC

Metadata/payload

MEASURED / ESTIMATED

Filter indexes

STACK-SPECIFIC

WAL / temporary data

STACK-SPECIFIC

Replication

EXPLICIT

Backup / snapshots

EXPLICIT

Actual DB footprint

MEASURED

Если database/index ещё не выбран:

FULL DB FOOTPRINT:

CONDITIONAL

Hybrid search нужно считать отдельно

Некоторые RAG systems используют одновременно dense и sparse retrieval.

В таком случае нельзя применить формулу dense-vector payload ко всему индексу.

Нужно отдельно учитывать:

dense vectors

dense ANN index


sparse representation

sparse index


metadata/filter indexes

Например, Qdrant capacity guidance отдельно считает sparse vectors по числу ненулевых элементов, а не по dense dimension.

Для ingestion важнее change rate, чем только total corpus

После initial load система обычно продолжает получать:

new documents

changed documents

deleted documents

Поэтому нужны:

New documents/day:

Changed documents/day:

Deleted documents/day:


Peak update batch:

Allowed processing window:

Для простого workload budget:

RequiredDocsPerSecond=DocumentsToProcessAvailableProcessingWindowSecondsRequiredDocsPerSecond= \frac{DocumentsToProcess} {AvailableProcessingWindowSeconds}

Для page-oriented extraction:

RequiredPagesPerSecond=PagesToProcessAvailableProcessingWindowSecondsRequiredPagesPerSecond= \frac{PagesToProcess} {AvailableProcessingWindowSeconds}

А для embedding stage:

RequiredEmbeddingsPerSecond=EmbeddingsToCreateAvailableProcessingWindowSecondsRequiredEmbeddingsPerSecond= \frac{EmbeddingsToCreate} {AvailableProcessingWindowSeconds}

Это требование к workload, а не заявленная производительность CPU или GPU.

Freshness нужно считать до searchable state

Для корпоративной базы знаний полезен отдельный KPI:

UpdateLag=tsearchable−tsource changeUpdateLag= t_{searchable}-t_{source\ change}

Например, бизнес может требовать, чтобы изменённый документ появлялся в production retrieval не позже определённого времени после изменения источника.

В UpdateLag могут входить:

source sync

extraction

chunking

embedding

DB write

index update

visibility

Поэтому завершение embedding job ещё не обязательно означает, что новые сведения доступны пользователю.

Для exact vector DB нужно определить её реальные semantics:

durably written

searchable

fully indexed / optimized

и не переносить поведение одного продукта на другой.

Initial load и steady-state ingestion — разные тесты

Нужно минимум два ingestion profile.

Сценарий

Что проверяем

Initial / bulk load

сколько времени занимает загрузка существующей базы

Steady-state

укладываются ли регулярные изменения в freshness SLA

Третий профиль — самый важный для architecture decision:

Steady-state ingestion одновременно с production query workload.

При массовой загрузке Qdrant, например, одновременно работает с writes, indexing и optimizer operations; его документация отдельно предупреждает о нагрузке на память, диск и search performance во время bulk ingestion.

Это stack-specific пример общего принципа: ingestion нельзя считать полностью независимым от retrieval, если они делят ресурсы.

Число сотрудников не равно concurrency

Фраза:

система для 5 000 сотрудников

не означает:

5 000 concurrent requests

Для online workload нужны:

Baseline QPS:

Peak QPS:


Peak concurrency:


Burst duration:


Arrival profile:


Evidence:

MEASURED / FORECAST / ASSUMPTION

NVIDIA sizing guide тоже использует concurrent requests и latency constraint как непосредственные параметры sizing. В самой документации есть пример оценки concurrency из доли пользователей, но такой процент относится к её sizing example и не должен становиться универсальной формулой Start Server.

Если известен только штат сотрудников, concurrency нужно сначала смоделировать или измерить отдельно.

QPS и concurrency не взаимозаменяемы

QPS отвечает на вопрос:

Сколько запросов приходит или завершается за секунду?

Concurrency:

Сколько запросов одновременно находятся в работе?

При длинных запросах умеренный QPS может создавать высокую concurrency.

Поэтому оба параметра сохраняются отдельно.

Production retrieval benchmark должен включать filters

В корпоративной системе запрос нередко ограничивается:

tenant

department

group

document type

security classification

project

Benchmark без таких условий может не отражать production retrieval.

Qdrant, например, рекомендует payload indexes для полей, используемых при filtering; эти индексы влияют на структуру vector index и сами требуют ресурсов.

Поэтому record должен содержать:

Production filters:

Filter fields:

Indexing:

Filter selectivity:

ACL correctness и filter performance — разные задачи

SS-021 занимается infrastructure sizing.

Поэтому разделяем:

SECURITY CORRECTNESS


может ли этот пользователь

видеть документ?

и:

FILTER PERFORMANCE


укладывается ли retrieval

с production ACL filters

в SLA?

Второе входит в benchmark.

Первое требует отдельного security review.

Retrieval latency без Top-K почти бесполезна

Результат:

Vector search = 20 ms

нужно сопровождать:

Vector count:

Dimensions/datatype:


Index/version:


Filters:

Top-K:


QPS:

Concurrency:


Hardware:

Software version:

NVIDIA также использует Top-K как отдельный параметр RAG workload, наряду с concurrency, chunk size и input/output sequence length.

Но конкретные рекомендуемые значения Top-K из одной reference architecture не становятся default для другого RAG.

Retrieval Top-K и context Top-N — разные параметры

Если используется reranker:

retrieval

→ K candidates

→ reranker

→ N chunks

→ LLM

где обычно:

N≤KN\leq K

если именно так устроен pipeline.

Поэтому храните две строки:

Retrieval Top-K:

Reranker output Top-N:

Это важно и для retrieval load, и для downstream token profile.

Reranker не обязателен для каждого RAG

В worksheet:

Reranker:

USED / NOT USED / TEST


Model/version:

Если reranker есть, удобная workload metric:

CandidatePairsPerSecond=QPS×CandidatesPerQueryCandidatePairsPerSecond = QPS\times CandidatesPerQuery

Например:

40 QPS

× 25 candidates

=

1 000 query-document pairs/s

Это только арифметическое описание нагрузки.

Из него нельзя заключить:

нужна GPU X

без benchmark конкретного reranker, runtime, precision и batching.

Generation начинается с token profile

Для LLM нужны:

Model/version:

Precision:


Base prompt tokens:

Retrieved-context tokens:

Total input tokens:


Output tokens:


Peak concurrency:

Название модели само по себе недостаточно.

Актуальный vLLM отдельно собирает distributions prompt tokens и generation tokens, что позволяет анализировать фактический serving profile, а не только model name.

TTFT, ITL и E2E нельзя смешивать

Для streaming LLM полезно разделять:

Метрика

Что помогает понять

Queue time

сколько запрос ожидает scheduling

TTFT

задержку до первого output token

ITL / TPOT

скорость продолжения генерации

E2E

общую пользовательскую задержку

Точная семантика начала/конца каждой метрики зависит от serving runtime и версии, поэтому в benchmark нужно хранить tool/version.

vLLM, например, отдельно экспортирует TTFT, inter-token latency, end-to-end latency, running/waiting requests, а также prefill/decode-related metrics.

Это помогает не путать:

slow generation

с:

request waits

because service is saturated

Queue time — отдельный bottleneck signal

Если TTFT вырос, это ещё не означает, что нужна более быстрая GPU.

Причиной могут быть:

queueing

high concurrency

long prefill

KV-cache pressure

scheduler capacity

vLLM отдельно показывает waiting requests и queue intervals именно для такого анализа.

Поэтому generation record включает:

Waiting requests:

Queue latency:


TTFT:

ITL:

E2E:

RAG Latency Budget

Для design stage используйте бюджет:

Stage

Target

p50

p95

p99

Conditions

Query embedding

Filtered retrieval

Reranking

Context/orchestration

LLM TTFT

Generation / ITL

End-to-end

Stage budget не равен фактическому critical path

2
Stage budget не равен фактическому critical path

Для предварительной модели можно написать:

Tbudget=Tembed+Tretrieve+Trerank+Tcontext+TLLMT_{budget} = T_{embed} + T_{retrieve} + T_{rerank} + T_{context} + T_{LLM}

Но runtime может содержать:

parallel operations

async execution

overlap

cache hits

queueing

streaming

Поэтому эта сумма — budgeting tool, а не доказательство фактической E2E latency.

Факт берётся из end-to-end measurement и trace.

Среднего значения недостаточно

average latency = 600 ms

может скрывать длинный tail.

Поэтому benchmark должен заранее определить:

Target percentile:

p95 / p99 / project-defined


Target:

Measured:

Нет универсального:

p95 < 2 seconds

для любого корпоративного RAG.

Target зависит от use case.

Быстрый retrieval бесполезен, если качество стало неприемлемым

Изменение:

Top-K

index parameters

quantization

search mode

может менять и performance, и retrieval quality.

Поэтому рядом с latency:

Retrieval evaluation dataset:


Quality metric:

Target:

Measured:

Qdrant, например, прямо рекомендует проверять recall при использовании quantization.

Universal recall threshold статья не назначает.

Нужно ли vector DB полностью помещать в RAM

Универсального ответа нет.

Конкретные vector stores позволяют по-разному размещать vectors, indexes и payload structures.

Например, Qdrant различает memory tiers для dense vectors, HNSW, payload, payload indexes и quantized representations. Это создаёт разные RAM/disk/latency trade-offs.

Поэтому нельзя писать ни:

Vector DB всегда должна полностью помещаться в RAM.

ни:

Vector DB всегда можно держать на NVMe без влияния на latency.

Проверяется exact stack и working set.

Главный тест: query и ingestion одновременно

Перед решением один сервер или несколько нужны три режима.

TEST A


production query load

without ingestion

TEST B


target ingestion/update load

without online queries

TEST C


production query load

+

target ingestion load

Во всех трёх режимах измеряем:

CPU


RAM


storage latency / throughput


GPU / VRAM where relevant


retrieval p95/p99


reranker latency


LLM queue


TTFT / ITL / E2E


UpdateLag

Как трактовать combined-load test

Если:

A = PASS

B = PASS

C = PASS

shared deployment остаётся жизнеспособным кандидатом.

Если:

A = PASS

B = PASS

C = FAIL

доказан конфликт ресурсов при совместной нагрузке.

Но ещё не доказано, что требуется новый физический сервер.

Следующие варианты могут включать:

tuning


resource limits


different scheduling


memory/storage placement


service isolation


independent scale-out

Когда компонент становится отдельным scaling domain

Наблюдение

Следующий архитектурный вопрос

LLM queue растёт, retrieval стабилен

масштабировать generation?

Retrieval SLA нарушается при свободном LLM

нужен независимый search tier?

Reranker saturates отдельно

масштабировать reranking?

Ingestion ухудшает online latency

schedule/isolate/separate ingestion?

Index footprint упирается в RAM/storage

менять VDB topology/placement?

Service требует независимого HA/restart cycle

отделить failure domain?

NVIDIA reference design также масштабирует LLM, embedding, reranker, RAG server и vector DB nodes по bottleneck соответствующего компонента. Это подтверждает принцип независимых scaling domains, но не её конкретные resource ratios как универсальный sizing rule.

Production не означает автоматически multi-node

Нельзя использовать:

production RAG

=

минимум 3 сервера

Перед HA design нужны:

Availability target:


RTO:

RPO:


Maintenance window:


Allowed degraded mode:

Single-node может пройти performance requirements, но не пройти availability requirements.

Это разные решения.

RAG Architecture & Sizing Worksheet

3
RAG Architecture & Sizing Worksheet

Ниже — основной самостоятельный инструмент статьи.

USE CASE


Use case:

Departments:


Availability target:

RTO:

RPO:


End-to-end latency target:

Target percentile:



CORPUS


Documents:

Pages / objects:

Raw bytes:


Growth/month:


Formats:


PDF:

DOCX:

HTML:

Scans:

Tables:

Images:


Representative sample:



PARSING / CHUNKING


Parser/version:

Tokenizer/version:


Chunking method:

Chunk size:

Overlap:


Measured chunks/sample:


Estimated total chunks:


Status:

MEASURED /

ASSUMPTION /

UNKNOWN



EMBEDDINGS


Model/version:


Dense:

YES / NO


Dimensions:

Datatype:


Sparse/hybrid:

YES / NO


Replication:



UPDATES


New documents/day:

Changed documents/day:

Deleted documents/day:


Peak batch:


Available update window:


Required docs/s:

Required pages/s:

Required embeddings/s:


Maximum UpdateLag:



VECTOR STORAGE


Vector DB/version:

Index/version:


Dense vector count:

Dense raw bytes:


Sparse structures:

if applicable


ANN/vector index:


Metadata/payload:

Filter indexes:


WAL/temp:


Replication:


Snapshots/backup:


Measured DB footprint:



RETRIEVAL


Baseline QPS:

Peak QPS:


Peak concurrency:

Burst duration:


Production filters:

ACL-related filters:


Retrieval Top-K:


Quality metric:

Target:


p50:

p95:

p99:



RERANK


USED /

NOT USED /

TEST


Model/version:


Candidates/request:

Output chunks/request:


Peak requests/s:


Candidate pairs/s:


Concurrency:


p50:

p95:

p99:



GENERATION


LLM/version:

Precision:


Base prompt tokens:


Retrieved-context tokens:


Total input tokens:

Output tokens:


Peak concurrency:


Waiting requests:

Queue latency:


TTFT:

ITL / TPOT:

E2E:



COMBINED LOAD


A — query only:

PASS / FAIL


B — ingestion only:

PASS / FAIL


C — query + ingestion:

PASS / FAIL



RESOURCE OBSERVATION


CPU:

RAM:


Storage latency:

Storage throughput:


GPU:

VRAM:


Network:


Other:



DEPLOYMENT


Extraction:

SHARED / ISOLATED /

SEPARATE / TEST


Embedding:

SHARED / ISOLATED /

SEPARATE / TEST


Vector DB:

SHARED / ISOLATED /

SEPARATE / TEST


Reranker:

SHARED / ISOLATED /

SEPARATE / TEST


LLM:

SHARED / ISOLATED /

SEPARATE / TEST



RESULT


Primary bottleneck:


Freshness SLA:

PASS / FAIL


Retrieval SLA:

PASS / FAIL


Generation SLA:

PASS / FAIL


E2E SLA:

PASS / FAIL


Independent scaling required:

YES / NO / TEST


Critical unknowns:

...

Как трактовать результат

Не выводите конкретный сервер, если критические workload inputs неизвестны.

Используем четыре состояния:

Статус

Значение

SIZED

workload/SLA подтверждены и architecture прошла требуемый benchmark

CANDIDATE

предварительный sizing есть, требуется validation

CONDITIONAL

результат зависит от software/index/config assumption

INSUFFICIENT DATA

критических данных для sizing нет

Например, если неизвестны:

chunk/vector count


peak concurrency


production filters


Top-K


token profile


freshness SLA


latency SLA

правильный вывод:

INSUFFICIENT DATA

а не выбор SKU по размеру исходной папки.

Scaling Domain Matrix

Component

Load driver

KPI

Возможный конфликт

Decision

Extraction

docs/pages over time

docs/s, pages/s

CPU/GPU/RAM

Embedding

chunks/time

embeddings/s

compute

Indexing

vectors/updates

UpdateLag

CPU/RAM/I/O

Retrieval

QPS + filters

p95/p99 + quality

RAM/I/O/CPU/GPU by stack

Reranking

QPS × candidates

pairs/s + latency

compute

LLM

tokens + concurrency

queue/TTFT/ITL/E2E

GPU/VRAM

Storage

corpus/index growth

capacity/I/O

NVMe/storage

Колонка resource не должна заранее превращаться в:

embedding = GPU

retrieval = CPU

Практический порядок расчёта

1. Зафиксировать corpus

        ↓

2. Прогнать representative sample

        ↓

3. Получить chunk/vector count

        ↓

4. Зафиксировать change rate

        ↓

5. Определить UpdateLag SLA

        ↓

6. Получить ingestion target

        ↓

7. Рассчитать raw vector payload

        ↓

8. Получить stack-specific DB footprint

        ↓

9. Зафиксировать production filters

        ↓

10. Определить QPS + concurrency

        ↓

11. Benchmark filtered retrieval

        ↓

12. Зафиксировать Top-K

        ↓

13. Получить reranker workload

        ↓

14. Зафиксировать LLM token profile

        ↓

15. Проверить queue / TTFT / ITL / E2E

        ↓

16. Запустить query-only test

        ↓

17. Запустить ingestion-only test

        ↓

18. Запустить combined-load test

        ↓

19. Определить bottleneck

        ↓

20. Выбрать:

shared / isolated /

independently scaled

Какие данные нужны для подбора

Для первичного sizing достаточно собрать:

CORPUS


documents / pages

formats

raw volume

growth



CHANGE PROFILE


new documents/day

changed documents/day

update window

freshness SLA



PIPELINE


parser/chunker

embedding model


vector DB/index

if already selected


filters / ACL requirements



QUERY LOAD


peak QPS

peak concurrency


burst profile


retrieval Top-K



RERANK


used / not used


model

candidates/query



LLM


model/version

precision


input tokens

retrieved context

output tokens


concurrency



SLA


UpdateLag


retrieval latency


TTFT / ITL / E2E


availability

RTO / RPO

Если данных пока нет, preliminary sizing должен явно помечать их как ASSUMPTION или UNKNOWN.