Documentation menu

Getting started

Install php-loves-ai/multimodal-ai-runner with Composer, download the runners and generate your first AI image from PHP in minutes, without Python.

php-loves-ai/multimodal-ai-runner runs small Hugging Face models on your own machine, straight from PHP. It works in Laravel, Symfony or plain PHP, and it needs no Python installation.

Quick start#

Four commands take you from an empty project to your first AI-generated image:

Terminal
composer require php-loves-ai/multimodal-ai-runner
vendor/bin/loves-ai setup text-to-image
vendor/bin/loves-ai pull stabilityai/sd-turbo
vendor/bin/loves-ai text-to-image stabilityai/sd-turbo "a cozy cat by the fireplace" --steps=1 --guidance=0 --output=cat.png

The same image, generated from PHP:

PHP
use PhpLovesAi\Runner\TextToImage;

$image = (new TextToImage())->generate(
    model: 'stabilityai/sd-turbo',
    prompt: 'a cozy cat by the fireplace',
    outputPath: storage_path('app/cat.png'),
    steps: 1,
    guidanceScale: 0.0,
);

How it works#

The Composer package is tiny and contains only PHP code. The heavy parts live outside of it:

  1. The puller is a prebuilt binary that downloads models from Hugging Face and saves them in your project.
  2. Runners are prebuilt binaries, one per task. A runner loads a model you pulled and runs it. One runner serves many models of its task.
  3. vendor/bin/loves-ai setup downloads the binaries that match your operating system from the GitHub release of your package version.
  4. You choose which models to pull. Model weights are never shipped through Composer.
  5. The PHP classes call the binaries through Symfony Process and give you a native, typed API.

Requirements#

  • PHP 8.2 or newer
  • proc_open enabled, to run the binaries
  • allow_url_fopen and the openssl extension, so setup can download the binaries
  • tar on the PATH (built into macOS, Linux and Windows 10+)

Supported platforms: macOS arm64, Linux x86_64, Linux arm64 and Windows x86_64.

Installation#

Install the package, then download the puller. setup also asks once for an optional Hugging Face API key.

Terminal
composer require php-loves-ai/multimodal-ai-runner
vendor/bin/loves-ai setup
Output
๐Ÿงฐ Setting up php-loves-ai (v6.0.0) for darwin-arm64
๐Ÿ”‘ Hugging Face API key (optional)
   Public models, like stabilityai/sd-turbo, are pulled without a key. Private and gated models need one:
   create it at https://huggingface.co/settings/tokens
   Paste your key (hidden), or press Enter to use public models only:
โœ… Saved your Hugging Face API key to /var/www/my-app/.local/huggingface/credentials.json
โœ… The puller is installed at /var/www/my-app/.local/runners/puller-darwin-arm64
๐ŸŽ‰ All set! Happy hacking ๐Ÿช

Installing runners#

Each task has its own runner of a few hundred MB. Install only the ones you use:

Terminal
vendor/bin/loves-ai setup text-to-image    # generate images from a prompt
vendor/bin/loves-ai setup text-to-text     # generate text with language models
vendor/bin/loves-ai setup image-to-text    # describe images
vendor/bin/loves-ai setup speech-to-text   # transcribe speech
vendor/bin/loves-ai setup text-to-speech   # read text aloud
vendor/bin/loves-ai setup image-to-image   # upscale and redraw images
vendor/bin/loves-ai setup text-to-video    # generate videos
vendor/bin/loves-ai setup image-to-video   # animate images

After upgrading the package, run vendor/bin/loves-ai setup --force, plus setup <task> --force for every runner you use, to get the matching binaries. setup --debug shows the URLs and paths used.

Commands#

Everything runs through one command, vendor/bin/loves-ai. Running it without arguments lists the tasks and marks the runners that are installed:

Output
๐Ÿงฐ php-loves-ai v6.0.0 โ€” run small AI models locally, without installing Python

Usage: vendor/bin/loves-ai <command> [arguments] [options]

     setup           Download the runner binaries for this computer
     pull            Pull a model from the Hugging Face Hub

Tasks (โœ… = runner installed, run `setup <task>` for the others):
  โœ… text-to-image   Generate an image from a text prompt
     image-to-image  Enlarge an image, or redraw it following a prompt
     text-to-video   Generate a video from a text prompt
     image-to-video  Animate an image into a video
  โœ… text-to-text    Generate text: answer a prompt or continue it
     image-to-text   Describe an image, or answer a question about it
     speech-to-text  Transcribe speech in an audio or video file
     text-to-speech  Read text aloud into an audio file

Run vendor/bin/loves-ai <command> --help for a command's arguments and options, and vendor/bin/loves-ai --version for the installed version.

Hugging Face API key#

A key is optional. Public models are pulled without one; private and gated models need it. Create one at huggingface.co/settings/tokens.

setup asks for the key once and saves it in .local/huggingface/credentials.json, readable only by its owner. To save or replace it later, run:

Terminal
vendor/bin/loves-ai setup --token=hf_...

When there is no terminal to ask in (Docker builds, CI, deploy scripts), setup skips the question, so pass --token there if you need a key. The key is never read from environment variables, so every process running the project uses the same one.

Where models and runners live#

Everything is stored inside your project, next to vendor/, in one fixed place:

.local/
<project root>/.local/
โ”œโ”€โ”€ models/        models pulled by `vendor/bin/loves-ai pull`, as models/<model id>
โ”œโ”€โ”€ runners/       binaries installed by `vendor/bin/loves-ai setup`
โ””โ”€โ”€ huggingface/   credentials.json with your Hugging Face API key

These paths depend only on the project directory, never on the user, HOME or environment variables. The CLI, php-fpm, queue workers and other containers sharing the project directory all find the same models and runners, and no code or config ever needs a path.

  • On a server or in Docker, run setup and pull once in the project. The web server's user needs read and execute access to .local.
  • setup and pull add a .gitignore to .local, so its hundreds of MB and your API key are never committed.
  • Add .local/ to .dockerignore if you build images from the project directory.

Next steps#

Pull a model, then pick the task you need: