feature-engineering-examples
Justin Miller
newsletter-july-2026
ChanChan Mao
crewai-rebuilt-agent-memory-on-lancedb
CrewAI
one-table-to-train-your-robot-lancedb-as-the-data-layer-for-lerobot
Ayush Chaurasia
volcano-engine-lance-agent-memory
Bytedance
make-handwritten-notes-searchable-optimizing-an-ocr-pipeline-with-lancedb
Prashanth Rao
china-merchants-lancedb-story
China Merchants Lion Rock AI Lab
rabitq-gets-faster-higher-recall-lower-latency-query-time-control
Yang Cen
newsletter-june-2026
ChanChan Mao
from-messy-pdfs-to-verifiable-answers-with-liteparse-and-lancedb
Prashanth Rao
Clelia Astra Bertelli
faster-vlm-fine-tuning-with-materialized-model-features-in-lancedb
Prashanth Rao
Ayush Chaurasia
lance-blob-v2-late-materialization-for-large-binary-data-in-spark
Drew Gallardo
semantic-memory-for-hermes-agent-with-lancedb
Prashanth Rao
a-metadata-benchmark-of-lance-delta-lake-and-iceberg-on-s3
Jack Ye
scalable-feature-engineering-on-multimodal-datasets
Prashanth Rao
stable-worldmodel-a-high-performance-platform-for-reproducible-world-model-research
Ayush Chaurasia
Quentin Lhoest
Lucas Maes
Quentin Le Lidec
reproducible-data-curation-in-the-multimodal-lakehouse
Prashanth Rao
newsletter-may-2026
ChanChan Mao
newsletter-april-2026
ChanChan Mao
how-lancedb-accelerates-vector-search-at-10-billion-scale
Yang Cen
opensearch-vs-lancedb-for-vector-search-query-cost-and-infrastructure
Justin Miller
volcano-engine-autonomous-driving-data-lake-solution
Kejian Ju
unifying-the-av-ml-stack-lancedb
Ayush Chaurasia
lance-json-support-why-you-might-not-really-need-variant
Jack Ye
building-a-storage-format-for-the-next-era-of-biology
Pavan Ramkumar
newsletter-march-2026
ChanChan Mao
smart-parsing-meets-sharp-retrieval-combining-liteparse-and-lancedb
Clelia Astra Bertelli
Prashanth Rao
lance-format-v2-2-benchmarks-half-the-storage-none-of-the-slowdown
Xuanwo
make-your-sql-workflows-multimodal-with-lancedb-x-duckdb
Prashanth Rao
agentic-coding-as-community-stewardship
Xuanwo
what-we-mean-by-multimodal
Prashanth Rao
ai-native-development-local-continue-lancedb
Ty Dunn
lance-file-format-2-2-taming-complex-data
Xuanwo
lance-blob-v2
Xuanwo
Jack Ye
openclaw-lancedb-memory-layer
Xuanwo
Prashanth Rao
openclaw-lancedb-seed2
LanceDB
openclaw-memory-from-zero-to-lancedb-pro
Prashanth Rao
upload-lance-datasets-to-hf-hub
Prashanth Rao
zero-shot-image-classification-with-vector-search
Vipul Maheshwari
werides-data-platform-transformation-how-lancedb-fuels-model-development-velocity
Qian Zhu
Fei Chen
training-a-variational-autoencoder-from-scratch-with-the-lance-file-format
LanceDB
track-ai-trends-crewai-agents-rag
LanceDB
tokens-per-second-is-not-all-you-need
Mingran Wang
Tan Li
the-future-of-open-source-table-formats-iceberg-and-lance
Jack Ye
the-case-for-random-access-i-o
LanceDB
series-a-funding
Chang She
semanticdotart
Ayush Chaurasia
second-dinners-secret-weapon-lancedb-powered-rag-for-faster-smarter-game-development
Qian Zhu
search-within-an-image-331b54e4285e
Kaushal Choudhary
scalable-computer-vision-with-lancedb-voxel51-d8b65066d5f6
LanceDB
rethinking-table-file-paths-lance-multi-base-layout
Jack Ye
rag-isnt-one-size-fits-all
Leonard Marcq
python-package-to-convert-image-datasets-to-lance-type
Vipul Maheshwari
one-million-iops
Weston Pace
november-feature-roundup
Will Jones
newsletter-september-2025
Jasmine Wang
newsletter-october-2025
Jasmine Wang
newsletter-november-2025
ChanChan Mao
newsletter-june-2025
David Myriel
newsletter-july-2025
Jasmine Wang
newsletter-january-2026
ChanChan Mao
newsletter-february-2026
ChanChan Mao
newsletter-december-2025
ChanChan Mao
newsletter-august-2025
Jasmine Wang
my-summer-internship-experience-at-lancedb-2
Raunak Sinha
my-simd-is-faster-than-yours-fb2989bf25e7
LanceDB
multimodal-myntra-fashion-search-engine-using-lancedb
LanceDB
multimodal-lakehouse
David Myriel
multi-document-agentic-rag-a-walkthrough
Vipul Maheshwari
modified-rag-parent-document-bigger-chunk-retriever-62b3d1e79bc6
Mahesh Deshwal
memgpt-os-inspired-llms-that-manage-their-own-memory-793d6eed417e
Ayush Chaurasia
late-interaction-efficient-multi-modal-retrievers-need-more-than-just-a-vector-index
Ayush Chaurasia
lancedb-x-continue
LanceDB
lance-x-huggingface-a-new-era-of-sharing-multimodal-data
Prashanth Rao
Quentin Lhoest
Xuanwo
Ayush Chaurasia
lance-x-duckdb-sql-retrieval-on-the-multimodal-lakehouse-format
Xuanwo
lance-windows-windows-lance
Chang She
lance-v2
Weston Pace
lance-namespace-lancedb-and-ray
Jack Ye
lance-file-2-1-stable
Weston Pace
lance-file-2-1-smaller-and-simpler
Weston Pace
lance-data-viewer
Gordon Murray
lance-community-governance
Jack Ye
introducing-lance-namespace-spark-integration
Jack Ye
implementing-corrective-rag-in-the-easiest-way-2
LanceDB
hybrid-search-rag-for-real-life-production-grade-applications-e1e727b3965a
Mahesh Deshwal
hybrid-search-combining-bm25-and-semantic-search-for-better-results-with-lan-1358038fe7e6
LanceDB
hybrid-search-and-custom-reranking-with-lancedb-4c10a6a3447e
LanceDB
how-to-reduce-hallucinations-from-llm-powered-agents-using-long-term-memory-72f262c3cc1f
Tevin Wang
guide-to-use-contextual-retrieval-and-prompt-caching-with-lancedb
LanceDB
grpo-understanding-and-fine-tuning-the-next-gen-reasoning-model-2
Mahesh Deshwal
graphrag-hierarchical-approach-to-retrieval-augmented-generation
Akash Desai
gpu-accelerated-indexing-in-lancedb-27558fa7eee5
LanceDB
geo-support
Jack Ye
geneva-twelvelabs
David Myriel
geneva-feature-engineering
Jonathan Hsieh
from-bi-to-ai-lance-and-iceberg
Jack Ye
Prashanth Rao
fluss-integration
Wayne Wang
file-readers-in-depth-parallelism-without-row-groups
Weston Pace
feature-rabitq-quantization
David Myriel
Yang Cen
feature-full-text-search
David Myriel
enhance-rag-integrate-contextual-compression-and-filtering-for-precision-a29d4a810301
Kaushal Choudhary
effortlessly-loading-and-processing-images-with-lance-a-code-walkthrough
LanceDB
designing-a-table-format-for-ml-workloads
Weston Pace
custom-dataset-for-llm-training-using-lance
LanceDB
creating-a-fintech-agent
Vipul Maheshwari
convert-any-image-dataset-to-lance
LanceDB
columnar-file-readers-in-depth-structural-encoding
Weston Pace
columnar-file-readers-in-depth-repetition-definition-levels
Weston Pace
columnar-file-readers-in-depth-compression-transparency
Weston Pace
columnar-file-readers-in-depth-column-shredding
Weston Pace
columnar-file-readers-in-depth-backpressure
Weston Pace
columnar-file-readers-in-depth-apis-and-fusion
Weston Pace
chunking-techniques-with-langchain-and-llamaindex
Prashant Kumar
chunking-analysis-which-is-the-right-chunking-approach-for-your-language
Shresth Shukla
chat-with-csv-excel-using-lancedb
LanceDB
case-study-netflix
David Myriel
case-study-dosu
Qian Zhu
Michael Ludden
case-study-cognee
David Myriel
Vasilije Markovic
case-study-coderabbit
Qian Zhu
building-rag-on-codebases-part-2
Sankalp Shubham
building-rag-on-codebases-part-1
Sankalp Shubham
branching-and-shallow-clone
Jack Ye
better-rag-with-active-retrieval-augmented-generation-flare-3b66646e2a9f
LanceDB
benchmarking-random-access-in-lance
Chang She
benchmarking-lancedb-92b01032874a-2
LanceDB
benchmarking-cohere-reranker-with-lancedb
LanceDB
anythingllms-competitive-edge-lancedb-for-seamless-rag-and-agent-workflows
Ayush Chaurasia
announcing-lance-sdk
Weston Pace
agentic-rag-using-langgraph-building-a-simple-customer-support-autonomous-agent
LanceDB
advanced-rag-precise-zero-shot-dense-retrieval-with-hyde-0946c54dfdcb
LanceDB
accelerate-vector-search-applications-using-openvino-lancedb
LanceDB
a-primer-on-text-chunking-and-its-types-a420efc96a13
Prashant Kumar
a-practical-guide-to-training-custom-rerankers
Ayush Chaurasia
a-practical-guide-to-fine-tuning-embedding-models
Ayush Chaurasia
keep-your-data-fresh-with-cocoindex-and-lancedb
Prashanth Rao
Linghua Jin

