Hub documentation
Lance
Lance
Lance — это открытый мультимодальный формат таблиц lakehouse для ИИ. Вы можете использовать пути Hugging Face (hf://) для доступа к наборам данных Lance на Hub. Это позволяет сканировать и искать в больших наборах данных на Hugging Face Hub, не копируя весь набор данных локально.

Начало работы
Для начала установите pylance и pyarrow с помощью pip:
pip install pylance pyarrow
Зачем нужен Lance?
- Оптимизирован для задач ML/AI: Lance — это современный колоночный формат, разработанный для быстрого случайного доступа без ущерба для производительности сканирования, что делает его полезным для поиска, аналитики, обучения, создания признаков и многих других сценариев использования.
- Мультимодальные ресурсы хранятся в Lance в виде байтов, или двоичных объектов («blobs as files»), наряду с эмбеддингами и традиционными скалярными данными — это упрощает управление, обмен и распространение ваших больших наборов данных через Hub.
- Индексирование является полноправным элементом формата (встроено в сам формат): в Lance из коробки реализованы быстрые, масштабируемые векторные и FTS-индексы, которые хранятся на диске рядом с набором данных на Hub. Это позволяет делиться не только данными, но и эмбеддингами и индексами, не заставляя пользователей пересчитывать их заново.
- Гибкая схема и эволюция данных позволяют постепенно добавлять новые признаки/колонки (теги модерации, эмбеддинги и т. д.) без необходимости переписывать всю таблицу.
Храните все свои данные в одном месте
В Lance ваши мультимодальные данные (изображения, аудио, видео) хранятся в виде сырых байтов рядом со скалярными метаданными и эмбеддингами. Это позволяет сканировать и фильтровать датасет в одном месте, не needing собирать данные из нескольких систем хранения.
Потоковая загрузка из Hub с помощью datasets
Используйте load_dataset(..., streaming=True), чтобы просматривать и итерировать данные без их локального скачивания.
from datasets import load_dataset
# Return as a Hugging Face dataset
ds = load_dataset(
"lance-format/laion-1m",
split="train",
streaming=True
)
# Take first three rows
for row in ds.take(3):
print(row["caption"])Стриминг отлично подходит для выборочного просмотра метаданных, чтобы понять, что у вас есть. Для векторного поиска или работы с большими бинарными объектами можно использовать API набора данных dataset в Lance, описанный ниже.
Стриминг быстро работает при выборке простых скалярных метаданных, но не так быстр для эмбеддингов или крупных мультимодальных объектов. Для работы с большими наборами данных рекомендуется просканировать метаданные, определить нужные подмножества и скачать эту часть набора данных локально, чтобы избежать ограничений скорости Hub:
hf download lance-format/laion-1m --repo-type dataset --local-dir ./laion
Потоковая загрузка из Hub с помощью lance.dataset
Также можно просканировать датасет Lance, хранящийся на Hugging Face Hub, с помощью спецификатора пути hf://. Это позволяет просканировать удалённый датасет без необходимости его локального скачивания. С помощью API dataset Lance очень просто задать ограничения, фильтры и проекции, чтобы получить только нужные данные.
import lance
# Return as a Lance dataset
ds = lance.dataset("hf://datasets/lance-format/laion-1m/data/train.lance")
scanner = ds.scanner(
columns=["caption", "url", "similarity"],
limit=5
)
rows = scanner.to_table().to_pylist()
for row in rows:
print(row)Работа с двоичными ресурсами
Пример ниже показывает, как изображения извлекаются из набора данных Lance в виде необработанных байтов JPEG в столбце image и используются далее.
Используйте ds.take, чтобы получить байты и записать их на диск, чтобы вы могли использовать их в других местах.
import lance
from pathlib import Path
ds = lance.dataset("hf://datasets/lance-format/laion-1m/data/train.lance")
dir_name = "laion_samples"
Path(dir_name).mkdir(exist_ok=True)
rows = ds.take([0, 1], columns=["image", "caption"]).to_pylist()
for idx, row in enumerate(rows):
with open(f"{dir_name}/{idx}.jpg", "wb") as f:
f.write(row["image"])
print(f"Wrote image with caption: {row['caption']}")Запись подмножества в новый датасет Lance
Работаете с большими наборами данных? Легко выполнить отфильтрованное сканирование, чтобы выбрать подмножество строк из Hub и материализовать их в локальный набор данных Lance.
import lance
ds = lance.dataset("hf://datasets/lance-format/laion-1m/data/train.lance")
scanner = ds.scanner(
columns=["image", "caption", "width", "height"],
filter="width >= 200 AND height >= 100",
limit=10,
)
subset = scanner.to_table()
lance.write_dataset(subset, "./laion_subset")Создать индекс
Если для вашего набора данных ещё не создан индекс, вы можете создать его после локального скачивания.
# ds is a local Lance dataset
ds.create_index(
"img_emb",
index_type="IVF_PQ",
num_partitions=256,
num_sub_vectors=96,
replace=True,
)См. документацию Lance по созданию векторных индексов для более подробного примера. После создания векторного индекса вы можете выполнять поиск по сходству в данных с помощью эмбеддингов.
Векторный поиск
Поскольку индексы в Lance являются полноправными объектами, вы можете хранить не только данные, но и эмбеддинги и индексы вместе, и выполнять запросы к ним напрямую на Hub. Просто используйте метод describe_indices(), чтобы получить список информации об индексах в наборе данных. Если индекс в наборе данных отсутствует, вы можете использовать lance.write_dataset(), чтобы записать локальную версию набора данных, и LanceDataset.create_index, чтобы создать индекс под ваши нужды.
Пример ниже показывает набор данных, для которого уже существует векторный индекс для поля img_emb:
import lance
ds = lance.dataset("hf://datasets/lance-format/laion-1m/data/train.lance")
print(ds.list_indices())
# Returns
# [
# IndexDescription(
# name=img_emb_idx,
# type_url=/lance.table.VectorIndexDetails,
# num_rows_indexed=1209588,
# fields=[15],
# field_names=["img_emb"],
# num_segments=1
#. )
# ]Вы можете выполнять запросы векторного поиска непосредственно на удалённом датасете без его загрузки (или, если хотите, скачать датасет локально и создать новый индекс). Пример ниже показывает, как выполнить поиск ближайших соседей по векторному индексу, используя эмбеддинг изображения в качестве вектора запроса.
import lance
import pyarrow as pa
ds = lance.dataset("hf://datasets/lance-format/laion-1m/data/train.lance")
emb_field = ds.schema.field("img_emb")
ref = ds.take([0], columns=["img_emb"]).to_pylist()[0]["img_emb"]
query = pa.array([ref], type=emb_field.type)
neighbors = ds.scanner(
nearest={
"column": emb_field.name,
"q": query[0],
"k": 6,
"nprobes": 16,
"refine_factor": 30,
},
columns=["caption", "url", "similarity"],
).to_table().to_pylist()Установка большого значения
kилиnprobes, а также отправка большого пакета запросов одновременно могут привести к превышению лимитов частоты обращений к Hub. Для интенсивного использования скачайте датасет (или его часть) локально и укажите Lance локальный путь, чтобы избежать троттлинга.
Эволюция набора данных
Одной из самых мощных возможностей Lance является гибкая эволюция данных без дополнительных затрат, что позволяет добавлять производные столбцы без переписывания исходной таблицы. Для очень больших таблиц, содержащих множество крупных объектов, экономия на операциях ввода-вывода может быть весьма значительной. Эта функция особенно актуальна, если вы экспериментируете с данными для задач машинного обучения и искусственного интеллекта и часто добавляете новые признаки, эмбеддинги или производные метаданные.
Пример ниже показывает, как добавить производный столбец moderation_label, который помечает изображение как NSFW на основе существующего столбца со значениями. При внесении этого изменения только backfill нового столбца записывает данные в новый столбец, не затрагивая исходные изображения или данные в других столбцах. Также можно просто добавить схему нового столбца без backfill каких-либо данных.
import lance
import pyarrow as pa
# Assumes you ran the export to Lance example above to store a local subset of the data
local_ds = lance.dataset("./laion_subset")
# schema only (data to be added later)
local_ds.add_columns(pa.field("moderation_label", pa.string()))
# with data backfill
local_ds.add_columns(
{
"moderation_label": "case WHEN \"NSFW\" > 0.5 THEN 'review' ELSE 'ok' END"
}
)См. документацию Lance по эволюции данных, чтобы узнать, как изменять и удалять столбцы в наборах данных Lance.
Работа с видео-блобами
Таблицы Lance также поддерживают большие встроенные видеоблобы. Набор данных OpenVid-1M (из этой статьи) содержит высококачественные выразительные видео и их описания. Видеоданные хранятся в столбце video_blob следующего набора данных Lance на Hub.
import lance
lance_ds = lance.dataset("hf://datasets/lance-format/Openvid-1M/data/train.lance")
blob_file = lance_ds.take_blobs("video_blob", ids=[0])[0]
video_bytes = blob_file.read()В отличие от других форматов данных, крупные мультимодальные бинарные объекты (blobs) являются полноправными гражданами в Lance. blob API предоставляет высокоуровневый интерфейс для хранения и извлечения крупных blobs в наборах данных Lance. Приведённый ниже пример демонстрирует, как эффективно просматривать метаданные без загрузки более тяжёлых видеобlobs, а затем по запросу получать нужные видеобlobs.
import lance
ds = lance.dataset("hf://datasets/lance-format/Openvid-1M/data/train.lance")
# 1. Browse metadata without loading video blobs.
metadata = ds.scanner(
columns=["caption", "aesthetic_score"],
filter="aesthetic_score >= 4.5",
limit=2,
).to_table().to_pylist()
# 2. Fetch a single video blob by row index.
selected_index = 0
blob_file = ds.take_blobs("video_blob", ids=[selected_index])[0]
with open("video_0.mp4", "wb") as f:
f.write(blob_file.read())Подготовка данных для обучения
Область, в которой также полезны высокая скорость случайного доступа и сканирования в Lance, — это обучение. Вы можете использовать наборы данных Lance в качестве механизма хранения данных для обучения, перемешивая их и загружая в батчи в рамках ваших конвейеров обучения.
API для объектов в Lance совместим с torchcodec, поэтому вы можете легко декодировать видеоблобы в тензоры torch:
from torchcodec.decoders import VideoDecoder
decoder = VideoDecoder(blob_file)
tensor = decoder[0] # uint8 tensor of shape [C, H, W]См. документацию torchcodec для получения информации о других функциях для эффективного декодирования видео.
Кроме того, вы можете обратиться к документации Lance, где приведены дополнительные примеры загрузки данных изображений в torchvision для обучения собственных моделей изображений.
Другие наборы данных Lance
Lance — это открытый формат с нативной поддержкой мультимодальных блобов наряду с традиционными табличными данными. Благодаря интеграции с Hugging Face Hub вы можете легко работать с изображениями, аудио, видео, текстом, эмбеддингами и скалярными метаданными в одном месте.
Ознакомьтесь с другими наборами данных Lance на Hugging Face Hub и поделитесь своими наборами данных Lance с другими участниками сообщества! Дополнительные фрагменты кода и примеры вы найдёте на lance.org.
Update on GitHub