Hub documentation
Lance
Lance
Lance es un formato de tabla de lakehouse multimodal abierto para IA. Puedes usar rutas de Hugging Face (hf://) para acceder a conjuntos de datos Lance en el Hub. Esto te permite escanear y buscar en conjuntos de datos grandes en el Hugging Face Hub sin tener que copiar todo el conjunto de datos localmente.

Primeros pasos
Para empezar, instala pylance y pyarrow con pip:
pip install pylance pyarrow
¿Por qué Lance?
- Optimizado para cargas de trabajo de ML/IA: Lance es un formato columnar moderno diseñado para un acceso aleatorio rápido sin comprometer el rendimiento de escaneo, lo que lo hace útil para búsqueda, análisis, entrenamiento, ingeniería de características y muchos otros casos de uso.
- Los activos multimodales se almacenan como bytes u objetos binarios (“blobs as files”) en Lance junto con los embeddings y los datos escalares tradicionales, lo que facilita gobernar, compartir y distribuir tus grandes conjuntos de datos a través del Hub.
- El indexado es un ciudadano de primera clase (nativo del propio formato): Lance incluye índices de vector y FTS rápidos, en disco y escalables que se encuentran justo junto al conjunto de datos en el Hub, por lo que puedes compartir no solo tus datos, sino también tus embeddings e índices, sin que tus usuarios tengan que recalcularlos.
- El esquema flexible y la evolución de datos permiten añadir nuevas características/columnas (etiquetas de moderación, embeddings, etc.) de forma incremental sin necesidad de reescribir la tabla completa.
Almacena todos tus datos en un solo lugar
En Lance, tus activos de datos multimodales (imágenes, audio, video) se almacenan como bytes crudos junto con tus metadatos escalares y embeddings. Esto facilita escanear y filtrar tu conjunto de datos en un solo lugar, sin necesidad de integrar varios sistemas de almacenamiento.
Transmisión desde el Hub con datasets
Use load_dataset(..., streaming=True) para escanear e iterar sobre los datos sin descargarlos localmente.
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"])El streaming es ideal para muestrear metadatos y comprender qué se tiene. Para la búsqueda vectorial o el trabajo con grandes blobs binarios, se puede usar la API de dataset de Lance, explicada a continuación.
El streaming es rápido para muestrear metadatos escalares simples, pero no es tan ágil para embeddings o activos multimodales grandes. Para trabajar con conjuntos de datos grandes, se recomienda escanear los metadatos, identificar los subconjuntos que necesitas y descargar esa parte del conjunto de datos localmente para evitar alcanzar los límites de tasa del Hub:
hf download lance-format/laion-1m --repo-type dataset --local-dir ./laion
Transmisión desde el Hub con lance.dataset
También puedes escanear un conjunto de datos Lance almacenado en el Hugging Face Hub usando el especificador de ruta hf://. Esto escanea el conjunto de datos remoto sin necesidad de descargarlo localmente. Con la API de dataset de Lance, es muy sencillo establecer límites, filtros y proyecciones para obtener solo los datos que necesitas.
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)Trabajar con activos binarios
El ejemplo siguiente muestra cómo se recuperan las imágenes de un conjunto de datos Lance como bytes JPEG crudos en la columna image y cómo se utilizan a continuación.
Use ds.take para obtener los bytes y escribirlos en el disco para que pueda utilizarlos en otro lugar.
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']}")Escribe un subconjunto en un nuevo dataset de Lance
¿Trabaja con conjuntos de datos grandes? Es sencillo ejecutar un filtrado para seleccionar un subconjunto de filas del Hub y materializarlas en un conjunto de datos Lance local.
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")Crear índice
Si tu conjunto de datos no tiene un índice asociado, puedes crear uno después de descargarlo localmente.
# ds is a local Lance dataset
ds.create_index(
"img_emb",
index_type="IVF_PQ",
num_partitions=256,
num_sub_vectors=96,
replace=True,
)Consulta la documentación de Lance sobre la creación de índices vectoriales para un ejemplo más detallado. Una vez que hayas creado un índice vectorial, puedes realizar búsquedas de similitud en los datos mediante embeddings.
Búsqueda vectorial
Dado que los índices son ciudadanos de primera clase en Lance, puedes almacenar no solo tus datos, sino también tus embeddings e índices juntos y consultarlos directamente en el Hub. Simplemente usa el método describe_indices() para listar la información de los índices del conjunto de datos. Si un índice no existe en el conjunto de datos, puedes usar lance.write_dataset() para escribir una versión local del conjunto de datos y usar LanceDataset.create_index para crear un índice según tus necesidades.
El siguiente ejemplo muestra un conjunto de datos para el que ya existe un índice vectorial en el campo 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
#. )
# ]Puede ejecutar consultas de búsqueda vectorial directamente en el conjunto de datos remoto sin descargarlo (o, si lo prefiere, descargar el conjunto de datos localmente y crear un nuevo índice). El ejemplo siguiente muestra cómo ejecutar una búsqueda de vecinos más cercanos en un índice vectorial utilizando un embedding de imagen como vector de consulta.
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()Establecer un valor grande para
konprobes, o enviar un lote grande de consultas a la vez, puede alcanzar los límites de velocidad del Hub. Para un uso intensivo, descargue el conjunto de datos (o un subconjunto de él) localmente y apunte Lance a la ruta local para evitar la limitación.
Evolución de los conjuntos de datos
Una de las funciones más potentes de Lance es la evolución de datos flexible y sin coste, lo que significa que puedes añadir columnas derivadas sin reescribir la tabla original. Para tablas muy grandes con muchos blobs de gran tamaño, el ahorro en E/S puede ser bastante significativo. Esta función es muy relevante si estás experimentando con tus datos para tareas de ingeniería de ML/IA y te encuentras con frecuencia añadiendo nuevas características, embeddings o metadatos derivados.
El siguiente ejemplo muestra cómo añadir una columna derivada moderation_label que marca una imagen como NSFW en función de una columna de puntuación existente. Al realizar este cambio, el backfill de la nueva columna solo escribe los datos de la nueva columna, sin modificar los blobs de imagen originales ni los datos de otras columnas. También puedes optar por añadir únicamente el esquema de la nueva columna sin realizar ningún backfill de datos.
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"
}
)Consulte la documentación de Lance sobre evolución de datos para aprender a modificar y eliminar columnas en conjuntos de datos de Lance.
Trabajar con blobs de video
Las tablas Lance también admiten blobs de video grandes en línea. El conjunto de datos OpenVid-1M (de este artículo) contiene videos de alta calidad y expresivos, junto con sus descripciones. Los datos de video se almacenan en la columna video_blob del siguiente conjunto de datos Lance en el 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()A diferencia de otros formatos de datos, los objetos binarios multimodales de gran tamaño (blobs) son ciudadanos de primera clase en Lance. La API de blobs proporciona una API de alto nivel para almacenar y recuperar blobs grandes en conjuntos de datos de Lance. El siguiente ejemplo muestra cómo explorar de forma eficiente los metadatos sin cargar los blobs de video más pesados y, a continuación, recuperar los blobs de video relevantes bajo demanda.
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())Preparar datos para el entrenamiento
El entrenamiento es otro ámbito en el que el rápido acceso aleatorio y el rendimiento de escaneo de Lance pueden ser útiles. Puede utilizar conjuntos de datos de Lance como mecanismo de almacenamiento para sus datos de entrenamiento, barajándolos y cargándolos en lotes como parte de sus pipelines de entrenamiento.
La API de blobs en Lance es compatible con torchcodec, por lo que puedes decodificar fácilmente blobs de video como tensores de torch:
from torchcodec.decoders import VideoDecoder
decoder = VideoDecoder(blob_file)
tensor = decoder[0] # uint8 tensor of shape [C, H, W]Consulte la documentación de torchcodec para conocer más funciones para decodificar videos de manera eficiente.
Además, también puedes consultar la documentación de Lance para ver más ejemplos sobre cómo cargar datos de imágenes en torchvision para entrenar tus propios modelos de imágenes.
Explora más conjuntos de datos de Lance
Lance es un formato abierto con soporte nativo para blobs multimodales junto a tus datos tabulares tradicionales. Con la integración de Hugging Face Hub, puedes trabajar fácilmente con imágenes, audio, video, texto, embeddings y metadatos escalares, todo en un solo lugar.
Explora más conjuntos de datos Lance en el Hugging Face Hub y comparte tus propios conjuntos de datos Lance con otros miembros de la comunidad. Puedes visitar lance.org para ver más fragmentos de código y ejemplos.
Update on GitHub