Hub Python Library documentation

Entender o cache

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

Entender o cache

huggingface_hub usa um cache local baseado em arquivos para armazenar os arquivos individuais baixados do Hub e evitar baixar novamente arquivos que não foram alterados quando um repositório é atualizado. Além disso, o hf_xet armazena um cache de shards e dados de staging para otimizar uploads (veja Cache do Xet).

Este guia aborda as ferramentas de gerenciamento de cache específicas para Python fornecidas por huggingface_hub. Para uma visão geral independente de linguagem sobre como o sistema de cache do Hugging Face Hub funciona, consulte a documentação do Hub sobre cache local.

Cache baseado em arquivos

O sistema de cache do Hugging Face Hub foi projetado para ser o cache central compartilhado entre as bibliotecas que dependem do Hub. Ele foi atualizado na v0.8.0 para evitar o re-download dos mesmos arquivos entre revisões.

O sistema de cache é projetado da seguinte forma:

<CACHE_DIR>
├─ <MODELS>
├─ <DATASETS>
├─ <SPACES>
├─ <KERNELS>

O valor padrão de <CACHE_DIR> é ~/.cache/huggingface/hub. No entanto, ele pode ser personalizado com o argumento cache_dir em todos os métodos, ou especificando a variável de ambiente HF_HOME ou HF_HUB_CACHE.

Modelos, conjuntos de dados, espaços e kernels compartilham uma raiz comum. Cada um desses repositórios contém o tipo de repositório, o namespace (organização ou nome de usuário), se existir, e o nome do repositório:

<CACHE_DIR>
├─ models--julien-c--EsperBERTo-small
├─ models--lysandrejik--arxiv-nlp
├─ models--bert-base-cased
├─ datasets--glue
├─ datasets--huggingface--DataMeasurementsFiles
├─ spaces--dalle-mini--dalle-mini

É dentro dessas pastas que todos os arquivos serão baixados do Hub. O cache garante que um arquivo não seja baixado duas vezes se ele já existir e não tiver sido atualizado; mas, se ele tiver sido atualizado e você estiver solicitando o arquivo mais recente, o arquivo mais recente será baixado (mantendo o arquivo anterior intacto, caso você precise dele novamente).

Para alcançar isso, todas as pastas contêm o mesmo esqueleto:

<CACHE_DIR>
├─ datasets--glue
│  ├─ refs
│  ├─ blobs
│  ├─ snapshots
│  ├─ trees
...

Cada pasta é projetada para conter o seguinte:

Referências

A pasta refs contém arquivos que indicam a revisão mais recente da referência dada. Por exemplo, se buscamos anteriormente um arquivo da branch main de um repositório, a pasta refs conterá um arquivo chamado main, que por sua vez conterá o identificador do commit do head atual.

Se o commit mais recente de main tiver aaaaaa como identificador, ele conterá aaaaaa.

Se esse mesmo branch for atualizado com um novo commit, que tem bbbbbb como identificador, então baixar novamente um arquivo dessa referência atualizará o arquivo refs/main para conter bbbbbb.

Blobs

A pasta blobs contém os arquivos reais que foram baixados. O nome de cada arquivo é o seu hash.

Snapshots

A pasta snapshots contém links simbólicos para os blobs mencionados acima. Ela é composta por várias pastas: uma para cada revisão conhecida!

Na explicação acima, inicialmente obtivemos um arquivo da revisão aaaaaa, antes de obter um arquivo da revisão bbbbbb. Nessa situação, agora teríamos duas pastas na pasta snapshots: aaaaaa e bbbbbb.

Em cada uma dessas pastas, há links simbólicos que têm os nomes dos arquivos que baixamos. Por exemplo, se tivéssemos baixado o arquivo README.md na revisão aaaaaa, teríamos o seguinte caminho:

<CACHE_DIR>/<REPO_NAME>/snapshots/aaaaaa/README.md

O arquivo README.md é, na verdade, um link simbólico que aponta para o blob que possui o hash do arquivo.

Ao criar o esqueleto dessa forma, abrimos o mecanismo para o compartilhamento de arquivos: se o mesmo arquivo foi obtido na revisão bbbbbb, ele teria o mesmo hash e o arquivo não precisaria ser baixado novamente.

Árvores

A pasta trees faz o cache da lista de arquivos que um repositório contém em um determinado commit. Como um commit é imutável, sua lista de arquivos nunca muda. Isso significa que a lista pode ser armazenada em cache para sempre, sem nunca precisar ser verificada novamente contra o Hub.

Cada lista em cache é nomeada com base em um hash de commit e armazenada como um arquivo JSON, por exemplo trees/aaaaaa.json. Para cada arquivo no repositório naquele commit, ela registra o que é necessário para baixar o arquivo: seu caminho, seu tamanho e seu hash. Essa é a mesma informação que o Hub retornaria de outra forma, mas normalmente custa uma chamada de rede por arquivo para obtê-la.

