中文翻译暂不可用,显示俄语原文。

Как реализовать online/offline feature consistency для LLM?

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

feature feature Online/offline feature feature consistency — это критическая проблема MLOps, когда признаки (features), используемые при обучении модели (offline), отличаются от признаков, подаваемых на инференс (online). Для LLM (в том числе в архитектурах RAG|Agentic RAG) это ведёт к деградации качества ответов. Основные решения: point-in-time correct joins (batch scoring), использование feature store (например, Feast) и log-and-apply подход. Обязательны мониторинг распределений признаков (data drift) и периодическая валидация консистентности.


1. Проблема: почему возникает неконсистентность

Признаки для обучения LLM-моделей (или для retrieval/ранжирования в RAG-агентах) часто вычисляются из исторических логов с задержкой. В момент инференса (online) могут использоваться те же признаки, но вычисленные «на лету» — из-за разных источников данных, времени среза или логики вычисления расхождения неизбежны.

Пример расхождения

  • Offline: «средний рейтинг товара за последние 7 дней» считается из таблицы с данными на вчерашний вечер.
  • Online: тот же признак считается из live-стрима с учётом сегодняшних оценок.
  • Результат: модель обучена на одних значениях, а видит совсем другие → падение accuracy / faithfulness.

Термин Feature consistency (консистентность признаков) — мера того, насколько распределения и конкретные значения признаков в offline и online совпадают.


2. Термины: offline vs online признаки

ТипИсточникХранениеЦельРиск
OfflineИсторические данные (Parquet, HDFS)Озёра данных, feature repo (аналитические)Обучение модели, backtesting«Застывшие» срезы — не учитывают новые данные
OnlineРеал-тайм потоки (Kafka, API)Feature store (Redis, DynamoDB)Инференс в момент запросаМогут отличаться логикой или задержкой

Для LLM в Agentic RAG признаки могут включать: эмбеддинги запроса, историю диалога, контекстные сигналы (время суток, гео, профиль пользователя). Любое расхождение сдвигает распределение и снижает качество.


3. Решение 1: Batch scoring (Point-in-time correct join)

Идея при обучении эмулировать онлайн-срез данных. Для каждого обучающего примера «замораживается» время и берутся признаки, которые были известны системе ровно в этот момент (point-in-time).

Реализация

  • Для каждого события (например, клик, запрос к LLM) записываем timestamp.
  • При join с таблицами признаков используем условие feature_timestamp <= event_timestamp и берем последнее доступное значение (AS OF join).
  • При инференсе также используем признак, вычисленный на момент запроса.
# Пример с Pandas (упрощённо)
import pandas as pd

events = pd.DataFrame({'user_id': [1], 'event_time': [pd.Timestamp('2025-04-10 12:30:00')]})
features = pd.DataFrame({
    'user_id': [1, 1],
    'feature_time': [pd.Timestamp('2025-04-10 11:00:00'), pd.Timestamp('2025-04-10 13:00:00')],
    '7day_avg_rating': [4.2, 4.5]
})

# Point-in-time join: берем последний признак до event_time
result = pd.merge_asof(
    events.sort_values('event_time'),
    features.sort_values('feature_time'),
    by='user_id',
    left_on='event_time',
    right_on='feature_time',
    direction='backward'
)
print(result)  # получит 4.2 (до 12:30), а не 4.5 (после)

Плюсы единая логика, консистентность гарантируется математически.
Минусы требует хранения временных меток, сложные join’ы для больших данных.


4. Решение 2: Использование Feature Store (Feast, Tecton, Hopsworks)

Feature store — единый репозиторий признаков, который предоставляет один и тот же признак для обучения (offline) и для инференса (online) из общего источника.

Как работает

  • Признаки определяются один раз (feature definition) — код вычисления, источник, агрегация.
  • Offline serving — из исторического хранилища (Parquet, BigQuery) с поддержкой point-in-time.
  • Online serving — из low-latency хранилища (Redis, DynamoDB), которое обновляется стримингом или batch-загрузкой.

Пример на Feast

# feature_view.yaml
name: user_stats
entities: [user_id]
features:
  - name: avg_rating_7d
    dtype: float
    timestamp_column: event_timestamp
batch_source: 
  type: parquet
  path: s3://bucket/features/*
online_source:
  type: redis
  host: redis-cluster

Плюсы прозрачная синхронизация, автоматическая проверка схемы.
Минусы дополнительная инфраструктура, latency при записи онлайн.


5. Решение 3: Log-and-apply

Идея во время инференса логировать все признаки, которые были использованы для ответа LLM. Затем эти же признаки подавать на обучение/дообучение (fine-tuning).

Шаги:

  1. При получении запроса от пользователя вычислить онлайн-признаки.
  2. Сохранить их вместе с запросом и ответом в лог (например, в Kafka → S3).
  3. В обучающем пайплайне читать эти логи как «золотой стандарт» признаков.
  4. Обучать модель ровно на тех значениях, которые были в production.

