Thanks to visit codestin.com
Credit goes to github.com

Skip to content

Commit 89a969d

Browse files
committed
[Platform] Split bridges into dedicated packages
1 parent 8c8dedc commit 89a969d

11 files changed

Lines changed: 671 additions & 0 deletions

README.md

Lines changed: 12 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,12 @@
1+
Perplexity Platform
2+
===================
3+
4+
Perplexity platform bridge for Symfony AI.
5+
6+
Resources
7+
---------
8+
9+
* [Contributing](https://symfony.com/doc/current/contributing/index.html)
10+
* [Report issues](https://github.com/symfony/ai/issues) and
11+
[send Pull Requests](https://github.com/symfony/ai/pulls)
12+
in the [main Symfony AI repository](https://github.com/symfony/ai)
Lines changed: 66 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,66 @@
1+
<?php
2+
3+
/*
4+
* This file is part of the Symfony package.
5+
*
6+
* (c) Fabien Potencier <[email protected]>
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\Bridge\Perplexity\Tests\Contract;
13+
14+
use PHPUnit\Framework\Attributes\DataProvider;
15+
use PHPUnit\Framework\TestCase;
16+
use Symfony\AI\Platform\Bridge\Perplexity\Contract\FileUrlNormalizer;
17+
use Symfony\AI\Platform\Bridge\Perplexity\Perplexity;
18+
use Symfony\AI\Platform\Contract;
19+
use Symfony\AI\Platform\Message\Content\DocumentUrl;
20+
21+
final class FileUrlNormalizerTest extends TestCase
22+
{
23+
public function testSupportsNormalization()
24+
{
25+
$normalizer = new FileUrlNormalizer();
26+
27+
$this->assertTrue($normalizer->supportsNormalization(new DocumentUrl(\dirname(__DIR__, 7).'/fixtures/not-a-document.pdf'), context: [
28+
Contract::CONTEXT_MODEL => new Perplexity('sonar'),
29+
]));
30+
$this->assertFalse($normalizer->supportsNormalization('not a document'));
31+
}
32+
33+
public function testGetSupportedTypes()
34+
{
35+
$normalizer = new FileUrlNormalizer();
36+
37+
$expected = [
38+
DocumentUrl::class => true,
39+
];
40+
41+
$this->assertSame($expected, $normalizer->getSupportedTypes(null));
42+
}
43+
44+
#[DataProvider('normalizeDataProvider')]
45+
public function testNormalize(DocumentUrl $document, array $expected)
46+
{
47+
$normalizer = new FileUrlNormalizer();
48+
49+
$normalized = $normalizer->normalize($document);
50+
51+
$this->assertEquals($expected, $normalized);
52+
}
53+
54+
public static function normalizeDataProvider(): iterable
55+
{
56+
yield 'document from file url' => [
57+
new DocumentUrl(\dirname(__DIR__, 7).'/fixtures/document.pdf'),
58+
[
59+
'type' => 'file_url',
60+
'file_url' => [
61+
'url' => \dirname(__DIR__, 7).'/fixtures/document.pdf',
62+
],
63+
],
64+
];
65+
}
66+
}

Tests/ModelCatalogTest.php

Lines changed: 38 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,38 @@
1+
<?php
2+
3+
/*
4+
* This file is part of the Symfony package.
5+
*
6+
* (c) Fabien Potencier <[email protected]>
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\Bridge\Perplexity\Tests;
13+
14+
use Symfony\AI\Platform\Bridge\Perplexity\ModelCatalog;
15+
use Symfony\AI\Platform\Bridge\Perplexity\Perplexity;
16+
use Symfony\AI\Platform\Capability;
17+
use Symfony\AI\Platform\ModelCatalog\ModelCatalogInterface;
18+
use Symfony\AI\Platform\Test\ModelCatalogTestCase;
19+
20+
/**
21+
* @author Oskar Stark <[email protected]>
22+
*/
23+
final class ModelCatalogTest extends ModelCatalogTestCase
24+
{
25+
public static function modelsProvider(): iterable
26+
{
27+
yield 'sonar' => ['sonar', Perplexity::class, [Capability::INPUT_MESSAGES, Capability::INPUT_PDF, Capability::OUTPUT_TEXT, Capability::OUTPUT_STREAMING, Capability::OUTPUT_STRUCTURED, Capability::INPUT_IMAGE]];
28+
yield 'sonar-pro' => ['sonar-pro', Perplexity::class, [Capability::INPUT_MESSAGES, Capability::INPUT_PDF, Capability::OUTPUT_TEXT, Capability::OUTPUT_STREAMING, Capability::OUTPUT_STRUCTURED, Capability::INPUT_IMAGE]];
29+
yield 'sonar-reasoning' => ['sonar-reasoning', Perplexity::class, [Capability::INPUT_MESSAGES, Capability::INPUT_PDF, Capability::OUTPUT_TEXT, Capability::OUTPUT_STREAMING, Capability::OUTPUT_STRUCTURED, Capability::INPUT_IMAGE]];
30+
yield 'sonar-reasoning-pro' => ['sonar-reasoning-pro', Perplexity::class, [Capability::INPUT_MESSAGES, Capability::INPUT_PDF, Capability::OUTPUT_TEXT, Capability::OUTPUT_STREAMING, Capability::OUTPUT_STRUCTURED, Capability::INPUT_IMAGE]];
31+
yield 'sonar-deep-research' => ['sonar-deep-research', Perplexity::class, [Capability::INPUT_MESSAGES, Capability::INPUT_PDF, Capability::OUTPUT_TEXT, Capability::OUTPUT_STREAMING, Capability::OUTPUT_STRUCTURED]];
32+
}
33+
34+
protected function createModelCatalog(): ModelCatalogInterface
35+
{
36+
return new ModelCatalog();
37+
}
38+
}

Tests/ModelClientTest.php

Lines changed: 110 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,110 @@
1+
<?php
2+
3+
/*
4+
* This file is part of the Symfony package.
5+
*
6+
* (c) Fabien Potencier <[email protected]>
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 Bridge\Perplexity;
13+
14+
use PHPUnit\Framework\Attributes\TestWith;
15+
use PHPUnit\Framework\TestCase;
16+
use Symfony\AI\Platform\Bridge\Perplexity\ModelClient;
17+
use Symfony\AI\Platform\Bridge\Perplexity\Perplexity;
18+
use Symfony\AI\Platform\Exception\InvalidArgumentException;
19+
use Symfony\Component\HttpClient\EventSourceHttpClient;
20+
use Symfony\Component\HttpClient\MockHttpClient;
21+
use Symfony\Component\HttpClient\Response\MockResponse;
22+
use Symfony\Contracts\HttpClient\ResponseInterface as HttpResponse;
23+
24+
/**
25+
* @author Mathieu Santostefano <[email protected]>
26+
*/
27+
final class ModelClientTest extends TestCase
28+
{
29+
public function testItThrowsExceptionWhenApiKeyIsEmpty()
30+
{
31+
$this->expectException(InvalidArgumentException::class);
32+
$this->expectExceptionMessage('The API key must not be empty.');
33+
34+
new ModelClient(new MockHttpClient(), '');
35+
}
36+
37+
#[TestWith(['api-key-without-prefix'])]
38+
#[TestWith(['plx-api-key'])]
39+
#[TestWith(['PPLX-api-key'])]
40+
#[TestWith(['pplxapikey'])]
41+
#[TestWith(['pplx api-key'])]
42+
#[TestWith(['pplx'])]
43+
public function testItThrowsExceptionWhenApiKeyDoesNotStartWithPplx(string $invalidApiKey)
44+
{
45+
$this->expectException(InvalidArgumentException::class);
46+
$this->expectExceptionMessage('The API key must start with "pplx-".');
47+
48+
new ModelClient(new MockHttpClient(), $invalidApiKey);
49+
}
50+
51+
public function testItAcceptsValidApiKey()
52+
{
53+
$modelClient = new ModelClient(new MockHttpClient(), 'pplx-valid-api-key');
54+
55+
$this->assertInstanceOf(ModelClient::class, $modelClient);
56+
}
57+
58+
public function testItWrapsHttpClientInEventSourceHttpClient()
59+
{
60+
$httpClient = new MockHttpClient();
61+
$modelClient = new ModelClient($httpClient, 'pplx-valid-api-key');
62+
63+
$this->assertInstanceOf(ModelClient::class, $modelClient);
64+
}
65+
66+
public function testItAcceptsEventSourceHttpClientDirectly()
67+
{
68+
$httpClient = new EventSourceHttpClient(new MockHttpClient());
69+
$modelClient = new ModelClient($httpClient, 'pplx-valid-api-key');
70+
71+
$this->assertInstanceOf(ModelClient::class, $modelClient);
72+
}
73+
74+
public function testItIsSupportingTheCorrectModel()
75+
{
76+
$modelClient = new ModelClient(new MockHttpClient(), 'pplx-api-key');
77+
78+
$this->assertTrue($modelClient->supports(new Perplexity('sonar')));
79+
}
80+
81+
public function testItIsExecutingTheCorrectRequest()
82+
{
83+
$resultCallback = static function (string $method, string $url, array $options): HttpResponse {
84+
self::assertSame('POST', $method);
85+
self::assertSame('https://api.perplexity.ai/chat/completions', $url);
86+
self::assertSame('Authorization: Bearer pplx-api-key', $options['normalized_headers']['authorization'][0]);
87+
self::assertSame('{"model":"sonar","messages":[{"role":"user","content":"test message"}]}', $options['body']);
88+
89+
return new MockResponse();
90+
};
91+
$httpClient = new MockHttpClient([$resultCallback]);
92+
$modelClient = new ModelClient($httpClient, 'pplx-api-key');
93+
$modelClient->request(new Perplexity('sonar'), ['model' => 'sonar', 'messages' => [['role' => 'user', 'content' => 'test message']]]);
94+
}
95+
96+
public function testItIsExecutingTheCorrectRequestWithArrayPayload()
97+
{
98+
$resultCallback = static function (string $method, string $url, array $options): HttpResponse {
99+
self::assertSame('POST', $method);
100+
self::assertSame('https://api.perplexity.ai/chat/completions', $url);
101+
self::assertSame('Authorization: Bearer pplx-api-key', $options['normalized_headers']['authorization'][0]);
102+
self::assertSame('{"model":"sonar","messages":[{"role":"user","content":"Hello"}]}', $options['body']);
103+
104+
return new MockResponse();
105+
};
106+
$httpClient = new MockHttpClient([$resultCallback]);
107+
$modelClient = new ModelClient($httpClient, 'pplx-api-key');
108+
$modelClient->request(new Perplexity('sonar'), ['model' => 'sonar', 'messages' => [['role' => 'user', 'content' => 'Hello']]]);
109+
}
110+
}

Tests/PerplexityTest.php

Lines changed: 37 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,37 @@
1+
<?php
2+
3+
/*
4+
* This file is part of the Symfony package.
5+
*
6+
* (c) Fabien Potencier <[email protected]>
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\Bridge\Perplexity\Tests;
13+
14+
use PHPUnit\Framework\TestCase;
15+
use Symfony\AI\Platform\Bridge\Perplexity\Perplexity;
16+
17+
/**
18+
* @author Mathieu Santostefano <[email protected]>
19+
*/
20+
final class PerplexityTest extends TestCase
21+
{
22+
public function testItCreatesPerplexityWithDefaultSettings()
23+
{
24+
$perplexity = new Perplexity('sonar');
25+
26+
$this->assertSame('sonar', $perplexity->getName());
27+
$this->assertSame([], $perplexity->getOptions());
28+
}
29+
30+
public function testItCreatesPerplexityWithCustomSettings()
31+
{
32+
$perplexity = new Perplexity('sonar-pro', options: ['temperature' => 0.5, 'max_tokens' => 1000]);
33+
34+
$this->assertSame('sonar-pro', $perplexity->getName());
35+
$this->assertSame(['temperature' => 0.5, 'max_tokens' => 1000], $perplexity->getOptions());
36+
}
37+
}

Tests/PlatformFactoryTest.php

Lines changed: 47 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,47 @@
1+
<?php
2+
3+
/*
4+
* This file is part of the Symfony package.
5+
*
6+
* (c) Fabien Potencier <[email protected]>
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\Bridge\Perplexity\Tests;
13+
14+
use PHPUnit\Framework\TestCase;
15+
use Symfony\AI\Platform\Bridge\Perplexity\PlatformFactory;
16+
use Symfony\AI\Platform\Platform;
17+
use Symfony\Component\HttpClient\EventSourceHttpClient;
18+
use Symfony\Component\HttpClient\MockHttpClient;
19+
20+
/**
21+
* @author Mathieu Santostefano <[email protected]>
22+
*/
23+
final class PlatformFactoryTest extends TestCase
24+
{
25+
public function testItCreatesPlatformWithDefaultSettings()
26+
{
27+
$platform = PlatformFactory::create('pplx-test-api-key');
28+
29+
$this->assertInstanceOf(Platform::class, $platform);
30+
}
31+
32+
public function testItCreatesPlatformWithCustomHttpClient()
33+
{
34+
$httpClient = new MockHttpClient();
35+
$platform = PlatformFactory::create('pplx-test-api-key', $httpClient);
36+
37+
$this->assertInstanceOf(Platform::class, $platform);
38+
}
39+
40+
public function testItCreatesPlatformWithEventSourceHttpClient()
41+
{
42+
$httpClient = new EventSourceHttpClient(new MockHttpClient());
43+
$platform = PlatformFactory::create('pplx-test-api-key', $httpClient);
44+
45+
$this->assertInstanceOf(Platform::class, $platform);
46+
}
47+
}

0 commit comments

Comments
 (0)