Skip to content
Draft
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
3 changes: 1 addition & 2 deletions src/ai-bundle/config/services.php
Original file line number Diff line number Diff line change
Expand Up @@ -46,7 +46,6 @@
use Symfony\AI\Platform\Bridge\Mistral\ModelCatalog as MistralModelCatalog;
use Symfony\AI\Platform\Bridge\Mistral\TokenOutputProcessor as MistralTokenOutputProcessor;
use Symfony\AI\Platform\Bridge\Ollama\Contract\OllamaContract;
use Symfony\AI\Platform\Bridge\Ollama\ModelCatalog as OllamaModelCatalog;
use Symfony\AI\Platform\Bridge\OpenAi\Contract\OpenAiContract;
use Symfony\AI\Platform\Bridge\OpenAi\ModelCatalog as OpenAiModelCatalog;
use Symfony\AI\Platform\Bridge\OpenAi\TokenOutputProcessor as OpenAiTokenOutputProcessor;
Expand All @@ -67,6 +66,7 @@
use Symfony\AI\Store\Command\DropStoreCommand;
use Symfony\AI\Store\Command\IndexCommand;
use Symfony\AI\Store\Command\SetupStoreCommand;
use Symfony\Component\DependencyInjection\Reference;

return static function (ContainerConfigurator $container): void {
$container->services()
Expand Down Expand Up @@ -99,7 +99,6 @@
->set('ai.platform.model_catalog.huggingface', HuggingFaceModelCatalog::class)
->set('ai.platform.model_catalog.lmstudio', LmStudioModelCatalog::class)
->set('ai.platform.model_catalog.mistral', MistralModelCatalog::class)
->set('ai.platform.model_catalog.ollama', OllamaModelCatalog::class)
->set('ai.platform.model_catalog.openai', OpenAiModelCatalog::class)
->set('ai.platform.model_catalog.openrouter', OpenRouterModelCatalog::class)
->set('ai.platform.model_catalog.perplexity', PerplexityModelCatalog::class)
Expand Down
12 changes: 10 additions & 2 deletions src/ai-bundle/src/AiBundle.php
Original file line number Diff line number Diff line change
Expand Up @@ -45,6 +45,7 @@
use Symfony\AI\Platform\Bridge\Gemini\PlatformFactory as GeminiPlatformFactory;
use Symfony\AI\Platform\Bridge\LmStudio\PlatformFactory as LmStudioPlatformFactory;
use Symfony\AI\Platform\Bridge\Mistral\PlatformFactory as MistralPlatformFactory;
use Symfony\AI\Platform\Bridge\Ollama\OllamaCatalog;
use Symfony\AI\Platform\Bridge\Ollama\PlatformFactory as OllamaPlatformFactory;
use Symfony\AI\Platform\Bridge\OpenAi\PlatformFactory as OpenAiPlatformFactory;
use Symfony\AI\Platform\Bridge\OpenRouter\PlatformFactory as OpenRouterPlatformFactory;
Expand Down Expand Up @@ -442,7 +443,14 @@ private function processPlatformConfig(string $type, array $platform, ContainerB
}

if ('ollama' === $type) {
$platformId = 'ai.platform.ollama';
$catalogDefinition = (new Definition(OllamaCatalog::class))
->setArguments([
$platform['host_url'],
new Reference('http_client'),
]);

$container->setDefinition('ai.platform.model_catalog.ollama', $catalogDefinition);

$definition = (new Definition(Platform::class))
->setFactory(OllamaPlatformFactory::class.'::create')
->setLazy(true)
Expand All @@ -455,7 +463,7 @@ private function processPlatformConfig(string $type, array $platform, ContainerB
])
->addTag('ai.platform', ['name' => 'ollama']);

$container->setDefinition($platformId, $definition);
$container->setDefinition('ai.platform.ollama', $definition);

return;
}
Expand Down
46 changes: 46 additions & 0 deletions src/platform/src/Bridge/Ollama/OllamaCatalog.php
Original file line number Diff line number Diff line change
@@ -0,0 +1,46 @@
<?php

