Hub Python Library documentation

通过文件系统 API 与 Hub 交互

Hugging Face's logo
Join the Hugging Face community

and get access to the augmented documentation experience

to get started

通过文件系统 API 与 Hub 交互

除了 HfApi 之外,huggingface_hub 库还提供了 HfFileSystem,这是一个符合 Python 风格的、兼容 fsspec 的 Hugging Face Hub 文件接口。HfFileSystem 基于 HfApi 构建,并提供了典型的文件系统风格操作,例如 cp、mv、ls、du、glob、get_file 和 put_file。

HfFileSystem 提供 fsspec 兼容性,这对于需要该兼容性的库非常有用(例如,直接使用 pandas 读取 Hugging Face 数据集和存储桶)。然而,由于这一兼容性层,它会引入额外的开销。为了获得更好的性能和可靠性,建议尽可能使用 HfApi 方法。

用法

>>> from huggingface_hub import hffs

>>> # List all files in a dataset directory
>>> hffs.ls("datasets/my-username/my-dataset-repo/data", detail=False)
['datasets/my-username/my-dataset-repo/data/train.csv', 'datasets/my-username/my-dataset-repo/data/test.csv']

>>> # List all files in a bucket directory
>>> hffs.ls("buckets/my-username/my-bucket/experiment-data", detail=False)
['bucket/my-username/my-bucket/data/train-0000.parquet', 'bucket/my-username/my-bucket/data/train-0001.parquet', ...]

>>> # List all ".csv" files in a dataset repository
>>> hffs.glob("datasets/my-username/my-dataset-repo/**/*.csv")
['datasets/my-username/my-dataset-repo/data/train.csv', 'datasets/my-username/my-dataset-repo/data/test.csv']

>>> # Read a remote file
>>> with hffs.open("datasets/my-username/my-dataset-repo/data/train.csv", "r") as f:
...     train_data = f.readlines()

>>> # Read the content of a remote file as a string
>>> train_data = hffs.read_text("datasets/my-username/my-dataset-repo/data/train.csv", revision="dev")

>>> # Write a remote file
>>> with hffs.open("datasets/my-username/my-dataset-repo/data/validation.csv", "w") as f:
...     f.write("text,label")
...     f.write("Fantastic movie!,good")

可选的 revision 参数可用于从特定提交(例如分支、标签名称或提交哈希值)运行操作。请注意,revision 与 Buckets 不兼容。

与 Python 内置的 open 不同,fsspec 的 open 默认使用二进制模式 "rb"。这意味着在文本模式下,您必须显式地将 mode 设置为 "r" 以进行读取,或设置为 "w" 以进行写入。目前尚不支持向文件追加内容(模式 "a" 和 "ab")。

列出大型仓库

递归列出文件的操作(例如 find 和 glob)需要获取仓库的全部内容。Hub 会分页返回这些条目,且只有在收到上一页后才能请求下一页:列出包含 80 万个文件的仓库需要约 800 次顺序请求,因此耗时约 30 分钟。

为避免这种情况,HfFileSystem 会并行地逐个目录列出大型仓库:

>>> from huggingface_hub import hffs

>>> # Takes ~30s on a repository holding 800k files
>>> files = hffs.glob("datasets/allenai/objaverse/**/*.glb", maxdepth=3)

并发请求的数量由 HfFileSystem 的 max_workers 参数控制。其默认值为 16,可以设置为 1 以禁用并行列表。请注意,传入 maxdepth 也会显著加快列表速度,因为 Hub 此时仅返回实际请求的条目。

保持列表最新

目录仅列出一次,其内容会被缓存,因此其他人刚刚修改的目录不会被自动获取。HfFileSystem.invalidate_cache() 会清除缓存的目录列表,可以针对单个路径(及其父目录)进行清除,也可以在无参数调用时清除所有缓存:

>>> hffs.ls("buckets/my-username/my-bucket/data", detail=False)  # listing is cached
>>> # ... another process uploads a file to the bucket ...
>>> hffs.invalidate_cache("buckets/my-username/my-bucket/data")
>>> hffs.ls("buckets/my-username/my-bucket/data", detail=False)  # listed again
['buckets/my-username/my-bucket/data/train.csv', 'buckets/my-username/my-bucket/data/new-file.csv']

对于 bucket,huggingface_hub 可以为您完成此操作:Hub 会实时流式传输 bucket 的文件变更,而 HfFileSystem 会在变更到达时立即丢弃受影响的列表。使用 live_follow=True 启用此功能:

