Hub Python Library documentation

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

You are viewing main version, which requires installation from source. If you'd like regular pip install, checkout the latest stable version (v2.4.0).
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