Как организовать data versioning (DVC, LakeFS, Delta Lake)?

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

versioning|Data versioning — это практика хранения, отслеживания и управления версиями наборов данных, моделей и артефактов машинного обучения. Для RAG-систем это критично: документы, эмбеддинги и чанки часто обновляются, и без контроля версий невозможно воспроизвести старые эксперименты или откатить изменения. Три популярных инструмента — DVC (лёгкий, Git-подобный), Delta Lake / Iceberg (тяжёлые, со встроенными ACID-транзакциями) и LakeFS (Git semantics|Git-интерфейс для data lake) — покрывают разные сценарии: от маленьких команд до enterprise data lakes.


1. Термин: Data Versioning (Версионирование данных)

Это практика сохранения снимков (snapshots) данных, чтобы можно было:

  • Воспроизвести точно такую же версию датасета, которая использовалась в обучении.
  • Откатиться к предыдущей версии, если новая оказалась испорченной.
  • Экспериментировать — создать ветку (branch) с новыми данными, не затрагивая основную.
  • Сравнивать метрики модели на разных версиях данных.

В контексте Agentic RAG versioning|data versioning особенно важен: агенты могут генерировать и добавлять в базу новые документы, и нужно иметь историю изменений индекса.


2. Основные подходы к data versioning

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

ПодходПримерыИдея
Git-basedDVC, git-lfsМетаданные в Git, данные во внешнем хранилище (S3, GCS).
Table formatDelta Lake, Apache Iceberg, Apache HudiФайлы формата Parquet поверх хранилища (S3, HDFS); встроенные транзакции, версионирование.
Object store with Git semanticsLakeFSGit-подобные операции (branch, commit, merge) прямо над объектным хранилищем.

Выбор зависит от масштаба данных, требуемых гарантий (ACID) и инфраструктурных ограничений.


3. DVC (Data Version Control)

DVC — это инструмент, который позволяет версионировать данные так же, как Git версионирует код. Он хранит хеши файлов (MD5) в файле .dvc вместо Git-репозитория, а сами файлы — в удалённом кэше (S3, GCS, локальном хранилище).

Как работает

  1. dvc init — создаёт .dvc директорию.
  2. dvc add data/documents.parquet — вычисляет хеш, добавляет файл в .gitignore, создаёт data/documents.parquet.dvc.
  3. git add . && git commit — коммитим .dvc файл.
  4. dvc push — отправляет реальные данные в удалённый кэш (S3 bucket).
  5. Для получения старой версии: git checkout <commit> + dvc checkout — восстанавливает данные по хешу.

Пример команд

# Установка
pip install dvc
dvc init
dvc remote add -d myremote s3://my-bucket/dvc-cache
dvc add docs/raw # папка с документами
git add docs/raw.dvc .gitignore
git commit -m "add initial document set"
dvc push

Плюсы и минусы

  • Плюсы: лёгкая интеграция с Git, работает с любыми файлами (не требует Spark), дешёвый для малых и средних проектов.
  • Минусы: нет ACID-транзакций; при работе с миллионами файлов производительность падает; сложный ручной мерж.

4. Delta Lake (Databricks)

Delta Lake — это табличный формат (table format) с открытым исходным кодом, построенный поверх Parquet. Он добавляет уровень метаданных в виде транзакционного лога (delta log), что даёт ACID-транзакции, time travel и schema evolution.

Ключевые особенности

  • ACID транзакции: одновременные операции чтения/записи не конфликтуют (serializable isolation).
  • Time travel: чтение данных на определённый момент времени или номер версии.
  • Schema evolution: автоматическое или ручное добавление/удаление колонок без полного перезаписывания.

Пример на Python (PySpark)

from pyspark.sql import SparkSession

spark = SparkSession.builder \
    .appName("delta_example") \
    .config("spark.sql.extensions", "io.delta.sql.DeltaSparkSessionExtension") \
    .config("spark.sql.catalog.spark_catalog", "org.apache.spark.sql.delta.catalog.DeltaCatalog") \
    .getOrCreate()