>>> from huggingface_hub import HfFileSystem
>>> hffs = HfFileSystem(live_follow=True)
>>> hffs.ls("buckets/my-username/my-bucket/data", detail=False)  # starts following that bucket
>>> # ... another process uploads a file to the bucket ...
>>> hffs.ls("buckets/my-username/my-bucket/data", detail=False)  # refreshed as changes arrive
['buckets/my-username/my-bucket/data/train.csv', 'buckets/my-username/my-bucket/data/new-file.csv']

它也可以通过 fsspec.filesystem("hf", live_follow=True) 经由 fsspec 传递,或者通过接受该参数的库(pandas、arrow 等)的 storage_options 参数传递。

关于它,有几点需要了解:

  • 仅限存储桶。模型、数据集和空间仓库均为 git 仓库,Hub 不会流式传输其变更:请向 HfFileSystem.ls() 传入 refresh=True(或使用 HfApi.list_repo_tree())以查看新的提交。
  • 仅刷新列表及其携带的元数据。读取文件时始终会从 Hub 请求其内容,因此实时跟踪仅影响 ls、info、exists、glob、… 所报告的内容。
  • 只要列出了某个存储桶,跟随操作便会立即开始,并且每个被跟随的存储桶都会保持一个后台连接处于打开状态,该连接由所有 HfFileSystem 实例共享。因此,该选项采用选择性启用(opt-in)的方式。

集成

HfFileSystem 可与任何集成了 fsspec 的库配合使用,前提是 URL 遵循以下格式:

hf://[<repo_type_prefix>]<repo_id>[@<revision>]/<path/in/repo>

repo_type_prefix 对于数据集为 datasets/,对于 Spaces 为 spaces/,而模型的 URL 中无需前缀。

除了仓库之外,HfFileSystem 还支持 Hugging Face Buckets,这是一种类似 S3 的对象存储(有关更多详细信息,请参阅此指南):

hf://buckets/<bucket_id>/<path/in/bucket>

以下是一些有趣的集成,其中 HfFileSystem 简化了与 Hub 的交互:

  • 从/向 Hub 仓库读取/写入 Pandas DataFrame:

    >>> import pandas as pd
    
    >>> # Read a remote CSV file into a dataframe
    >>> df = pd.read_csv("hf://datasets/my-username/my-dataset-repo/train.csv")
    >>> df = pd.read_csv("hf://buckets/my-username/my-bucket/train.csv")
    
    >>> # Write a dataframe to a remote CSV file
    >>> df.to_csv("hf://datasets/my-username/my-dataset-repo/test.csv")
    >>> df.to_csv("hf://buckets/my-username/my-bucket/test.csv")

相同的流程也可用于 Dask 和 Polars DataFrame。

  • 使用 DuckDB 查询(远程)Hub 文件:

    >>> from huggingface_hub import HfFileSystem
    >>> import duckdb
    
    >>> fs = HfFileSystem()
    >>> duckdb.register_filesystem(fs)
    >>> # Query a remote file and get the result back as a dataframe
    >>> fs_query_file = "hf://datasets/my-username/my-dataset-repo/data_dir/data.parquet"
    >>> df = duckdb.query(f"SELECT * FROM '{fs_query_file}' LIMIT 10").df()
  • 使用 Hub 作为 Zarr 数组存储:

    >>> import numpy as np
    >>> import zarr
    
    >>> embeddings = np.random.randn(50000, 1000).astype("float32")
    
    >>> # Write an array to a repo
    >>> root = zarr.open_group("hf://my-username/my-model-repo/array-store", mode="w")
    >>> foo = root.create_group("embeddings")
    >>> foobar = foo.zeros(name="experiment_0", shape=(50000, 1000), chunks=(10000, 1000), dtype="f4")
    >>> foobar[:] = embeddings
    
    >>> # Read an array from a repo
    >>> root = zarr.open_group("hf://my-username/my-model-repo/array-store", mode="r")
    >>> first_row = root["embeddings/experiment_0"][0]

身份验证

在许多情况下,你必须使用 Hugging Face 账户登录才能与 Hub 进行交互。请参阅文档中的 Authentication 部分,以了解有关 Hub 上身份验证方法的更多信息。

也可以通过将 token 作为参数传递给 HfFileSystem 来以编程方式登录:

>>> from huggingface_hub import HfFileSystem
>>> hffs = HfFileSystem(token=token)

如果您以这种方式登录,请注意在分享源代码时不要意外泄露令牌!

Update on GitHub