symfony/ai-albert-platform
Symfony AI bridge for the French government’s Albert Platform (OpenGateLLM). Connect Symfony apps to Albert’s OpenAI-compatible chat and embeddings endpoints, with links to the API reference, supported models, and upstream sources.
Install the Package Require the package via Composer in your Laravel project:
composer require symfony/ai-albert-platform
Configure the Provider
Add the Albert provider to your Symfony AI configuration (assuming you're using symfony/ai):
# config/packages/symfony_ai.yaml
framework:
ai:
providers:
albert:
client: albert_client
models:
chat: mistral-7b
embeddings: all-minilm
Set Up HTTP Client
Configure an HTTP client for Albert’s API (Symfony’s HttpClient works seamlessly with Laravel):
// config/services.php
'albert_client' => fn() => new \Symfony\Contracts\HttpClient\HttpClient(
['base_uri' => 'https://albert.api.etalab.gouv.fr']
),
First Use Case: Chat Completion Inject the AI client into a service or controller and use it for chat completions:
use Symfony\Component\AI\Client\AiClientInterface;
class ChatService {
public function __construct(private AiClientInterface $aiClient) {}
public function generateResponse(string $prompt): string {
return $this->aiClient->completeChat(
'albert',
$prompt,
temperature: 0.7
);
}
}
Register the Service
Bind the Symfony AI client to Laravel’s container in AppServiceProvider:
public function register() {
$this->app->bind(AiClientInterface::class, fn($app) =>
new \Symfony\Component\AI\Client\AiClient(
$app['config']['services.albert_client']
)
);
}
Leverage the Provider abstraction to route requests dynamically between Albert and other providers (e.g., OpenAI). Define a custom provider resolver:
// app/Services/AiProviderResolver.php
use Symfony\Component\AI\Client\AiClientInterface;
use Symfony\Component\AI\Client\Provider\ProviderInterface;
class AiProviderResolver {
public function __construct(
private AiClientInterface $aiClient,
private array $providerConfig
) {}
public function resolveProvider(string $requestType): ProviderInterface {
$providerName = $this->providerConfig['default_provider'] ?? 'albert';
return $this->aiClient->getProvider($providerName);
}
}
Usage in Controller:
public function askAi(string $question) {
$provider = $this->aiProviderResolver->resolveProvider('chat');
$response = $provider->completeChat($question);
return response()->json(['response' => $response]);
}
Use Albert’s embeddings to generate vectors for search or recommendations. Cache embeddings to optimize performance:
use Illuminate\Support\Facades\Cache;
public function generateEmbedding(string $text): array {
$cacheKey = "embedding:$text";
return Cache::remember($cacheKey, now()->addHours(1), function() {
return $this->aiClient->getProvider('albert')
->createEmbedding($text)
->getEmbedding();
});
}
Integration with Meilisearch:
public function indexDocument(string $documentId, string $content) {
$embedding = $this->generateEmbedding($content);
$client = new \Meilisearch\Client('http://localhost:7700', 'masterKey');
$index = $client->index('documents');
$index->addDocuments([
'id' => $documentId,
'content' => $content,
'embedding' => $embedding
]);
}
Offload AI requests to a queue to avoid blocking user requests. Use Laravel’s queue system:
use Illuminate\Support\Facades\Bus;
Bus::dispatch(new GenerateAiResponse($prompt));
Queue Job:
class GenerateAiResponse implements ShouldQueue {
use Dispatchable, InteractsWithQueue, Queueable, SerializesModels;
public function __construct(public string $prompt) {}
public function handle() {
$response = $this->aiClient->completeChat('albert', $this->prompt);
// Store or broadcast response
}
}
Route requests to different models based on business logic (e.g., cost vs. quality):
public function getModelForRequest(string $requestType): string {
return match ($requestType) {
'high_quality' => 'llama-2',
'cost_efficient' => 'mistral-7b',
default => config('ai.default_model'),
};
}
public function generateResponse(string $prompt) {
$model = $this->getModelForRequest('cost_efficient');
return $this->aiClient->completeChat('albert', $prompt, model: $model);
}
Service Provider Binding
Bind Symfony’s AiClient to Laravel’s container for seamless dependency injection:
$this->app->singleton(AiClientInterface::class, function ($app) {
return new AiClient(
$app['config']['services.albert_client'],
$app['config']['ai.providers.albert']
);
});
Configuration Management Use Laravel’s config system to manage Albert-specific settings:
# config/ai.php
albert:
api_key: '%env(ALBERT_API_KEY)%'
base_uri: 'https://albert.api.etalab.gouv.fr'
default_model: 'mistral-7b'
timeout: 30
Exception Handling Catch Albert-specific exceptions and log them using Laravel’s logging:
try {
$response = $this->aiClient->completeChat('albert', $prompt);
} catch (\Symfony\Component\AI\Exception\AiException $e) {
Log::error("Albert API Error: " . $e->getMessage());
throw new \RuntimeException("AI service unavailable. Please try again later.");
}
Testing with Mocks Use Laravel’s HTTP testing helpers to mock Albert’s API in tests:
public function testChatCompletion() {
Http::fake([
'albert.api.etalab.gouv.fr' => Http::response([
'choices' => [['message' => ['content' => 'Mocked response']]]
], 200),
]);
$response = $this->aiClient->completeChat('albert', 'Test prompt');
$this->assertEquals('Mocked response', $response);
}
Blade Integration for Frontend Pass AI responses to Blade templates for dynamic content:
return view('chat', [
'aiResponse' => $this->aiService->generateResponse($userInput),
]);
<div class="ai-response">
{!! nl2br(e($aiResponse)) !!}
</div>
HttpClient with retry middleware or implement a custom retry logic:
$client = \Symfony\Contracts\HttpClient\HttpClient::create([
'base_uri' => 'https://albert.api.etalab.gouv.fr',
'timeout' => 30,
'max_retries' => 3,
'retry_on' => [429, 500, 502, 503, 504],
]);
text-embedding-ada-002 may not be available.public function createEmbedding(string $text): array {
try {
return $this->aiClient->getProvider('albert')
->createEmbedding($text, model: 'all-minilm')
->getEmbedding();
} catch (\InvalidArgumentException $e) {
Log::warning("Unsupported embedding model: " . $e->getMessage());
throw new \RuntimeException("Embedding generation failed. Check supported models.");
}
}
How can I help you explore Laravel packages today?