Skip to content

Commit 3aa39fd

Browse files
authored
feat: add inline tool definition and chain in chain 🤯 (#75)
1 parent 1e10544 commit 3aa39fd

File tree

4 files changed

+56
-3
lines changed

4 files changed

+56
-3
lines changed

README.md

+14-1
Original file line numberDiff line numberDiff line change
@@ -50,7 +50,20 @@ llm_chain:
5050
system_prompt: 'You are a helpful assistant that can answer questions.' # The default system prompt of the chain
5151
include_tools: true # Include tool definitions at the end of the system prompt
5252
tools:
53-
- 'PhpLlm\LlmChain\Chain\ToolBox\Tool\SimilaritySearch'
53+
# Referencing a service with #[AsTool] attribute
54+
- 'PhpLlm\LlmChain\Chain\Toolbox\Tool\SimilaritySearch'
55+
56+
# Referencing a service without #[AsTool] attribute
57+
- service: 'App\Chain\Tool\CompanyName'
58+
name: 'company_name'
59+
description: 'Provides the name of your company'
60+
method: 'foo' # Optional with default value '__invoke'
61+
62+
# Referencing a chain => chain in chain 🤯
63+
- service: 'llm_chain.chain.research'
64+
name: 'wikipedia_research'
65+
description: 'Can research on Wikipedia'
66+
is_chain: true
5467
research:
5568
platform: 'llm_chain.platform.anthropic'
5669
model:

src/DependencyInjection/Configuration.php

+15-1
Original file line numberDiff line numberDiff line change
@@ -98,7 +98,21 @@ public function getConfigTreeBuilder(): TreeBuilder
9898
->children()
9999
->booleanNode('enabled')->defaultTrue()->end()
100100
->arrayNode('services')
101-
->scalarPrototype()->end()
101+
->arrayPrototype()
102+
->children()
103+
->scalarNode('service')->isRequired()->end()
104+
->scalarNode('name')->end()
105+
->scalarNode('description')->end()
106+
->scalarNode('method')->end()
107+
->booleanNode('is_chain')->defaultFalse()->end()
108+
->end()
109+
->beforeNormalization()
110+
->ifString()
111+
->then(function (string $v) {
112+
return ['service' => $v];
113+
})
114+
->end()
115+
->end()
102116
->end()
103117
->end()
104118
->end()

src/DependencyInjection/LlmChainExtension.php

+26-1
Original file line numberDiff line numberDiff line change
@@ -26,6 +26,10 @@
2626
use PhpLlm\LlmChain\Chain\Toolbox\Attribute\AsTool;
2727
use PhpLlm\LlmChain\Chain\Toolbox\ChainProcessor as ToolProcessor;
2828
use PhpLlm\LlmChain\Chain\Toolbox\FaultTolerantToolbox;
29+
use PhpLlm\LlmChain\Chain\Toolbox\MetadataFactory\ChainFactory;
30+
use PhpLlm\LlmChain\Chain\Toolbox\MetadataFactory\MemoryFactory;
31+
use PhpLlm\LlmChain\Chain\Toolbox\MetadataFactory\ReflectionFactory;
32+
use PhpLlm\LlmChain\Chain\Toolbox\Tool\Chain as ChainTool;
2933
use PhpLlm\LlmChain\ChainInterface;
3034
use PhpLlm\LlmChain\Embedder;
3135
use PhpLlm\LlmChain\Model\EmbeddingsModel;
@@ -249,9 +253,30 @@ private function processChainConfig(string $name, array $config, ContainerBuilde
249253
if ($config['tools']['enabled']) {
250254
// Create specific toolbox and process if tools are explicitly defined
251255
if (0 !== count($config['tools']['services'])) {
252-
$tools = array_map(static fn (string $tool) => new Reference($tool), $config['tools']['services']);
256+
$memoryFactoryDefinition = new Definition(MemoryFactory::class);
257+
$container->setDefinition('llm_chain.toolbox.'.$name.'.memory_factory', $memoryFactoryDefinition);
258+
$chainFactoryDefinition = new Definition(ChainFactory::class, [
259+
'$factories' => [new Reference('llm_chain.toolbox.'.$name.'.memory_factory'), new Reference(ReflectionFactory::class)],
260+
]);
261+
$container->setDefinition('llm_chain.toolbox.'.$name.'.chain_factory', $chainFactoryDefinition);
262+
263+
$tools = [];
264+
foreach ($config['tools']['services'] as $tool) {
265+
$reference = new Reference($tool['service']);
266+
// We use the memory factory in case method, description and name are set
267+
if (isset($tool['name'], $tool['description'])) {
268+
if ($tool['is_chain']) {
269+
$chainWrapperDefinition = new Definition(ChainTool::class, ['$chain' => $reference]);
270+
$container->setDefinition('llm_chain.toolbox.'.$name.'.chain_wrapper.'.$tool['name'], $chainWrapperDefinition);
271+
$reference = new Reference('llm_chain.toolbox.'.$name.'.chain_wrapper.'.$tool['name']);
272+
}
273+
$memoryFactoryDefinition->addMethodCall('addTool', [$reference, $tool['name'], $tool['description'], $tool['method'] ?? '__invoke']);
274+
}
275+
$tools[] = $reference;
276+
}
253277

254278
$toolboxDefinition = (new ChildDefinition('llm_chain.toolbox.abstract'))
279+
->replaceArgument('$metadataFactory', new Reference('llm_chain.toolbox.'.$name.'.chain_factory'))
255280
->replaceArgument('$tools', $tools);
256281
$container->setDefinition('llm_chain.toolbox.'.$name, $toolboxDefinition);
257282

src/Resources/config/services.php

+1
Original file line numberDiff line numberDiff line change
@@ -33,6 +33,7 @@
3333
->autowire()
3434
->abstract()
3535
->args([
36+
'$metadataFactory' => service(MetadataFactory::class),
3637
'$tools' => abstract_arg('Collection of tools'),
3738
])
3839
->set(Toolbox::class)

0 commit comments

Comments
 (0)