Hub에 파일 업로드
파일과 작업 공유는 Hub의 중요한 측면입니다. huggingface_hub에는 파일을 Hub에 업로드하기 위한 여러 옵션이 제공됩니다. 이러한 함수를 독립적으로 사용하거나 라이브러리에 통합하여 사용자가 Hub와 상호작용하는 것을 더 편리하게 만들 수 있습니다.
Hub에 파일을 업로드하려면 Hugging Face 계정에 로그인해야 합니다. 인증에 대한 자세한 내용은 이 섹션을 확인하세요.
파일 업로드
create_repo()로 저장소를 생성한 후, upload_file()를 사용하여 파일 저장소에 파일을 업로드할 수 있습니다.
업로드할 파일의 경로, 저장소 내 파일 업로드 위치, 파일을 추가할 저장소 이름을 지정합니다. 저장소 유형에 따라 저장소 유형을 dataset, model, 또는 space로 선택적으로 설정할 수 있습니다.
>>> from huggingface_hub import HfApi
>>> api = HfApi()
>>> api.upload_file(
... path_or_fileobj="/path/to/local/folder/README.md",
... path_in_repo="README.md",
... repo_id="username/test-dataset",
... repo_type="dataset",
... )폴더 업로드
upload_folder() 함수를 사용하여 로컬 폴더를 기존 저장소에 업로드합니다. 업로드할 로컬 폴더의 경로, 저장소 내에서 폴더를 업로드할 위치, 그리고 폴더를 추가할 저장소의 이름을 지정합니다. 저장소 유형에 따라 저장소 유형을 dataset, model, 또는 space로 선택적으로 설정할 수 있습니다.
>>> from huggingface_hub import HfApi
>>> api = HfApi()
# Upload all the content from the local folder to your remote Space.
# By default, files are uploaded at the root of the repo
>>> api.upload_folder(
... folder_path="/path/to/local/space",
... repo_id="username/my-cool-space",
... repo_type="space",
... )기본적으로 .gitignore 파일이 참조되어 커밋할 파일과 커밋하지 않을 파일을 결정합니다. 기본적으로 커밋에 .gitignore 파일이 있는지 확인하고, 없으면 Hub에 존재하는지 확인합니다. 루트 디렉터리에만 존재하는 .gitignore 파일만 사용된다는 점에 유의하세요. 하위 디렉터리의 .gitignore 파일은 확인하지 않습니다.
하드코딩된 .gitignore 파일을 사용하지 않으려면 allow_patterns와 ignore_patterns 인수를 사용하여 업로드할 파일을 필터링할 수 있습니다. 이 매개변수는 단일 패턴 또는 패턴 목록을 받아들입니다. 패턴은 여기에 문서화된 표준 와일드카드(globbing 패턴)입니다. allow_patterns와 ignore_patterns가 모두 제공되면 두 제약 조건이 모두 적용됩니다.
.gitignore 파일과 허용/무시 패턴 외에도, 하위 디렉터리 어디에 존재하는 .git/ 폴더는 무시됩니다.
>>> api.upload_folder(
... folder_path="/path/to/local/folder",
... path_in_repo="my-dataset/train", # Upload to a specific folder
... repo_id="username/test-dataset",
... repo_type="dataset",
... ignore_patterns="**/logs/*.txt", # Ignore all text logs
... )delete_patterns 인수를 사용하여 같은 커밋에서 저장소에서 삭제할 파일도 지정할 수 있습니다.
파일을 푸시하기 전에 원격 폴더를 정리하고 싶지만 이미 어떤 파일이 존재하는지 모르는 경우 유용합니다.
아래 예제는 로컬 ./logs 폴더를 원격 /experiment/logs/ 폴더에 업로드합니다. txt 파일만 업로드되지만, 그 전에 리포지토리에 있는 이전 로그가 모두 삭제됩니다. 이 모든 작업이 단일 커밋으로 수행됩니다.
>>> api.upload_folder(
... folder_path="/path/to/local/folder/logs",
... repo_id="username/trained-model",
... path_in_repo="experiment/logs/",
... allow_patterns="*.txt", # Upload all local text files
... delete_patterns="*.txt", # Delete all remote text files before
... )파일이 업로드되는 방식
hf_xet이 설치된 경우(기본적으로 설치되어 있습니다) upload_folder()는 스트림된 파이프라인을 통해 파일을 업로드합니다. 파일은 Hub와 대조된 후 Xet 스토리지 백엔드에 업로드되고(이 과정에서 내부적으로 청킹, 중복 제거 및 전송 재시도가 수행됩니다), 적응형 배치로 커밋되며, 이 모든 작업이 병렬로 실행됩니다. 실제로 이는 다음과 같은 것을 의미합니다:
- 크기 제한이 없는 폴더: 작은 폴더는 단일 커밋으로 업로드되고, 파일이 많은 폴더는 서버 제한을 초과하지 않도록 자동으로 여러 커밋으로 나뉩니다. 이 경우 후속 커밋의 커밋 메시지에
(part 2),(part 3), … 접미사가 붙습니다. - 재개 가능: 업로드가 어떤 이유로든 중단된 경우, 동일한 호출을 다시 실행하면 됩니다. 이미 커밋된 파일은 감지되어 건너뛰고, 이미 업로드된 청크는 중복 제거됩니다. 다시 업로드해도 (거의) 데이터가 전송되지 않습니다. 로컬 상태가 관여하지 않으므로 다른 머신에서 재개할 수도 있습니다. 예외적으로
create_pr=True인 경우, 다시 실행하면 새로운 pull request가 열립니다. 업로드를 재개할 때는 대신revision="refs/pr/N"로 다시 실행하는 것을 권장합니다. - 이중 읽기 없음: 업로드를 위한 청크 분할 과정에서 파일이 해시되며, 이는 단일 읽기 패스에서 수행됩니다. 업로드 시작 전 별도의 “해싱” 단계가 없습니다.
실시간 진행 상황 표시는 세 가지 단계를 추적합니다:
Found 5,000 files to upload
Preparing ████████████████████ 5,000 / 5,000 ✓
Uploading ██████████████░░░░░░ 423 / 603 files 3.8GB · 19.7MB/s
Committing ██████████████████░░ 4,580 / 5,000 6 commitshf_xet이 설치되어 있지 않으면 upload_folder()은 레거시 동작으로 전환됩니다. 먼저 모든 파일을 해시하고, HTTP를 통해 업로드한 후, 단일 커밋을 생성합니다. 더 나은 견고성을 위해 hf_xet을 항상 설치해 두는 것을 권장합니다.
CLI에서 업로드
터미널에서 hf upload 명령을 사용하여 파일을 Hub에 직접 업로드할 수 있습니다. 내부적으로 위에서 설명한 upload_file() 및 upload_folder() 헬퍼를 동일하게 사용합니다.
…
# Usage: hf upload [repo_id] [local_path] [path_in_repo]
>>> hf upload Wauplin/my-cool-model ./models/model.safetensors model.safetensors
https://huggingface.co/Wauplin/my-cool-model/blob/main/model.safetensors
>>> hf upload Wauplin/my-cool-model ./models .
https://huggingface.co/Wauplin/my-cool-model/tree/mainlocal_path와 path_in_repo는 선택 사항이며 암묵적으로 추론될 수 있습니다. local_path가 설정되지 않은 경우, 도구는 repo_id와 동일한 이름을 가진 로컬 폴더 또는 파일이 있는지 확인합니다. 해당 폴더 또는 파일이 존재하면 그 내용이 업로드됩니다. 그렇지 않으면 local_path를 명시적으로 설정하도록 요청하는 예외가 발생됩니다. 어떤 경우든 path_in_repo가 설정되지 않으면 파일은 저장소의 루트에 업로드됩니다.
대상은 문법 hf://[<TYPE>/]<ID>[@<REVISION>][/<PATH>]을 따르는 단일 hf:// URI로도 표현할 수 있습니다(전체 문법은 HF URIs reference를 참조). 이 경우 리포지토리 유형, 리비전 및 path_in_repo는 URI에서 읽히며, --repo-type 및 --revision 옵션과 함께 사용할 수 없습니다:
# Upload a single file to a dataset on a specific branch
>>> hf upload hf://datasets/Wauplin/my-cool-dataset@my-branch/data/train.csv ./train.csv
https://huggingface.co/datasets/Wauplin/my-cool-dataset/blob/my-branch/data/train.csv대용량 파일의 최대 업로드 처리량을 위해
HF_XET_HIGH_PERFORMANCE=1환경 변수를 설정하세요. 이 설정은hf_xet의 고성능 모드를 활성화하여 사용 가능한 대역폭과 CPU 코어를 최대한 활용합니다. 참고:hf_transfer가hf_xet로 대체되어 제거되었으므로, 레거시HF_HUB_ENABLE_HF_TRANSFER=1플래거는 더 이상 사용되지 않습니다. 대신HF_XET_HIGH_PERFORMANCE=1을 설정하세요.
CLI 업로드 명령에 대한 자세한 내용은 CLI 가이드를 참고하세요.
큰 폴더 업로드
upload_folder()와 hf upload 명령은 Hub에 파일을 업로드하는 기본 솔루션으로, 매우 큰 폴더도 지원합니다. 파일은 여러 커밋으로 나뉘어 Hub에 스트리밍되며, 처리가 중단되면 자동으로 재개됩니다. 동일한 호출을 다시 실행하면 이미 업로드된 파일은 건너뜁니다.
>>> api.upload_folder(
... repo_id="HuggingFaceM4/Docmatix",
... repo_type="dataset",
... folder_path="/path/to/local/docmatix",
... )또는 터미널에서:
hf upload HuggingFaceM4/Docmatix --repo-type=dataset /path/to/local/docmatix
대용량 업로드 팁 및 트릭
리포지토리에 대량의 데이터를 다룰 때 인지해야 할 몇 가지 제한 사항이 있습니다. 데이터를 스트리밍하는 데 걸리는 시간을 고려할 때, 프로세스의 마지막에 업로드/푸시가 실패하거나 hf.co에서든 로컬에서 작업하든든 저하된 경험을 마주하게 되면 매우 번거로울 수 있습니다.
Hub에서 저장소를 구성하는 모범 사례에 대한 저장소 제한 사항 및 권장 사항 가이드를 확인해 보세요. 이제 업로드 과정을 최대한 원활하게 진행할 수 있는 실용적인 팁을 살펴보겠습니다.
- 소규모로 시작하기: 업로드 스크립트를 테스트하기 위해 소량의 데이터로 시작하는 것을 권장합니다. 실패할 때 걸리는 시간이 적을수록 스크립트를 반복 개선하기가 더 쉽습니다.
- 실패를 예상하세요: 대량의 데이터를 스트리밍하는 것은 어려운 작업입니다. 어떤 일이 발생할지 알 수 없지만, 기계, 연결 또는 서버의 문제와 관계없이 적어도 한 번은 무언가가 실패할 수 있다고 가정하는 것이 항상 최선입니다. 예를 들어, 대량의 파일을 업로드할 계획이라면 다음 배치 업로드 전에 이미 업로드한 파일을 로컬에서 추적하는 것이 좋습니다. 이미 커밋된 LFS 파일이 두 번 다시 업로드되지 않는다는 것은 보장되지만, 클라이언트 측에서 이를 확인하면 시간을 절약할 수 있습니다. upload_folder()가 이 역할을 수행합니다.
hf_xet사용: Hub의 새로운 스토리지 백엔드를 활용하며 Rust로 작성되었고, 이제 누구나 사용할 수 있습니다. 실제로hf_xet는huggingface_hub를 사용할 때 기본적으로 활성화되어 있습니다. 최대 성능을 위해HF_XET_HIGH_PERFORMANCE=1을 환경 변수로 설정하세요. 고성능 모드가 활성화되면 해당 도구가 사용 가능한 모든 대역폭과 CPU 코어를 사용하려고 시도한다는 점에 유의하세요.
고급 기능
대부분의 경우, 파일을 Hub에 업로드하려면 upload_file()와 upload_folder()만 있으면 충분합니다.
하지만 huggingface_hub에는 작업을 더 쉽게 만들어 주는 고급 기능도 있습니다. 함께 살펴보세요!
더 빠른 업로드
hf_xet를 활용하여 더 빠른 업로드를 경험해 보세요. hf_xet는 xet-core 라이브러리의 Python 바인딩으로, 청크 기반 중복 제거를 통해 업로드와 다운로드 속도를 높여 줍니다. hf_xet는 huggingface_hub와 완벽하게 통합되지만, LFS 대신 Rust 기반 xet-core 라이브러리와 Xet 스토리지를 사용합니다.
hf_xet는 파일을 불변(immutable) 청크로 분해하는 Xet 저장 시스템을 사용합니다. 이 시스템은 이러한 청크의 컬렉션(블록 또는 xorb라고 함)을 원격에 저장하고, 요청 시 이를 가져와 파일을 재조립합니다. 업로드 시, 사용자가 해당 저장소에 쓰기 권한이 있는지 확인한 후 hf_xet는 파일을 스캔하여 청크로 분해하고, 이러한 청크를 xorb로 수집합니다(알려진 청크 간 중복 제거 포함). 이후 이러한 xorb를 Xet 콘텐츠 주소 지정 서비스(CAS)에 업로드합니다. CAS는 xorb의 무결성을 검증하고, 조회/다운로드를 지원하기 위해 LFS SHA256 해시와 함께 xorb 메타데이터를 등록한 다음, xorb를 원격 저장소에 기록합니다.
활성화하려면 huggingface_hub의 최신 버전을 설치하면 됩니다:
pip install -U "huggingface_hub"huggingface_hub 0.32.0부터 hf_xet도 함께 설치됩니다.
기타 모든 huggingface_hub API는 수정 없이 계속 작동합니다. Xet 스토리지와 hf_xet의 이점에 대해 자세히 알아보려면 이 섹션을 참조하세요.
클러스터 / 분산 파일 시스템 업로드 고려 사항
클러스터에서 업로드할 때, 업로드 대상 파일은 분산 또는 네트워크 파일시스템(NFS, EBS, Lustre, Fsx 등)에 저장되어 있는 경우가 많습니다. Xet 스토리지에서는 이러한 파일을 청크로 나누어 로컬에 블록(또는 xorbs라고도 함)으로 작성하고, 블록 작성이 완료되면 업로드합니다. 분산 파일시스템에서 업로드할 때 성능을 개선하려면 HF_XET_CACHE를 로컬 디스크(예: 로컬 NVMe 또는 SSD 디스크)에 있는 디렉토리로 설정하십시오. Xet 캐시의 기본 위치는 HF_HOME 아래에 있는 (~/.cache/huggingface/xet)이며, 이는 사용자의 홈 디렉토리에 위치하므로 분산 파일시스템에 있는 경우가 많습니다.
비동기 업로드
일부 경우에서는 메인 스레드를 차단하지 않고 데이터를 업로드하는 것이 필요합니다. 이는 학습을 계속 진행하면서 로그와 아티팩트를 업로드할 때 특히 유용합니다. 이를 위해 upload_file()과 upload_folder() 모두에서 run_as_future 인수를 사용할 수 있습니다. 그러면 업로드 상태를 확인할 수 있는 concurrent.futures.Future 객체가 반환됩니다.
>>> from huggingface_hub import HfApi
>>> api = HfApi()
>>> future = api.upload_folder( # Upload in the background (non-blocking action)
... repo_id="username/my-model",
... folder_path="checkpoints-001",
... run_as_future=True,
... )
>>> future
Future(...)
>>> future.done()
False
>>> future.result() # Wait for the upload to complete (blocking action)
...
run_as_future=True를 사용하면 백그라운드 작업이 큐에 추가됩니다. 이는 작업이 올바른 순서로 실행된다는 것을 보장합니다.
백그라운드 작업은 주로 데이터 업로드/커밋 생성에 유용하지만, run_as_future()를 사용하여 원하는 메서드를 큐에 추가할 수 있습니다. 예를 들어, 리포지토리를 생성한 후 백그라운드에서 해당 리포지토리에 데이터를 업로드하는 데 사용할 수 있습니다. 업로드 메서드의 내장 run_as_future 인수는 이를 감싸는 별칭일 뿐입니다.
>>> from huggingface_hub import HfApi
>>> api = HfApi()
>>> api.run_as_future(api.create_repo, "username/my-model", exists_ok=True)
Future(...)
>>> api.upload_file(
... repo_id="username/my-model",
... path_in_repo="file.txt",
... path_or_fileobj=b"file content",
... run_as_future=True,
... )
Future(...)저장소 간 파일 복사
Hub의 저장소 간에 파일을 복사하거나 폴더를 복사할 때, 대용량 데이터를 다운로드하거나 다시 업로드하지 않고 copy_files()를 사용할 수 있습니다. 이는 모델 변형 간에 가중치를 복제하거나, 저장소 간에 데이터셋 파일을 복사하거나, 저장소 간에 파일을 재구성하고 싶을 때 유용합니다. 내부적으로 CommitOperationCopy 작업을 포함하는 커밋을 생성합니다.
>>> from huggingface_hub import HfApi
>>> api = HfApi()
# Copy a single file between repos
>>> api.copy_files(
... "hf://username/source-model/weights.safetensors",
... "hf://username/target-model/weights.safetensors",
... )
# Copy an entire folder
>>> api.copy_files(
... "hf://datasets/username/source-dataset/data/",
... "hf://datasets/username/target-dataset/data/",
... )같은 저장소 내에서 복사할 수도 있습니다:
# Duplicate a file in the same repo
>>> api.copy_files(
... "hf://username/my-model/config.json",
... "hf://username/my-model/backup/config.json",
... )폴더를 복사할 때, 소스에
/가 뒤에 붙어 있으면 rsync 스타일 의미론이 적용되어 폴더 자체를 중첩하지 않고 폴더의 내용만 복사됩니다./가 뒤에 붙지 않으면 폴더 자체가 대상 위치에 중첩됩니다.
copy_files()는 Buckets로 파일을 복사하는 것도 지원합니다. 자세한 내용은 Buckets 가이드를 참조하세요.
예약 업로드
Hugging Face Hub를 사용하면 데이터를 저장하고 버전 관리하는 것이 쉽습니다. 하지만 동일한 파일을 수천 번 업데이트하는 경우 몇 가지 제한 사항이 있습니다. 예를 들어, 학습 과정의 로그나 배포된 Space에 대한 사용자 피드백을 저장하고 싶을 수 있습니다. 이러한 경우 데이터를 Hub에 데이터셋으로 업로드하는 것이 적절하지만, 올바르게 수행하기가 어려울 수 있습니다. 그 주된 이유는 데이터의 모든 업데이트를 버전 관리하면 git 저장소를 사용할 수 없게 되기 때문입니다. CommitScheduler 클래스는 이 문제를 해결하는 방법을 제공합니다.
이 아이디어는 로컬 폴더를 Hub에 정기적으로 push하는 백그라운드 작업을 실행하는 것입니다. 텍스트를 입력받아 두 가지 번역을 생성하는 Gradio Space가 있다고 가정해 보겠습니다. 그러면 사용자는 원하는 번역을 선택할 수 있습니다. 각 실행마다 결과를 분석하기 위해 입력, 출력, 사용자 선호도를 저장하고 싶습니다. 이는 CommitScheduler의 완벽한 사용 사례입니다. Hub에 데이터를 저장해야 하지만(수백만 건의 사용자 피드백이 될 수도 있음), 각 사용자의 입력을 실시간으로 저장할 필요는 없습니다. 대신 데이터를 로컬의 JSON 파일에 저장하고 10분마다 업로드할 수 있습니다. 예를 들어:
>>> import json
>>> import uuid
>>> from pathlib import Path
>>> import gradio as gr
>>> from huggingface_hub import CommitScheduler
# Define the file where to save the data. Use UUID to make sure not to overwrite existing data from a previous run.
>>> feedback_file = Path("user_feedback/") / f"data_{uuid.uuid4()}.json"
>>> feedback_folder = feedback_file.parent
# Schedule regular uploads. Remote repo and local folder are created if they don't already exist.
>>> scheduler = CommitScheduler(
... repo_id="report-translation-feedback",
... repo_type="dataset",
... folder_path=feedback_folder,
... path_in_repo="data",
... every=10,
... )
# Define the function that will be called when the user submits its feedback (to be called in Gradio)
>>> def save_feedback(input_text:str, output_1: str, output_2:str, user_choice: int) -> None:
... """
... Append input/outputs and user feedback to a JSON Lines file using a thread lock to avoid concurrent writes from different users.
... """
... with scheduler.lock:
... with feedback_file.open("a") as f:
... f.write(json.dumps({"input": input_text, "output_1": output_1, "output_2": output_2, "user_choice": user_choice}))
... f.write("\n")
# Start Gradio
>>> with gr.Blocks() as demo:
>>> ... # define Gradio demo + use `save_feedback`
>>> demo.launch()그리고 끝입니다! 사용자 입력/출력 및 피드백은 Hub에서 데이터셋으로 사용할 수 있습니다. 고유한 JSON 파일 이름을 사용하면 이전 실행의 데이터나 동일한 저장소에 동시에 데이터를 푸시하는 다른 Spaces/레플리카의 데이터를 덮어쓰지 않는 것이 보장됩니다.
CommitScheduler에 대한 자세한 내용은 다음과 같습니다:
- append-only: 폴더에 콘텐츠만 추가할 것으로 가정합니다. 기존 파일에 데이터를 추가하거나 새 파일을 생성해야 합니다. 파일을 삭제하거나 덮어쓰면 저장소가 손상될 수 있습니다.
- git history:
스케줄러는
every분마다 폴더를 커밋합니다. git 저장소가 과도하게 오염되는 것을 방지하기 위해 최소 5분 값을 설정하는 것이 권장됩니다. 또한 스케줄러는 빈 커밋을 피하도록 설계되어 있습니다. 폴더에서 새로운 콘텐츠가 감지되지 않으면 예약된 커밋이 삭제됩니다. - errors: 스케줄러는 백그라운드 스레드로 실행됩니다. 클래스를 인스턴스화할 때 시작되며,
stop()이 호출되거나 프로세스가 종료될 때까지 실행됩니다. 업로드 중 오류가 발생하면(예: 연결 문제) 오류가 기록되고, 스케줄러는 다음 예약된 커밋 시점에 재시도합니다. - scripts: 수명이 제한된 스크립트(예: 학습)에서는 스케줄러를 컨텍스트 매니저로 사용합니다.
with블록을 벗어나면 마지막 업로드가 트리거되고, 완료까지 대기한 후 스케줄러가 중지됩니다. - 스레드 안전성: 대부분의 경우, 잠금 파일을 걱정하지 않고 파일에 안전하게 쓸 수 있다고 가정할 수 있습니다. 업로드 중 폴더에 내용을 작성해도 스케줄러가 충돌하거나 손상되지 않습니다. 실제로, 부하가 높은 앱에서는 동시성 문제가 발생할 수 있습니다. 이 경우, 스레드 안전성을 보장하기 위해
scheduler.lock잠금을 사용하는 것을 권장합니다. 이 잠금은 스케줄러가 폴더를 스캔하여 변경 사항을 확인하는 동안에만 차단되며, 데이터를 업로드하는 동안에는 차단되지 않습니다. Space의 사용자 경험에 영향을 미치지 않는다고 안전하게 가정할 수 있습니다.
Space 영속성 데모
Space에서 Hub의 Dataset으로 데이터를 영속화하는 것은 CommitScheduler의 주요 사용 사례입니다. 사용 사례에 따라 데이터를 다른 구조로 구성할 수 있습니다. 동시 사용자 및 재시작에 견고해야 하므로 UUID를 생성해야 하는 경우가 많습니다. 견고성 외에도 나중에 재사용할 수 있도록 🤗 Datasets 라이브러리가 읽을 수 있는 형식으로 데이터를 업로드해야 합니다. 여러 다른 데이터 형식을 저장하는 방법을 보여주는 Space를 만들었습니다(자신의 특정 요구 사항에 맞게 수정해야 할 수 있습니다).
커스텀 업로드
CommitScheduler assumes your data is append-only and should be uploading “as is”. However, you
might want to customize the way data is uploaded. You can do that by creating a class inheriting from CommitScheduler and overwrite the push_to_hub method (feel free to overwrite it any way you want). You are guaranteed it will
be called every every minutes in a background thread. You don’t have to worry about concurrency and errors but you
must be careful about other aspects, such as pushing empty commits or duplicated data.
아래 (단순화된) 예시에서는 Hub의 저장소에 과부하가 걸리는 것을 방지하기 위해 모든 PNG 파일을 단일 아카이브로 압축하도록 push_to_hub를 재정의합니다:
class ZipScheduler(CommitScheduler):
def push_to_hub(self):
# 1. List PNG files
png_files = list(self.folder_path.glob("*.png"))
if len(png_files) == 0:
return None # return early if nothing to commit
# 2. Zip png files in a single archive
with tempfile.TemporaryDirectory() as tmpdir:
archive_path = Path(tmpdir) / "train.zip"
with zipfile.ZipFile(archive_path, "w", zipfile.ZIP_DEFLATED) as zip:
for png_file in png_files:
zip.write(filename=png_file, arcname=png_file.name)
# 3. Upload archive
self.api.upload_file(..., path_or_fileobj=archive_path)
# 4. Delete local png files to avoid re-uploading them later
for png_file in png_files:
png_file.unlink()push_to_hub를 재정의하면 CommitScheduler의 속성에 접근할 수 있으며, 특히 다음을 사용할 수 있습니다:
- HfApi 클라이언트:
api - 폴더 매개변수:
folder_path및path_in_repo - 리포지토리 매개변수:
repo_id,repo_type,revision - 스레드 잠금:
lock
커스텀 스케줄러의 더 많은 예제는 데모 Space를 확인해 보세요. 사용 사례에 따라 다양한 구현이 포함되어 있습니다.
create_commit
upload_file() 및 upload_folder() 함수는 일반적으로 사용하기 편리한 고수준 API입니다. 낮은 수준에서 작업할 필요가 없다면 먼저 이 함수들을 사용해 보시는 것을 권장합니다. 그러나 커밋 수준에서 작업하려면 create_commit() 함수를 직접 사용할 수 있습니다.
create_commit()이 지원하는 작업은 세 가지 유형이 있습니다:
CommitOperationAdd는 파일을 Hub에 업로드합니다. 파일이 이미 존재하는 경우 파일 내용이 덮어쓰기됩니다. 이 연산은 두 개의 인수를 받습니다:
path_in_repo: 파일을 업로드할 저장소 경로.path_or_fileobj: 파일 시스템의 파일 경로 또는 파일 유사 객체입니다. 이는 Hub에 업로드할 파일의 내용입니다.
CommitOperationDelete는 저장소에서 파일 또는 폴더를 삭제합니다. 이 작업은
path_in_repo를 인수로 받습니다.CommitOperationCopy는 저장소 내부 또는 저장소 간에 파일을 복사합니다. 이 작업은 다음 인수를 받습니다:
src_path_in_repo: 복사할 파일의 저장소 경로.path_in_repo: 파일을 복사할 저장소 경로.src_revision: 선택 사항 - 다른 브랜치/리비전에서 파일을 복사하려면 복사할 파일의 리비전입니다.src_repo_id: 선택 사항 - 복사할 소스 저장소(예:"username/source-model"). 기본값은 대상 저장소입니다.src_repo_type: 선택 사항 - 소스 저장소의 유형("model","dataset"또는"space").src_repo_id가 설정된 경우 필수입니다.
예를 들어, Hub 저장소에서 두 개의 파일을 업로드하고 파일을 삭제하려면:
CommitOperation의 적절한 유형을 사용하여 파일을 추가하거나 삭제하고 폴더를 삭제합니다:
>>> from huggingface_hub import HfApi, CommitOperationAdd, CommitOperationDelete
>>> api = HfApi()
>>> operations = [
... CommitOperationAdd(path_in_repo="LICENSE.md", path_or_fileobj="~/repo/LICENSE.md"),
... CommitOperationAdd(path_in_repo="weights.h5", path_or_fileobj="~/repo/weights-final.h5"),
... CommitOperationDelete(path_in_repo="old-weights.h5"),
... CommitOperationDelete(path_in_repo="logs/"),
... CommitOperationCopy(src_path_in_repo="image.png", path_in_repo="duplicate_image.png"),
... ]- 작업을 create_commit()에 전달하세요:
>>> api.create_commit(
... repo_id="lysandre/test-model",
... operations=operations,
... commit_message="Upload my model weights and license",
... )upload_file()와 upload_folder() 외에도 다음 함수들은 내부적으로 create_commit()를 사용합니다:
- delete_file()는 Hub의 저장소에서 단일 파일을 삭제합니다.
- delete_folder()는 Hub의 저장소에서 폴더 전체를 삭제합니다.
- metadata_update()는 저장소의 메타데이터를 업데이트합니다.
자세한 정보는 HfApi 참고 문서를 확인하세요.
커밋 전에 LFS 파일을 사전 업로드
일부 경우, 커밋 호출을 하기 전에 S3에 대용량 파일을 업로드하고 싶을 수 있습니다. 예를 들어, 메모리에서 생성된 여러 샤드로 구성된 데이터셋을 커밋하는 경우, 메모리 부족 문제를 피하기 위해 샤드를 하나씩 업로드해야 합니다. 하나의 해결책은 각 샤드를 저장소의 별도 커밋으로 업로드하는 것입니다. 이 방법은 완전히 유효하지만, 수십 개의 커밋을 생성하여 git 히스토리를 혼란스럽게 만들 수 있다는 단점이 있습니다. 이 문제를 극복하려면 파일을 하나씩 S3에 업로드한 후 마지막에 단일 커밋을 생성할 수 있습니다. 이는 preupload_lfs_files()와 create_commit()를 조합하여 사용할 수 있습니다.
이것은 고급 사용자를 위한 방법입니다. 파일 사전 업로드의 저수준 로직을 직접 처리하는 대신 대부분의 경우 upload_file(), upload_folder() 또는 create_commit()를 직접 사용하는 것이 권장됩니다. preupload_lfs_files()의 주요 주의 사항은 커밋이 실제로 생성되기 전까지는 업로드된 파일에 Hub의 저장소에서 접근할 수 없다는 점입니다. 질문이 있으시면 Discord 또는 GitHub issue를 통해 문의해 주세요.
… 파일을 사전 업로드하는 방법을 보여주는 간단한 예시입니다:
>>> from huggingface_hub import CommitOperationAdd, preupload_lfs_files, create_commit, create_repo
>>> repo_id = create_repo("test_preupload").repo_id
>>> operations = [] # List of all `CommitOperationAdd` objects that will be generated
>>> for i in range(5):
... content = ... # generate binary content
... addition = CommitOperationAdd(path_in_repo=f"shard_{i}_of_5.bin", path_or_fileobj=content)
... preupload_lfs_files(repo_id, additions=[addition])
... operations.append(addition)
>>> # Create commit
>>> create_commit(repo_id, operations=operations, commit_message="Commit all shards")먼저 CommitOperationAdd 객체를 하나씩 생성합니다. 실제 사용 예시에서는 해당 객체에 생성된 샤드가 포함됩니다. 각 파일은 다음 파일을 생성하기 전에 업로드됩니다. preupload_lfs_files() 단계에서 CommitOperationAdd 객체가 변경됩니다. 이 객체는 create_commit()에 직접 전달하는 용도로만 사용해야 합니다. 객체의 주요 변경 사항은 바이너리 콘텐츠가 제거된다는 것으로, 다른 참조를 저장하지 않으면 가비지 컬렉션 대상이 됩니다. 이미 업로드된 콘텐츠를 메모리에 유지하고 싶지 않으므로 이는 예상된 동작입니다. 마지막으로 모든 작업을 create_commit()에 전달하여 커밋을 생성합니다. 아직 처리되지 않은 추가 작업(추가, 삭제 또는 복사)을 전달할 수 있으며, 이들은 올바르게 처리됩니다.