# Запись первой версии
df = spark.read.parquet("docs_raw")
df.write.format("delta").mode("overwrite").save("/mnt/delta/docs")

# Чтение версии 5
df_v5 = spark.read.format("delta") \
    .option("versionAsOf", 5) \
    .load("/mnt/delta/docs")

# Оптимизация и vacuum (очистка старых версий)
spark.sql("VACUUM delta.`/mnt/delta/docs` RETAIN 168 HOURS")

Time travel через SQL

-- Чтение данных на конкретную версию
SELECT * FROM delta.`/mnt/delta/docs` VERSION AS OF 10;
-- Чтение на временную метку
SELECT * FROM delta.`/mnt/delta/docs` TIMESTAMP AS OF '2025-03-01T12:00:00Z';

Применение в RAG

  • Версионирование документов: можно хранить историю изменений каждого документа.
  • Версионирование эмбеддингов: если эмбеддинги хранятся в Parquet, можно откатывать индекс.
  • Совместная работа: несколько пайплайнов пишут в одну таблицу без конфликтов.

5. Apache Iceberg

Apache Iceberg — альтернатива Delta Lake с похожими возможностями, но с открытой архитектурой (входит в топовые data lakehouse). Отличия:

ХарактеристикаDelta LakeIceberg
РазработчикDatabricks (open-source)Apache Software Foundation
Формат логаParquet + JSON (delta log)Avro-based manifest
Partition evolutionЧастичная поддержкаПолная (сплит, сортировка)
Встроенные оптимизацииОптимизатор по умолчанию (OPTIMIZE)Требует явных операций (rewrite)
Интеграция с SparkНативная (Databricks)Полная (Spark 3.x)
Поддержка Flink/TrinoЕсть (третьи стороны)Первоклассная

Вывод: Iceberg лучше подходит для мульти-движковых (multi-engine) озер данных, Delta Lake — для стеков Databricks.


6. LakeFS (Git-подход для Data Lake)

LakeFS — это open-source платформа, которая предоставляет Git-подобный интерфейс (branch, commit, merge, revert) непосредственно для данных, хранящихся в S3/GCS/ADLS. Он встраивается перед объектным хранилищем как прокси или через SDK.

Основные операции

# Создать ветку
lakectl branch create lakefs://repo-main/new-experiment

# Добавить файл и закоммитить
lakectl upload lakefs://repo-main/branch-new/data.parquet --source /tmp/data.parquet
lakectl commit lakefs://repo-main/branch-new -m "add new document set"

# Слияние (merge) в main
lakectl merge lakefs://repo-main/branch-new lakefs://repo-main/main

# Откат (revert)
lakectl revert lakefs://repo-main/main -m "revert bad update" --commit-branch branch-revert

Когда использовать

  • Когда нужно несколько изолированных сред для разных экспериментов (ветки).
  • Когда команда привыкла к Git-воркфлоу (Pull Request для данных).
  • Когда данные очень большие, и копировать их целиком накладно (ветки в LakeFS — это виртуальные снимки, почти zero-copy).

7. Сравнительная таблица инструментов

КритерийDVCDelta Lake / IcebergLakeFS
Основная сфераНебольшие датасеты (GB)Большие данные (TB–PB)Озёра данных (TB–PB)
ACID транзакцииНетДаНет (но атомарность коммитов)
Time travelЧерез git checkout + dvc checkoutВстроенный (версии, timestamp)Через коммиты (похож на Git)
Schema evolutionНетДа (Delta, Iceberg)Нет (работает на уровне файлов)
Необходим SparkНетДа (обычно)Нет (CLI, Python SDK)
Интеграция с GitПолная (через .dvc файлы)НетЧастичная (lakectl, но сам не Git)
Как версионировать в RAGХранить архив .parquet файлов документовТаблица с колонками content, metadata, updated_atКаждая ветка – отдельная коллекция чанков
Сложность настройкиНизкаяСредняя (требуется Spark кластер)Средняя (нужен собственный сервер)

8. Data versioning в контексте RAG

