symfony/ai-perplexity-platform
Symfony AI bridge for the Perplexity Platform. Provides integration with Perplexity’s Sonar chat completions API for building AI chat experiences in Symfony apps, with links to Perplexity docs and contribution resources.
Install the Package
composer require symfony/ai-perplexity-platform symfony/ai-platform symfony/http-client
For Laravel, ensure compatibility with Symfony components via:
composer require spatie/laravel-symfony-support
Configure API Key
Add to .env:
PERPLEXITY_API_KEY=your_api_key_here
Basic Usage Example Create a service to wrap the Perplexity client:
// app/Services/PerplexityService.php
namespace App\Services;
use Symfony\AI\Perplexity\PerplexityClient;
use Symfony\Contracts\HttpClient\HttpClientInterface;
class PerplexityService
{
public function __construct(
private PerplexityClient $client
) {}
public function ask(string $question): string
{
$response = $this->client->chat([
new \Symfony\AI\Message($question, 'user'),
]);
return $response->getContent();
}
}
Bind the Service
Register in AppServiceProvider:
public function register()
{
$this->app->singleton(PerplexityService::class, function ($app) {
$httpClient = \Symfony\Contracts\HttpClient\HttpClient::create([
'auth_bearer' => $app['config']['perplexity.api_key'],
]);
return new PerplexityService(
new PerplexityClient($httpClient, 'sonar')
);
});
}
First Use Case Use in a controller or command:
use App\Services\PerplexityService;
class ChatController extends Controller
{
public function __invoke(PerplexityService $perplexity)
{
$response = $perplexity->ask('What is Laravel?');
return response()->json(['answer' => $response]);
}
}
Chat Completions
Use the chat() method for synchronous responses:
$response = $perplexity->chat([
new \Symfony\AI\Message('Explain Symfony AI', 'user'),
new \Symfony\AI\Message('Keep it concise', 'assistant'),
]);
Streaming Responses For real-time UI updates (e.g., chat apps):
$perplexity->chatStream([
new \Symfony\AI\Message('Generate a summary', 'user'),
], function ($delta) {
// Append to view or process chunk
echo $delta->getContent();
});
Model Routing
Leverage Symfony’s Provider abstraction to switch models dynamically:
$client = new PerplexityClient($httpClient, 'sonar');
// Later, override model for specific use cases
$client->setModel('sonar-lite');
Laravel HTTP Client Bridge
Use symfony/http-client-guzzle to share middleware (retries, auth) between Symfony and Laravel’s Guzzle:
$httpClient = \Symfony\Contracts\HttpClient\HttpClient::create([
'plugins' => [
new \Symfony\Contracts\HttpClient\Plugin\RetryPlugin(),
],
]);
Error Handling
Catch Symfony’s ApiError and map to Laravel exceptions:
try {
$response = $perplexity->chat([...]);
} catch (\Symfony\AI\Exception\ApiError $e) {
throw new \App\Exceptions\AIServiceException($e->getMessage(), $e->getCode());
}
Configuration
Centralize settings in config/perplexity.php:
return [
'api_key' => env('PERPLEXITY_API_KEY'),
'default_model' => 'sonar',
'timeout' => 30,
];
Testing
Mock the PerplexityClient in tests:
$mockClient = $this->createMock(PerplexityClient::class);
$mockClient->method('chat')->willReturn(new \Symfony\AI\Response('Mock answer'));
$this->app->instance(PerplexityClient::class, $mockClient);
Symfony-Specific Abstractions
Message, Response, and DeltaInterface, which may conflict with Laravel’s native types.// Convert Symfony Message to Laravel-friendly array
$message = new \Symfony\AI\Message('Hello', 'user');
$arrayMessage = [
'role' => $message->getRole(),
'content' => $message->getContent(),
];
Streaming in Laravel
DeltaInterface) doesn’t integrate natively with Laravel’s request/response cycle.Swoole or ReactPHP for async processing, or buffer chunks in memory:
$chunks = [];
$perplexity->chatStream([...], function ($delta) use (&$chunks) {
$chunks[] = $delta->getContent();
});
return response()->json(['response' => implode('', $chunks)]);
API Key Management
HttpClient expects the API key in auth_bearer, but Laravel’s .env may use PERPLEXITY_API_KEY.$httpClient = \Symfony\Contracts\HttpClient\HttpClient::create([
'auth_bearer' => config('perplexity.api_key'),
]);
Rate Limiting
throttle middleware:
$httpClient = \Symfony\Contracts\HttpClient\HttpClient::create([
'plugins' => [
new class implements \Symfony\Contracts\HttpClient\Plugin\PluginInterface {
public function handleRequest(Request $request, callable $next) {
if ($request->getMethod() === 'POST') {
$request = $request->withHeader('X-RateLimit', '100');
}
return $next($request);
}
},
],
]);
Model-Specific Quirks
sonar model may behave differently than OpenAI or other providers.README.md.Enable Symfony Debug Mode
Add to config/app.php:
'debug' => env('APP_DEBUG', true),
This exposes detailed API error responses.
Log Raw Responses Use Laravel’s logging to inspect Perplexity’s raw output:
$response = $perplexity->chat([...]);
\Log::debug('Perplexity Response:', $response->getContent());
Validate Request Payloads
Ensure payloads match Perplexity’s API schema (e.g., messages array structure):
$messages = [
new \Symfony\AI\Message('Question', 'user'),
new \Symfony\AI\Message('Context', 'system'),
];
Custom Providers
Extend Symfony’s Provider abstraction to support multi-provider routing:
class PerplexityProvider implements \Symfony\AI\Provider\ProviderInterface
{
public function getModel(): string
{
return 'sonar';
}
public function chat(array $messages): \Symfony\AI\Response
{
// Custom logic
}
}
Laravel Event Integration Dispatch Laravel events for AI responses:
$perplexity->chat([...], function ($response) {
event(new \App\Events\AIResponseGenerated($response));
});
Queue Workers for Async Processing Use Laravel queues to offload Perplexity calls:
class GenerateContentJob implements ShouldQueue
{
public function handle(PerplexityService $perplexity)
{
$perplexity->ask('Generate content for blog post');
}
}
Nova/Panel Integration Create a Nova resource to manage Perplexity configurations:
class PerplexitySettings extends Resource
{
public static function index(Request $request)
{
return new LengthAwarePaginator(
[config('perplexity')],
1,
1
);
}
}
How can I help you explore Laravel packages today?