Daft v0.7.17 新增了 daft.datasets.lerobot,用于支持 LeRobot v3 机器人数据;原生支持 HDF5 文件;同时通过 Transformers provider 提供本地 LLM 推理能力。
pip install -U daft==0.7.17
Daft v0.7.17 完善了从上一版本 DROID 开始构建的机器人数据处理技术栈,新增第二种原生支持特定模态的文件类型,并提供了一种针对开放权重(open-weight)模型运行 Prompt 的方式,无需额外搭建推理服务。
本文中的大多数代码示例都是独立的 PEP 723 脚本(https://peps.python.org/pep-0723/?)——将任意示例复制到文件中,然后使用
uv run script.py执行,即可自动安装所需依赖。部分示例需要真实数据集、模型下载或网络请求,因此仅用于展示代码结构,并非开箱即用的可运行脚本。还没有uv?可以在这里安装(https://docs.astral.sh/uv/getting-started/installation/?)。
LeRobot Dataset v3.0 (https://huggingface.co/docs/lerobot/lerobot-dataset-v3?)是Hugging Face 针对机器人学习数据设计的数据格式:使用分块(chunked)Parquet 文件存储 episode 和帧级元数据,同时使用按相机划分的 MP4 shard 存储视频。此前,要读取这类数据,通常需要自行编写 episode 表与帧表之间的 join 逻辑,以及自行处理时间戳计算,以便将解码后的视频帧与传感器读数进行对齐。
daft.datasets.lerobot.read() 提供了一个统一的 lazy DataFrame,每一行对应一个帧(frame)——该接口会将 episode 元数据与帧级传感器数据进行 join;当传入 load_video_frames 时,还会根据时间戳,从对应的 MP4 shard 中解码匹配的相机图像。
import daft from daft.datasets import lerobot # One row per frame, with the primary camera decoded into an image column frames = lerobot.read( ”your-org/your-robot-dataset”, load_video_frames=”observation.image”, ) frames.select(”episode_index”, ”frame_index”, ”observation.image”).show(3)
视频解码需要额外安装可选依赖 av 和 pillow(pip install av pillow)。数据集 URI 可以是本地目录、hf://datasets/org/name 路径,也可以直接使用 Hugging Face repo ID(如 org/name)。
由 @srilman 在 #7090(https://github.com/Eventual-Inc/Daft/pull/7090?)中贡献。
HDF5 在机器人与科学数据领域中非常常见——DROID 的每个 episode 轨迹(trajectory)底层就是以 HDF5 格式存储的——但此前在 Daft 中读取 HDF5 数据,意味着必须降级使用原生 h5py,并自行管理文件句柄(file handle)。
daft.Hdf5File 在 HDF5 的 group/dataset 数据模型之上封装了一个 lazy file reference,而 hdf5_keys、hdf5_metadata 和 hdf5_attrs 则提供了常用的数据检查操作——包括列出 group 成员、遍历元数据以及读取属性(attributes)。这些操作均以 DataFrame expression 的形式提供,而不再需要编写命令式的 h5py 调用代码。
# /// script # description = ”Inspect an HDF5 file's structure with daft.Hdf5File expressions” # requires-python = ”>=3.12” # dependencies = [”daft[hdf5]==0.7.17”, ”h5py”] # /// import daft import h5py import tempfile import os from daft.functions import hdf5_file, hdf5_keys, hdf5_metadata tmpdir = tempfile.mkdtemp() path = os.path.join(tmpdir, ”trajectory.h5”) with h5py.File(path, ”w”) as f: grp = f.create_group(”robot”) grp.create_dataset(”joint_positions”, data=[[0.1, 0.2, 0.3], [0.4, 0.5, 0.6]]) grp.attrs[”units”] = ”radians” df = daft.from_pydict({”path”: [path]}) df = df.with_column(”file”, hdf5_file(daft.col(”path”))) df = df.with_column(”keys”, hdf5_keys(daft.col(”file”), group=”/robot”)) df = df.with_column(”metadata”, hdf5_metadata(daft.col(”file”), group=”/robot”)) df.select(”keys”, ”metadata”).show()
对于 DROID 轨迹(trajectory)这类结构已知的数据布局,可以将 Hdf5File 与一个通过 daft.func 装饰的、类型明确的 UDF 配合使用,直接读取指定的数据集(dataset)。这种方式可以完全跳过通用遍历流程,并直接返回具有明确类型的 tensor 列。
由 @everettVT 在 #7159(https://github.com/Eventual-Inc/Daft/pull/7159?)和 #7160(https://github.com/Eventual-Inc/Daft/pull/7160?)中贡献。
其他 prompt() provider 都默认你是在调用托管式 API。但在某些场景下,你可能希望针对开放权重(open-weight)模型执行离线批量推理——无需 API key、没有速率限制,也不依赖网络连接。
provider="transformers" 会在本地运行 Hugging Face 的 pipeline("text-generation"),并根据当前可用设备自动选择运行环境(优先 CUDA,其次 MPS,最后 CPU)。诸如 max_new_tokens 和 temperature 等生成参数(generation kwargs)会直接传递给 pipeline 调用;而 dtype 和 trust_remote_code 等构造阶段选项,则通过 pipeline_kwargs 传递。
import daft from daft.functions import prompt df = daft.from_pydict({”quote”: [”I am going to be the king of the pirates!”]}) df = df.with_column( ”response”, prompt( daft.col(”quote”), provider=”transformers”, model=”HuggingFaceTB/SmolLM2-360M-Instruct”, system_message=”Classify the anime from the quote in one short sentence.”, max_new_tokens=100, ), ) df.show()
同一个 provider 还支持直接接收文本文件列(text-file columns)——传入带有 text/* MIME 类型的 daft.File 或 bytes 值后,系统会读取文件内容并将其内联(inline)到 prompt 中,同时使用模型能够区分的标签(tag)将文件内容与用户指令进行包裹和区分。安装方式如下:pip install 'daft[transformers]'。
由 @YuangGao 在 #7152(https://github.com/Eventual-Inc/Daft/pull/7152?)和#7174(https://github.com/Eventual-Inc/Daft/pull/7174?)中贡献。
Common Crawl 为大规模语言模型预训练提供了相当大一部分 Web-scale 文本数据,但其标准访问方式——位于 us-east-1 区域的 AWS S3——会向从该区域之外读取数据的用户收取数据传出(egress)费用。
daft.datasets.common_crawl 现在支持从 Hugging Face 托管的镜像读取数据,为用户提供了一种无需凭证(credential-free)的替代方案:使用 source="hf"(或者完全不传参数,对于 2026 年及之后的 crawl 数据而言)会通过 hf://buckets/commoncrawl/commoncrawl/... 路径访问数据,而不再经过 S3。这样,你无需 AWS 账户,也不受区域限制,即可获得一个由 daft.read_warc 驱动的 DataFrame。
import daft # Reads from the HuggingFace bucket automatically for 2026+ crawls; # pass source=”hf” explicitly to force it for earlier crawls. df = daft.datasets.common_crawl(”CC-MAIN-2026-25”, source=”hf”, num_files=1) df.select(”WARC-Target-URI”, ”WARC-Type”, ”WARC-Date”).show(3)
当 S3 凭证和 Hugging Face 镜像均不适用时,HTTPS endpoint 仍会作为 fallback(回退方案)。
由 @lhoestq 在 #7103(https://github.com/Eventual-Inc/Daft/pull/7103?)中贡献。
过去,在分组聚合(grouped aggregation)中,如果将 any_value() 与数值列上的 sum()、min() 或 max() 混合使用,整个查询都会回退到 Daft 较慢的通用聚合路径(general aggregation path)——即使其他所有聚合操作都符合快速内联路径(fast inline path)的条件,只要存在一个 any_value 调用,就会导致整个查询降级。
现在,any_value 针对数值数据类型(numeric dtypes)拥有独立的内联累加器(inline accumulator),支持 Int8 至 Int64、UInt8 至 UInt64 以及 Float32/Float64。因此,它可以与通常搭配使用的其他聚合操作一起继续走快速路径——在执行数值汇总(numeric rollup)的同时,获取一行具有代表性的元数据(metadata)。
# /// script # description = ”Mix any_value with sum/min/max in one groupby aggregation” # requires-python = ”>=3.12” # dependencies = [”daft==0.7.17”] # /// import daft from daft.functions import any_value df = daft.from_pydict({ ”sensor”: [”a”, ”a”, ”a”, ”b”, ”b”], ”reading”: [10.0, 12.0, 9.0, 100.0, 110.0], ”unit”: [”celsius”, ”celsius”, ”celsius”, ”celsius”, ”celsius”], }) result = df.groupby(”sensor”).agg( df[”reading”].sum().alias(”total”), df[”reading”].min().alias(”low”), df[”reading”].max().alias(”high”), any_value(df[”unit”]).alias(”unit”), ) result.sort(”sensor”).show()
非数值类型的 any_value 目标(如字符串、二进制数据)仍然使用通用路径(general path)——此次变更仅针对已经符合内联 sum/min/max 快速路径条件的数值类型。
由 @BABTUNA 在 #7036(https://github.com/Eventual-Inc/Daft/pull/7036?)中贡献。
当你同时连接多个 catalog 时,create_namespace、drop_namespace 和 has_namespace 之前会忽略 "warehouse.staging" 这类标识符中的 catalog 限定符(catalog qualifier)——只有 create_table 和 drop_table 能够正确进行路由。对于非当前 catalog 执行 namespace 操作时,要么操作被错误地落到了其他位置,要么直接执行失败。
现在,这三个操作都会按照表操作(table operations)原有的解析方式,对限定标识符(qualified identifier)中的 catalog 部分进行解析。因此,无论连接了多少个 catalog,namespace 管理操作都能够正确作用于对应的 catalog,而不再局限于当前 catalog。
# /// script # description = ”Create a namespace in a non-current attached catalog by qualified name” # requires-python = ”>=3.12” # dependencies = [”daft==0.7.17”] # /// import daft from daft.catalog import Catalog primary = Catalog.from_pydict({”orders”: {”id”: [1, 2, 3]}}, name=”primary”) warehouse = Catalog.from_pydict({”events”: {”id”: [1, 2, 3]}}, name=”warehouse”) daft.attach_catalog(primary, alias=”primary”) daft.attach_catalog(warehouse, alias=”warehouse”) daft.create_namespace(”warehouse.staging”) print(”staging lives in warehouse:”, daft.has_namespace(”warehouse.staging”)) print(”primary is unaffected:”, daft.has_namespace(”primary.staging”))
由 @Lucas61000 在 #7171(https://github.com/Eventual-Inc/Daft/pull/7171?)中贡献。
- Hugging Face IO 的 Xet 读取支持:支持 Hugging Face 基于 chunk 的 Xet 存储后端,直接使用 hf-xet crate,而不再通过 OpenDAL 进行路由(@srilman #7183 https://github.com/Eventual-Inc/Daft/pull/7183?)。
- GooseFS 存储后端:通过新增的 GooseFSConfig,goosefs:// 路径现在可以与所有标准 reader 和 writer 配合使用。该实现基于 OpenDAL 的 services-goosefs backend 构建(@XuQianJin-Stars #7109 https://github.com/Eventual-Inc/Daft/pull/7109?)。
- 分布式 Aligned Asof Join:针对已排序且分区对齐(aligned partitions)的 asof join,新增了一条可跳过 shuffle 的内部执行路径;同时修复了现有 shuffle 路径中的 carryover 正确性问题,该问题由新增测试发现(@euanlimzx #7177 https://github.com/Eventual-Inc/Daft/pull/7177?)。
- Iceberg Table Read 支持ignore_corrupt_files:上一版本引入的 ignore_corrupt_files 选项现在也会通过 Table.from_iceberg(...).read(...) 向下传递,不再仅适用于独立的 read_iceberg 路径(@jackylee-ch #7147 https://github.com/Eventual-Inc/Daft/pull/7147?)。
- 修复无 Scheme 的 S3 Endpoint:部分 Iceberg REST catalog 返回的 s3.endpoint 不包含 scheme,例如 s3.example.com 而不是 https://s3.example.com。此前这会导致 URL 解析失败,使所有读取操作失败,而写入操作却会静默成功。现在 Daft 默认使用 https,与 PyArrow 的行为保持一致(@plusplusjiajia #7111 https://github.com/Eventual-Inc/Daft/pull/7111?)。
- 更简洁的 Rust 错误信息:嵌套的 Rust 错误此前会在 Python 中显示为冗长的 ProviderError { source: ... } 文本。现在它们会被格式化为简短、易读的错误链:(@srilman #7178 https://github.com/Eventual-Inc/Daft/pull/7178?)
- Pillow 依赖:VideoFile 现在会在缺少 Pillow 时抛出信息明确的错误,而不再出现难以判断原因的导入失败;同时,Pillow 已被加入并固定(pin)到 video extra 中,因此执行 pip install 'daft[video]' 时会自动安装 Pillow(@everettVT #7213 https://github.com/Eventual-Inc/Daft/pull/7213?)。
7 位外部贡献者在 v0.7.17 中贡献了功能和修复:
uv add ”daft>=0.7.17”
或者,也可以尝试最新的 nightly 版本:
uv pip install daft --pre --extra-index-url https://nightly.daft.ai
查看完整的 changelog(https://github.com/Eventual-Inc/Daft/releases/tag/v0.7.17?),了解所有已合并PR 的详细列表。
对于 LeRobot 数据集、HDF5 文件,或使用 Transformers provider 运行本地 LLM 推理有疑问?欢迎加入 Daft 社区: