diff --git a/src/platform/src/Bridge/Ollama/ModelCatalog.php b/src/platform/src/Bridge/Ollama/ModelCatalog.php index 41869a3d2..f3b791ac9 100644 --- a/src/platform/src/Bridge/Ollama/ModelCatalog.php +++ b/src/platform/src/Bridge/Ollama/ModelCatalog.php @@ -12,6 +12,9 @@ namespace Symfony\AI\Platform\Bridge\Ollama; use Symfony\AI\Platform\Capability; +use Symfony\AI\Platform\Exception\InvalidArgumentException; +use Symfony\AI\Platform\Exception\ModelNotFoundException; +use Symfony\AI\Platform\Model; use Symfony\AI\Platform\ModelCatalog\AbstractModelCatalog; /** @@ -20,7 +23,7 @@ final class ModelCatalog extends AbstractModelCatalog { /** - * @param array, capabilities: list}> $additionalModels + * @param array, capabilities: list}> $additionalModels */ public function __construct(array $additionalModels = []) { @@ -210,4 +213,35 @@ public function __construct(array $additionalModels = []) $this->models = array_merge($defaultModels, $additionalModels); } + + public function getModel(string $modelName): Model + { + if ('' === $modelName) { + throw new InvalidArgumentException('Model name cannot be empty.'); + } + + $parsed = self::parseModelName($modelName); + $actualModelName = $parsed['name']; + $options = $parsed['options']; + + $baseModelName = explode(':', $actualModelName, 2)[0]; + + if (!isset($this->models[$actualModelName]) && !isset($this->models[$baseModelName])) { + throw new ModelNotFoundException(\sprintf('Model "%s" not found.', $actualModelName)); + } + + $modelConfig = $this->models[$actualModelName] ?? $this->models[$baseModelName]; + $modelClass = $modelConfig['class']; + + if (!class_exists($modelClass)) { + throw new InvalidArgumentException(\sprintf('Model class "%s" does not exist.', $modelClass)); + } + + $model = new $modelClass($actualModelName, $modelConfig['capabilities'], $options); + if (!$model instanceof Model) { + throw new InvalidArgumentException(\sprintf('Model class "%s" must extend "%s".', $modelClass, Model::class)); + } + + return $model; + } } diff --git a/src/platform/tests/Bridge/Ollama/ModelCatalogTest.php b/src/platform/tests/Bridge/Ollama/ModelCatalogTest.php index 9e1c3fad5..dac4e8b97 100644 --- a/src/platform/tests/Bridge/Ollama/ModelCatalogTest.php +++ b/src/platform/tests/Bridge/Ollama/ModelCatalogTest.php @@ -30,6 +30,7 @@ public static function modelsProvider(): iterable yield 'llama3' => ['llama3', Ollama::class, [Capability::INPUT_MESSAGES, Capability::OUTPUT_TEXT, Capability::OUTPUT_STRUCTURED, Capability::TOOL_CALLING]]; yield 'mistral' => ['mistral', Ollama::class, [Capability::INPUT_MESSAGES, Capability::OUTPUT_TEXT, Capability::OUTPUT_STRUCTURED, Capability::TOOL_CALLING]]; yield 'qwen3' => ['qwen3', Ollama::class, [Capability::INPUT_MESSAGES, Capability::OUTPUT_TEXT, Capability::OUTPUT_STRUCTURED, Capability::TOOL_CALLING]]; + yield 'qwen3:32b' => ['qwen3:32b', Ollama::class, [Capability::INPUT_MESSAGES, Capability::OUTPUT_TEXT, Capability::OUTPUT_STRUCTURED, Capability::TOOL_CALLING]]; yield 'qwen' => ['qwen', Ollama::class, [Capability::INPUT_MESSAGES, Capability::OUTPUT_TEXT, Capability::OUTPUT_STRUCTURED, Capability::TOOL_CALLING]]; yield 'qwen2' => ['qwen2', Ollama::class, [Capability::INPUT_MESSAGES, Capability::OUTPUT_TEXT, Capability::OUTPUT_STRUCTURED, Capability::TOOL_CALLING]]; yield 'qwen2.5' => ['qwen2.5', Ollama::class, [Capability::INPUT_MESSAGES, Capability::OUTPUT_TEXT, Capability::OUTPUT_STRUCTURED, Capability::TOOL_CALLING]]; @@ -45,6 +46,7 @@ public static function modelsProvider(): iterable yield 'nomic-embed-text' => ['nomic-embed-text', Ollama::class, [Capability::INPUT_MESSAGES, Capability::OUTPUT_TEXT, Capability::OUTPUT_STRUCTURED, Capability::INPUT_MULTIPLE]]; yield 'bge-m3' => ['bge-m3', Ollama::class, [Capability::INPUT_MESSAGES, Capability::OUTPUT_TEXT, Capability::OUTPUT_STRUCTURED, Capability::INPUT_MULTIPLE]]; yield 'all-minilm' => ['all-minilm', Ollama::class, [Capability::INPUT_MESSAGES, Capability::OUTPUT_TEXT, Capability::OUTPUT_STRUCTURED, Capability::INPUT_MULTIPLE]]; + yield 'all-minilm:33m' => ['all-minilm:33m', Ollama::class, [Capability::INPUT_MESSAGES, Capability::OUTPUT_TEXT, Capability::OUTPUT_STRUCTURED, Capability::INPUT_MULTIPLE]]; } protected function createModelCatalog(): ModelCatalogInterface