# 🤗 API de Hugging Face Hub

Utilidades oficiales para usar la API de Hugging Face Hub.

## Instalación

```console
pnpm add @huggingface/hub

npm add @huggingface/hub

yarn add @huggingface/hub
```

### Deno

```ts
// esm.sh
import { uploadFiles, listModels } from "https://esm.sh/@huggingface/hub"
// or npm:
import { uploadFiles, listModels } from "npm:@huggingface/hub"
```

## Uso

Para algunas de las llamadas, necesitas crear una cuenta y generar un [token de acceso](https://huggingface.co/settings/tokens).

Aprende a encontrar modelos gratuitos usando el paquete hub en este [tutorial interactivo](https://scrimba.com/scrim/c7BbVPcd?pl=pkVnrP7uP).

```ts
import * as hub from "@huggingface/hub";
import type { RepoDesignation } from "@huggingface/hub";

const repo: RepoDesignation = { type: "model", name: "myname/some-model" };

const {name: username} = await hub.whoAmI({accessToken: "hf_..."});

for await (const model of hub.listModels({search: {owner: username}, accessToken: "hf_..."})) {
  console.log("My model:", model);
}

const specificModel = await hub.modelInfo({name: "openai-community/gpt2"});
await hub.checkRepoAccess({repo, accessToken: "hf_..."});

await hub.createRepo({ repo, accessToken: "hf_...", license: "mit" });

await hub.uploadFiles({
  repo,
  accessToken: "hf_...",
  files: [
    // path + blob content
    {
      path: "file.txt",
      content: new Blob(["Hello World"]),
    },
    // Local file URL
    pathToFileURL("./pytorch-model.bin"),
    // Local folder URL
    pathToFileURL("./models"),
    // Web URL
    new URL("https://huggingface.co/xlm-roberta-base/resolve/main/tokenizer.json"),
    // Path + Web URL
    {
      path: "myfile.bin",
      content: new URL("https://huggingface.co/bert-base-uncased/resolve/main/pytorch_model.bin")
    }
    // Can also work with native File in browsers
  ],
});

// or

for await (const progressEvent of await hub.uploadFilesWithProgress({
  repo,
  accessToken: "hf_...",
  files: [
    ...
  ],
})) {
  console.log(progressEvent);
}

// Edit a file in place, without downloading/uploading its unchanged data
const file = await hub.downloadFile({ repo, path: "myfile.bin", accessToken: "hf_..." });
await hub.uploadFile({
  repo,
  accessToken: "hf_...",
  file: {
    path: "myfile.bin",
    originalContent: file,
    edits: [{
      // Replace bytes [0, 4)
      start: 0,
      end: 4,
      content: new Blob(["new prefix"])
    }, {
      // Append at the end
      start: file.size,
      end: file.size,
      content: new Blob(["suffix"])
    }]
  }
});

await hub.deleteFile({repo, accessToken: "hf_...", path: "myfile.bin"});

await (await hub.downloadFile({ repo, path: "README.md" })).text();

for await (const fileInfo of hub.listFiles({repo})) {
  console.log(fileInfo);
}

await hub.deleteRepo({ repo, accessToken: "hf_..." });
```

### Buckets

Los [Storage Buckets](https://huggingface.co/docs/hub/storage-buckets) son almacenamiento mutable y sin versiones en el Hub. Utilice el prefijo `buckets/` (o `{ type: "bucket", name }`) con las mismas funciones:

```ts
const bucket = "buckets/myname/my-bucket";

await hub.createRepo({ repo: bucket, accessToken: "hf_..." });

await hub.uploadFiles({ repo: bucket, accessToken: "hf_...", files: [pathToFileURL("./checkpoints")] });

for await (const fileInfo of hub.listFiles({ repo: bucket, recursive: true, accessToken: "hf_..." })) {
  console.log(fileInfo.path, fileInfo.uploadedAt);
}

// Copy files from a model or dataset repo into a bucket server-side, without downloading them
await hub.copyFolder({
  source: { repo: { type: "dataset", name: "myname/my-dataset" }, path: "data" },
  destination: { repo: bucket, path: "data" },
  accessToken: "hf_...",
});
```

## Uso de la CLI

Puedes usar `@huggingface/hub` en modo CLI para subir y descargar archivos y carpetas a/desde tu repositorio.

```console
npx @huggingface/hub upload coyotte508/test-model .
npx @huggingface/hub upload datasets/coyotte508/test-dataset .
# Same thing
npx @huggingface/hub upload --repo-type dataset coyotte508/test-dataset .
# Upload new data with 0 history in a separate branch
npx @huggingface/hub branch create coyotte508/test-model release --empty
npx @huggingface/hub upload coyotte508/test-model . --revision release

# Download files to the current directory (or --local-dir)
npx @huggingface/hub download coyotte508/test-model config.json
npx @huggingface/hub download coyotte508/test-model config.json README.md --local-dir ./test-model
# Download an entire repo, optionally filtered with --include / --exclude
npx @huggingface/hub download coyotte508/test-model --local-dir ./test-model
npx @huggingface/hub download --repo-type dataset coyotte508/test-dataset --include "*.json"

npx @huggingface/hub --help
npx @huggingface/hub upload --help
npx @huggingface/hub download --help
```

También puedes instalarlo globalmente con `npm install -g @huggingface/hub`. Después puedes hacer lo siguiente:

```console
hfjs upload coyotte508/test-model .

hfjs branch create --repo-type dataset coyotte508/test-dataset release --empty
hfjs upload --repo-type dataset coyotte508/test-dataset . --revision release

hfjs download coyotte508/test-model config.json
hfjs download coyotte508/test-model --local-dir ./test-model

hfjs --help
hfjs  upload --help

hfjs help jobs
hfjs download --help
```

## Inicio de sesión con OAuth

Es posible iniciar sesión usando OAuth (["Iniciar sesión con HF"](https://huggingface.co/docs/hub/oauth)).

Esto te permitirá obtener un token de acceso para usar algunas de las API, dependiendo de los scopes configurados dentro del Space o de la aplicación OAuth.

```ts
import { oauthLoginUrl, oauthHandleRedirectIfPresent } from "@huggingface/hub";

const oauthResult = await oauthHandleRedirectIfPresent();

if (!oauthResult) {
  // If the user is not logged in, redirect to the login page
  window.location.href = await oauthLoginUrl();
}

// You can use oauthResult.accessToken, oauthResult.accessTokenExpiresAt and oauthResult.userInfo
console.log(oauthResult);
```

Prueba la demo: https://huggingface.co/spaces/huggingfacejs/client-side-oauth

## Caché de Hugging Face

El paquete `@huggingface/hub` proporciona capacidades básicas para escanear el directorio de caché. Obtenga más información sobre [Manage huggingface_hub cache-system](https://huggingface.co/docs/huggingface_hub/en/guides/manage-cache).

### `scanCacheDir`

Puedes obtener la lista de repositorios en caché usando la función `scanCacheDir`.

```ts
import { scanCacheDir } from "@huggingface/hub";

const result = await scanCacheDir();

console.log(result);
```
Nota: esto no funciona en el navegador

### `downloadFileToCacheDir`

Puede cachear un archivo de un repositorio usando la función `downloadFileToCacheDir`.

```ts
import { downloadFileToCacheDir } from "@huggingface/hub";

const file = await downloadFileToCacheDir({
  repo: 'foo/bar',
  path: 'README.md'
});

console.log(file);
```
Nota: esto no funciona en el navegador

### `snapshotDownload`

Puedes descargar un repositorio completo en una revisión determinada en el directorio de caché usando la función `snapshotDownload`.

```ts
import { snapshotDownload } from "@huggingface/hub";

const directory = await snapshotDownload({
  repo: 'foo/bar',
});

console.log(directory);
```
El código utiliza internamente la función `downloadFileToCacheDir`.

Nota: esto no funciona en el navegador

## Consideraciones de rendimiento

Al subir archivos grandes, es posible que desees ejecutar las llamadas `commit` dentro de un worker para descargar las computaciones de sha256.

Los recursos remotos y los archivos locales deben pasarse como `URL` siempre que sea posible, para que se puedan cargar de forma diferida en fragmentos y reducir el uso de RAM. Pasar un `File` dentro del contexto del navegador es correcto, ya que se comporta de forma nativa como un `Blob`.

Por debajo, `@huggingface/hub` utiliza una implementación de blob perezosa para cargar el archivo.

Para editar un archivo existente, prefiere una operación de commit `edit` con el blob devuelto por `downloadFile` como `originalContent`: solo se descargan, se redividen en fragmentos y se calcula el hash de las regiones editadas. Para agregados repetidos al mismo archivo, pase una `rangeEditCache: new Map()` compartida a las llamadas de `commit` para omitir también los intercambios de metadatos de almacenamiento.

## Dependencias

- `@huggingface/tasks` : Solo tipado

