Documentation menu

Pulling models from Hugging Face

Download Hugging Face models into your PHP project from the command line or from PHP, with only the files the local runners can read.

Runners only work with models you pulled into your project first. Public models need no API key; private and gated models use the key saved by setup (see Hugging Face API key).

From the command line#

Terminal
vendor/bin/loves-ai pull openai-community/gpt2 [--revision=main] [--token=hf_...] [--all] [--log-file=PATH] [--debug]
Output
☕ Pulling openai-community/gpt2… Big downloads take a moment — perfect time for a cup of tea and some cookies 🍪
If you wish to see all logs, re-run the command with the "--debug" option.
🎉 Pulled openai-community/gpt2 into /var/www/my-app/.local/models/openai-community/gpt2
   Skipped 3 files (450.0 MB) the runners cannot read: other frameworks or training leftovers.

pull downloads one model at a time into .local/models/<model id>. The puller's own output is hidden unless --debug is given.

Option Meaning
--revision=REVISION Branch, tag or commit to pull (default: main)
--token=hf_... Hugging Face API key for private and gated models; it is saved for next time
--all Download every file in the repository, skipping nothing
--log-file=PATH Append each run to this file, with a timestamp, the puller's output and the outcome
--debug Show the puller's output while downloading

Output is colored on terminals; set NO_COLOR=1 to disable colors. Exit codes: 0 success, 1 pull failed, 2 invalid usage.

Only the files the runners can read#

Hugging Face repositories often publish the same weights several times, for PyTorch, TensorFlow, Flax and ONNX. The runners read PyTorch only, so pull leaves the rest out:

Model Repository Pulled
openai/whisper-tiny0.61 GB0.16 GB
SfinOe/stable-diffusion-v1.510.96 GB5.48 GB
facebook/mms-tts-eng0.29 GB0.15 GB
nlpconnect/vit-gpt2-image-captioning0.98 GB0.98 GB

Skipped are weights for other frameworks (.h5, .msgpack, .onnx, .gguf, .ckpt), single-file copies of a diffusers pipeline, alternative versions such as fp16 and non_ema, training leftovers (optimizer.pt, trainer_state.json, checkpoint-*) and sample media.

A .bin file is skipped only when the same repository also publishes it as .safetensors, so models that ship .bin alone, like the last row above, are pulled untouched. Pass --all if a model ever needs a file these rules leave out.

Gated and private models#

When Hugging Face refuses a model, pull explains why and what to do:

Output
Error: meta-llama/Llama-3.2-1B is not available: it is a gated model, which needs a Hugging Face API key.
Re-run with your key: vendor/bin/loves-ai pull meta-llama/Llama-3.2-1B --token=<your Hugging Face API key>

A gated model also needs its terms accepted on its Hugging Face page, with the account the key belongs to.

From PHP#

PHP
use PhpLovesAi\Process\ModelPuller;

$paths = (new ModelPuller())->pull(
    ['openai-community/gpt2', 'distilbert/distilbert-base-uncased'],
    onProgress: fn (string $chunk) => fwrite(STDERR, $chunk),
    // allFiles: true,  // download every file, as `pull --all` does
    onSkipped: fn (string $model, int $files, int $bytes) => fwrite(STDERR, "{$model}: skipped {$files} files\n"),
);
// ['openai-community/gpt2' => '/var/www/my-app/.local/models/openai-community/gpt2', ...]

To save a key from PHP, use (new PhpLovesAi\HuggingFace\Credentials())->saveApiKey('hf_...').

Errors#

Failures throw exceptions implementing PhpLovesAi\Exception\PhpLovesAiException:

  • ModelAccessDeniedException when Hugging Face refuses a model, with $model, $reason (gated or not_found) and $apiKeyUsed.
  • PullFailedException for any other failure.

Both list the models pulled before the failure in $pulled.

Configuration#

Defaults come from config/pull.php:

Key Default Overridden by
revisionmain--revision
log_filenull (output discarded)--log-file