Для RAG-систем data versioning особенно актуален:

  1. Версионирование документов: датасет документов может обновляться (добавляются новые, исправляются старые). DVC хорошо подходит для небольших проектов (сотни–тысячи файлов).
  2. Версионирование чанков: после чанкинга и векторизации создаются эмбеддинги. Их хранение — тяжёлые векторы (миллионы строк). Здесь лучше использовать Delta Lake (или Milvus с механизмом aliases).
  3. Версионирование индекса: полный перезапуск индекса — дорого. С LakeFS можно создать ветку для теста и быстро смержить в main.
  4. Эксперименты: для каждого эксперимента можно зафиксировать версию данных (DVC коммит), версию эмбеддеров, версию LLM (через MLflow).

Пример workflow с DVC

.git/
├── data/
│   └── documents.dvc      # ссылка на хеш в S3
├── .dvc/
│   └── cache/             # локальный кэш (опционально)
s3://my-bucket/dvc-cache/  # реальные файлы .parquet по хешам

При изменении документов: dvc add data/documents.parquet → новый хеш → git commitdvc push. В Git сохраняется история версий данных.


9. Интеграция с MLOps

Data versioning — это часть пайплайна MLOps. Типичная связка:

  • DVC + Git → версионирование исходных данных и моделей.
  • MLflow → трекинг экспериментов, логирование метрик, артефакты (модели).
  • Delta Lake → хранение больших таблиц с историей.
  • LakeFS → организация сред (staging/main) для data lake.

CI/CD пайплайн (например, GitHub Actions) может:

  • По коммиту в Git → запускать dvc pull, тренировать модель, замерять метрики.
  • Если метрики упали → откатить данные через git revert + dvc checkout.
  • Для RAG: после обновления документов пересчитывать эмбеддинги и тестировать MRR — если падает, откат.

10. Практические рекомендации

  • Начинайте с DVC: если проект малый (датасет < 10 GB) или вы только знакомитесь с data versioning. DVC + Git — это минималка.
  • Для продакшна с большими данными: используйте Delta Lake или Iceberg. Они дадут ACID, оптимизированные чтения и time travel.
  • Если нужно управлять ветками данных: добавьте LakeFS. Особенно полезно, когда несколько команд одновременно экспериментируют с разными наборами документов.
  • Для RAG с агентами: объединяйте DVC (для версионирования сырых документов) и Delta Lake (для хранения результатов чанкинга и эмбеддингов). LakeFS может быть оверхедом, если не требуется сложный Git-воркфлоу.

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

Задача: Разработать пайплайн, который версионирует датасет документов для RAG с помощью DVC и автоматически пересчитывает эмбеддинги при изменении данных.

Инструменты: Python, DVC, Git, AWS S3 (или MinIO), FAISS, sentence-transformers.

Шаги:

  1. Создайте Git-репозиторий rag-data-versioning.
  2. Инициализируйте DVC и настройте удалённый кэш (S3/minio).
  3. Поместите набор документов (например, 100 текстовых файлов) в папку docs/.
  4. Выполните dvc add docs/, закоммитьте .dvc файл, запушите данные.
  5. Напишите Python-скрипт build_index.py, который:
    • Загружает документы из docs/.
    • Чанкует и эмбеддит через SentenceTransformer.
    • Сохраняет индекс FAISS и метаданные в файл.
  6. В CI (GitHub Actions) при пуше в main: dvc pull, python build_index.py, коммитить новый индекс.
  7. Сделайте изменение в документах (добавьте/удалите файл), закоммитьте новый .dvc, повторно запустите CI.
  8. Используйте dvc diff для просмотра изменений между коммитами.

Ожидаемый результат: Вы сможете откатываться к любой версии документов (git checkout <commit> + dvc checkout), и индекс автоматически перестроится. Поймёте, как data versioning связан с воспроизводимостью RAG-системы.


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

ВопросТема
267Как устроены data lakes и data lakehouse?
855Как организовать CI/CD для RAG-системы?
854Как управлять конфигурациями экспериментов RAG?
857Как хранить большие объёмы документов в RAG?
858Как деплоить RAG-систему с обновлением данных?
859Как обеспечить воспроизводимость RAG-экспериментов?

Навигация