Este cache é gravado por snapshot_download(). Na primeira vez que você baixa um commit, a lista de arquivos é obtida uma vez e salva aqui. Na próxima vez que você baixar o mesmo commit, a lista é lida do disco em vez de ser obtida novamente. Como resultado, reexecutar um download quando tudo já está em cache custa uma única chamada de rede: a necessária para resolver o nome da branch ou tag em um hash de commit.

Tanto o snapshot_download() quanto o hf_hub_download() leem esse cache para evitar chamadas de rede. Quando você baixa um arquivo com um hash de commit como revisão (é exatamente isso que o snapshot_download() faz internamente para cada arquivo), os metadados de download são lidos da lista de arquivos em cache e a chamada de rede por arquivo é ignorada. Isso significa que um hf_hub_download() para um único arquivo também se beneficia de uma lista de arquivos que um snapshot_download() anterior salvou para o mesmo commit.

Como a lista de arquivos em cache descreve exatamente o que um commit deve conter, snapshot_download() também pode indicar se um snapshot local está completo. Se o Hub não puder ser acessado (você está offline, a conexão falha ou você passou local_files_only=True) e alguns arquivos esperados estiverem ausentes do snapshot local, snapshot_download() lança IncompleteSnapshotError em vez de retornar uma pasta parcial. Antes disso, um snapshot incompleto era retornado silenciosamente, o que poderia deixá-lo trabalhando com arquivos ausentes sem saber. Arquivos excluídos por allow_patterns ou ignore_patterns não são contados como ausentes. A exceção expõe o caminho para o snapshot incompleto por meio de seu atributo snapshot_path, para que você ainda possa localizar os arquivos parcialmente em cache, se necessário.

.no_exist (avançado)

Além das pastas blobs, refs e snapshots, você também pode encontrar uma pasta .no_exist no seu cache. Essa pasta mantém o registro de arquivos que você tentou baixar uma vez, mas que não existem no Hub. Sua estrutura é a mesma da pasta snapshots, com 1 subpasta por revisão conhecida:

<CACHE_DIR>/<REPO_NAME>/.no_exist/aaaaaa/config_that_does_not_exist.json

Diferentemente da pasta snapshots, os arquivos são simplesmente arquivos vazios (sem links simbólicos). Neste exemplo, o arquivo "config_that_does_not_exist.json" não existe no Hub para a revisão "aaaaaa". Como ele armazena apenas arquivos vazios, esta pasta é desprezível em termos de uso de disco.

Agora você pode se perguntar por que essa informação é relevante. Em alguns casos, um framework tenta carregar arquivos opcionais para um modelo. Salvar a inexistência de arquivos opcionais torna o carregamento de um modelo mais rápido, pois economiza 1 chamada HTTP por arquivo opcional possível. Esse é o caso, por exemplo, em transformers, onde cada tokenizer pode suportar arquivos adicionais. Na primeira vez que você carrega o tokenizer na sua máquina, ele faz o cache de quais arquivos opcionais existem (e quais não existem) para tornar o tempo de carregamento mais rápido nas próximas inicializações.

Para testar se um arquivo está em cache localmente (sem fazer nenhuma requisição HTTP), você pode usar o helper try_to_load_from_cache(). Ele retornará o caminho do arquivo (se existir e estiver em cache), o objeto _CACHED_NO_EXIST (se a inexistência estiver em cache) ou None (se não soubermos).

from huggingface_hub import try_to_load_from_cache, _CACHED_NO_EXIST

filepath = try_to_load_from_cache()
if isinstance(filepath, str):
    # file exists and is cached
    ...
elif filepath is _CACHED_NO_EXIST:
    # non-existence of file is cached
    ...
else:
    # file is not cached
    ...

Na prática

Na prática, seu cache deve ter a seguinte estrutura de árvore:

    [  96]  .
    └── [ 160]  models--julien-c--EsperBERTo-small
        ├── [ 160]  blobs
        │   ├── [321M]  403450e234d65943a7dcf7e05a771ce3c92faa84dd07db4ac20f592037a1e4bd
        │   ├── [ 398]  7cb18dc9bafbfcf74629a4b760af1b160957a83e
        │   └── [1.4K]  d7edf6bd2a681fb0175f7735299831ee1b22b812
        ├── [  96]  refs
        │   └── [  40]  main
        ├── [ 128]  snapshots
        │   ├── [ 128]  2439f60ef33a0d46d85da5001d52aeda5b00ce9f
        │   │   ├── [  52]  README.md -> ../../blobs/d7edf6bd2a681fb0175f7735299831ee1b22b812
        │   │   └── [  76]  pytorch_model.bin -> ../../blobs/403450e234d65943a7dcf7e05a771ce3c92faa84dd07db4ac20f592037a1e4bd
        │   └── [ 128]  bbc77c8132af1cc5cf678da3f1ddf2de43606d48
        │       ├── [  52]  README.md -> ../../blobs/7cb18dc9bafbfcf74629a4b760af1b160957a83e
        │       └── [  76]  pytorch_model.bin -> ../../blobs/403450e234d65943a7dcf7e05a771ce3c92faa84dd07db4ac20f592037a1e4bd
        └── [  96]  trees
            ├── [ 521]  2439f60ef33a0d46d85da5001d52aeda5b00ce9f.json
            └── [ 521]  bbc77c8132af1cc5cf678da3f1ddf2de43606d48.json

