symfony/ai-transformers-php-platform
Symfony AI bridge for TransformersPHP, enabling local transformer models within Symfony apps. Connect TransformersPHP pipelines for embeddings and inference through a platform adapter, with links to docs and the main Symfony AI repo for issues and contributions.
Install Dependencies:
composer require symfony/ai-platform codewithkyrian/transformers
Ensure your system has Python 3.8+ and the transformers library installed:
pip install transformers torch
Configure Symfony AI in Laravel:
Add to config/ai.php:
'providers' => [
TransformersPhpProvider::class => [
'model_path' => storage_path('app/models/distilbert'),
'options' => [
'device' => 'cpu', // or 'cuda' if available
'quantization' => 'int8', // optional for smaller models
],
],
],
Download a Model:
Use the transformers-php CLI or Python to download a model (e.g., distilbert-base-uncased) to the configured path. Example:
python -c "from transformers import AutoModel; AutoModel.from_pretrained('distilbert-base-uncased').save_pretrained('storage/app/models/distilbert')"
First Usage in Laravel:
Register the Symfony AI service in AppServiceProvider:
public function register()
{
$this->app->register(\Symfony\Component\AI\Bridge\Laravel\AIServiceProvider::class);
}
Use in a controller or service:
use Symfony\Component\AI\Platform\AIPlatformInterface;
public function generateEmbedding(AIPlatformInterface $ai)
{
$model = $ai->getModel('distilbert');
$embedding = $model->embed('Sample text to embed');
return response()->json($embedding);
}
Test Locally: Call the endpoint and verify the response. Check logs for Python/FFI errors.
storage_path(): Default location for model files (customize via config).'providers' => [
TransformersPhpProvider::class => [
'model_path' => storage_path('app/models/all-MiniLM-L6-v2'),
'options' => ['device' => 'cpu'],
],
],
public function index(AIPlatformInterface $ai)
{
$model = $ai->getModel('all-MiniLM-L6-v2');
$products = Product::all();
$embeddings = $products->map(fn ($product) =>
$model->embed($product->description)
);
// Store embeddings in a vector DB (e.g., FAISS, Weaviate).
}
public function search(AIPlatformInterface $ai, Request $request)
{
$queryEmbedding = $ai->getModel('all-MiniLM-L6-v2')->embed($request->query);
// Compare with stored embeddings (e.g., cosine similarity).
}
use Symfony\Component\Process\Process;
use Symfony\Component\Process\Exception\ProcessFailedException;
public function handle()
{
$process = new Process(['python', '-m', 'transformers', 'download', 'distilbert-base-uncased', '--output', storage_path('app/models')]);
$process->run();
if (!$process->isSuccessful()) {
throw new ProcessFailedException($process);
}
}
storage/app/models and clear cache on updates:
public function clearModelCache()
{
File::cleanDirectory(storage_path('app/models'));
}
Leverage Symfony AI’s Provider Abstraction to route requests:
// config/ai.php
'providers' => [
TransformersPhpProvider::class => [
'model_path' => storage_path('app/models/distilbert'),
'priority' => 1, // Higher priority = preferred provider
],
HuggingFaceProvider::class => [ // Hypothetical cloud fallback
'api_key' => env('HUGGINGFACE_API_KEY'),
'priority' => 2,
],
],
In code:
$ai = app(AIPlatformInterface::class);
$embedding = $ai->getModel('distilbert')->embed('text'); // Uses highest-priority provider.
Process multiple inputs efficiently:
public function batchEmbed(AIPlatformInterface $ai, array $texts)
{
$model = $ai->getModel('distilbert');
return array_map(fn ($text) => $model->embed($text), $texts);
}
Implement a fallback for critical paths:
public function safeEmbed(AIPlatformInterface $ai, string $text)
{
try {
return $ai->getModel('distilbert')->embed($text);
} catch (ModelLoadException $e) {
// Fallback to cloud (e.g., Hugging Face API).
$client = new \GuzzleHttp\Client();
$response = $client->post('https://api-inference.huggingface.co/models/...', [
'json' => ['inputs' => $text],
]);
return json_decode($response->getBody(), true);
}
}
Service Container Binding: Bind Symfony AI’s services to Laravel’s container:
public function register()
{
$this->app->bind(AIPlatformInterface::class, function ($app) {
return new \Symfony\Component\AI\Platform\AIPlatform(
$app['config']['ai.providers']
);
});
}
Artisan Commands: Create commands for model management:
php artisan ai:download-model distilbert-base-uncased
php artisan ai:list-models
Event Listeners: Trigger events for model loading/errors:
event(new ModelLoaded($modelName));
Caching: Cache embeddings or model outputs:
$cacheKey = "embedding:{$text}";
return Cache::remember($cacheKey, now()->addHours(1), function () use ($ai, $text) {
return $ai->getModel('distilbert')->embed($text);
});
int8 or int4 quantization for smaller models:
'options' => [
'device' => 'cpu',
'quantization' => 'int8',
],
$model = $ai->getModel('distilbert');
$batchSize = 32;
$batches = array_chunk($texts, $batchSize);
$results = [];
foreach ($batches as $batch) {
$results[] = $model->batchEmbed($batch);
}
'options' => [
'device' => 'cuda',
],
use Illuminate\Support\Facades\Validator;
$validator = Validator::make(['text' => $request->input('text')], [
'text' => 'required|string|max:5000',
]);
Python Dependency Hell:
FROM python:3.8-slim
RUN pip install transformers torch
Or isolate with pyenv:
pyenv install 3.8.18
pyenv local 3.8.18
FFI Crashes:
How can I help you explore Laravel packages today?