Hub 로컬 캐시
Hub 로컬 캐시 (Hub Local Cache)
이 문서는 HF Hub 로컬 캐시의 디스크 레이아웃을 설명해요. 어떤 언어든 캐시 시스템을 재구현하기 위한 참고 자료로 작성된 거예요.
출처: 문서
본문
이 캐시 레이아웃을 사용하는 라이브러리와 애플리케이션의 일부 목록이에요. 자신을 추가하려면 PR을 열어주세요.
라이브러리
| 라이브러리 | 언어 | 참고 |
|---|---|---|
huggingface_hub |
Python | 그리고 그것에 의존하는 모든 라이브러리 (예: transformers, diffusers, datasets, mlx, vllm …) |
hf-hub |
Rust | |
swift-huggingface |
Swift | |
@huggingface/hub |
JavaScript | Node.js 전용 |
SMILE |
Java | HuggingFaceHub 문서 참고 |
애플리케이션
| 애플리케이션 | 언어 | 참고 |
|---|---|---|
llama.cpp |
C++ | #20775 이후 |
LlamaBarn |
Swift | macOS 앱, llama.cpp 기반 |
HuggingFaceModelDownloader |
Go | |
oMLX |
Python | macOS MLX 추론 서버, v0.4.0 이후 |
캐시 위치
기본 캐시 디렉토리는 다음과 같아요.
~/.cache/huggingface/hub
환경 변수로 덮어쓸 수 있어요.
HF_HUB_CACHE- 캐시 디렉토리의 직접 경로 (우선순위를 가짐)HF_HOME- Hugging Face 홈 디렉토리 경로; 설정하면 캐시는$HF_HOME/hub에 있음
개요
<CACHE_DIR>/
├── .locks/ # 동시 다운로드 안전을 위한 잠금 파일
├── models--<org>--<repo>/ # 캐시된 모델 저장소
├── datasets--<org>--<repo>/ # 캐시된 데이터셋 저장소
└── spaces--<org>--<repo>/ # 캐시된 space 저장소
다운로드된 각 저장소는 단일 플랫 폴더를 얻어요. 각 저장소 폴더 안에서 파일은 content-addressed blobs/ 디렉토리에 한 번 저장되고 snapshots/ 심볼릭 링크로 접근돼요. 명명된 참조(branch, tag)는 refs/에서 추적돼요.
스키마
┌──────────────────────────────────────────┐
│ Repository folder │
│ models--julien-c--EsperBERTo-small │
└──────────────┬───────────────────────────┘
│
┌─────────────┬───────┴───────┬──────────────┐
│ │ │ │
v v v v
┌───────┐ ┌────────┐ ┌────────────┐ ┌──────────┐
│ refs/ │ │ blobs/ │ │ snapshots/ │ │.no_exist/│
└───┬───┘ └────┬───┘ └──────┬─────┘ └────┬─────┘
│ │ │ │
│ │ │ │
"main" contains Files stored One folder Empty marker
commit hash by content per commit files for
e.g. "aaaaaa" hash (SHA-1 hash, e.g. files known
or SHA-256) aaaaaa/ not to exist
Resolves a bbbbbb/
branch/tag to │
a snapshot ──────────────────────► Contains symlinks
to ../../blobs/{hash}
저장소 폴더 이름
저장소는 캐시 루트에 플랫 디렉토리로 저장돼요. 폴더 이름은 저장소 유형과 저장소 ID를 인코딩해요.
{type}s--{repo_id_with_slashes_replaced_by_--}
규칙:
- 저장소 유형은 복수형:
models,datasets,spaces - 저장소 ID의 슬래시(
/)는--로 대체 - 모든 부분 사이의 구분자는
-- - 대소문자는 보존
예시:
| Hub 저장소 ID | 저장소 유형 | 캐시 폴더 이름 |
|---|---|---|
julien-c/EsperBERTo-small |
model | models--julien-c--EsperBERTo-small |
huggingface/DataMeasurementsFiles |
dataset | datasets--huggingface--DataMeasurementsFiles |
dalle-mini/dalle-mini |
space | spaces--dalle-mini--dalle-mini |
[!NOTE] Bucket은 git 기반이 아니므로 이 캐시로 처리되지 않아요. 전용
hf buckets sync명령을 대신 사용하세요.
저장소 폴더 내부
모든 캐시된 저장소는 같은 내부 구조를 가져요.
<repo_folder>/
├── blobs/
├── refs/
├── snapshots/
└── .no_exist/ # 항상 존재하지는 않을 수 있음
blobs/: 콘텐츠 주소형 파일 저장
blobs/ 디렉토리는 실제 파일 내용을 저장해요. 각 파일은 Hub의 파일 etag 이름을 따서 명명돼요.
- Git 추적 파일: SHA-1 해시(16진수 40자)로 명명
- Git LFS 파일: SHA-256 해시(16진수 64자)로 명명
이것은 플랫 디렉토리예요 — 하위 디렉토리가 없어요. 서로 다른 리비전 간에 동일한 파일은 한 번만 저장돼요.
blobs/
├── 403450e234d65943a7dcf7e05a771ce3c92faa84dd07db4ac20f592037a1e4bd # SHA-256 (LFS)
├── 7cb18dc9bafbfcf74629a4b760af1b160957a83e # SHA-1 (git)
└── d7edf6bd2a681fb0175f7735299831ee1b22b812 # SHA-1 (git)
refs/: branch 및 tag 참조
refs/ 디렉토리는 사람이 읽을 수 있는 참조(branch 이름, tag, PR 번호)를 커밋 해시에 매핑해요.
각 참조는 한 줄(전체 커밋 해시, 16진수 40자)을 포함하는 일반 텍스트 파일이에요.
refs/
├── main # 예: "bbc77c8132af1cc5cf678da3f1ddf2de43606d48" 포함
├── 2.4.0 # tag
└── refs/
└── pr/
└── 1 # pull request 참조
브랜치나 태그 이름으로 파일을 다운로드하면 해당 ref 파일이 최신 커밋 해시로 생성되거나 업데이트돼요.
snapshots/: 리비전 뷰
snapshots/ 디렉토리는 캐시된 각 리비전(커밋 해시)당 하나의 하위 디렉토리를 포함해요. 각 리비전 디렉토리는 Hub의 저장소 파일 구조를 반영하지만, 파일은 ../../blobs/{hash}를 가리키는 심볼릭 링크예요.
snapshots/
├── 2439f60ef33a0d46d85da5001d52aeda5b00ce9f/
│ ├── README.md -> ../../blobs/d7edf6bd2a681fb0175f7735299831ee1b22b812
│ └── pytorch_model.bin -> ../../blobs/403450e234d65943a7dcf7e05a771ce3c92faa84dd07db4ac20f592037a1e4bd
└── bbc77c8132af1cc5cf678da3f1ddf2de43606d48/
├── README.md -> ../../blobs/7cb18dc9bafbfcf74629a4b760af1b160957a83e
└── pytorch_model.bin -> ../../blobs/403450e234d65943a7dcf7e05a771ce3c92faa84dd07db4ac20f592037a1e4bd
주요 속성:
- 심볼릭 링크는 상대 경로:
../../blobs/{hash}사용 - 두 리비전 사이에 파일이 변하지 않으면 두 심볼릭 링크 모두 같은 blob을 가리켜 데이터 중복이 없음
- Hub의 하위 디렉토리 파일은 snapshot의 하위 디렉토리로 표현됨(전체 상대 경로 보존)
snapshot 전환은 로컬 git 저장소에서 git checkout을 사용하는 것과 비슷해요.
.no_exist/: 비존재 캐시
./no_exist/ 디렉토리는 요청되었지만 Hub에 존재하지 않는 파일을 추적해요. 선택적 파일에 대한 반복 HTTP 요청을 피하게 해줘요.
구조는 snapshots/를 반영해요. 커밋 해시당 하나의 하위 디렉토리이며, 없어진 파일 이름을 딴 (심볼릭 링크가 아닌) 빈 파일을 포함해요.
.no_exist/
└── 2439f60ef33a0d46d85da5001d52aeda5b00ce9f/
└── config_that_does_not_exist.json # empty file
이것들은 빈 마커 파일일 뿐이라 디스크 사용량은 무시할 수 있어요.
잠금 파일
잠금 파일은 동시 프로세스가 같은 blob을 동시에 다운로드하지 못하게 해요. 캐시 루트의 .locks/ 디렉토리(repo 폴더 안이 아님)에 저장돼요.
<CACHE_DIR>/.locks/<repo_folder_name>/<blob_hash>.lock
예시:
<CACHE_DIR>/.locks/models--julien-c--EsperBERTo-small/403450e234d65943a7dcf7e05a771ce3c92faa84dd07db4ac20f592037a1e4bd.lock
전체 예시
~/.cache/huggingface/hub/
├── .locks/
│ └── models--julien-c--EsperBERTo-small/
│ └── 403450e234d65943a7dcf7e05a771ce3c92faa84dd07db4ac20f592037a1e4bd.lock
│
└── models--julien-c--EsperBERTo-small/
├── blobs/
│ ├── [321M] 403450e234d65943a7dcf7e05a771ce3c92faa84dd07db4ac20f592037a1e4bd
│ ├── [ 398] 7cb18dc9bafbfcf74629a4b760af1b160957a83e
│ └── [1.4K] d7edf6bd2a681fb0175f7735299831ee1b22b812
│
├── refs/
│ └── main # "bbc77c8132af1cc5cf678da3f1ddf2de43606d48" 포함
│
├── snapshots/
│ ├── 2439f60ef33a0d46d85da5001d52aeda5b00ce9f/
│ │ ├── README.md -> ../../blobs/d7edf6bd2a681fb0175f7735299831ee1b22b812
│ │ └── pytorch_model.bin -> ../../blobs/403450e234d65943a7dcf7e05a771ce3c92faa84dd07db4ac20f592037a1e4bd
│ │
│ └── bbc77c8132af1cc5cf678da3f1ddf2de43606d48/
│ ├── README.md -> ../../blobs/7cb18dc9bafbfcf74629a4b760af1b160957a83e
│ └── pytorch_model.bin -> ../../blobs/403450e234d65943a7dcf7e05a771ce3c92faa84dd07db4ac20f592037a1e4bd
│
└── .no_exist/
└── 2439f60ef33a0d46d85da5001d52aeda5b00ce9f/
└── optional_config.json # empty file
pytorch_model.bin이 두 리비전 모두에서 같은 blob을 가리키는 방식을 주목하세요. 321MB 파일은 디스크에 한 번만 저장돼요.
파일 해석 로직
캐시된 파일을 디스크에서 찾으려면:
-
리비전을 커밋 해시로 해석
- 리비전이 이미 40자 16진수 문자열이면 그대로 사용
- 아니면
refs/{revision}에서 파일을 읽어 커밋 해시를 얻음
-
snapshot 확인
snapshots/{commit_hash}/{relative_path}를 찾음- 존재하면(심볼릭 링크든 파일이든) 파일이 캐시된 것. 심볼릭 링크를 따라가 내용을 얻음
-
비존재 확인
.no_exist/{commit_hash}/{relative_path}를 찾음- 존재하면 이 리비전에서 파일이 Hub에 없다는 것을 알고 있음
-
캐시 미스
- 두 경로 모두 없으면 파일이 아직 캐시되지 않음
Windows 동작
캐시는 심볼릭 링크에 의존해요. 심볼릭 링크를 사용할 수 없는 Windows 시스템에서는 캐시가 저하 모드(degraded mode) 로 동작해요. 심볼릭 링크 대신 실제 파일 복사본이 snapshots/에 직접 배치돼요. 이 모드에서는 blobs/ 디렉토리가 사용되지 않아요.
즉 같은 파일 내용이 리비전 간에 중복되어 디스크 사용량이 늘어날 수 있어요. Windows에서 심볼릭 링크 지원을 활성화하려면 Developer Mode를 활성화하거나 관리자로 실행하세요.
더 알아보기 (Learn more)
캐시는 blobs/(콘텐츠 주소형 실제 데이터), snapshots/(리비전별 심볼릭 링크 뷰), refs/(브랜치→커밋 매핑), .no_exist/(없는 파일 캐시)로 구성돼요. 같은 파일은 리비전이 달라도 blob 하나로 공유돼 디스크를 아껴요. Windows는 심볼릭 링크가 없으면 저하 모드로 동작해 데이터가 중복될 수 있어요.