CACHEDIR.TAG

huggingface_hub cria automaticamente um arquivo CACHEDIR.TAG dentro do diretório de cache. Essa tag segue o Cache Directory Tagging Standard e informa às ferramentas de backup (por exemplo, Borg, restic, rsync) que o diretório contém dados de cache que podem ser baixados novamente e podem ser excluídos com segurança dos backups.

Limitações

Para ter um sistema de cache eficiente, o huggingface-hub usa links simbólicos. No entanto, links simbólicos não são suportados em todas as máquinas. Esta é uma limitação conhecida, especialmente no Windows. Quando isso ocorre, o huggingface_hub não usa o diretório blobs/, mas armazena os arquivos diretamente no diretório snapshots/. Essa solução alternativa permite que os usuários baixem e façam cache de arquivos do Hub exatamente da mesma forma. As ferramentas para inspecionar e excluir o cache (veja abaixo) também são suportadas. No entanto, o sistema de cache é menos eficiente, pois um único arquivo pode ser baixado várias vezes se várias revisões do mesmo repositório forem baixadas.

Se você deseja se beneficiar do sistema de cache baseado em links simbólicos em uma máquina Windows, você precisa ativar o Modo Desenvolvedor ou executar o Python como administrador.

Se você deseja usar proativamente o modo de cache sem symlinks (por exemplo, em um sistema de arquivos compartilhado que não lida bem com symlinks), você pode definir a variável de ambiente HF_HUB_DISABLE_SYMLINKS para 1. Os arquivos serão copiados diretamente para snapshots/ em vez de criar symlinks para blobs/.

Quando os links simbólicos não são suportados, uma mensagem de aviso é exibida ao usuário para alertá-lo de que ele está usando uma versão degradada do sistema de cache. Esse aviso pode ser desativado definindo a variável de ambiente HF_HUB_DISABLE_SYMLINKS_WARNING como true.

Blobs compartilhados entre repositórios

Por padrão, os arquivos Xet também são deduplicados entre repositórios. Um arquivo Xet baixado por meio de hf_xet é armazenado uma única vez em <CACHE_DIR>/blobs/<prefix>/<xet_hash>, e a entrada blobs/<etag> do repositório é um link simbólico relativo para ele. Quando outro repositório precisa do mesmo arquivo, ele recebe um link simbólico em vez de um download: nenhum byte é transferido e nenhum espaço extra é utilizado. O layout do snapshot não muda. Um arquivo de marcador identifica o armazenamento, de modo que um diretório blobs que não foi criado por huggingface_hub nunca é alterado.

Cada arquivo compartilhado possui um manifesto <xet_hash>.refs que lista os blobs do repositório que o utilizam. O hf cache rm lê esse manifesto para verificar apenas os arquivos compartilhados afetados por uma exclusão, e o hf cache prune remove arquivos compartilhados que nenhum repositório em cache utiliza mais. O manifesto é apenas uma dica: cada entrada é verificada em relação ao sistema de arquivos, e um arquivo com metadados ausentes ou ilegíveis é mantido. A limpeza prioriza deixar dados recuperáveis em vez de quebrar uma entrada de cache válida.

Os tamanhos por repositório permanecem lógicos, de modo que um arquivo compartilhado é contabilizado para cada repositório que o utiliza. O size_on_disk de todo o cache é físico: cada arquivo compartilhado é contabilizado uma única vez, incluindo arquivos que nenhum repositório utiliza mais.

Clientes mais antigos (huggingface_hub, huggingface.js, hf-hub, llama.cpp e qualquer coisa que siga links simbólicos) continuam lendo e baixando normalmente, nas mesmas pastas do repositório. Duas limitações:

  • huggingface_hub<=1.31 deixa os arquivos compartilhados de um repositório excluído na store, onde hf cache ls os sinaliza e hf cache prune os remove. As ferramentas de exclusão de cache de outros clientes podem, em vez disso, excluir um arquivo compartilhado ainda usado por outros repositórios; os arquivos afetados são baixados novamente no próximo uso. Use uma versão atualizada do huggingface_hub para hf cache rm, hf cache prune e exclusão programática.
  • Os scanners de cache deles podem relatar o diretório de nível superior blobs como uma entrada desconhecida.

A store requer o layout de cache baseado em symlinks e é desativado por HF_HUB_DISABLE_XET=1. Qualquer falha ao compartilhar um arquivo, como um sistema de arquivos não suportado, um erro de permissão ou um diretório blobs pré-existente sem marcação, faz com que o sistema retorne silenciosamente para o armazenamento local regular do repositório. Defina HF_HUB_DISABLE_SHARED_BLOBS=1 para desativar completamente.

