Laravel wrapper for Black Forest Labs FLUX API - AI-powered image generation and fine-tuning services
lanos/laravel-bfl is a Laravel package for laravel wrapper for black forest labs flux api - ai-powered image generation and fine-tuning services.
It currently has 0 GitHub stars and 0 downloads on Packagist (latest version v1.0.0).
Install it with composer require lanos/laravel-bfl.
Discover more Laravel packages by lanos
or browse all Laravel packages to compare alternatives.
Last updated
A professional Laravel wrapper for Black Forest Labs' FLUX API, providing seamless integration for AI-powered image generation and fine-tuning services.
Install the package via Composer:
composer require lanos/laravel-bfl
Publish the migration and config files:
php artisan vendor:publish --provider="Lanos\LaravelBFL\BFLServiceProvider"
Or publish them separately:
# Publish only the config
php artisan vendor:publish --tag="bfl-config"
# Publish only migrations
php artisan vendor:publish --tag="bfl-migrations"
Run the migrations:
php artisan migrate
Add your BFL API key to your .env file:
BFL_API_KEY=your-black-forest-labs-api-key
BFL_STORE_FILES=true
BFL_STORAGE_DISK=local
BFL_STORAGE_PATH_PREFIX=generated-bfl-images
The package publishes a configuration file to config/bfl.php. Key configuration options:
return [
'api_key' => env('BFL_API_KEY'),
'storage' => [
'store_files' => env('BFL_STORE_FILES', true),
'disk' => env('BFL_STORAGE_DISK', 'local'),
'path_prefix' => env('BFL_STORAGE_PATH_PREFIX', 'generated-bfl-images'),
'public' => env('BFL_STORAGE_PUBLIC', false),
],
'jobs' => [
'queue_connection' => env('BFL_QUEUE_CONNECTION', 'default'),
'queue_name' => env('BFL_QUEUE_NAME', 'default'),
'polling' => [
'max_attempts' => env('BFL_POLLING_MAX_ATTEMPTS', 120),
'delay_seconds' => env('BFL_POLLING_DELAY_SECONDS', 3),
],
'cleanup_after_days' => env('BFL_CLEANUP_AFTER_DAYS', 30),
],
];
The package provides three different processing modes:
Create a job and manually check its status:
use Lanos\LaravelBFL\Facades\BFL;
use Lanos\LaravelBFL\Models\BFLJob;
// Create a manual job
$job = BFL::createManualJob(
BFLJob::MODEL_FLUX_1_PRO,
'A majestic dragon soaring through clouds at sunset',
[
'width' => 1024,
'height' => 768,
'steps' => 50,
'guidance' => 3.5,
],
['user_request_id' => 'req_123'], // metadata
auth()->user() // optional user association
);
// Later, check the job status
$updatedJob = BFL::checkJobStatus($job);
if ($updatedJob->isCompleted()) {
echo "Job completed! Files stored at: ";
foreach ($updatedJob->file_paths ?? [] as $path) {
echo BFL::getFileUrl($path) . "\n";
}
} elseif ($updatedJob->isFailed()) {
echo "Job failed: " . $updatedJob->error_message;
}
Create a job and wait for completion:
// This will block until completion or timeout
$job = BFL::createSyncJob(
BFLJob::MODEL_FLUX_1_PRO,
'A beautiful sunset over mountains',
[
'aspect_ratio' => '16:9',
'steps' => 28,
'safety_tolerance' => 2,
]
);
// Job is automatically completed when this returns
if ($job->isCompleted()) {
echo "Generated image result: " . json_encode($job->result);
}
Create a job that processes in the background:
// Dispatch to queue for background processing
$job = BFL::createQueueJob(
BFLJob::MODEL_FLUX_11_PRO_ULTRA,
'An abstract artistic composition with vibrant colors',
[
'aspect_ratio' => '1:1',
'raw' => false,
],
[], // metadata
auth()->user(), // user
'redis', // queue connection (optional)
'images' // queue name (optional)
);
echo "Job queued with ID: {$job->id}";
// Check status later
$job->refresh();
if ($job->isCompleted()) {
// Handle completion
}
// Generation models
BFLJob::MODEL_FLUX_1_PRO // 'flux-1-pro'
BFLJob::MODEL_FLUX_1_DEV // 'flux-1-dev'
BFLJob::MODEL_FLUX_11_PRO // 'flux-1.1-pro'
BFLJob::MODEL_FLUX_11_PRO_ULTRA // 'flux-1.1-pro-ultra'
// Editing models
BFLJob::MODEL_FLUX_1_FILL // 'flux-1-fill'
BFLJob::MODEL_FLUX_1_EXPAND // 'flux-1-expand'
BFLJob::MODEL_FLUX_1_CANNY // 'flux-1-canny'
BFLJob::MODEL_FLUX_1_DEPTH // 'flux-1-depth'
// Context models
BFLJob::MODEL_FLUX_KONTEXT_PRO // 'flux-kontext-pro'
BFLJob::MODEL_FLUX_KONTEXT_MAX // 'flux-kontext-max'
$parameters = [
// Dimensions
'width' => 1024,
'height' => 768,
'aspect_ratio' => '16:9', // Alternative to width/height
// Generation settings
'steps' => 50, // Denoising steps
'guidance' => 3.5, // How closely to follow prompt
'seed' => 42, // For reproducible results
'safety_tolerance' => 2, // Content filtering (0=strict, 6=lenient)
'output_format' => 'png', // 'png' or 'jpeg'
// Advanced options
'image_prompt' => base64_encode(file_get_contents('reference.jpg')),
'prompt_upsampling' => true,
// Webhooks
'webhook_url' => 'https://your-site.com/webhooks/bfl',
'webhook_secret' => 'your-webhook-secret',
];
Fill/Inpainting models:
$parameters = [
'image' => base64_encode(file_get_contents('input.jpg')),
'mask' => base64_encode(file_get_contents('mask.png')), // Optional
];
Expand models:
$parameters = [
'image' => base64_encode(file_get_contents('input.jpg')),
'top' => 100, // Pixels to add
'bottom' => 100,
'left' => 50,
'right' => 50,
];
Control models (Canny/Depth):
$parameters = [
'control_image' => base64_encode(file_get_contents('control.jpg')),
'canny_low_threshold' => 50, // For Canny model
'canny_high_threshold' => 200,
];
The package provides comprehensive fine-tuning support through the BFLFinetune facade:
use Lanos\LaravelBFL\Facades\BFLFinetune;
use Lanos\LaravelBFL\Enums\FinetuneMode;
// Create from file paths (automatically zips and encodes)
$finetune = BFLFinetune::create([
'files' => [
'/path/to/image1.jpg',
'/path/to/image2.jpg',
'/path/to/image3.jpg',
],
'finetune_comment' => 'My custom style training',
'mode' => FinetuneMode::STYLE, // or 'style' as string
'trigger_word' => 'MYSTYLE',
'iterations' => 500,
]);
// Or create from pre-encoded ZIP
$finetune = BFLFinetune::create([
'file_data' => base64_encode(file_get_contents('training_data.zip')),
'finetune_comment' => 'Character fine-tune',
'mode' => 'character',
'trigger_word' => 'MYCHAR',
'iterations' => 800,
]);
// Get finetune details
$details = BFLFinetune::getDetails('ft-123');
// List your finetunes
$finetunes = BFLFinetune::listMyFinetunes();
// Delete a finetune
$result = BFLFinetune::delete('ft-123');
// Generate with fine-tuned Pro
$job = BFLFinetune::generateWithFinetunedPro(
'ft-123',
'A beautiful sunset in MYSTYLE',
['width' => 1024, 'height' => 768]
);
// Generate with fine-tuned Ultra
$job = BFLFinetune::generateWithFinetunedUltra(
'ft-123',
'Portrait in MYSTYLE',
['raw' => true]
);
// Generate with fine-tuned control models
$job = BFLFinetune::generateWithFinetunedCanny(
'ft-123',
'Landscape in MYSTYLE',
base64_encode(file_get_contents('control.jpg'))
);
$job = BFLJob::find(1);
// Status checks
$job->isPending(); // Job created but not started
$job->isProcessing(); // Job is currently running
$job->isCompleted(); // Job finished successfully
$job->isFailed(); // Job failed
$job->isFinished(); // Job is in any terminal state
// Progress tracking
echo "Progress: {$job->progress}%";
echo "Started: {$job->started_at}";
echo "Completed: {$job->completed_at}";
// Create job for specific user
$job = BFL::createManualJob(
BFLJob::MODEL_FLUX_1_PRO,
'User generated image',
[],
[],
User::find(1)
);
// Get user's jobs
$userJobs = BFL::getUserJobs(auth()->user(), [
'status' => BFLJob::STATUS_COMPLETED,
'model_type' => BFLJob::MODEL_FLUX_1_PRO,
]);
Configure queue processing in config/bfl.php:
'jobs' => [
'queue_connection' => 'redis',
'queue_name' => 'bfl-jobs',
'polling' => [
'max_attempts' => 120, // Maximum poll attempts
'delay_seconds' => 3, // Delay between polls
],
],
# Start worker for BFL jobs
php artisan queue:work --queue=bfl-jobs
# With specific connection
php artisan queue:work redis --queue=bfl-jobs
Generated images are automatically downloaded and stored when store_files is enabled:
// Access stored files
$job = BFLJob::find(1);
$filePaths = $job->file_paths; // Array of stored file paths
// Get public URLs
foreach ($filePaths as $path) {
echo BFL::getFileUrl($path);
}
// Use S3 or other disks
'storage' => [
'disk' => 's3',
'public' => true,
],
// Clean up old jobs (respects cleanup_after_days config)
$deletedCount = BFL::cleanupOldJobs();
// Access underlying FLUX client for advanced usage
$client = BFL::getClient();
$config = BFL::getConfig();
Run the package test suite:
composer test
use Lanos\LaravelBFL\Services\BFLService;
use Lanos\LaravelBFL\Models\BFLJob;
public function test_image_generation()
{
$mockService = $this->mock(BFLService::class);
$mockJob = new BFLJob([
'bfl_task_id' => 'test-task',
'status' => BFLJob::STATUS_COMPLETED,
]);
$mockService->allows('createManualJob')
->andReturn($mockJob);
// Test your application logic
}
// Job creation
BFL::createManualJob(string $modelType, string $prompt, array $parameters = [], array $metadata = [], ?object $user = null): BFLJob
BFL::createSyncJob(string $modelType, string $prompt, array $parameters = [], array $metadata = [], ?object $user = null): BFLJob
BFL::createQueueJob(string $modelType, string $prompt, array $parameters = [], array $metadata = [], ?object $user = null, ?string $queueConnection = null, ?string $queueName = null): BFLJob
// Job management
BFL::checkJobStatus(BFLJob $job): BFLJob
BFL::completeJob(BFLJob $job, GetResultResponse $result): BFLJob
// Utility methods
BFL::getStorageDisk(): \Illuminate\Contracts\Filesystem\Filesystem
BFL::getFileUrl(string $filePath): string
BFL::cleanupOldJobs(): int
BFL::getUserJobs(object $user, array $filters = []): \Illuminate\Database\Eloquent\Collection
BFL::getClient(): \Lanos\PHPBFL\FluxClient
BFL::getConfig(): array
// Finetune management
BFLFinetune::create(array $params): array
BFLFinetune::getDetails(string $finetuneId): array
BFLFinetune::listMyFinetunes(): array
BFLFinetune::delete(string $finetuneId): array
// Generation with finetuned models
BFLFinetune::generateWithFinetunedPro(string $finetuneId, string $prompt, array $parameters = [], array $metadata = [], ?object $user = null): BFLJob
BFLFinetune::generateWithFinetunedUltra(string $finetuneId, string $prompt, array $parameters = [], array $metadata = [], ?object $user = null): BFLJob
BFLFinetune::generateWithFinetunedDepth(string $finetuneId, string $prompt, string $controlImage, array $parameters = [], array $metadata = [], ?object $user = null): BFLJob
BFLFinetune::generateWithFinetunedCanny(string $finetuneId, string $prompt, string $controlImage, array $parameters = [], array $metadata = [], ?object $user = null): BFLJob
BFLFinetune::generateWithFinetunedFill(string $finetuneId, string $image, array $parameters = [], array $metadata = [], ?object $user = null): BFLJob
// Status checks
$job->isPending(): bool
$job->isProcessing(): bool
$job->isCompleted(): bool
$job->isFailed(): bool
$job->isFinished(): bool
// Status updates
$job->markAsProcessing(): self
$job->markAsCompleted(?array $result = null, ?array $filePaths = null): self
$job->markAsFailed(?string $errorMessage = null): self
$job->updateProgress(float $progress): self
We welcome contributions! Please ensure all tests pass and follow PSR-12 coding standards.
Please review our security policy on how to report security vulnerabilities.
The MIT License (MIT). Please see License File for more information.
Please see CHANGELOG.md for more information on what has changed recently.