Search by

syncfly / transformers-torch-php

sync-fly

Full support for Transformers and PyTorch in PHP. Run locally any of the 1,000,000+ AI models from the Hugging Face — and train or fine-tune your own

Package info

github.com/SyncFly/transformers-torch-php

pkg:composer/syncfly/transformers-torch-php

Statistics

Installs: 1

Dependents: 0

Suggesters: 0

Stars: 7

Open Issues: 0

0.9.0 2026-08-28 17:50 UTC

This package is auto-updated.

Last update: 2026-09-02 08:46:15 UTC


README

🐘 Full support for Transformers and PyTorch in PHP. Run any of the 1,000,000+ AI models from the Hugging Face Hub locally — and train or fine-tune your own 🔥

This is a kit for PHP developers who want to use or train AI models in their projects. The package turns your PHP project into a complete ML environment: it bundles syncfly/python-in-php with a set of ML packages like transformers, torch, accelerate, bitsandbytes, timm, librosa, safetensors.

This is the most comprehensive and mature ML solution for PHP 🏆

A single composer require gives you a working AI stack — no Python knowledge, no manual setup, thanks to syncfly/python-in-php. See syncfly/python-in-php for custom Python packages and advanced usage.

<?php
require_once __DIR__ . '/vendor/autoload.php';

use py\transformers;

$generator = transformers::pipeline('text-generation', model: 'Qwen/Qwen2.5-1.5B-Instruct');

$messages = [['role' => 'user', 'content' => 'Why is PHP great? Answer in one short sentence.']];
$output = $generator($messages, max_new_tokens: 100);

echo end($output[0]['generated_text'])['content'];
// Outputs: "PHP is a versatile and widely-used programming language known for its ease of use, large community, and extensive library support."

Note: The model is downloaded on first run, so you’ll need to wait a little while.

Why this package

One-command installcomposer require sets up PyTorch, Transformers, and everything else automatically. No manual setup required.

Automatic GPU backend selectionsyncfly/python-in-php detects your hardware and picks the right PyTorch build:

  • CUDA for NVIDIA
  • ROCm for AMD
  • Metal for Apple Silicon
  • CPU backend when no GPU is present

Inference and training — you can fine-tune models directly from PHP. Full torch API support: tensors, autograd, nn modules, optimizers.

Full control with PHP code — not only the simple pipeline() method is supported, but all available classes and methods. syncfly/python-in-php exposes the AI frameworks as regular PHP classes, methods, properties, and arguments. You can take a Python example from any model card and translate it to PHP line by line — for example, obj.attr becomes $obj->attr.

use py\torch;
use py\transformers\AutoTokenizer;
use py\transformers\AutoModelForCausalLM;

$model_name = 'Qwen/Qwen3-1.7B';

$tokenizer = AutoTokenizer::from_pretrained($model_name);
$model = AutoModelForCausalLM::from_pretrained(
    $model_name,
    dtype: torch::$bfloat16,
    device_map: 'auto'
);

$messages = [['role' => 'user', 'content' => 'Which is the most popular PHP framework? Give a short answer.']];

// BatchEncoding is a dict subclass, so it arrives as a PHP array of tensors
$inputs = $tokenizer->apply_chat_template(
    $messages,
    add_generation_prompt: true,
    return_tensors: 'pt',
    enable_thinking: false
);

$outputs = $model->generate(
    input_ids: $inputs['input_ids']->to($model->device),
    attention_mask: $inputs['attention_mask']->to($model->device),
    max_new_tokens: 1024
);

$input_len = $inputs['input_ids']->shape[1];
$generated = array_slice($outputs[0]->tolist(), $input_len);
echo $tokenizer->decode($generated, skip_special_tokens: true);

See usage examples for other tasks below.

Native IDE autocompletionsyncfly/python-in-php generates PHPDoc for every installed Python package, so your IDE completes transformers, torch and friends like regular PHP code, with all available classes, methods, properties, and arguments.

System requirements

Requirement Version
PHP ≥ 8.2
OS Linux, macOS, Windows
Architecture x86_64, arm64

Python is not required — the environment is installed automatically into vendor/bin/python-in-php/ on first composer install.

Installation

composer require syncfly/transformers-torch-php

Answer yes when Composer asks to activate the syncfly/python-in-php plugin. This will automatically download dependencies, create a virtual Python environment in vendor/bin/python-in-php/, install the ML packages, and generate PHPDoc stubs in vendor/syncfly/python-in-php/py/ for IDE completion.

⭐️ Please star this repository and syncfly/python-in-php to show that there is demand for them, so you can be sure the packages will continue to be maintained.

Popular models

Any Hugging Face model with transformers support works — pass its name to pipeline() or from_pretrained(). A few proven starting points, grouped by what your hardware can handle.

Chat / text generation — the models people actually run day to day:

Note: Some models (Gemma, Llama, Mistral) are gated. You need to accept the license on their Hugging Face pages and pass token: 'hf_…' to from_pretrained()/pipeline().

Size Model Params VRAM (bf16) Good for
Small Qwen/Qwen3-0.6B 0.6B ~1.5 GB Runs fast on CPU; drafting, classification
Small meta-llama/Llama-3.2-1B-Instruct 1B ~2.5 GB Lightweight chat, on-device
Small google/gemma-3-1b-it 1B ~2.5 GB Lightweight chat
Medium google/gemma-3-4b-it 4B ~9 GB Chat + vision (multimodal)
Medium Qwen/Qwen2.5-7B-Instruct 7B ~15 GB Strong all-round chat
Medium meta-llama/Llama-3.1-8B-Instruct 8B ~17 GB The workhorse — fits on a 24 GB GPU
Medium deepseek-ai/DeepSeek-R1-Distill-Qwen-7B 7B ~15 GB Reasoning (chain-of-thought)
Medium microsoft/phi-4 14B ~29 GB Math & reasoning, punches above its weight
Large google/gemma-3-27b-it 27B ~55 GB Multimodal, near-frontier quality
Large Qwen/Qwen3-32B 32B ~65 GB Reasoning, agentic use
Large mistralai/Mixtral-8x7B-Instruct-v0.1 47B MoE ~90 GB Mixture-of-experts, ~13B active
Large meta-llama/Llama-3.3-70B-Instruct 70B ~140 GB Frontier-class open weights

The "Large" models fit on a single consumer GPU only when quantized (4-bit ≈ ⅓ the VRAM — see below) or split across GPUs/CPU with device_map: 'auto'.

Other tasks — small, task-specific models that run comfortably on CPU:

Model Task Params VRAM (bf16)
google/flan-t5-base Translation, summarization 250M ~1 GB
distilbert/distilbert-base-uncased-finetuned-sst-2-english Sentiment analysis 67M ~0.3 GB
dslim/bert-base-NER Named-entity recognition 108M ~0.5 GB
deepset/roberta-base-squad2 Question answering 124M ~0.5 GB
sentence-transformers/all-MiniLM-L6-v2 Embeddings (search / RAG) 22M ~0.1 GB
openai/whisper-large-v3-turbo Speech recognition 809M ~2 GB
google/vit-base-patch16-224 Image classification 86M ~0.4 GB

How much VRAM do I need?

Rule of thumb: parameters × bytes per parameter, plus ~20% overhead for activations and the KV cache. bf16/fp16 uses 2 bytes per parameter, float32 uses 4, quantized models less:

Model size bf16 / fp16 8-bit 4-bit
1B ~2.5 GB ~1.5 GB ~1 GB
3–4B ~8–10 GB ~4–5 GB ~3 GB
7–8B ~15–18 GB ~8–9 GB ~5–6 GB
13B ~28 GB ~14 GB ~8 GB
70B ~140 GB ~70 GB ~40 GB

If the model doesn't fit:

  • Quantizebitsandbytes is bundled; pass quantization_config: new BitsAndBytesConfig(load_in_4bit: true) to from_pretrained().
  • Offloaddevice_map: 'auto' (via the bundled accelerate) automatically spills layers that don't fit in VRAM to CPU RAM.
  • CPU-only works too — every model runs without a GPU, just slower; small models (< 1B) are perfectly usable on CPU.

Usage examples for different tasks

All examples are covered by the test suite in tests/.

Text classification / sentiment analysis

use py\transformers;

$classifier = transformers::pipeline(
    'text-classification',
    model: 'distilbert/distilbert-base-uncased-finetuned-sst-2-english'
);

$result = $classifier('This library is amazing!');
echo $result[0]['label'];           // POSITIVE
echo $result[0]['score'];           // 0.9998

// Batching works out of the box
$results = $classifier(['I love PHP.', 'I hate bugs.']);

Fill-mask

use py\transformers;

$unmasker = transformers::pipeline('fill-mask', model: 'google-bert/bert-base-uncased');

foreach ($unmasker('Paris is the [MASK] of France.', top_k: 3) as $candidate) {
    echo "{$candidate['token_str']}: {$candidate['score']}\n";
}

Named-entity recognition (token classification)

use py\transformers;

$ner = transformers::pipeline('token-classification', model: 'dslim/bert-base-NER');

foreach ($ner('My name is Sarah and I live in London.') as $entity) {
    echo "{$entity['word']}{$entity['entity']}\n";
}

Question answering

Transformers v5 removed the question-answering pipeline task; extractive QA works through the model class directly:

use py\torch;
use py\transformers\AutoTokenizer;
use py\transformers\AutoModelForQuestionAnswering;