Fixar uma revisão (avançado)

Se você está integrando o Hub em uma biblioteca de ML, uma única chamada de snapshot_download() continua sendo a abordagem recomendada: ela resolve a revisão uma vez, baixa tudo em paralelo e faz o cache da lista de arquivos. O que segue é útil apenas para bibliotecas complexas que baixam e carregam muitos componentes separadamente (config, pesos, tokenizer, processor, adapters, …) e não podem usar uma única chamada.

Quando uma biblioteca baixa vários arquivos um por um, cada chamada precisa resolver revision="main" em um hash de commit novamente. Isso custa uma chamada HTTP por arquivo e, pior, duas chamadas feitas a poucos segundos de distância podem cair em dois commits diferentes se o repositório for atualizado no intervalo.

HfApi.resolve_revision() resolve a revisão uma única vez e retorna um ResolvedRevision:

>>> from huggingface_hub import resolve_revision
>>> revision = resolve_revision("openai-community/gpt2")
>>> revision
ResolvedRevision(initial=None, resolved='607a30d783dfa663caf39e06633721c8d4cfcd7e')

ResolvedRevision é uma subclasse de str, portanto, pode ser passada a qualquer método do huggingface_hub que aceite um argumento revision. Seu valor de string é o que o usuário solicitou inicialmente ("main" aqui, o que resulta em mensagens de erro legíveis), enquanto .resolved contém o hash do commit:

>>> revision == "main"
True
>>> revision.resolved
'607a30d783dfa663caf39e06633721c8d4cfcd7e'

Os auxiliares de download (hf_hub_download(), snapshot_download(), get_cached_repo_tree()) detectam um ResolvedRevision e usam o hash do commit diretamente. É garantido que todos os arquivos venham do mesmo commit e, uma vez que os arquivos estejam em cache, nenhuma chamada HTTP é necessária:

>>> from huggingface_hub import hf_hub_download
>>> config = hf_hub_download("openai-community/gpt2", "config.json", revision=revision)
>>> weights = hf_hub_download("openai-community/gpt2", "model.safetensors", revision=revision)

O mapeamento de revision -> commit hash também é gravado na pasta refs/ do cache (veja Refs). Isso significa que, se o Hub não puder ser acessado posteriormente (modo offline, erro de conexão, tempo limite, indisponibilidade do Hub), HfApi.resolve_revision() recorre de forma transparente ao valor em cache. Se nada estiver em cache, um RevisionResolutionError é lançado.

Um hash de commit só tem significado para o repositório em que foi resolvido, e os auxiliares de download o utilizam como está. Portanto, um ResolvedRevision deve ser passado apenas para o repositório para o qual foi resolvido. Se uma biblioteca também faz download de outro repositório (um modelo base, um adaptador, um componente que reside em seu próprio repositório, ...), ela precisa de uma revisão resolvida para esse repositório. Basta passar o ResolvedRevision de volta para HfApi.resolve_revision(): ele lembra a qual repositório pertence e resolve novamente a revisão inicialmente solicitada ("main" aqui) para o novo repositório.

>>> other_revision = resolve_revision("openai-community/gpt2-medium", revision=revision)  # resolves "main" again
>>> other_revision.resolved
'6dcaa7a952f72f9298047fd5137cd6e4f05f41da'
>>> config = hf_hub_download("openai-community/gpt2-medium", "config.json", revision=other_revision)

Cache do Xet

Para fornecer uploads mais eficientes, o hf_xet adiciona um diretório xet ao cache existente do huggingface_hub. Ele armazena shards (uma estrutura de dados que mapeia arquivos para chunks) e dados de staging usados para deduplicação e retomada de uploads. Para mais informações sobre o sistema de armazenamento Xet, veja esta seção.

hf_xet não usa mais um cache local de blocos para downloads. Definir HF_XET_CHUNK_CACHE_SIZE_BYTES não ativa um. Os arquivos baixados ainda são armazenados no cache baseado em arquivos.

O diretório xet, localizado por padrão em ~/.cache/huggingface/xet, pode ser configurado com HF_XET_CACHE. Ele tem a seguinte estrutura:

<CACHE_DIR>
├─ xet
│  ├─ environment_identifier
│  │  ├─ shard-cache
│  │  ├─ staging

O diretório environment_identifier é uma string codificada (pode aparecer na sua máquina como https___cas_serv-tGqkUaZf_CBPHQ6h). Isso é usado durante o desenvolvimento, permitindo que versões locais e de produção do cache coexistam simultaneamente. Também é usado ao baixar de repositórios que residem em diferentes regiões de armazenamento. Você pode ver múltiplas entradas assim no diretório xet, cada uma correspondendo a um ambiente diferente, mas sua estrutura interna é a mesma.

Os diretórios internos servem aos seguintes propósitos:

  • shard-cache contém shards em cache que são utilizados no caminho de upload.
  • staging é um espaço de trabalho projetado para suportar uploads retomáveis.

