Как вы обрабатываете real-time фичи для LLM (например, текущий сток товара)?
Краткий тезис
Real-time фичи — это динамические данные (текущий сток, цена, баланс пользователя), которые LLM должна учитывать при генерации ответа. Прямой запрос к БД на каждый call|вызов LLM слишком медленный. Решение — feature store (например, Redis) с low-latency доступом, tool calling для получения фичей по требованию, кэширование с TTL и event-driven обновление через Kafka. Это позволяет LLM получать актуальные данные за <10ms без перегрузки основных систем.
1. Термин: Real-time фичи для LLM
Real-time фичи — это признаки, которые быстро меняются во времени и влияют на релевантность ответа LLM. Примеры:
current_stock— остаток товара на складе- price — текущая цена (может меняться из-за акций)
user_balance— баланс пользователяpromotion_active— активна ли скидка
Без real-time фичей LLM может предложить товар, которого нет в наличии, или назвать устаревшую цену. В RAG|agentic RAG LLM действует как агент, вызывая инструменты для получения таких данных.
Проблема LLM не имеет встроенного доступа к базам данных. Каждый запрос к БД (PostgreSQL, MongoDB) занимает 10–100ms, что неприемлемо для интерактивного диалога. Нужна специализированная инфраструктура.
2. Feature store как центральное хранилище фичей
Feature store — это система для хранения, обслуживания и доставки признаков (features) в реальном времени. Популярные реализации: Redis, Feast, Tecton, Aerospike.
| Свойство | Описание |
|---|---|
| Latency | Чтение из памяти (Redis) — <1ms, из SSD — <5ms |
| Согласованность | Eventual consistency (допускается небольшая задержка обновления) |
| API | Простой get/set по ключу (например, stock:product_123) |
| TTL | Автоматическое удаление устаревших записей |
В контексте LLM feature store выступает как источник истины для динамических данных. LLM не обращается напрямую к БД заказов, а читает предварительно агрегированные фичи из Redis.
3. Tool calling для получения фичей
Tool calling (function calling) — механизм, позволяющий LLM вызывать внешние функции. В нашем случае LLM может вызвать функцию get_current_stock(product_id), которая:
- Проверяет наличие ключа
stock:{product_id}в Redis. - Если есть — возвращает значение.
- Если нет — возвращает fallback (например,
unknownили запрашивает из БД и кэширует).
Пример реализации на Python (с использованием библиотеки redis):
import redis
r = redis.Redis(host='localhost', port=6379, decode_responses=True)
def get_current_stock(product_id: str) -> int:
"""Возвращает текущий остаток товара."""
key = f"stock:{product_id}"
value = r.get(key)
if value is not None:
return int(value)
# fallback: запрос к основной БД (медленно)
stock = query_db(f"SELECT stock FROM products WHERE id = {product_id}")
r.setex(key, 60, stock) # кэшируем на 1 минуту
return stock
LLM получает описание функции в системном промпте и решает, когда её вызвать. Например, пользователь спрашивает: «Есть ли iPhone 15 в наличии?» — LLM вызывает get_current_stock("iphone15") и получает ответ 42.
4. Кэширование с TTL для снижения нагрузки
Кэширование — временное хранение результатов для повторного использования. TTL (Time-To-Live) — время жизни записи в кэше.
| Параметр | Значение |
|---|---|
| TTL для стока | 1 минута |
| TTL для цены | 5 минут (меняется реже) |
| TTL для баланса | 30 секунд (чувствительные данные) |
Выбор TTL — компромисс между актуальностью и нагрузкой. Слишком короткий TTL (например, 1 секунда) — частые запросы к БД. Слишком длинный (1 час) — риск устаревших данных.
Почему не запрашивать БД каждый раз? Даже если БД быстрая (10ms), при 1000 RPS это 10 секунд процессорного времени только на чтение. Кэш снижает нагрузку в 10–100 раз.
5. Event-driven обновление через Kafka
Event-driven архитектура — система реагирует на события (изменения данных) и обновляет кэш немедленно. Apache Kafka — популярная платформа для потоковой обработки событий.
Схема работы
- Внешняя система (например, сервис заказов) публикует событие
stock_changedв топик Kafka. - Consumer (сервис фичей) читает событие и обновляет Redis:
SET stock:product_123 10. - LLM при следующем вызове
get_current_stockполучает актуальное значение.
Преимущества
- Минимальная задержка обновления (секунды).
- Отсутствие polling (периодических запросов к БД).
- Масштабируемость: Kafka выдерживает миллионы событий в секунду.
Недостатки
- Сложность инфраструктуры (нужен Kafka-кластер).
- Возможна потеря событий (нужна настройка гарантий доставки).
6. Обработка race conditions и согласованность
Race condition — ситуация, когда два процесса одновременно читают и пишут одни и те же данные, приводя к некорректному состоянию. Пример: LLM получила сток = 5, но через 1 мс пришло событие об уменьшении до 3. Если LLM уже начала формировать ответ, он может быть неверным.
Стратегии
- Optimistic locking — использовать версионирование (например, Redis CAS).
- Read-after-write consistency — для критичных фичей (баланс) можно читать напрямую из БД, игнорируя кэш.
- Eventual consistency — допустить, что данные могут быть устаревшими на несколько секунд. Для стока товара это приемлемо (пользователь не заметит задержку в 2 секунды).
Рекомендация Для большинства фичей использовать eventual consistency. Для финансовых транзакций — строгую согласованность через БД.
7. Мониторинг и метрики
Чтобы убедиться, что real-time фичи работают корректно, нужно отслеживать:
| Метрика | Описание | Целевое значение |
|---|---|---|
| P99 latency | Время получения фичи из feature store | <10ms |
| Cache hit rate | Доля запросов, найденных в кэше | >95% |
| Staleness | Средняя задержка между изменением данных и обновлением кэша | <5 секунд |
| Error rate | Доля неудачных вызовов (Redis недоступен) | <0.1% |
Инструменты: Prometheus + Grafana, Datadog, New Relic.
8. Альтернативные подходы
| Подход | Описание | Когда использовать |
|---|---|---|
| In-memory cache (local) | Хранить фичи в памяти самого LLM-сервиса (например, Python dict) | Для прототипов, малой нагрузки |
| CDN для статических фичей | Использовать CDN (Cloudflare, Akamai) для фичей, которые меняются раз в час | Для цен каталога, описаний |
| Precomputed features | Заранее рассчитать фичи для всех возможных запросов и сохранить в векторной БД | Для рекомендательных систем |
| GraphQL subscriptions | Подписка на изменения через WebSocket | Для интерактивных чатов |
В production обычно комбинируют Redis (для горячих данных) и Kafka (для обновлений).
9. Пример архитектуры (текстовая диаграмма)
[Пользователь] → [LLM Agent]
↓
[Tool: get_current_stock]
↓
[Redis (Feature Store)]
↑
[Kafka Consumer]
↑
[Kafka Topic: stock_changes]
↑
[Сервис заказов] (публикует события)
LLM вызывает tool, tool читает из Redis. Redis обновляется асинхронно через Kafka при каждом изменении стока.
Пет-проект для закрепления
Задача Реализовать микросервис для получения real-time фичей стока товаров, который используется LLM-агентом.
Инструменты Python, Redis (через redis-py), Kafka (через confluent-kafka), FastAPI (для демонстрации).
Шаги:
- Запустите Redis и Kafka локально (через Docker Compose).
- Напишите consumer, который слушает топик
stock_changesи обновляет Redis. - Напишите FastAPI-эндпоинт
/stock/{product_id}, который возвращает значение из Redis (имитация tool calling). - Напишите скрипт, который публикует тестовые события в Kafka.
- Подключите LLM (например, через OpenAI API) и передайте описание функции
get_current_stock. Проверьте, что LLM вызывает её при запросе «Сколько iPhone в наличии?».
Ожидаемый результат Работающий сервис, где LLM получает актуальный сток с задержкой <10ms, а обновления происходят через Kafka.
Связь с другими вопросами
| Вопрос | Тема |
|---|---|
| 530 | Как проектировать tool calling для LLM? |
| 531 | Как кэшировать результаты вызовов инструментов? |
| 532 | Как обрабатывать ошибки при вызове внешних API? |
| 534 | Как обеспечить согласованность данных в agentic RAG? |
| 535 | Как мониторить производительность агентов? |
| 536 | Как тестировать агентные системы? |
Навигация
- Предыдущий: 532
- Следующий: 534
- Индекс: 00. Индекс разборов