Как вы уменьшаете latency RAG-системы (время ответа)?

Краткий тезис

Latency RAG-системы складывается из трёх этапов: pre-retrieval (подготовка запроса), retrieval (поиск в векторной БД) и generation (генерация ответа LLM). Оптимизация каждого этапа даёт совокупный эффект. Ключевые методы: кэширование, настройка ANN индексов, уменьшение top-k, использование меньших LLM, streaming ответов и специализированные инференс-серверы (vLLM, TGI). Реальный результат: latency снижается с 5-10 секунд до 1-2 секунд.


1. Термин: Latency (латентность, задержка)

Что это Время от получения запроса пользователем до получения полного ответа.

Из чего складывается в RAG

Total Latency = T_pre_retrieval + T_retrieval + T_post_retrieval + T_generation
ЭтапЧто происходитТипичная latency
Pre-retrievalEmbedding запроса, query rewriting50-200 ms
RetrievalПоиск в векторной БД, ANN, фильтрация10-100 ms
Post-retrievalReranking, сжатие контекста50-500 ms
GenerationLLM генерирует ответ (самый долгий)500-5000 ms

Термин «P95 latency» 95-й перцентиль — 95% запросов выполняются быстрее этого времени. Важнее средней (average), потому что показывает "хвост" медленных запросов.

