From efd1b9642e79530b2b200c2d45a130ab0f4b821f Mon Sep 17 00:00:00 2001 From: Christopher Hertel Date: Sun, 1 Jun 2025 16:11:41 +0200 Subject: [PATCH] chore: support LLM Chain 0.22 --- Makefile | 3 - composer.json | 2 +- src/DependencyInjection/Configuration.php | 2 +- src/DependencyInjection/LlmChainExtension.php | 74 ++++++++----------- src/Profiler/DataCollector.php | 6 +- src/Profiler/TraceablePlatform.php | 10 +-- src/Profiler/TraceableToolbox.php | 6 +- src/Resources/config/services.php | 10 +-- tests/Profiler/TraceableToolboxTest.php | 24 +++--- 9 files changed, 62 insertions(+), 75 deletions(-) diff --git a/Makefile b/Makefile index 73a44fa..05ae363 100644 --- a/Makefile +++ b/Makefile @@ -35,6 +35,3 @@ ci-lowest: deps-low rector cs phpstan tests ci-dev: deps-dev rector cs phpstan tests git restore composer.json - -coverage: - XDEBUG_MODE=coverage vendor/bin/phpunit --coverage-html=coverage diff --git a/composer.json b/composer.json index 1617889..5f74bf4 100644 --- a/composer.json +++ b/composer.json @@ -15,7 +15,7 @@ ], "require": { "php": ">=8.2", - "php-llm/llm-chain": "^0.21", + "php-llm/llm-chain": "^0.22", "symfony/config": "^6.4 || ^7.0", "symfony/dependency-injection": "^6.4 || ^7.0", "symfony/framework-bundle": "^6.4 || ^7.0", diff --git a/src/DependencyInjection/Configuration.php b/src/DependencyInjection/Configuration.php index 890b0c6..340a337 100644 --- a/src/DependencyInjection/Configuration.php +++ b/src/DependencyInjection/Configuration.php @@ -4,7 +4,7 @@ namespace PhpLlm\LlmChainBundle\DependencyInjection; -use PhpLlm\LlmChain\PlatformInterface; +use PhpLlm\LlmChain\Platform\PlatformInterface; use PhpLlm\LlmChain\Store\StoreInterface; use Symfony\Component\Config\Definition\Builder\TreeBuilder; use Symfony\Component\Config\Definition\ConfigurationInterface; diff --git a/src/DependencyInjection/LlmChainExtension.php b/src/DependencyInjection/LlmChainExtension.php index ae2cce9..81fbbce 100644 --- a/src/DependencyInjection/LlmChainExtension.php +++ b/src/DependencyInjection/LlmChainExtension.php @@ -4,40 +4,38 @@ namespace PhpLlm\LlmChainBundle\DependencyInjection; -use PhpLlm\LlmChain\Bridge\Anthropic\Claude; -use PhpLlm\LlmChain\Bridge\Anthropic\PlatformFactory as AnthropicPlatformFactory; -use PhpLlm\LlmChain\Bridge\Azure\OpenAI\PlatformFactory as AzureOpenAIPlatformFactory; -use PhpLlm\LlmChain\Bridge\Azure\Store\SearchStore as AzureSearchStore; -use PhpLlm\LlmChain\Bridge\ChromaDB\Store as ChromaDBStore; -use PhpLlm\LlmChain\Bridge\Google\Gemini; -use PhpLlm\LlmChain\Bridge\Google\PlatformFactory as GooglePlatformFactory; -use PhpLlm\LlmChain\Bridge\Meta\Llama; -use PhpLlm\LlmChain\Bridge\MongoDB\Store as MongoDBStore; -use PhpLlm\LlmChain\Bridge\OpenAI\Embeddings; -use PhpLlm\LlmChain\Bridge\OpenAI\GPT; -use PhpLlm\LlmChain\Bridge\OpenAI\PlatformFactory as OpenAIPlatformFactory; -use PhpLlm\LlmChain\Bridge\Pinecone\Store as PineconeStore; -use PhpLlm\LlmChain\Bridge\Voyage\Voyage; -use PhpLlm\LlmChain\Chain; -use PhpLlm\LlmChain\Chain\InputProcessor; +use PhpLlm\LlmChain\Chain\Chain; +use PhpLlm\LlmChain\Chain\ChainInterface; use PhpLlm\LlmChain\Chain\InputProcessor\SystemPromptInputProcessor; -use PhpLlm\LlmChain\Chain\OutputProcessor; +use PhpLlm\LlmChain\Chain\InputProcessorInterface; +use PhpLlm\LlmChain\Chain\OutputProcessorInterface; use PhpLlm\LlmChain\Chain\StructuredOutput\ChainProcessor as StructureOutputProcessor; use PhpLlm\LlmChain\Chain\Toolbox\Attribute\AsTool; use PhpLlm\LlmChain\Chain\Toolbox\ChainProcessor as ToolProcessor; use PhpLlm\LlmChain\Chain\Toolbox\FaultTolerantToolbox; -use PhpLlm\LlmChain\Chain\Toolbox\MetadataFactory\ChainFactory; -use PhpLlm\LlmChain\Chain\Toolbox\MetadataFactory\MemoryFactory; -use PhpLlm\LlmChain\Chain\Toolbox\MetadataFactory\ReflectionFactory; use PhpLlm\LlmChain\Chain\Toolbox\Tool\Chain as ChainTool; -use PhpLlm\LlmChain\ChainInterface; -use PhpLlm\LlmChain\Embedder; -use PhpLlm\LlmChain\Model\EmbeddingsModel; -use PhpLlm\LlmChain\Model\LanguageModel; -use PhpLlm\LlmChain\Platform; -use PhpLlm\LlmChain\Platform\ModelClient; -use PhpLlm\LlmChain\Platform\ResponseConverter; -use PhpLlm\LlmChain\PlatformInterface; +use PhpLlm\LlmChain\Chain\Toolbox\ToolFactory\ChainFactory; +use PhpLlm\LlmChain\Chain\Toolbox\ToolFactory\MemoryToolFactory; +use PhpLlm\LlmChain\Chain\Toolbox\ToolFactory\ReflectionToolFactory; +use PhpLlm\LlmChain\Platform\Bridge\Anthropic\Claude; +use PhpLlm\LlmChain\Platform\Bridge\Anthropic\PlatformFactory as AnthropicPlatformFactory; +use PhpLlm\LlmChain\Platform\Bridge\Azure\OpenAI\PlatformFactory as AzureOpenAIPlatformFactory; +use PhpLlm\LlmChain\Platform\Bridge\Google\Gemini; +use PhpLlm\LlmChain\Platform\Bridge\Google\PlatformFactory as GooglePlatformFactory; +use PhpLlm\LlmChain\Platform\Bridge\Meta\Llama; +use PhpLlm\LlmChain\Platform\Bridge\OpenAI\Embeddings; +use PhpLlm\LlmChain\Platform\Bridge\OpenAI\GPT; +use PhpLlm\LlmChain\Platform\Bridge\OpenAI\PlatformFactory as OpenAIPlatformFactory; +use PhpLlm\LlmChain\Platform\Bridge\Voyage\Voyage; +use PhpLlm\LlmChain\Platform\ModelClientInterface; +use PhpLlm\LlmChain\Platform\Platform; +use PhpLlm\LlmChain\Platform\PlatformInterface; +use PhpLlm\LlmChain\Platform\ResponseConverterInterface; +use PhpLlm\LlmChain\Store\Bridge\Azure\SearchStore as AzureSearchStore; +use PhpLlm\LlmChain\Store\Bridge\ChromaDB\Store as ChromaDBStore; +use PhpLlm\LlmChain\Store\Bridge\MongoDB\Store as MongoDBStore; +use PhpLlm\LlmChain\Store\Bridge\Pinecone\Store as PineconeStore; +use PhpLlm\LlmChain\Store\Embedder; use PhpLlm\LlmChain\Store\StoreInterface; use PhpLlm\LlmChain\Store\VectorStoreInterface; use PhpLlm\LlmChainBundle\Profiler\DataCollector; @@ -86,10 +84,6 @@ public function load(array $configs, ContainerBuilder $container): void if (1 === count($config['chain']) && isset($chainName)) { $container->setAlias(ChainInterface::class, 'llm_chain.chain.'.$chainName); } - $llms = array_keys($container->findTaggedServiceIds('llm_chain.model.language_model')); - if (1 === count($llms)) { - $container->setAlias(LanguageModel::class, reset($llms)); - } foreach ($config['store'] ?? [] as $type => $store) { $this->processStoreConfig($type, $store, $container); @@ -106,10 +100,6 @@ public function load(array $configs, ContainerBuilder $container): void if (1 === count($config['embedder']) && isset($embedderName)) { $container->setAlias(Embedder::class, 'llm_chain.embedder.'.$embedderName); } - $embeddings = array_keys($container->findTaggedServiceIds('llm_chain.model.embeddings_model')); - if (1 === count($embeddings)) { - $container->setAlias(EmbeddingsModel::class, reset($embeddings)); - } $container->registerAttributeForAutoconfiguration(AsTool::class, static function (ChildDefinition $definition, AsTool $attribute): void { $definition->addTag('llm_chain.tool', [ @@ -119,13 +109,13 @@ public function load(array $configs, ContainerBuilder $container): void ]); }); - $container->registerForAutoconfiguration(InputProcessor::class) + $container->registerForAutoconfiguration(InputProcessorInterface::class) ->addTag('llm_chain.chain.input_processor'); - $container->registerForAutoconfiguration(OutputProcessor::class) + $container->registerForAutoconfiguration(OutputProcessorInterface::class) ->addTag('llm_chain.chain.output_processor'); - $container->registerForAutoconfiguration(ModelClient::class) + $container->registerForAutoconfiguration(ModelClientInterface::class) ->addTag('llm_chain.platform.model_client'); - $container->registerForAutoconfiguration(ResponseConverter::class) + $container->registerForAutoconfiguration(ResponseConverterInterface::class) ->addTag('llm_chain.platform.response_converter'); if (false === $container->getParameter('kernel.debug')) { @@ -253,10 +243,10 @@ private function processChainConfig(string $name, array $config, ContainerBuilde if ($config['tools']['enabled']) { // Create specific toolbox and process if tools are explicitly defined if (0 !== count($config['tools']['services'])) { - $memoryFactoryDefinition = new Definition(MemoryFactory::class); + $memoryFactoryDefinition = new Definition(MemoryToolFactory::class); $container->setDefinition('llm_chain.toolbox.'.$name.'.memory_factory', $memoryFactoryDefinition); $chainFactoryDefinition = new Definition(ChainFactory::class, [ - '$factories' => [new Reference('llm_chain.toolbox.'.$name.'.memory_factory'), new Reference(ReflectionFactory::class)], + '$factories' => [new Reference('llm_chain.toolbox.'.$name.'.memory_factory'), new Reference(ReflectionToolFactory::class)], ]); $container->setDefinition('llm_chain.toolbox.'.$name.'.chain_factory', $chainFactoryDefinition); diff --git a/src/Profiler/DataCollector.php b/src/Profiler/DataCollector.php index bb4ca99..b95c981 100644 --- a/src/Profiler/DataCollector.php +++ b/src/Profiler/DataCollector.php @@ -4,8 +4,8 @@ namespace PhpLlm\LlmChainBundle\Profiler; -use PhpLlm\LlmChain\Chain\Toolbox\Metadata; use PhpLlm\LlmChain\Chain\Toolbox\ToolboxInterface; +use PhpLlm\LlmChain\Platform\Tool\Tool; use Symfony\Bundle\FrameworkBundle\DataCollector\AbstractDataCollector; use Symfony\Component\DependencyInjection\Attribute\TaggedIterator; use Symfony\Component\HttpFoundation\Request; @@ -45,7 +45,7 @@ public function __construct( public function collect(Request $request, Response $response, ?\Throwable $exception = null): void { $this->data = [ - 'tools' => $this->defaultToolBox->getMap(), + 'tools' => $this->defaultToolBox->getTools(), 'platform_calls' => array_merge(...array_map(fn (TraceablePlatform $platform) => $platform->calls, $this->platforms)), 'tool_calls' => array_merge(...array_map(fn (TraceableToolbox $toolbox) => $toolbox->calls, $this->toolboxes)), ]; @@ -65,7 +65,7 @@ public function getPlatformCalls(): array } /** - * @return Metadata[] + * @return Tool[] */ public function getTools(): array { diff --git a/src/Profiler/TraceablePlatform.php b/src/Profiler/TraceablePlatform.php index 229aa1f..f10caff 100644 --- a/src/Profiler/TraceablePlatform.php +++ b/src/Profiler/TraceablePlatform.php @@ -4,11 +4,11 @@ namespace PhpLlm\LlmChainBundle\Profiler; -use PhpLlm\LlmChain\Model\Message\Content\File; -use PhpLlm\LlmChain\Model\Model; -use PhpLlm\LlmChain\Model\Response\AsyncResponse; -use PhpLlm\LlmChain\Model\Response\ResponseInterface; -use PhpLlm\LlmChain\PlatformInterface; +use PhpLlm\LlmChain\Platform\Message\Content\File; +use PhpLlm\LlmChain\Platform\Model; +use PhpLlm\LlmChain\Platform\PlatformInterface; +use PhpLlm\LlmChain\Platform\Response\AsyncResponse; +use PhpLlm\LlmChain\Platform\Response\ResponseInterface; /** * @phpstan-type PlatformCallData array{ diff --git a/src/Profiler/TraceableToolbox.php b/src/Profiler/TraceableToolbox.php index ed8d247..ccbd63f 100644 --- a/src/Profiler/TraceableToolbox.php +++ b/src/Profiler/TraceableToolbox.php @@ -5,7 +5,7 @@ namespace PhpLlm\LlmChainBundle\Profiler; use PhpLlm\LlmChain\Chain\Toolbox\ToolboxInterface; -use PhpLlm\LlmChain\Model\Response\ToolCall; +use PhpLlm\LlmChain\Platform\Response\ToolCall; /** * @phpstan-type ToolCallData array{ @@ -25,9 +25,9 @@ public function __construct( ) { } - public function getMap(): array + public function getTools(): array { - return $this->toolbox->getMap(); + return $this->toolbox->getTools(); } public function execute(ToolCall $toolCall): mixed diff --git a/src/Resources/config/services.php b/src/Resources/config/services.php index 3092fcb..8581a8e 100644 --- a/src/Resources/config/services.php +++ b/src/Resources/config/services.php @@ -8,10 +8,10 @@ use PhpLlm\LlmChain\Chain\StructuredOutput\ResponseFormatFactory; use PhpLlm\LlmChain\Chain\StructuredOutput\ResponseFormatFactoryInterface; use PhpLlm\LlmChain\Chain\Toolbox\ChainProcessor as ToolProcessor; -use PhpLlm\LlmChain\Chain\Toolbox\MetadataFactory; -use PhpLlm\LlmChain\Chain\Toolbox\MetadataFactory\ReflectionFactory; use PhpLlm\LlmChain\Chain\Toolbox\Toolbox; use PhpLlm\LlmChain\Chain\Toolbox\ToolboxInterface; +use PhpLlm\LlmChain\Chain\Toolbox\ToolFactory\ReflectionToolFactory; +use PhpLlm\LlmChain\Chain\Toolbox\ToolFactoryInterface; use PhpLlm\LlmChainBundle\Profiler\DataCollector; use PhpLlm\LlmChainBundle\Profiler\TraceableToolbox; @@ -33,7 +33,7 @@ ->autowire() ->abstract() ->args([ - '$metadataFactory' => service(MetadataFactory::class), + '$metadataFactory' => service(ToolFactoryInterface::class), '$tools' => abstract_arg('Collection of tools'), ]) ->set(Toolbox::class) @@ -42,8 +42,8 @@ '$tools' => tagged_iterator('llm_chain.tool'), ]) ->alias(ToolboxInterface::class, Toolbox::class) - ->set(ReflectionFactory::class) - ->alias(MetadataFactory::class, ReflectionFactory::class) + ->set(ReflectionToolFactory::class) + ->alias(ToolFactoryInterface::class, ReflectionToolFactory::class) ->set('llm_chain.tool.chain_processor.abstract') ->class(ToolProcessor::class) ->abstract() diff --git a/tests/Profiler/TraceableToolboxTest.php b/tests/Profiler/TraceableToolboxTest.php index 64edd64..f037d61 100644 --- a/tests/Profiler/TraceableToolboxTest.php +++ b/tests/Profiler/TraceableToolboxTest.php @@ -4,10 +4,10 @@ namespace PhpLlm\LlmChainBundle\Tests\Profiler; -use PhpLlm\LlmChain\Chain\Toolbox\ExecutionReference; -use PhpLlm\LlmChain\Chain\Toolbox\Metadata; use PhpLlm\LlmChain\Chain\Toolbox\ToolboxInterface; -use PhpLlm\LlmChain\Model\Response\ToolCall; +use PhpLlm\LlmChain\Platform\Response\ToolCall; +use PhpLlm\LlmChain\Platform\Tool\ExecutionReference; +use PhpLlm\LlmChain\Platform\Tool\Tool; use PhpLlm\LlmChainBundle\Profiler\TraceableToolbox; use PHPUnit\Framework\Attributes\CoversClass; use PHPUnit\Framework\Attributes\Small; @@ -21,11 +21,11 @@ final class TraceableToolboxTest extends TestCase #[Test] public function getMap(): void { - $metadata = new Metadata(new ExecutionReference('Foo\Bar'), 'bar', 'description', null); + $metadata = new Tool(new ExecutionReference('Foo\Bar'), 'bar', 'description', null); $toolbox = $this->createToolbox(['tool' => $metadata]); $traceableToolbox = new TraceableToolbox($toolbox); - $map = $traceableToolbox->getMap(); + $map = $traceableToolbox->getTools(); self::assertSame(['tool' => $metadata], $map); } @@ -33,7 +33,7 @@ public function getMap(): void #[Test] public function execute(): void { - $metadata = new Metadata(new ExecutionReference('Foo\Bar'), 'bar', 'description', null); + $metadata = new Tool(new ExecutionReference('Foo\Bar'), 'bar', 'description', null); $toolbox = $this->createToolbox(['tool' => $metadata]); $traceableToolbox = new TraceableToolbox($toolbox); $toolCall = new ToolCall('foo', '__invoke'); @@ -47,19 +47,19 @@ public function execute(): void } /** - * @param Metadata[] $metadata + * @param Tool[] $tools */ - private function createToolbox(array $metadata): ToolboxInterface + private function createToolbox(array $tools): ToolboxInterface { - return new class($metadata) implements ToolboxInterface { + return new class($tools) implements ToolboxInterface { public function __construct( - private readonly array $metadata, + private readonly array $tools, ) { } - public function getMap(): array + public function getTools(): array { - return $this->metadata; + return $this->tools; } public function execute(ToolCall $toolCall): string