symfony/ai-ollama-platform
Symfony AI bridge for the Ollama platform. Connect Symfony AI to Ollama’s chat and embedding APIs, including NDJSON streaming, using Ollama models and Modelfile capabilities. Links to docs, issues, and contributions in the main Symfony AI repo.
Install the Package
composer require symfony/ai-ollama-platform
Note: Laravel lacks native Symfony AI integration, so this is a "low-level" package. Use it for HTTP calls only.
Configure Ollama Client Create a service to wrap the Symfony client with Laravel’s HTTP client:
// app/Services/OllamaService.php
use Symfony\Component\AI\Ollama\OllamaClient;
use Illuminate\Support\Facades\Http;
class OllamaService
{
public function __construct()
{
$this->client = new OllamaClient(
Http::macro('createClient', fn() => Http::client())
);
}
public function chat(string $model, string $message): string
{
return $this->client->chat($model, [$message]);
}
}
Register the Service
Bind it in AppServiceProvider:
public function register()
{
$this->app->singleton(OllamaService::class, fn($app) => new OllamaService());
}
First Use Case: Chat Completion
use App\Services\OllamaService;
$response = app(OllamaService::class)->chat('llama3', 'Explain Laravel 11 features.');
echo $response;
Where to Look Next
OllamaClient methods: generate(), embed(), list().// Basic chat
$response = $ollama->chat('llama3', ['What is Laravel?']);
// With structured output (v0.7.0+)
$response = $ollama->chat('llama3', [
'What are Laravel 11 features?',
], [
'options' => ['structured_output' => true],
]);
use Symfony\Component\AI\Streaming\StreamingResponse;
$stream = $ollama->chatStream('llama3', ['Explain Symfony AI.']);
foreach ($stream as $delta) {
echo $delta->getContent(); // Incremental output
}
Laravel Tip: Use Swoole or ReactPHP for async streaming in Laravel’s request lifecycle.
$embeddings = $ollama->embed('llama3', ['vectorize this text']);
// Process embeddings for vector search (e.g., with Laravel Scout).
// Define a provider to route models dynamically
use Symfony\Component\AI\Ollama\ModelProviderInterface;
class LaravelModelProvider implements ModelProviderInterface
{
public function getModel(string $name): string
{
return match ($name) {
'math' => 'llama3:8b',
default => 'llama3',
};
}
}
// Inject into OllamaClient
$client = new OllamaClient($httpClient, new LaravelModelProvider());
HttpClient with Laravel’s Http facade by overriding the client factory:
$client = new OllamaClient(
Http::macro('createClient', fn() => Http::client())
);
try-catch for Ollama-specific exceptions:
try {
$response = $ollama->chat('nonexistent-model', ['...']);
} catch (\Symfony\Component\AI\Exception\OllamaException $e) {
report($e);
return back()->withError('Model not found.');
}
.env:
OLLAMA_URL=http://localhost:11434
Then inject it into the client:
$client = new OllamaClient(
Http::baseUrl(config('ollama.url'))
);
| Use Case | Implementation Pattern | Example |
|---|---|---|
| Chatbot UI | Streaming + Laravel Echo/Pusher | Broadcast $delta->getContent() to frontend via WebSockets. |
| Document Search | Embeddings + Laravel Scout | Store embeddings in Scout, query with ->where('vector', $queryEmbed). |
| Structured Data | structured_output + JSON parsing |
Parse $response->getContent() as JSON for programmatic use. |
| Audio Processing | gemma:2b model + base64 audio input |
Encode audio as base64, pass to $ollama->chat('gemma:2b', [$audio]). |
| Batch Processing | Laravel Queues + generate() |
Dispatch jobs to process large text chunks asynchronously. |
OllamaClient and test Laravel services:
$mockClient = Mockery::mock(OllamaClient::class);
$mockClient->shouldReceive('chat')
->andReturn('Mock response');
$service = new OllamaService($mockClient);
docker run -d -p 11434:11434 ollama/ollama
Then test against http://localhost:11434.HttpClient, AI component, and Messenger.ProviderInterface directly unless you replicate Symfony’s DI container.$loop = React\EventLoop\Factory::create();
$consumer = new React\AI\OllamaStreamConsumer($ollama->chatStream(...));
$loop->run();
$stream->onDelta(fn($delta) => broadcast(new OllamaDelta($delta))->toOthers());
OllamaApiCatalog requires network calls to list models.$catalog = Cache::remember('ollama_models', now()->addHours(1), fn() =>
new OllamaApiCatalog($ollama->list())
);
gemma:2b require base64-encoded audio input.Storage facade to encode files:
$audioBase64 = base64_encode(
file_get_contents(storage_path('app/audio.wav'))
);
$response = $ollama->chat('gemma:2b', [$audioBase64]);
Stringable interfaces:
composer require symfony/polyfill-stringable
| Error | Cause | Solution |
|---|---|---|
InvalidArgumentException |
Passing a string to generate() |
Use $ollama->chat() for text or $ollama->generate() for raw prompts. |
Connection refused |
Ollama server not running | Start Ollama: docker run -d -p 11434:11434 ollama/ollama. |
NDJSON parsing errors |
Malformed streaming response | Validate the response with json_decode($chunk, true). |
Class not found |
Missing Symfony dependencies | Only use OllamaClient; avoid other Symfony AI classes. |
Enable debug logging for Ollama requests
How can I help you explore Laravel packages today?