Estes estão documentados abaixo.

O cache de shards e os dados de staging são gerenciados pelo hf_xet como uma camada de otimização para uploads. Para gerenciar arquivos baixados, use as APIs de cache baseadas em arquivos do huggingface_hub.

shard-cache

Este cache é usado ao enviar conteúdo para o Hub. O diretório é plano, composto apenas por arquivos de shard, cada um usando um ID como nome do shard.

<CACHE_DIR>
├─ xet
│  ├─ environment_identifier
│  │  ├─ shard-cache
│  │  │  ├─ 1fe4ffd5cf0c3375f1ef9aec5016cf773ccc5ca294293d3f92d92771dacfc15d.mdb
│  │  │  ├─ 906ee184dc1cd0615164a89ed64e8147b3fdccd1163d80d794c66814b3b09992.mdb
│  │  │  ├─ ceeeb7ea4cf6c0a8d395a2cf9c08871211fbbd17b9b5dc1005811845307e6b8f.mdb
│  │  │  ├─ e8535155b1b11ebd894c908e91a1e14e3461dddd1392695ddc90ae54a548d8b2.mdb

O shard-cache contém shards que são:

  • Gerado localmente e enviado com sucesso para o CAS
  • Baixado do CAS como parte do algoritmo global de deduplicação

Shards fornecem um mapeamento entre arquivos e chunks. Durante os uploads, cada arquivo é dividido em chunks e o hash de cada chunk é salvo. Em seguida, cada shard no cache é consultado. Se um shard contiver um hash de chunk que está presente no arquivo local sendo enviado, esse chunk pode ser descartado, pois já está armazenado no CAS.

Todos os shards têm uma data de expiração de 3 a 4 semanas a partir do momento em que são baixados. Shards que estão expirados não são carregados durante o upload e são excluídos uma semana após a expiração.

staging

Quando um upload é interrompido antes que o novo conteúdo tenha sido commitado no repositório, será necessário retomar a transferência do arquivo. No entanto, é possível que alguns chunks tenham sido enviados com sucesso antes da interrupção.

Para que você não precise recomeçar do zero, o diretório staging atua como um espaço de trabalho durante os uploads, armazenando metadados dos blocos enviados com sucesso. O diretório staging tem a seguinte estrutura:

<CACHE_DIR>
├─ xet
│  ├─ environment_identifier
│  │  ├─ staging
│  │  │  ├─ shard-session
│  │  │  │  ├─ 906ee184dc1cd0615164a89ed64e8147b3fdccd1163d80d794c66814b3b09992.mdb
│  │  │  │  ├─ xorb-metadata
│  │  │  │  │  ├─ 1fe4ffd5cf0c3375f1ef9aec5016cf773ccc5ca294293d3f92d92771dacfc15d.mdb

À medida que os arquivos são processados e os chunks são enviados com sucesso, seus metadados são armazenados em xorb-metadata como um shard. Ao retomar uma sessão de upload, cada arquivo é processado novamente e os shards neste diretório são consultados. Qualquer conteúdo que tenha sido enviado com sucesso é ignorado, e qualquer novo conteúdo é enviado (e seus metadados são salvos).

Enquanto isso, shard-session armazena informações de arquivo e de chunks para os arquivos processados. Ao concluir um upload com sucesso, o conteúdo desses shards é movido para o shard-cache mais persistente.

Limites e Restrições

O shard-cache tem um limite suave de 16GB, configurável por meio da variável de ambiente HF_XET_SHARD_CACHE_SIZE_LIMIT. Não há uma API de alto nível para gerenciar esse cache.

O cache de shards e os dados de staging são usados para otimizar os uploads. Para interagir com os próprios ativos, recomenda-se o uso das APIs do sistema de cache do huggingface_hub.

Se você precisar recuperar o espaço utilizado pelo Xet ou precisar depurar possíveis problemas relacionados ao cache, basta remover completamente o cache do xet executando rm -rf ~/<cache_dir>/xet, onde <cache_dir> é a localização do cache do Hugging Face, tipicamente ~/.cache/huggingface

Exemplo de árvore de diretório de cache xet:

<CACHE_DIR>
├─ xet
│  ├─ environment_identifier
│  │  ├─ shard-cache
│  │  │  ├─ 1fe4ffd5cf0c3375f1ef9aec5016cf773ccc5ca294293d3f92d92771dacfc15d.mdb
│  │  │  ├─ 906ee184dc1cd0615164a89ed64e8147b3fdccd1163d80d794c66814b3b09992.mdb
│  │  │  ├─ ceeeb7ea4cf6c0a8d395a2cf9c08871211fbbd17b9b5dc1005811845307e6b8f.mdb
│  │  │  ├─ e8535155b1b11ebd894c908e91a1e14e3461dddd1392695ddc90ae54a548d8b2.mdb
│  │  ├─ staging
│  │  │  ├─ shard-session
│  │  │  │  ├─ 906ee184dc1cd0615164a89ed64e8147b3fdccd1163d80d794c66814b3b09992.mdb
│  │  │  │  ├─ xorb-metadata
│  │  │  │  │  ├─ 1fe4ffd5cf0c3375f1ef9aec5016cf773ccc5ca294293d3f92d92771dacfc15d.mdb

