Skip to content
This repository was archived by the owner on Jul 16, 2025. It is now read-only.

Commit 911dcb0

Browse files
committed
Add tests and example
1 parent e33c4bc commit 911dcb0

File tree

5 files changed

+87
-9
lines changed

5 files changed

+87
-9
lines changed
Lines changed: 34 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,34 @@
1+
<?php
2+
3+
use PhpLlm\LlmChain\Bridge\OpenAI\GPT;
4+
use PhpLlm\LlmChain\Bridge\OpenAI\PlatformFactory;
5+
use PhpLlm\LlmChain\Chain;
6+
use PhpLlm\LlmChain\Chain\ToolBox\ChainProcessor;
7+
use PhpLlm\LlmChain\Chain\ToolBox\Tool\ClockWithoutAttribute;
8+
use PhpLlm\LlmChain\Chain\ToolBox\ToolAnalyzer;
9+
use PhpLlm\LlmChain\Chain\ToolBox\ToolBox;
10+
use PhpLlm\LlmChain\Model\Message\Message;
11+
use PhpLlm\LlmChain\Model\Message\MessageBag;
12+
use Symfony\Component\Clock\Clock as SymfonyClock;
13+
use Symfony\Component\Dotenv\Dotenv;
14+
15+
require_once dirname(__DIR__).'/vendor/autoload.php';
16+
(new Dotenv())->loadEnv(dirname(__DIR__).'/.env');
17+
18+
if (empty($_ENV['OPENAI_API_KEY'])) {
19+
echo 'Please set the OPENAI_API_KEY environment variable.'.PHP_EOL;
20+
exit(1);
21+
}
22+
23+
$platform = PlatformFactory::create($_ENV['OPENAI_API_KEY']);
24+
$llm = new GPT(GPT::GPT_4O_MINI);
25+
26+
$clock = new ClockWithoutAttribute(new SymfonyClock());
27+
$toolBox = new ToolBox(new ToolAnalyzer(), ['clock' => $clock]);
28+
$processor = new ChainProcessor($toolBox);
29+
$chain = new Chain($platform, $llm, [$processor], [$processor]);
30+
31+
$messages = new MessageBag(Message::ofUser('What date and time is it?'));
32+
$response = $chain->call($messages);
33+
34+
echo $response->getContent().PHP_EOL;

src/Chain/ToolBox/ChainProcessor.php

Lines changed: 2 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -19,7 +19,7 @@ final class ChainProcessor implements InputProcessor, OutputProcessor, ChainAwar
1919
use ChainAwareTrait;
2020

2121
public function __construct(
22-
private readonly ToolBoxInterface $toolBox,
22+
private ToolBoxInterface $toolBox,
2323
) {
2424
}
2525

@@ -30,12 +30,11 @@ public function processInput(Input $input): void
3030
}
3131

3232
$toolMap = $this->toolBox->getMap();
33-
34-
$options = $input->getOptions();
3533
if ([] === $toolMap) {
3634
return;
3735
}
3836

37+
$options = $input->getOptions();
3938
$options['tools'] = $toolMap;
4039
$input->setOptions($options);
4140
}

src/Chain/ToolBox/ToolAnalyzer.php

Lines changed: 1 addition & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -15,7 +15,6 @@ public function __construct(
1515
}
1616

1717
/**
18-
* @param int|string $toolKey
1918
* @param class-string $className
2019
*
2120
* @return iterable<Metadata>
@@ -26,7 +25,7 @@ public function getMetadata(string|int $toolKey, string $className): iterable
2625
$attributes = $reflectionClass->getAttributes(AsTool::class);
2726

2827
if (0 === \count($attributes)) {
29-
if (true !== is_string($toolKey)) {
28+
if (false === is_string($toolKey)) {
3029
throw new InvalidToolImplementation('Use AsTool attribute to configure your tools or create your toolBox like "new ToolBox([\'toolName\' => $toolInstance]")');
3130
}
3231

tests/Chain/ToolBox/ToolAnalyzerTest.php

Lines changed: 33 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -11,6 +11,7 @@
1111
use PhpLlm\LlmChain\Exception\InvalidToolImplementation;
1212
use PhpLlm\LlmChain\Tests\Fixture\Tool\ToolMultiple;
1313
use PhpLlm\LlmChain\Tests\Fixture\Tool\ToolRequiredParams;
14+
use PhpLlm\LlmChain\Tests\Fixture\Tool\ToolWithoutAttribute;
1415
use PhpLlm\LlmChain\Tests\Fixture\Tool\ToolWrong;
1516
use PHPUnit\Framework\Attributes\CoversClass;
1617
use PHPUnit\Framework\Attributes\Test;
@@ -32,17 +33,45 @@ protected function setUp(): void
3233
}
3334

3435
#[Test]
35-
public function withoutAttribute(): void
36+
public function toolWrong(): void
3637
{
3738
$this->expectException(InvalidToolImplementation::class);
38-
iterator_to_array($this->toolAnalyzer->getMetadata(ToolWrong::class));
39+
iterator_to_array($this->toolAnalyzer->getMetadata(0, ToolWrong::class));
40+
}
41+
42+
#[Test]
43+
public function toolWithoutAttribute(): void
44+
{
45+
$metadatas = iterator_to_array($this->toolAnalyzer->getMetadata('tool_without_attribute', ToolWithoutAttribute::class));
46+
47+
self::assertToolConfiguration(
48+
metadata: $metadatas[0],
49+
className: ToolWithoutAttribute::class,
50+
name: 'tool_without_attribute',
51+
description: 'Use "AsTool" attribute to add description',
52+
method: '__invoke',
53+
parameters: [
54+
'type' => 'object',
55+
'properties' => [
56+
'text' => [
57+
'type' => 'string',
58+
'description' => 'The text given to the tool',
59+
],
60+
'number' => [
61+
'type' => 'integer',
62+
'description' => 'A number given to the tool',
63+
],
64+
],
65+
'required' => ['text', 'number'],
66+
],
67+
);
3968
}
4069

4170
#[Test]
4271
public function getDefinition(): void
4372
{
4473
/** @var Metadata[] $metadatas */
45-
$metadatas = iterator_to_array($this->toolAnalyzer->getMetadata(ToolRequiredParams::class));
74+
$metadatas = iterator_to_array($this->toolAnalyzer->getMetadata(0, ToolRequiredParams::class));
4675

4776
self::assertToolConfiguration(
4877
metadata: $metadatas[0],
@@ -70,7 +99,7 @@ className: ToolRequiredParams::class,
7099
#[Test]
71100
public function getDefinitionWithMultiple(): void
72101
{
73-
$metadatas = iterator_to_array($this->toolAnalyzer->getMetadata(ToolMultiple::class));
102+
$metadatas = iterator_to_array($this->toolAnalyzer->getMetadata(0, ToolMultiple::class));
74103

75104
self::assertCount(2, $metadatas);
76105

Lines changed: 17 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,17 @@
1+
<?php
2+
3+
declare(strict_types=1);
4+
5+
namespace PhpLlm\LlmChain\Tests\Fixture\Tool;
6+
7+
final class ToolWithoutAttribute
8+
{
9+
/**
10+
* @param string $text The text given to the tool
11+
* @param int $number A number given to the tool
12+
*/
13+
public function __invoke(string $text, int $number): string
14+
{
15+
return sprintf('%s says "%d".', $text, $number);
16+
}
17+
}

0 commit comments

Comments
 (0)