$model_name = 'deepset/roberta-base-squad2';

$tokenizer = AutoTokenizer::from_pretrained($model_name);
$model = AutoModelForQuestionAnswering::from_pretrained($model_name);

$inputs = $tokenizer('What is my name?', 'My name is Clara and I live in Berkeley.', return_tensors: 'pt');

// ModelOutput is a dict subclass, so it arrives as a PHP array
$outputs = $model(input_ids: $inputs['input_ids'], attention_mask: $inputs['attention_mask']);

$start = torch::argmax($outputs['start_logits'])->item();
$end = torch::argmax($outputs['end_logits'])->item();

$ids = $inputs['input_ids'][0]->tolist();
$answer = $tokenizer->decode(array_slice($ids, $start, $end - $start + 1));

Translation / summarization (seq2seq)

The text2text-generation, translation and summarization pipeline tasks were removed in Transformers v5 — use AutoModelForSeq2SeqLM:

use py\transformers\AutoTokenizer;
use py\transformers\AutoModelForSeq2SeqLM;

$model_name = 'google/flan-t5-base';

$tokenizer = AutoTokenizer::from_pretrained($model_name);
$model = AutoModelForSeq2SeqLM::from_pretrained($model_name, device_map: 'auto');

$inputs = $tokenizer('Translate English to German: How old are you?', return_tensors: 'pt');
$outputs = $model->generate($inputs['input_ids']->to($model->device), max_new_tokens: 20);

echo $tokenizer->decode($outputs[0], skip_special_tokens: true); // "Wie old sind Sie?"

Image classification

use py\transformers;
use py\PIL\Image;

$classifier = transformers::pipeline('image-classification', model: 'google/vit-base-patch16-224');

// Open a file — or build an image on the fly with PIL
$image = Image::open('cat.jpg');

foreach ($classifier($image) as $prediction) {
    echo "{$prediction['label']}: {$prediction['score']}\n";
}

PyTorch in PHP

The whole torch API is available — not just for inference.

Tensors

use py\torch;

$t = torch::tensor([[1, 2], [3, 4]]);

$t->tolist();          // [[1, 2], [3, 4]] — back to a PHP array
$t->shape[0];          // 2
$t->sum()->item();     // 10
$t[1][0]->item();      // 3 — Python indexing via PHP array syntax
count($t);             // 2 — len() via count()

torch::arange(6)->reshape(2, 3)->t();      // transpose
torch::matmul($a, $b);                     // matrix multiplication
torch::tensor([1, 2], dtype: torch::$float32);

Note: PHP floats with a zero fractional part (3.0) cross the bridge as Python ints. When the dtype matters, pass dtype: torch::$float32 explicitly.

Autograd

use py\torch;

$x = torch::tensor([3.5], requires_grad: true);
$y = $x->pow(2)->sum();
$y->backward();

$x->grad->tolist();    // [7.0] — dy/dx = 2x

// Disable tracking for inference — the equivalent of `with torch.no_grad():`
$result = Py::with(torch::no_grad(), fn () => $model($input));

Training a model

use py\torch;
use py\torch\nn\Linear;
use py\torch\nn\MSELoss;
use py\torch\optim\SGD;

// Learn y = 2x + 1
$x = torch::rand(32, 1);
$y = $x->mul(2)->add(1);

$model = new Linear(1, 1);
$criterion = new MSELoss();
$optimizer = new SGD($model->parameters(), lr: 0.1);

for ($epoch = 0; $epoch < 200; $epoch++) {
    $optimizer->zero_grad();
    $loss = $criterion($model($x), $y);
    $loss->backward();
    $optimizer->step();
}

echo $model->weight->item(); // ≈ 2.0
echo $model->bias->item();   // ≈ 1.0

Saving and loading weights

use py\safetensors\torch as safetensors;

safetensors::save_file(['weight' => $model->weight, 'bias' => $model->bias], 'model.safetensors');
$tensors = safetensors::load_file('model.safetensors');

GPU

syncfly/python-in-php detects your hardware and picks the right build of PyTorch: CUDA for NVIDIA, ROCm for AMD, Metal for Apple Silicon, or the CPU backend when no GPU is present.

To force a specific backend, set the PYTHON_IN_PHP_TORCH_BACKEND environment variable (e.g. cpu, cu128, rocm7.2, or none to disable the default) or pass --torch-backend=... explicitly:

PYTHON_IN_PHP_TORCH_BACKEND=cpu composer pip install torch

Device selection is the same few lines everywhere — NVIDIA and AMD GPUs both show up as 'cuda', Apple Silicon as 'mps':

use py\torch;

$device = torch\cuda::is_available() ? 'cuda' : (torch\backends\mps::is_available() ? 'mps' : 'cpu');