One table to train your robot: LanceDB as the data layer for lerobot

July 20, 2026
Applications

Robotics datasets are conceptually simple: camera streams paired with a compact table of states, actions, timestamps, and task descriptions. Their storage stacks usually are not. Most split those modalities across Parquet files, MP4s, manifests, and application-specific bookkeeping.

LanceDB brings them into one queryable data layer that can train, stream, search, validate, and curate the same dataset. This post looks at robotics data broadly rather than targeting a particular framework. We use LeRobot, the field’s emerging open standard, as the worked example because it provides a clean, reproducible path from dataloader benchmarks through closed-loop evaluation.

The state of robotics data

Robot-learning data is video plus structured metadata: one or more camera streams, proprioceptive state, actions, timestamps, and task descriptions. Nearly every robotics stack stores it in roughly the same way:

  • Columnar files for structured values
  • Chunked MP4 files for camera streams
  • Manifests and metadata to keep the two aligned

The LeRobot v3 format is the canonical open implementation of this layout.

Video is the right container for camera streams. The coordination layer around it is where things become painful. A shuffled VLA training batch with a 50-step action chunk may need to seek across many MP4 files and repeatedly decode GOPs just to retrieve the requested frames. The same layout also cannot directly answer questions such as “show me every frame where the gripper is above the stove.” That requires a separate indexing or feature-extraction pipeline.