Плюсы гарантированная консистентность «как есть сейчас», полезно для active learning.
Минусы большой объем логов (каждый запрос — копия признаков), запаздывание данных для обучения (надо ждать накопления логов).


6. Проверка консистентности: мониторинг дрейфа признаков

Даже при использовании feature store или point-in-time возможны расхождения из-за сбоев в ETL, изменения источника данных. Обязательны мониторинг дрейфа (data drift) между offline и online распределениями.

Метрики:

  • Population Stability Index (PSI) — численная мера различия двух распределений.
  • Kolmogorov–Smirnov test — для непрерывных признаков.
  • Jensen–Shannon divergence — для дискретных.

Инструменты

Пример проверки PSI (Python):

import numpy as np
import pandas as pd

def psi(expected, actual, buckets=10):
    breaks = np.percentile(expected, np.linspace(0, 100, buckets+1)[1:-1])
    expected_bins = np.histogram(expected, bins=np.append(breaks, np.inf))[0] + 1e-10
    actual_bins = np.histogram(actual, bins=np.append(breaks, np.inf))[0] + 1e-10
    expected_pct = expected_bins / expected_bins.sum()
    actual_pct = actual_bins / actual_bins.sum()
    return np.sum((actual_pct - expected_pct) * np.log(actual_pct / expected_pct))

# Сравниваем offline и online распределение для признака 'avg_rating_7d'
offline_feat = pd.read_parquet('offline_features.parquet')['avg_rating_7d']
online_feat = pd.read_csv('online_logs.csv')['avg_rating_7d']
print(f"PSI: {psi(offline_feat, online_feat):.4f}")  # >0.2 - критично

7. Связь с Agentic RAG

В Agentic RAG агент может динамически выбирать источники, инструменты (tools) и генерировать планы. Признаки для такого выбора (например, уверенность retrieval, свежесть документа, стоимость вызова LLM) должны быть консистентны между тем, на чём обучался policy-агент (RL или fine-tuning), и реальным использованием. Если в обучении признак «стоимость LLM» считался через усреднение по прошлым вызовам, а в production — как мгновенная цена — поведение агента ухудшится.

Пример: fine-tuning агента на offline-данных с фиксированным порогом retrieval, а в online этот порог динамический → расхождение.


8. Сравнение подходов

ПодходКонсистентностьСложность инфраструктурыЗадержка (latency)Применимость для LLM
Point-in-time (batch scoring)ГарантированаСредняяВысокая (если пересчёт на лету)Только для batch обучения
Feature storeОчень высокая (единый источник)ВысокаяНизкая (online — кэш)Универсально
Log-and-applyАбсолютная (логи)СредняяНет влиянияДля дообучения (fine-tuning)
Мониторинг (контроль)Не гарантирует, но выявляетНизкаяНетОбязательный слой

9. Рекомендуемая практика

  1. Определить все признаки, используемые LLM/агентом (как input, так и скрытые — например, эмбеддинги модели если они считаются отдельно).
  2. Выбрать базовый подход (обычно feature store + point-in-time для обучения).
  3. Развернуть мониторинг распределений (PSI для каждого признака, алерты при превышении порога 0.2).
  4. Периодически (раз в неделю/месяц) запускать валидацию — для случайной выборки запросов в production сравнивать online-признаки с теми, которые получились бы при offline-пересчёте.
  5. Автоматизировать retrain при обнаружении значительного дрейфа.

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

Задача построить демонстрацию online/offline feature consistency для простого ранжировщика документов в RAG-агенте.

Инструменты Python, Pandas, Redis, Feast (можно локально через Docker), Kafka или file-based лог.

Шаги:

  1. Создать синтетический датасет документов и запросов с меткой времени.
  2. Определить признак: «количество похожих запросов за последний час» (для оценки популярности).
  3. Реализовать три режима:
    • Offline: считать признак из исторического Parquet с point-in-time join.
    • Online: считать признак из Redis, обновляемого стримингом.
    • Log-and-apply: каждый online-запрос сохранять признаки в CSV для обучения.
  4. Добавить симуляцию дрейфа (изменить источник данных для online).
  5. Написать скрипт проверки PSI между offline и online признаками.
  6. Обучить простую модель (логистическую регрессию) на offline-признаках и проверить точность на online— показать падение при расхождении.

Ожидаемый результат

  • Понимание, как выглядит неконсистентность в цифрах.
  • Рабочий feature store (даже упрощённый) с двумя сервинг-режимами.
  • Метрика PSI, которая вовремя сигнализирует о проблеме.

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

ВопросТема
855Как синхронизировать эмбеддинги между обучением и инференсом
858Как организовать A/B тестирование признаков для LLM
860Как бороться с data drift в Agentic RAG
820Feature engineering для retrieval
835Мониторинг качества моделей в production

Навигация