Skip to content

Commit 9003e50

Browse files
committed
minor #507 [Platform][Replicate] Add tests (OskarStark)
This PR was squashed before being merged into the main branch. Discussion ---------- [Platform][Replicate] Add tests | Q | A | ------------- | --- | Bug fix? | no | New feature? | no | Docs? | no | Issues | -- | License | MIT Commits ------- 3ca1d73 [Platform][Replicate] Add tests
2 parents e2463a3 + 3ca1d73 commit 9003e50

File tree

4 files changed

+321
-0
lines changed

4 files changed

+321
-0
lines changed
Lines changed: 79 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,79 @@
1+
<?php
2+
3+
/*
4+
* This file is part of the Symfony package.
5+
*
6+
* (c) Fabien Potencier <fabien@symfony.com>
7+
*
8+
* For the full copyright and license information, please view the LICENSE
9+
* file that was distributed with this source code.
10+
*/
11+
12+
namespace Symfony\AI\Platform\Tests\Bridge\Replicate;
13+
14+
use PHPUnit\Framework\Attributes\CoversClass;
15+
use PHPUnit\Framework\TestCase;
16+
use Symfony\AI\Platform\Bridge\Replicate\Client;
17+
use Symfony\Component\Clock\MockClock;
18+
use Symfony\Component\HttpClient\MockHttpClient;
19+
use Symfony\Component\HttpClient\Response\MockResponse;
20+
21+
/**
22+
* @author Oskar Stark <oskarstark@googlemail.com>
23+
*/
24+
#[CoversClass(Client::class)]
25+
final class ClientTest extends TestCase
26+
{
27+
public function testRequestWithImmediateSuccess()
28+
{
29+
$httpClient = new MockHttpClient(new MockResponse('{"status": "succeeded", "output": ["Hello"]}'));
30+
31+
$client = new Client($httpClient, new MockClock(), 'test-api-key');
32+
$response = $client->request('meta/llama-3.1-405b-instruct', 'predictions', ['prompt' => 'Hello']);
33+
34+
$data = $response->toArray();
35+
$this->assertSame('succeeded', $data['status']);
36+
$this->assertSame(['Hello'], $data['output']);
37+
}
38+
39+
public function testRequestWithPolling()
40+
{
41+
$httpClient = new MockHttpClient([
42+
new MockResponse('{"id": "pred-123", "status": "starting"}'),
43+
new MockResponse('{"id": "pred-123", "status": "processing"}'),
44+
new MockResponse('{"id": "pred-123", "status": "succeeded", "output": ["World"]}'),
45+
]);
46+
47+
$client = new Client($httpClient, new MockClock(), 'test-api-key');
48+
$response = $client->request('meta/llama-3.1-405b-instruct', 'predictions', ['prompt' => 'Hello']);
49+
50+
$data = $response->toArray();
51+
$this->assertSame('succeeded', $data['status']);
52+
$this->assertSame(['World'], $data['output']);
53+
}
54+
55+
public function testRequestAuthenticationHeader()
56+
{
57+
$httpClient = new MockHttpClient(function (string $method, string $url, array $options) {
58+
self::assertSame('Authorization: Bearer secret-key', $options['normalized_headers']['authorization'][0]);
59+
60+
return new MockResponse('{"status": "succeeded"}');
61+
});
62+
63+
$client = new Client($httpClient, new MockClock(), 'secret-key');
64+
$client->request('meta/llama-3.1-405b-instruct', 'predictions', ['prompt' => 'test']);
65+
}
66+
67+
public function testRequestUrl()
68+
{
69+
$httpClient = new MockHttpClient(function (string $method, string $url, array $options) {
70+
self::assertSame('POST', $method);
71+
self::assertSame('https://api.replicate.com/v1/models/meta/llama-3.1-405b-instruct/predictions', $url);
72+
73+
return new MockResponse('{"status": "succeeded"}');
74+
});
75+
76+
$client = new Client($httpClient, new MockClock(), 'test-key');
77+
$client->request('meta/llama-3.1-405b-instruct', 'predictions', ['prompt' => 'test']);
78+
}
79+
}
Lines changed: 79 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,79 @@
1+
<?php
2+
3+
/*
4+
* This file is part of the Symfony package.
5+
*
6+
* (c) Fabien Potencier <fabien@symfony.com>
7+
*
8+
* For the full copyright and license information, please view the LICENSE
9+
* file that was distributed with this source code.
10+
*/
11+
12+
namespace Symfony\AI\Platform\Tests\Bridge\Replicate\Contract;
13+
14+
use PHPUnit\Framework\Attributes\CoversClass;
15+
use PHPUnit\Framework\TestCase;
16+
use Symfony\AI\Platform\Bridge\Meta\Llama;
17+
use Symfony\AI\Platform\Bridge\Replicate\Contract\LlamaMessageBagNormalizer;
18+
use Symfony\AI\Platform\Message\Message;
19+
use Symfony\AI\Platform\Message\MessageBag;
20+
use Symfony\AI\Platform\Model;
21+
22+
/**
23+
* @author Oskar Stark <oskarstark@googlemail.com>
24+
*/
25+
#[CoversClass(LlamaMessageBagNormalizer::class)]
26+
final class LlamaMessageBagNormalizerTest extends TestCase
27+
{
28+
public function testNormalizeWithSystemMessage()
29+
{
30+
$normalizer = new LlamaMessageBagNormalizer();
31+
$messageBag = new MessageBag(
32+
Message::forSystem('You are helpful'),
33+
Message::ofUser('Hello'),
34+
Message::ofAssistant('Hi there')
35+
);
36+
37+
$result = $normalizer->normalize($messageBag, null, ['model' => new Llama('llama-3.1-405b-instruct')]);
38+
39+
$this->assertArrayHasKey('system', $result);
40+
$this->assertArrayHasKey('prompt', $result);
41+
$this->assertStringContainsString('You are helpful', $result['system']);
42+
$this->assertStringContainsString('Hello', $result['prompt']);
43+
$this->assertStringContainsString('Hi there', $result['prompt']);
44+
}
45+
46+
public function testNormalizeWithoutSystemMessage()
47+
{
48+
$normalizer = new LlamaMessageBagNormalizer();
49+
$messageBag = new MessageBag(
50+
Message::ofUser('Hello'),
51+
Message::ofAssistant('Hi there')
52+
);
53+
54+
$result = $normalizer->normalize($messageBag, null, ['model' => new Llama('llama-3.1-405b-instruct')]);
55+
56+
$this->assertArrayHasKey('system', $result);
57+
$this->assertArrayHasKey('prompt', $result);
58+
$this->assertStringContainsString('system', $result['system']);
59+
$this->assertStringContainsString('Hello', $result['prompt']);
60+
$this->assertStringContainsString('Hi there', $result['prompt']);
61+
}
62+
63+
public function testSupportsLlamaModel()
64+
{
65+
$normalizer = new LlamaMessageBagNormalizer();
66+
$messageBag = new MessageBag(Message::ofUser('Hello'));
67+
68+
$this->assertTrue($normalizer->supportsNormalization($messageBag, null, ['model' => new Llama('llama-3.1-405b-instruct')]));
69+
}
70+
71+
public function testDoesNotSupportOtherModels()
72+
{
73+
$normalizer = new LlamaMessageBagNormalizer();
74+
$messageBag = new MessageBag(Message::ofUser('Hello'));
75+
$otherModel = $this->createMock(Model::class);
76+
77+
$this->assertFalse($normalizer->supportsNormalization($messageBag, null, ['model' => $otherModel]));
78+
}
79+
}
Lines changed: 73 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,73 @@
1+
<?php
2+
3+
/*
4+
* This file is part of the Symfony package.
5+
*
6+
* (c) Fabien Potencier <fabien@symfony.com>
7+
*
8+
* For the full copyright and license information, please view the LICENSE
9+
* file that was distributed with this source code.
10+
*/
11+
12+
namespace Symfony\AI\Platform\Tests\Bridge\Replicate;
13+
14+
use PHPUnit\Framework\Attributes\CoversClass;
15+
use PHPUnit\Framework\TestCase;
16+
use Symfony\AI\Platform\Bridge\Meta\Llama;
17+
use Symfony\AI\Platform\Bridge\Replicate\Client;
18+
use Symfony\AI\Platform\Bridge\Replicate\LlamaModelClient;
19+
use Symfony\AI\Platform\Exception\InvalidArgumentException;
20+
use Symfony\AI\Platform\Model;
21+
use Symfony\AI\Platform\Result\RawHttpResult;
22+
use Symfony\Component\Clock\MockClock;
23+
use Symfony\Component\HttpClient\MockHttpClient;
24+
use Symfony\Component\HttpClient\Response\MockResponse;
25+
26+
/**
27+
* @author Oskar Stark <oskarstark@googlemail.com>
28+
*/
29+
#[CoversClass(LlamaModelClient::class)]
30+
final class LlamaModelClientTest extends TestCase
31+
{
32+
public function testSupportsLlamaModel()
33+
{
34+
$httpClient = new MockHttpClient();
35+
$client = new Client($httpClient, new MockClock(), 'test-key');
36+
$modelClient = new LlamaModelClient($client);
37+
38+
$this->assertTrue($modelClient->supports(new Llama('llama-3.1-405b-instruct')));
39+
}
40+
41+
public function testDoesNotSupportOtherModels()
42+
{
43+
$httpClient = new MockHttpClient();
44+
$client = new Client($httpClient, new MockClock(), 'test-key');
45+
$modelClient = new LlamaModelClient($client);
46+
47+
$otherModel = $this->createMock(Model::class);
48+
$this->assertFalse($modelClient->supports($otherModel));
49+
}
50+
51+
public function testRequestWithLlamaModel()
52+
{
53+
$mockResponse = new MockResponse('{"status": "succeeded"}');
54+
$httpClient = new MockHttpClient($mockResponse);
55+
$client = new Client($httpClient, new MockClock(), 'test-key');
56+
57+
$modelClient = new LlamaModelClient($client);
58+
$result = $modelClient->request(new Llama('llama-3.1-405b-instruct'), ['prompt' => 'Hello']);
59+
60+
$this->assertInstanceOf(RawHttpResult::class, $result);
61+
}
62+
63+
public function testRequestThrowsExceptionForUnsupportedModel()
64+
{
65+
$modelClient = new LlamaModelClient(new Client(new MockHttpClient(), new MockClock(), 'test-key'));
66+
$otherModel = $this->createMock(Model::class);
67+
68+
$this->expectException(InvalidArgumentException::class);
69+
$this->expectExceptionMessage('The model must be an instance of "Symfony\AI\Platform\Bridge\Meta\Llama".');
70+
71+
$modelClient->request($otherModel, ['prompt' => 'Hello']);
72+
}
73+
}
Lines changed: 90 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,90 @@
1+
<?php
2+
3+
/*
4+
* This file is part of the Symfony package.
5+
*
6+
* (c) Fabien Potencier <fabien@symfony.com>
7+
*
8+
* For the full copyright and license information, please view the LICENSE
9+
* file that was distributed with this source code.
10+
*/
11+
12+
namespace Symfony\AI\Platform\Tests\Bridge\Replicate;
13+
14+
use PHPUnit\Framework\Attributes\CoversClass;
15+
use PHPUnit\Framework\TestCase;
16+
use Symfony\AI\Platform\Bridge\Meta\Llama;
17+
use Symfony\AI\Platform\Bridge\Replicate\LlamaResultConverter;
18+
use Symfony\AI\Platform\Exception\RuntimeException;
19+
use Symfony\AI\Platform\Model;
20+
use Symfony\AI\Platform\Result\RawResultInterface;
21+
use Symfony\AI\Platform\Result\TextResult;
22+
23+
/**
24+
* @author Oskar Stark <oskarstark@googlemail.com>
25+
*/
26+
#[CoversClass(LlamaResultConverter::class)]
27+
final class LlamaResultConverterTest extends TestCase
28+
{
29+
public function testSupportsLlamaModel()
30+
{
31+
$converter = new LlamaResultConverter();
32+
$this->assertTrue($converter->supports(new Llama('llama-3.1-405b-instruct')));
33+
}
34+
35+
public function testDoesNotSupportOtherModels()
36+
{
37+
$converter = new LlamaResultConverter();
38+
$otherModel = $this->createMock(Model::class);
39+
$this->assertFalse($converter->supports($otherModel));
40+
}
41+
42+
public function testConvertWithSingleOutput()
43+
{
44+
$rawResult = $this->createMock(RawResultInterface::class);
45+
$rawResult->method('getData')->willReturn(['output' => ['Hello world']]);
46+
47+
$converter = new LlamaResultConverter();
48+
$result = $converter->convert($rawResult);
49+
50+
$this->assertInstanceOf(TextResult::class, $result);
51+
$this->assertSame('Hello world', $result->getContent());
52+
}
53+
54+
public function testConvertWithMultipleOutputs()
55+
{
56+
$rawResult = $this->createMock(RawResultInterface::class);
57+
$rawResult->method('getData')->willReturn(['output' => ['Hello', ' ', 'world', '!']]);
58+
59+
$converter = new LlamaResultConverter();
60+
$result = $converter->convert($rawResult);
61+
62+
$this->assertInstanceOf(TextResult::class, $result);
63+
$this->assertSame('Hello world!', $result->getContent());
64+
}
65+
66+
public function testConvertThrowsExceptionWhenOutputMissing()
67+
{
68+
$rawResult = $this->createMock(RawResultInterface::class);
69+
$rawResult->method('getData')->willReturn(['status' => 'succeeded']);
70+
71+
$converter = new LlamaResultConverter();
72+
73+
$this->expectException(RuntimeException::class);
74+
$this->expectExceptionMessage('Response does not contain output.');
75+
76+
$converter->convert($rawResult);
77+
}
78+
79+
public function testConvertWithEmptyOutput()
80+
{
81+
$rawResult = $this->createMock(RawResultInterface::class);
82+
$rawResult->method('getData')->willReturn(['output' => []]);
83+
84+
$converter = new LlamaResultConverter();
85+
$result = $converter->convert($rawResult);
86+
87+
$this->assertInstanceOf(TextResult::class, $result);
88+
$this->assertSame('', $result->getContent());
89+
}
90+
}

0 commit comments

Comments
 (0)