/*
* This file is part of the Symfony package.
*
* (c) Fabien Potencier <fabien@symfony.com>
*
* For the full copyright and license information, please view the LICENSE
* file that was distributed with this source code.
*/

namespace Symfony\AI\Platform\Bridge\Ollama;

use Symfony\AI\Platform\Exception\InvalidArgumentException;
use Symfony\AI\Platform\Model;
use Symfony\AI\Platform\ModelCatalog\DynamicModelCatalog;
use Symfony\Contracts\HttpClient\HttpClientInterface;

final class OllamaCatalog extends DynamicModelCatalog
{
public function __construct(
private readonly string $host,
private readonly HttpClientInterface $httpClient,
) {
parent::__construct();
}

public function getModel(string $modelName): Model
{
$model = parent::getModel($modelName);

$response = $this->httpClient->request('POST', \sprintf('%s/api/show', $this->host), [
'json' => [
'model' => $model->getName(),
],
]);

$payload = $response->toArray();
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

now you would need to implement the option handling etc here as well

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Hum, maybe we can do parent::getModel() to retrieve an object with its options then transform it into the correct model 🤔

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Something like:

    public function getModel(string $modelName): Model
    {
        $model = parent::getModel($modelName);

        $response = $this->httpClient->request('POST', \sprintf('%s/api/show', $this->host), [
            'json' => [
                'model' => $model->getName(),
            ],
        ]);

        $payload = $response->toArray();

        if ([] === $payload['capabilities'] ?? []) {
            throw new InvalidArgumentException('The model information could not be retrieved from the Ollama API. Your Ollama server might be too old. Try upgrade it.');
        }

        return new Ollama($modelName, $payload['capabilities']);
    }


if ([] === $payload['capabilities'] ?? []) {
throw new InvalidArgumentException('The model information could not be retrieved from the Ollama API. Your Ollama server might be too old. Try upgrade it.');
}

return new Ollama($model->getName(), $payload['capabilities'], $model->getOptions());
}
}
16 changes: 2 additions & 14 deletions src/platform/src/Bridge/Ollama/OllamaClient.php
Original file line number Diff line number Diff line change
Expand Up @@ -35,21 +35,9 @@ public function supports(Model $model): bool

public function request(Model $model, array|string $payload, array $options = []): RawHttpResult
{
$response = $this->httpClient->request('POST', \sprintf('%s/api/show', $this->hostUrl), [
'json' => [
'model' => $model->getName(),
],
]);

$capabilities = $response->toArray()['capabilities'] ?? null;

if (null === $capabilities) {
throw new InvalidArgumentException('The model information could not be retrieved from the Ollama API. Your Ollama server might be too old. Try upgrade it.');
}

return match (true) {
\in_array('completion', $capabilities, true) => $this->doCompletionRequest($payload, $options),
\in_array('embedding', $capabilities, true) => $this->doEmbeddingsRequest($model, $payload, $options),
\in_array('completion', $model->getCapabilities(), true) => $this->doCompletionRequest($payload, $options),
\in_array('embedding', $model->getCapabilities(), true) => $this->doEmbeddingsRequest($model, $payload, $options),
default => throw new InvalidArgumentException(\sprintf('Unsupported model "%s": "%s".', $model::class, $model->getName())),
};
}
Expand Down
4 changes: 2 additions & 2 deletions src/platform/src/Bridge/Ollama/PlatformFactory.php
Original file line number Diff line number Diff line change
Expand Up @@ -26,15 +26,15 @@ final class PlatformFactory
public static function create(
string $hostUrl = 'http://localhost:11434',
?HttpClientInterface $httpClient = null,
ModelCatalogInterface $modelCatalog = new ModelCatalog(),
?ModelCatalogInterface $modelCatalog = null,
?Contract $contract = null,
): Platform {
$httpClient = $httpClient instanceof EventSourceHttpClient ? $httpClient : new EventSourceHttpClient($httpClient);

return new Platform(
[new OllamaClient($httpClient, $hostUrl)],
[new OllamaResultConverter()],
$modelCatalog,
$modelCatalog ?? new OllamaCatalog($hostUrl, $httpClient),
$contract ?? OllamaContract::create(),
);
}
Expand Down
Loading