Para saber mais sobre o Xet Storage, consulte esta seção.

Cache de ativos

Além de fazer o cache de arquivos do Hub, as bibliotecas de nível inferior frequentemente precisam fazer o cache de outros arquivos relacionados ao HF, mas que não são tratados diretamente pelo huggingface_hub (exemplo: arquivo baixado do GitHub, dados pré-processados, logs, …). Para fazer o cache desses arquivos, chamados de assets, é possível usar cached_assets_path(). Esse pequeno helper gera caminhos no cache do HF de forma unificada, com base no nome da biblioteca que solicita e, opcionalmente, em um namespace e no nome de uma subpasta. O objetivo é permitir que cada biblioteca de nível inferior gerencie seus assets do seu próprio jeito (por exemplo, sem regras sobre a estrutura), desde que permaneça na pasta de assets correta. Essas bibliotecas podem, então, aproveitar as ferramentas do huggingface_hub para gerenciar o cache, em particular varrendo e excluindo partes dos assets por meio de um comando de CLI.

from huggingface_hub import cached_assets_path

assets_path = cached_assets_path(library_name="datasets", namespace="SQuAD", subfolder="download")
something_path = assets_path / "something.json" # Do anything you like in your assets folder !

cached_assets_path() é a maneira recomendada de armazenar ativos, mas não é obrigatória. Se a sua biblioteca já usa o próprio cache, sinta-se à vontade para usá-lo!

Assets na prática

Na prática, o cache de seus ativos deve se parecer com a seguinte árvore:

    assets/
    └── datasets/
    │   ├── SQuAD/
    │   │   ├── downloaded/
    │   │   ├── extracted/
    │   │   └── processed/
    │   ├── Helsinki-NLP--tatoeba_mt/
    │       ├── downloaded/
    │       ├── extracted/
    │       └── processed/
    └── transformers/
        ├── default/
        │   ├── something/
        ├── bert-base-cased/
        │   ├── default/
        │   └── training/
    hub/
    └── models--julien-c--EsperBERTo-small/
        ├── blobs/
        │   ├── (...)
        │   ├── (...)
        ├── refs/
        │   └── (...)
        └── [ 128]  snapshots/
            ├── 2439f60ef33a0d46d85da5001d52aeda5b00ce9f/
            │   ├── (...)
            └── bbc77c8132af1cc5cf678da3f1ddf2de43606d48/
                └── (...)

Gerencie seu cache baseado em arquivos

Inspecione seu cache

No momento, os arquivos em cache nunca são excluídos do seu diretório local: ao baixar uma nova revisão de um branch, os arquivos anteriores são mantidos caso você precise deles novamente. Portanto, pode ser útil inspecionar seu diretório de cache para saber quais repositórios e revisões estão ocupando mais espaço em disco. O huggingface_hub fornece helpers que você pode usar pela CLI hf ou pelo Python.

Inspecionar o cache pelo terminal

Execute hf cache ls para explorar o que está armazenado localmente. Por padrão, o comando agrega as informações por repositório:

➜ hf cache ls
ID                                   SIZE   LAST_ACCESSED LAST_MODIFIED REFS
------------------------------------ ------- ------------- ------------- -------------------
dataset/glue                         116.3K 4 days ago     4 days ago     2.4.0 main 1.17.0
dataset/google/fleurs                 64.9M 1 week ago     1 week ago     main refs/pr/1
model/Jean-Baptiste/camembert-ner    441.0M 2 weeks ago    16 hours ago   main
model/bert-base-cased                  1.9G 1 week ago     2 years ago
model/t5-base                          10.1K 3 months ago   3 months ago   main
model/t5-small                        970.7M 3 days ago     3 days ago     main refs/pr/1

Found 6 repo(s) for a total of 12 revision(s) and 3.4G on disk.

Adicione --revisions para listar todos os snapshots em cache e encadene filtros para focar no que importa. Os filtros compreendem tamanhos e durações em formato legível, então expressões como size>1GB ou accessed>30d funcionam imediatamente:

➜ hf cache ls --revisions --filter "size>1GB" --filter "accessed>30d"
ID                                   REVISION            SIZE   LAST_MODIFIED REFS
------------------------------------ ------------------ ------- ------------- -------------------
model/bert-base-cased                6d1d7a1a2a6cf4c2    1.9G  2 years ago
model/t5-small                       1c610f6b3f5e7d8a    1.1G  3 months ago  main

Found 2 repo(s) for a total of 2 revision(s) and 3.0G on disk.