$t = torch::ones(2, 2)->to($device);
echo $t->device;   // cuda:0 / mps:0 / cpu

For transformers models you rarely need even that. device_map: 'auto' places the model on the best available device:

$model = AutoModelForCausalLM::from_pretrained($model_name, device_map: 'auto');
$outputs = $model->generate($inputs['input_ids']->to($model->device), max_new_tokens: 100);

Python → PHP syntax cheatsheet

Python PHP
import transformers use py\transformers;
from transformers import AutoTokenizer use py\transformers\AutoTokenizer;
pipeline("text-generation", model="…") transformers::pipeline('text-generation', model: '…')
AutoTokenizer.from_pretrained(name) AutoTokenizer::from_pretrained($name)
model.generate(ids, max_new_tokens=50) $model->generate($ids, max_new_tokens: 50)
torch.bfloat16 torch::$bfloat16
outputs[0] $outputs[0]
len(x) / str(x) count($x) / (string) $x
with torch.no_grad(): … Py::with(torch::no_grad(), fn () => …)

Python dict-like objects with string keys (e.g. BatchEncoding from a tokenizer, ModelOutput from a model call) arrive as plain PHP arrays; complex objects arrive as PythonObject references usable with ->, [], foreach and (string).

Full reference: python-in-php usage guide.

Bundled Python packages

Package Purpose
transformers Models, tokenizers, pipelines
torch Tensors, autograd, training (GPU build auto-selected)
accelerate device_map: 'auto', multi-device loading
bitsandbytes 4/8-bit quantization
safetensors Fast, safe weight serialization
timm Vision models
librosa, soundfile Audio processing
pillow Image processing
sentencepiece, tiktoken Tokenizers
optimum Inference optimization
huggingface-hub Model downloads and caching
scipy, einops, protobuf, blobfile Supporting libraries

Versions are pinned in composer.json under extra.python-in-php.packages.

Add other Python packages

Thanks to syncfly/python-in-php, you can add any other Python packages you want with:

composer pip install <name>.

See the docs for more details.

Testing

The package ships with a Pest test suite covering every model type above.

composer test        # fast suite — tiny models (~1-10 MB), downloads them on first run
composer test:heavy  # real models (gemma-3-1b-it, flan-t5-base) with meaningful-output checks
composer test:all    # everything

The suite probes the available backend once (CUDA/ROCm → MPS → CPU) with a real kernel launch in a throwaway subprocess and runs every model on the best device it finds — no configuration needed (see availableDevice() in tests/Pest.php).

Troubleshooting

The Python worker dies / "Object with ID … not found" during a pipeline call

Transformers auto-selects the GPU when one is detected. Current torch builds installed by this package support recent CUDA, ROCm (including integrated AMD GPUs) and MPS out of the box, but if your driver and the auto-selected build ever disagree, the first kernel launch can crash the Python process. Check whether your GPU actually works the same way the test suite does — with a throwaway probe that can't take your app down:

vendor/bin/python-in-php/envs/3.12/bin/python -c 'import torch; torch.ones(1).to("cuda"); print("ok")'

If the probe fails, fall back to the CPU (device: 'cpu' on pipelines, or reinstall torch with PYTHON_IN_PHP_TORCH_BACKEND=cpu composer pip install torch) and update your GPU driver.

Model downloads are slow or fail

Models are cached in ~/.cache/huggingface/hub after the first download. Set HF_HOME to relocate the cache; pass token: to from_pretrained()/pipeline() for gated models (e.g. Gemma requires accepting the license on the Hub).

Installation issues (uv download, symlinks on Windows, stub generation)

See the Python-in-PHP troubleshooting guide.

License

This project is released under the Apache License 2.0.

You are free to use, reproduce, modify and distribute the software, including in commercial projects, provided you retain the copyright, patent, trademark and attribution notices, and state any changes you made to the files. The license also grants an express patent license from contributors.

Contributions are welcome through pull requests to the official repository and are licensed under the same terms.

"SyncFly" and "Transformers-Torch-PHP" are trademarks of the project maintainers and are not covered by the Apache License; see TRADEMARKS for what use is permitted without asking.

Third-party packages and models

This package's license covers only its own code. Syncfly/python-in-php, Transformers, PyTorch, Python and all other bundled Python packages remain the property of their respective developers and are distributed under their own licenses — e.g. Transformers under Apache 2.0 (Hugging Face), PyTorch under the BSD-3-Clause license (PyTorch Foundation). This package claims no rights over them; all trademarks belong to their owners.

Model weights downloaded from the Hugging Face Hub are licensed individually by their authors (e.g. Gemma is subject to Google's Gemma Terms of Use, Llama to Meta's community license) — check each model card before commercial use.