lerobot-lancedb replaces the loose collection of files and manifests with two coordinated Lance tables: a frame-level table for structured columns and a blob table containing the same MP4 bytes. And because it's one table rather than a pile of files and manifests, the layout is an enforced schema, not a convention. Every episode a robot uploads either fits this contract or gets rejected at write time. There is no silent mismatch where the Parquet metadata claims an episode contains 214 frames while its MP4 contains only 212:

frames table — one row per frame            videos table — one row per episode × camera
─────────────────────────────────────       ─────────────────────────────────────────
episode_index      int64                    episode_index   int64
frame_index        int64                    camera          string
timestamp          float32                  video           large_binary
task               string                     └─ metadata: lance-encoding:blob=true
observation.state  fixed_size_list<float32>[8]
action             fixed_size_list<float32>[7]
emb_image          fixed_size_list<float32>[768]   ← added later, zero-copy

The dataset stays video-sized (1.9 GB for LIBERO's 273k frames), decoded pixels are bit-exact vs the source videos, and the format gives you what the glue can't: fast frame-level random access, S3 byte-range streaming, and secondary indexes on the same table. Everything below is measured on a 4×H100 box, and the code to reproduce it is in the lancedb/training example repo.

LanceDB dataloader for robotics

LanceDB's LeRobot plugin is  optimized for faster dataloading. It uses LanceDB's blob encoding to lazily seek requested frames from episodes without loading the entire file in memory.

The test: ACT (~50M params) on DROID-100 (3 cameras per frame). Identical 4×H100 training runs, same seed, same mp4 bytes. The only variables are the data layer and the CPU budget, pinned identically for both backends.

The full 20k-step wall clock at the 4 vCPU budget: 50m04s for Lance vs 1h55m37s for the baseline (2.31×) Loss curves match to the third decimal at every logged step. Same bytes, same model, same result. One of them just waits on its dataloader.

The gap depends on how dataloader-bound the run is. Give the run plenty of CPU and the loader hides.  The faster your GPUs get, the bigger this gap gets. The LanceDB dataloader for LeRobot can get up to 3-5x speedup or more when using enterprise. With efficient data loaders,  your GPU spends less time waiting for data:

Below, we show a few examples that evaluate models we trained.

"Transfer the cube to the other arm", before vs after:

“transfer the cube to the other arm” (episode 0)

BEFORE: untrained ACT, 0%
AFTER: trained on Lance in 53 min, success

“transfer the cube to the other arm” (episode 1)

BEFORE: untrained ACT, 0%
AFTER: trained on Lance in 53 min, success

Using LanceDB with Lerobot

You can use LanceDB dataloader by swapping out the base loader with a single line change

from lerobot_lancedb import LeRobotLanceVideoDataset

dataset = LeRobotLanceVideoDataset(
    "lerobot/droid_100", root="./droid100_lance",
    delta_timestamps=delta_timestamps,   # resolved from your policy config as usual
    return_uint8=True,
)
# everything downstream is unchanged: EpisodeAwareSampler, DataLoader, your train loop

Converting an existing dataset is a single command:

lerobot-convert-to-lance-video --repo-id=your/dataset --src-root=... --output=./ds_lance

Training a VLA: SmolVLA on LIBERO

Next, let's look at the popular VLA class of models. We finetuned SmolVLA (450M, language-conditioned) on the LIBERO benchmark with both backends. Identical 40k-step recipes, task strings flowing through the language collate, evaluated closed-loop over all four suites, 100 episodes per suite per model.  at 450M the GPU is the bottleneck and both formats keep it fed.

Here's every suite, same model before and after fine-tuning, side-by-side:

libero_spatial: 80% after finetuning

BEFORE: smolvla_base, 0%
AFTER: trained on Lance, success

libero_object: 89% after finetuning

BEFORE: smolvla_base, 0%
AFTER: trained on Lance, success

libero_goal: 77% after finetuning

BEFORE: smolvla_base, 0%
AFTER: trained on Lance, success

libero_10: 82% after finetuning

BEFORE: smolvla_base, 0%
AFTER: trained on Lance, success
💡 One evaluation "gotcha" we hit so you don't have to
LeRobot's
--policy.n_action_steps controls how much of SmolVLA's 50-step action chunk executes open-loop before re-planning, and it dominates measured success. The same checkpoint that scores 82% closed-loop scores 14.8% when it executes 10 steps per chunk (72% at 1 step, 1% at 25). If your LIBERO numbers look inexplicably bad, check this flag before blaming your model.

Training directly from remote object store

Base LeRobot has no remote object storage streaming  path. You sync the dataset down, then train. The Lance reader takes an s3:// URI directly and does byte-range reads against the blob column. No local copy ever gets created. With LanceDB, you get fast streaming from object storage so you can keep your GPUs fed, without having to copy expensive data every time you train. This is useful when your dataset grows from a few gigabytes to petabytes in size. LanceDB also supports streaming GCS, Azure and Hugging Face Buckets.

read pattern (8 workers) parquet+mp4, local NVMe Lance, streamed from S3 Lance, local NVMe
DROID (3 cams) 722 897 1,709
ALOHA sim 817 1,013 2,296
LIBERO (2 cams, SmolVLA pattern) 1,271 1,445 3,111

The table shows samples per second in a same-region bucket, with the time-to-first-batch is 10 to 15 seconds. At 16 workers the S3 numbers grow to 1,690 to 2,458 samples/s. That's enough to fully feed every training configuration above with the dataset never touching the machine.

There are several other advantages of using LanceDB as your data layer for robotics:

  • No dataset volume at all: the GPU node needs disk for checkpoints, not data
  • No sync step
  • Node boots, training starts, first batch in seconds. one copy shared by N nodes
  • Cheaper storage: object storage runs roughly 3 to 4× cheaper per GB than the SSD volumes you'd otherwise sync to, and robotics corpora only grow
  • Fine-tuning on curated set: because it can random-access over S3, a curated slice can train against a corpus that never fits on the node at all. You read the 50 GB you selected out of the 10 TB you own

Add features and evolve your data for free

LanceDB supports zero-copy data evolution, i.e, when add a new column (feature), it only writes the new data to the existing table and doesn't copy the original data. At terabyte scale (or beyond), this process saves a lot of time, storage and I/O. Feature engineering is a critical piece for training good models. LanceDB's feature engineering package, Geneva allow you to run feature engineering jobs at scale on LanceDB tables, without creating expensive copies, messing with k8s/Spark cluster configs or being gated on infra support.

As a researcher, you only worry about defining the right features, without being bogged down by the infrastructure needed to compute them at scale. LanceDB Enterprise takes care of distributing the jobs across workers, smart checkpointing, and more.

Backfill features with Geneva

We added a SigLIP2 embedding column with the feature engineering capabilities in LanceDB Enterprise, using stateful UDFs (where the model is loaded once per worker), batched (batches arrive as Arrow arrays), and GPU-scheduled.

from geneva import udf

@udf(data_type=pa.list_(pa.float32(), 768), num_gpus=1, input_columns=["index"])
class EmbedAgentview:                      # stateful: SigLIP2 loads once per worker
    def __call__(self, index: pa.Array) -> pa.Array:   # batched
        # decodes pixels straight from the Lance video blob table
        ...

tbl.add_columns({"emb_image": EmbedAgentview(lance_root)})
tbl.backfill("emb_image", concurrency=2)   # 273,465 frames ≈ 10 min on 2 GPUs

Two things are worth noticing here. The UDF reads pixels from the video blob column, so the Frames table never stores image bytes. And the write does zero-copy schema evolution: a commit that adds a new embedding column, with no rewrite of the video blob column.

Curation: Index it, search it

"The microwave door is open" top hits across 273k frames

That's a text query against the frame embeddings, answered by the same table the DataLoader reads. With Parquet+MP4 you'd need an embedding store, an index service, and a manifest pipeline to do this. Three systems that can drift out of sync with your training data.

Four more things the same table answers

Near-duplicate episodes. Embed once, and redundancy pruning becomes a simple search problem. Comparing mid-episode frames across all 1,693 episodes at over 0.995 cosine similarity. Drop one before training.

Outlier mining. Within a task, the frames farthest from the task's visual centroid are your teleop glitches and camera-occlusion moments. Episode 217 shows up twice in the top-5 anomalies for the microwave tasks: the arm swallowing the lens. Exactly the frames to eyeball before they pollute a fine-tuning run.

Hybrid queries. Full-text and vector search compose. "the gripper is holding the object in the air" restricted to task LIKE '%basket%'. "Find me mid-grasp frames in basket tasks" becomes one call.

Time travel. Every schema evolution and backfill committed a table version (this table has 26 versions). You can open the exact table version a run trained on and reproduce it later.

Training on the curated dataset

Curation only matters if it feeds back into training. Here a SQL filter on the task column becomes an episode list, and the episode list becomes a fine-tuning dataset.

eps = tbl.search().where(f"task IN ({object_tasks})") \
         .select(["episode_index"]).to_pandas()["episode_index"].unique()
# → 454 episodes, 66,984 frames; feed straight into --dataset.episodes

Now we run training directly from the source dataset filtering only the desired episodes. It went from 0% to **77% on its suite in 10k steps**, about 35 minutes of training. The 40-task generalist still wins the suite at 89%. At this scale, multi-task transfer beats a narrow fine-tune.

Efficiently store large video blobs with Blob v2

The video table stores each mp4's raw bytes in a large_binary column whose field metadata(lance-encoding:blob=true) turns on Lance's blob encoding. Values live in blob-oriented data files, the column materializes as lightweight (position, size) descriptors, and returns lazy file-like handles that support byte-range reads, locally or over S3. torchcodec decodes straight from those in-memory buffers. That's why conversion is instant, pixels are bit-exact, the dataset stays video-sized, and a shuffled DataLoader still gets frame-level random access.

The real world is 1000× bigger

Everything above was for a 1.9 GB benchmark. That's small enough to measure cleanly, but just large enough that almost any storage decision can show its significance. A robotics program does not remain 1.9 GB in size. A fleet of robots recording a few cameras can easily produce this amount of data every few minutes. The corpora we've worked with in the wild, like VPT-scale video datasets and multi-terabyte teleop archives, sit 3-4 orders of magnitude above this example. That's where the two-system layout really breaks down:

  • Ingestion becomes continuous, not a one-time conversion: Thousands of robots and sim workers appending episodes at the same time need atomic, conflict-free writes into one namespace, not a directory of Parquet shards and a manifest that two writers race to update. Lance commits are atomic and versioned, and the schema contract from the intro is enforced on every write, so a fleet can't silently upload malformed episodes.
  • Syncing the dataset to the node stops being a small startup delay step and becomes an expensive op. A fast streaming dataloader is the way out: one copy in object storage, and every trainer streams byte ranges of exactly the slice it needs.
  • Curation stops being optional. At 273k frames you can eyeball your data. At 200M+ frames, the only way to find duplicates, teleop glitches, or the 50 GB actually worth training on is the machinery above (embeddings, indexes, SQL over the same table), running as distributed jobs instead of a notebook.
  • A 10-minute, 2-GPU backfill becomes a thousand-GPU-hour job. It will be preempted, it will hit bad rows, and it has to resume. That's exactly why backfills in LanceDB (via Geneva) are checkpointed and distributed via stateful UDFs that handle the heavy-lifting, rather than manually running them with for-loops.
  • Lineage becomes a compliance question. When a policy misbehaves on a real robot, "which table version, which episode list, which checkpoint" has to be answerable months later. Table versions and versioned splits scale with the table. Manifest files and tribal knowledge don't.

This is the workload LanceDB Enterprise runs for production AI teams: the same open Lance format underneath, plus the operational layer this scale demands. High-throughput distributed ingestion into object storage. Automatic compaction and index maintenance as the corpus grows. Feature backfills are scheduled across GPU fleets. Petabyte-scale scan throughput to keep multi-node trainings fed. And SLA-backed serving of the same tables for search and curation.

The worked example above is the whole system in miniature. Enterprise is what it looks like when the fleet, not the benchmark, sets the scale. Check out the training examples repo for all the code, and learn more about lerobot-lancedb here. Lots more to come soon!

⚡ Multi-Bit RaBitQ Without Refine, 🌋 Bytedance’s Lance-Based AI Stack, 🤖 Lance for Embodied AI Data

ChanChan Mao
July 31, 2026
newsletter-july-2026

Feature Engineering for Multimodal Data: From Laptop to Cluster with LanceDB

Justin Miller
August 5, 2026
feature-engineering-examples

Why CrewAI Rebuilt Agent Memory on LanceDB, Powering 2B+ Agent Executions

CrewAI
July 23, 2026
crewai-rebuilt-agent-memory-on-lancedb