Precisa de uma saída amigável para máquinas? Use --format json para obter objetos estruturados ou --format csv para planilhas. Alternativamente, --quiet imprime apenas identificadores (um por linha) para que você possa encaminhá-los para outras ferramentas. Use --sort para ordenar as entradas por accessed, modified, name ou size (adicione :asc ou :desc para controlar a ordem) e --limit para restringir os resultados às N primeiras entradas. Combine essas opções com --cache-dir quando precisar inspecionar um cache armazenado fora de HF_HOME.

Filtrar com ferramentas comuns de shell

Saída tabular significa que você pode continuar usando as ferramentas que já conhece. Por exemplo, o trecho abaixo encontra todas as revisões em cache relacionadas a t5-small:

➜ eval "hf cache ls --revisions" | grep "t5-small"
model/t5-small                       1c610f6b3f5e7d8a    1.1G  3 months ago  main
model/t5-small                       8f3ad1c90fed7a62    820.1M 2 weeks ago   refs/pr/1

Inspecionar cache a partir do Python

Para um uso mais avançado, utilize scan_cache_dir(), que é a utilidade em Python chamada pela ferramenta de CLI.

Você pode usá-lo para obter um relatório detalhado estruturado em torno de 4 dataclasses:

Aqui está um exemplo simples de uso. Consulte a referência para mais detalhes.

>>> from huggingface_hub import scan_cache_dir

>>> hf_cache_info = scan_cache_dir()
HFCacheInfo(
    size_on_disk=3398085269,
    repos=frozenset({
        CachedRepoInfo(
            repo_id='t5-small',
            repo_type='model',
            repo_path=PosixPath(...),
            size_on_disk=970726914,
            nb_files=11,
            last_accessed=1662971707.3567169,
            last_modified=1662971107.3567169,
            revisions=frozenset({
                CachedRevisionInfo(
                    commit_hash='d78aea13fa7ecd06c29e3e46195d6341255065d5',
                    size_on_disk=970726339,
                    snapshot_path=PosixPath(...),
                    # No `last_accessed` as blobs are shared among revisions
                    last_modified=1662971107.3567169,
                    files=frozenset({
                        CachedFileInfo(
                            file_name='config.json',
                            size_on_disk=1197
                            file_path=PosixPath(...),
                            blob_path=PosixPath(...),
                            blob_last_accessed=1662971707.3567169,
                            blob_last_modified=1662971107.3567169,
                        ),
                        CachedFileInfo(...),
                        ...
                    }),
                ),
                CachedRevisionInfo(...),
                ...
            }),
        ),
        CachedRepoInfo(...),
        ...
    }),
    warnings=[
        CorruptedCacheException("Snapshots dir doesn't exist in cached repo: ..."),
        CorruptedCacheException(...),
        ...
    ],
)

Verifique seu cache

huggingface_hub pode verificar se os seus arquivos em cache correspondem aos checksums no Hub. Use o CLI hf cache verify para validar a consistência dos arquivos de uma revisão específica de um repositório específico:

>>> hf cache verify meta-llama/Llama-3.2-1B-Instruct
✅ Verified 13 file(s) for 'meta-llama/Llama-3.2-1B-Instruct' (model) in ~/.cache/huggingface/hub/models--meta-llama--Llama-3.2-1B-Instruct/snapshots/9213176726f574b556790deb65791e0c5aa438b6
  All checksums match.

Verifique uma revisão específica em cache:

>>> hf cache verify meta-llama/Llama-3.1-8B-Instruct --revision 0e9e39f249a16976918f6564b8830bc894c89659

Consulte a referência da CLI hf cache verify para mais detalhes sobre o uso e uma lista completa de opções.

Limpe o cache

Fazer o scan do cache é interessante, mas o que você geralmente quer fazer em seguida é excluir algumas partes para liberar espaço no seu disco. Isso é possível usando os comandos de CLI hf cache rm e hf cache prune. Também é possível usar programaticamente os helpers delete_revisions() e delete_files() do objeto HFCacheInfo retornado ao fazer o scan do cache.

Estratégia de exclusão

Para excluir parte do cache, você precisa passar uma lista de revisões a serem excluídas. A ferramenta define uma estratégia para liberar espaço com base nessa lista. Ela retorna um objeto DeleteCacheStrategy que descreve quais arquivos e pastas serão excluídos. O DeleteCacheStrategy permite informar quanto espaço é esperado que seja liberado. Uma vez que você concorde com a exclusão, é necessário executá-la para que a exclusão tenha efeito. Para evitar discrepâncias, não é possível editar manualmente um objeto de estratégia.

A estratégia para excluir revisões é a seguinte:

  • a pasta snapshot contendo os links simbólicos de revisão é excluída.
  • Os arquivos blobs que são alvo apenas de revisões a serem excluídas também são excluídos.
  • se uma revisão estiver vinculada a 1 ou mais refs, as referências serão excluídas.
  • se todas as revisões de um repositório forem excluídas, o repositório em cache inteiro será excluído.

A exclusão de arquivos individuais com delete_files() segue a mesma lógica: as entradas do snapshot são removidas e seus blobs são excluídos apenas se nenhum outro arquivo em cache os referenciar. As refs e as pastas de snapshot são mantidas.