Термин «TTFT» (Time To First Token Время до первого токена. Пользователь видит, что система начала отвечать (важно для UX).

Термин «TPOT» (Time Per Output Token Время на генерацию одного токена после первого.


Часть 1: Pre-retrieval оптимизации

1.1 Кэширование частых запросов (кэш)

Что это Хранение результатов частых запросов в быстром хранилище (Redis, in-memory), чтобы не вычислять каждый раз заново.

Термин «Кэш» (Cache Временное хранилище с быстрым доступом. Redisin-memory база данных с latency < 1ms.

Как работает

Запрос пользователя → Проверка кэша
                         │
                ┌────────┴────────┐
                ▼                 ▼
          Есть в кэше?       Нет в кэше?
                │                 │
                ▼                 ▼
         Вернуть ответ     Выполнить RAG
                │                 │
                └────────┬────────┘
                         ▼
                    Вернуть ответ
                    (и сохранить в кэш)

Пример ключа кэша

import hashlib

def get_cache_key(query: str, top_k: int, temperature: float) -> str:
    content = f"{query}|{top_k}|{temperature}"
    return hashlib.md5(content.encode()).hexdigest()

Термин «Cache hit ratio» Доля запросов, которые нашлись в кэше. Чем выше, тем лучше.

Стратегия кэшированияКогда использоватьПример
Точное совпадение (exact matchЗапросы повторяются дословноЧат-бот поддержки (100 пользователей спрашивают "как сменить пароль")
Семантический кэшЗапросы разные по формулировке, но одинаковые по смыслу"как поменять пароль" и "смена пароля инструкция"
TTL (Time To LiveДанные устареваютНовости, курсы валют (кэш на 5 минут)

Результат Cache hit ratio 30-50% → уменьшение latency на 70-90% для закэшированных запросов.

Цифра С Redis latency retrieval падает с 100ms до 1ms.


1.2 Асинхронная индексация документов

Что это Индексация новых документов происходит в фоновом режиме, не блокируя поисковые запросы.

Проблема Если при загрузке нового документа ждать, пока он вставится в векторную БД — пользовательский запрос зависнет.

Решение

  • Очередь задач (RabbitMQ, Kafka, Celery)
  • Документ → очередь → фоновая индексация
  • Поиск идёт по уже проиндексированным документам

Термин «Очередь задач» (Task queue Система, где задачи (индексация) складываются в очередь и обрабатываются воркерами. Kafka, RabbitMQ, Celery.

Цифра Latency поиска не увеличивается при загрузке новых документов (с 100ms → 100ms, а не 500ms).


Часть 2: Retrieval оптимизации

2.1 HNSW индексы (настройка параметров)

Термин «HNSW» (Hierarchical Navigable Small World ANN алгоритм для быстрого поиска векторов. Строит многослойный граф.

Ключевые параметры

ПараметрЧто делаетЗначение по умолчаниюВлияние на latency
M (max connections)Количество связей каждого узла в графе16Больше M → точнее, но медленнее и больше памяти
ef_constructРазмер динамического списка при построении индекса200Больше → точнее, но дольше строить индекс
ef_searchРазмер динамического списка при поиске128Больше → точнее, но медленнее поиск

Настройка для low latency

# Для скорости (жертвуем точностью)
M = 8                # меньше связей
ef_construct = 40    # быстрое построение
ef_search = 40       # быстрый поиск

# Для точности (жертвуем скоростью)
M = 32
ef_construct = 500
ef_search = 200

Trade-off Скорость ↔ Точность

НастройкаLatencyRecall@10Память
Fast (M=8, ef=40)5 ms0.92100 MB
Balanced (M=16, ef=128)15 ms0.97200 MB
Accurate (M=32, ef=200)50 ms0.99400 MB

Цифра Уменьшение ef_search со 200 до 40 снижает latency с 50ms до 5ms (10x), но recall падает с 0.99 до 0.92 (приемлемо для многих задач).


2.2 Уменьшение количества чанков (top-k)

Что такое top-k Количество документов (чанков), которые retrieval возвращает в LLM.

Проблема Больше k → больше контекста → лучше ответ, но дольше генерация (LLM обрабатывает больше токенов).

Рекомендации

kLatency generation (Llama-3-8B, 500 токенов ответа)Когда использовать
3800 msОчень быстрые сценарии (чат, поиск)
51200 msDefault (баланс качества и скорости
102000 msМедицина, юриспруденция (нужна полнота)
203500 msАналитика, исследования

Термин «Монотонный рост» Latency генерации растёт линейно с количеством токенов контекста. Двойной контекст → двойная latency.

Дополнительная оптимизация Не все top-k чанки одинаково важны. Можно передавать первые 3 чанка полностью, остальные — только суммаризации.

Цифра Уменьшение k с 20 до 5 снижает latency генерации с 3500ms до 1200ms (почти в 3 раза) с потерей качества 2-5%.


2.3 Quantization (квантование векторов)

Что такое квантование Уменьшение точности чисел (например, с 32-битных до 8-битных целых), чтобы экономить память и ускорять поиск.

Термин «FP32» (32-bit floating point Стандартная точность, 4 байта на число. 8. Как вы обрабатываете запросы, на которые нет ответа в документах|8]]. Как вы обрабатываете запросы, на которые нет ответа в документах|8]]. Как вы обрабатываете запросы, на которые нет ответа в документах|8]]-bit integer|Термин «INT8» (8-bit integer]] Целое число от -128 до 127, 1 байт.

ТипРазмер (1 млн векторов 768d)Latency поискаПотеря точности (recall)
FP32 (full precision)3 GB50 ms0% (baseline)
FP16 (half precision)1.5 GB30 ms0.5-1%
INT8 (scalar quantization)0.75 GB15 ms2-5%
Binary quantization0.1 GB5 ms10-20%

Пример квантования в Qdrant

from qdrant_client.http.models import ScalarQuantization, ScalarQuantizationConfig

client.create_collection(
    collection_name="my_docs",
    vectors_config=VectorParams(size=768, distance=Distance.COSINE),
    quantization_config=ScalarQuantization(
        scalar=ScalarQuantizationConfig(
            type="int8",   # или "int16"
            quantile=0.99
        )
    )
)

Термин «PQ (Product Quantization)» Более продвинутое квантование, разбивает вектор на подвекторы и кодирует каждый. Сжатие в 8-32 раза.

Цифра INT8 quantization снижает память в 4 раза и ускоряет поиск в 3 раза (50ms → 15ms) при потере recall всего на 2-5%.


Часть 3: Post-retrieval оптимизации

3.1 LLM distillation (дистилляция модели)

Что такое дистилляция Обучение маленькой модели (студента) имитировать большую модель (учителя). Студент быстрее, но почти так же качественно.

Термин «Teacher-student distillation» Учитель (GPT-4, 70B) генерирует ответы на датасете. Студент (Llama-3-8B) учится предсказывать эти ответы.

МодельLatency (1 токен)Качество (MMLU)Размер
GPT-450-100 ms86%~1.7T params
Llama-3-70B20-30 ms82%70B
Llama-3-8B (distilled)5-10 ms75%8B
Phi-3-mini-3.8B2-5 ms68%3.8B

Как выбрать модель под задачу

  • Сложные рассуждения (юриспруденция, медицина) → 70B+
  • Фактологические ответы (RAG) → 8B достаточно
  • Классификация, извлечение → 3B достаточно

Цифра Замена Llama-3-70B на Llama-3-8B снижает latency генерации с 1200ms до 200ms (6x ускорение) при потере качества 5-10% на RAG-задачах.


3.2 Streaming ответов (потоковая передача)

Что это LLM возвращает токены по одному по мере генерации, а не ждёт полный ответ.

Термин «Streaming» (потоковая передача Использование Server-Sent Events (SSE) или WebSockets для отправки данных частями.

Как это меняет восприятие пользователя

Без streaming: (ждём 3 секунды) → ответ целиком
Со streaming: токен за токеном, через 200ms уже первый токен

Реализация с FastAPI

from fastapi import FastAPI
from fastapi.responses import StreamingResponse

app = FastAPI()

@app.post("/chat/stream")
async def chat_stream(request: Request):
    async def generate():
        async for token in llm.stream(request.query):
            yield f"data: {token}\n\n"
        yield "data: [DONE]\n\n"

    return StreamingResponse(generate(), media_type="text/event-stream")

Термин «TTFT» (Time To First Token Время до первого токена. Со streaming пользователь видит, что система начала отвечать, даже если полный ответ через 5 секунд.

Цифра При генерации 500 токенов (10 секунд без streaming) → streaming даёт TTFT 200ms, что психологически воспринимается как "быстрый ответ", хотя полный ответ всё ещё 10 секунд.


Часть 4: Архитектурные оптимизации

4.1 vLLM или TGI для инференса LLM

Термин «vLLM» Инференс-сервер с paged attention и continuous batching. Ускоряет LLM в 2-10x.

Термин «TGI» (Text Generation Inference Аналог от Hugging Face с похожими оптимизациями.

Сравнение

ХарактеристикаvLLMTGIСтандартный Hugging Face
Continuous batching✅ Да✅ Да❌ Нет
Paged attention✅ Да❌ Нет❌ Нет
FlashAttention✅ Да✅ Да✅ Да
Throughput (токенов/сек1000-2000800-1500100-200
Latency p9550-200 ms70-250 ms500-2000 ms

Термин «Continuous batching» Вместо ожидания самого медленного запроса в батче, батч динамически обновляется (завершившиеся удаляются, новые добавляются).

Термин «Paged attention» KV-кэш разбивается на страницы, как в операционной системе, уменьшая фрагментацию памяти.

Цифра Переход с Hugging Face pipeline на vLLM снижает latency генерации с 2000ms до 200ms (10x ускорение).

Запуск vLLM

pip install vllm
python -m vllm.entrypoints.api_server --model meta-llama/Llama-3-8B --tensor-parallel-size 2

4.2 Edge-вычисления для простых запросов

Что это Маршрутизация (routing) запросов: простые запросы обрабатываются маленькой моделью на edge (пользовательское устройство или ближайший сервер), сложные — большой моделью в облаке.

Термин «Edge computing» Вычисления на периферии (ближе к пользователю), а не в центральном облаке.

Классификатор запросов (router

# Маленькая модель (DistilBERT) классифицирует сложность
def classify_query(query: str) -> str:
    if "сравните" in query or "проанализируйте" in query:
        return "complex"
    if len(query.split()) < 10:
        return "simple"
    # ... более сложная логика
    return "medium"

if classify_query(query) == "simple":
    model = "Phi-3-mini-3.8B"  # latency 500ms
else:
    model = "Llama-3-70B"       # latency 2000ms

Цифра 70% запросов простые (как поменять пароль, сколько стоит, какой адрес) → они идут на edge-модель за 200ms вместо 2000ms. Средняя latency падает с 2000ms до 740ms (0.3×2000 + 0.7×200 = 600+140 = 740ms).


Полная оптимизация: итоговые цифры

ЭтапДо оптимизацииПосле оптимизацииМетод
Pre-retrieval200 ms5 msКэш (Redis)
Retrieval100 ms15 msHNSW (ef=40) + INT8
Post-retrieval100 ms0 ms (убрали)Отказ от reranking
Generation5000 ms500 msvLLM + меньшая модель (8B)
Total5400 ms520 ms~10x ускорение

Реальный пример из практики «Я оптимизировал RAG для поддержки клиентов: кэширование частых запросов (500 запросов/час → cache hit 40%), замена 70B модели на 8B дистиллированную, vLLM вместо Hugging Face. Latency упала с 5.2 секунд до 1.2 секунд, качество осталось на уровне 92% faithfulness».


Пет-проект для закрепления

Задача Измерить и оптимизировать latency вашего RAG-пайплайна.

Инструменты Python, Qdrant, vLLM, Redis, Locust (нагрузочное тестирование)

Шаги

  1. Собрать базовый RAG (retrieval + Llama-3-70B через Hugging Face)
  2. Замерить baseline latency на 100 запросах (p50, p95)
  3. Применить оптимизации по очереди:
    • Добавить Redis кэш (exact match)
    • Уменьшить top-k с 20 до 5
    • Настроить HNSW (M=8, ef_search=40)
    • Включить INT8 quantization в Qdrant
    • Перейти с Hugging Face на vLLM
    • Заменить 70B на 8B модель
  4. После каждой оптимизации замерять latency и качество (faithfulness)
  5. Построить график trade-off скорость vs качество

Ожидаемый результат Вы получите реальные цифры для вашего домена и поймёте, какие оптимизации дают наибольший эффект.


Связь с другими вопросами

ВопросТема
4Векторная БД (HNSW, quantization)
5Оценка качества (чтобы убедиться, что оптимизации не убили качество)
6Гибридный поиск (тоже влияет на latency)
14Обрезка контекста (как уменьшить токены)
61-80Production & MLOps (vLLM, TGI, мониторинг latency)
201-220Inference optimization (глубоко про vLLM, paged attention, speculative decoding)

7. Как вы уменьшаете latency RAG-системы (время ответа)|7. Как вы уменьшаете latency RAG-системы (время ответа)|7. Как вы уменьшаете latency RAG-системы (время ответа)|7 полностью разобран. Переходим к вопросу 8, когда будете готовы|Вопрос 7 полностью разобран. Переходим к вопросу 8, когда будете готовы]]


Навигация