Filesystem API를 통해 Hub와 상호작용
HfApi 외에도 huggingface_hub 라이브러리는 Hugging Face Hub에 대한 파이썬 스타일의 fsspec-compatible 파일 인터페이스인 HfFileSystem를 제공합니다. 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"를 사용합니다. 따라서 텍스트 모드로 읽기에는 "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']버킷의 경우, huggingface_hub가 이를 대신 처리할 수 있습니다. 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.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, …가 보고하는 내용에만 영향을 줍니다. - 버킷이 나열되는 즉시 Following이 시작되며, 각 Following 대상 버킷당 하나의 백그라운드 연결이 유지됩니다. 이 연결은 모든 HfFileSystem 인스턴스에서 공유됩니다. 이러한 이유로 해당 옵션은 opt-in 방식입니다.
통합
URL이 다음 스키마를 따르는 경우, fsspec을 통합하는 모든 라이브러리와 함께 HfFileSystem를 사용할 수 있습니다:
hf://[<repo_type_prefix>]<repo_id>[@<revision>]/<path/in/repo>
repo_type_prefix는 데이터셋의 경우 datasets/, Spaces의 경우 spaces/이며, 모델은 URL에 접두사가 필요 없습니다.
리포지토리 외에도 HfFileSystem는 S3와 유사한 객체 저장소인 Hugging Face Buckets를 지원합니다(자세한 내용은 이 가이드를 참고하세요):
hf://buckets/<bucket_id>/<path/in/bucket>Hub와의 상호작용을 단순화하는 HfFileSystem의 몇 가지 흥미로운 통합은 다음과 같습니다:
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()Zarr를 배열 저장소로 Hub를 사용하는 방법:
>>> 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