Os hashes de revisão são únicos em todos os repositórios. Portanto, hf cache rm aceita um identificador de repositório (por exemplo, model/bert-base-uncased) ou um hash de revisão isolado; ao passar um hash, não é necessário especificar o repositório separadamente.

Se uma revisão não for encontrada no cache, ela será ignorada silenciosamente. Além disso, se um arquivo ou pasta não puder ser encontrado ao tentar excluí-lo, um aviso será registrado, mas nenhum erro será lançado. A exclusão continua para os outros caminhos contidos no objeto DeleteCacheStrategy.

Limpar o cache pelo terminal

Use hf cache rm para excluir permanentemente repositórios ou revisões do seu cache. Passe um ou mais identificadores de repositório (por exemplo, model/bert-base-uncased) ou hashes de revisão:

➜ hf cache rm model/bert-base-cased
About to delete 1 repo(s) totalling 1.9G.
  - model/bert-base-cased (entire repo)
Proceed with deletion? [y/N]: y
Deleted 1 repo(s) and 1 revision(s); freed 1.9G.

Você também pode usar hf cache rm em combinação com hf cache ls --quiet para excluir em lote as entradas identificadas por um filtro:

>>> hf cache rm $(hf cache ls --filter "accessed>1y" -q) -y
About to delete 2 repo(s) totalling 5.31G.
  - model/meta-llama/Llama-3.2-1B-Instruct (entire repo)
  - model/hexgrad/Kokoro-82M (entire repo)
Deleted 2 repo(s) and 2 revision(s); freed 5.31G.

Misture repositórios e revisões na mesma chamada. Adicione --dry-run para visualizar o impacto, ou --yes para pular o prompt de confirmação ao usar scripts:

➜ hf cache rm model/t5-small 8f3ad1c --dry-run
About to delete 1 repo(s) and 1 revision(s) totalling 1.1G.
  - model/t5-small:
      8f3ad1c [main] 1.1G
Dry run: no files were deleted.

Para remover um arquivo individual em vez de um repositório inteiro, por exemplo, uma quantização GGUF, passar um URI de arquivo hf://. O arquivo é removido de todas as revisões em cache do repositório, e seu blob é excluído apenas se nenhum outro arquivo em cache ainda o referenciar. A revisão permanece utilizável, e um arquivo excluído é baixado novamente na próxima vez que for necessário. Os caminhos devem corresponder exatamente: pastas e padrões glob não são suportados.

➜ hf cache rm hf://models/unsloth/gemma-3-27b-it-GGUF/gemma-3-27b-it-Q4_K_M.gguf --dry-run
About to delete 1 file(s) totalling 16.5G.
  - model/unsloth/gemma-3-27b-it-GGUF@3f4b5c1d2e6a7b8c9d0e1f2a3b4c5d6e7f8a9b0c/gemma-3-27b-it-Q4_K_M.gguf
Dry run: no files were deleted.

Ao trabalhar fora do local de cache padrão, combine o comando com --cache-dir PATH.

Para limpar o lixo do cache em lote, execute hf cache prune. Ele remove automaticamente revisões que não são mais referenciadas por um branch ou tag, arquivos .incomplete remanescentes de downloads interrompidos e blobs compartilhados que nenhum repositório em cache referencia mais:

➜ hf cache prune
About to delete 3 unreferenced revision(s) and 2 incomplete download(s) (2.4G total).
  - model/t5-small:
      1c610f6b [refs/pr/1] 820.1M
      d4ec9b72 [(detached)] 640.5M
  - dataset/google/fleurs:
      2b91c8dd [(detached)] 937.6M
Proceed? [y/N]: y
Deleted 3 unreferenced revision(s) and 2 incomplete download(s); freed 2.4G.

Arquivos .incomplete são blobs parciais deixados para trás quando um download é interrompido. Eles não são rastreados pela varredura baseada em revisão, portanto, hf cache ls apenas os sinaliza com uma dica (Found X incomplete download(s) ...), enquanto hf cache prune é o comando que efetivamente os remove. hf cache rm nunca os toca, exceto quando exclui um repositório inteiro.

Ambos os comandos suportam --dry-run, --yes e --cache-dir, permitindo que você visualize, automatize e direcione diretórios de cache alternativos conforme necessário.

Limpar o cache do Python

Para mais flexibilidade, você também pode usar o método delete_revisions() programaticamente. Aqui está um exemplo simples. Consulte a referência para mais detalhes.

>>> from huggingface_hub import scan_cache_dir

>>> delete_strategy = scan_cache_dir().delete_revisions(
...     "81fd1d6e7847c99f5862c9fb81387956d99ec7aa"
...     "e2983b237dccf3ab4937c97fa717319a9ca1a96d",
...     "6c0e6080953db56375760c0471a8c5f2929baf11",
... )
>>> print("Will free " + delete_strategy.expected_freed_size_str)
Will free 8.6G

>>> delete_strategy.execute()
Update on GitHub