Hub Python Library documentation

Взаимодействие с Hub через Filesystem API

Hugging Face's logo
Join the Hugging Face community

and get access to the augmented documentation experience

to get started

Взаимодействие с Hub через Filesystem API

Помимо HfApi, библиотека huggingface_hub предоставляет HfFileSystem — pythonic-интерфейс файловой системы, совместимый с fsspec, для работы с Hugging Face Hub. HfFileSystem построена на базе HfApi и предлагает типичные файловые операции, такие как cp, mv, ls, du, glob, get_file и put_file.

HfFileSystem обеспечивает совместимость с fsspec, что полезно для библиотек, требующих её (например, для прямого чтения наборов данных и бакетов Hugging Face с помощью pandas). Однако этот слой совместимости вносит дополнительные накладные расходы. Для лучшей производительности и надёжности рекомендуется по возможности использовать методы 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, функция open из fsspec по умолчанию работает в двоичном режиме "rb". Это означает, что для чтения и записи в текстовом режиме необходимо явно указать режимы "r" и "w" соответственно. Добавление данных в конец файла (режимы "a" и "ab") пока не поддерживается.

Список крупных репозиториев

Операции, перечисляющие файлы рекурсивно, такие как find и glob, требуют получения всего содержимого репозитория. Hub возвращает такие записи постранично, и запрос следующей страницы возможен только после получения предыдущей: для перечисления репозитория с 800 тыс. файлов требуется около 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)

Количество одновременных запросов контролируется аргументом max_workers класса HfFileSystem. По умолчанию он равен 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']

Для бакетов huggingface_hub может сделать это за вас: Хаб транслирует изменения файлов в бакете по мере их появления, а 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, с помощью fsspec.filesystem("hf", live_follow=True) или через аргумент storage_options в библиотеках, которые его поддерживают (pandas, arrow, …).

Несколько важных моментов:

  • Только корзины. Репозитории моделей, наборов данных и пространств являются git-репозиториями, и Хаб не транслирует их изменения: передайте refresh=True в HfFileSystem.ls() (или используйте HfApi.list_repo_tree()), чтобы увидеть новый коммит.
  • Обновляются только списки и их метаданные. При чтении файла его содержимое всегда запрашивается с Hub, поэтому live following влияет только на то, что сообщают ls, info, exists, glob, …
  • Подписка начинается сразу после получения списка объектов в бакете, и для каждого отслеживаемого бакета поддерживается одно фоновое соединение, общее для всех экземпляров HfFileSystem. Именно поэтому этот параметр включается явно.

Интеграции

Систему 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:

  • Чтение/запись Pandas DataFrame из/в репозиторий Hub:

    >>> 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")

Этот же рабочий процесс можно использовать и для DataFrames в Dask и Polars.

  • Запрос файлов (удалённого) Hub с помощью DuckDB:

    >>> 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]

Аутентификация

Во многих случаях для взаимодействия с Hub необходимо войти в систему с учётной записью Hugging Face. Подробнее о методах аутентификации на Hub см. в разделе Authentication документации.

Также можно выполнить вход в систему программно, передав ваш token в качестве аргумента в HfFileSystem:

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

Если вы входите в систему таким образом, будьте осторожны, чтобы случайно не раскрыть токен при публикации исходного кода!

Update on GitHub