Skip to content

Commit 9efdead

Browse files
committed
ref
1 parent e496475 commit 9efdead

File tree

3 files changed

+62
-60
lines changed

3 files changed

+62
-60
lines changed

src/platform/src/Bridge/ElevenLabs/ElevenLabsClient.php

Lines changed: 11 additions & 11 deletions
Original file line numberDiff line numberDiff line change
@@ -37,14 +37,18 @@ public function supports(Model $model): bool
3737

3838
public function request(Model $model, array|string $payload, array $options = []): RawResultInterface
3939
{
40+
if (!\is_array($payload)) {
41+
throw new InvalidArgumentException(\sprintf('The payload must be an array, received "%s".', get_debug_type($payload)));
42+
}
43+
4044
if (\in_array($model->getName(), [ElevenLabs::SCRIBE_V1, ElevenLabs::SCRIBE_V1_EXPERIMENTAL], true)) {
4145
return $this->doSpeechToTextRequest($model, $payload, $options);
4246
}
4347

4448
$capabilities = $this->retrieveCapabilities($model);
4549

46-
if ([] === $capabilities) {
47-
throw new InvalidArgumentException('The model information could not be retrieved from the ElevenLabs API. Your model might not be supported. Try to use another one.');
50+
if (!$capabilities['can_do_text_to_speech']) {
51+
throw new InvalidArgumentException(sprintf('The model "%s" does not support text-to-speech.', $model->getName()));
4852
}
4953

5054
return $this->doTextToSpeechRequest($model, $payload, $options);
@@ -56,10 +60,6 @@ public function request(Model $model, array|string $payload, array $options = []
5660
*/
5761
private function doSpeechToTextRequest(Model $model, array|string $payload, array $options): RawHttpResult
5862
{
59-
if (!\is_array($payload)) {
60-
throw new InvalidArgumentException(\sprintf('The payload must be an array, received "%s".', get_debug_type($payload)));
61-
}
62-
6363
return new RawHttpResult($this->httpClient->request('POST', \sprintf('%s/speech-to-text', $this->hostUrl), [
6464
'headers' => [
6565
'xi-api-key' => $this->apiKey,
@@ -78,11 +78,7 @@ private function doSpeechToTextRequest(Model $model, array|string $payload, arra
7878
private function doTextToSpeechRequest(Model $model, array|string $payload, array $options): RawHttpResult
7979
{
8080
if (!\array_key_exists('voice', $model->getOptions())) {
81-
throw new InvalidArgumentException('The model option is required.');
82-
}
83-
84-
if (!\is_array($payload)) {
85-
throw new InvalidArgumentException(\sprintf('The payload must be an array, received "%s".', get_debug_type($payload)));
81+
throw new InvalidArgumentException('The voice option is required.');
8682
}
8783

8884
if (!\array_key_exists('text', $payload)) {
@@ -114,6 +110,10 @@ private function retrieveCapabilities(Model $model): array
114110

115111
$currentModelConfiguration = array_filter($models, static fn (array $information): bool => $information['model_id'] === $model->getName());
116112

113+
if ([] === $currentModelConfiguration) {
114+
throw new InvalidArgumentException('The model information could not be retrieved from the ElevenLabs API. Your model might not be supported. Try to use another one.');
115+
}
116+
117117
return reset($currentModelConfiguration);
118118
}
119119
}

src/platform/tests/Bridge/ElevenLabs/ElevenLabsClientTest.php

Lines changed: 47 additions & 45 deletions
Original file line numberDiff line numberDiff line change
@@ -12,15 +12,19 @@
1212
namespace Symfony\AI\Platform\Tests\Bridge\ElevenLabs;
1313

1414
use PHPUnit\Framework\Attributes\CoversClass;
15+
use PHPUnit\Framework\Attributes\Group;
1516
use PHPUnit\Framework\Attributes\UsesClass;
1617
use PHPUnit\Framework\TestCase;
18+
use PHPUnit\Util\Json;
1719
use Symfony\AI\Platform\Bridge\ElevenLabs\ElevenLabs;
1820
use Symfony\AI\Platform\Bridge\ElevenLabs\ElevenLabsClient;
1921
use Symfony\AI\Platform\Contract\Normalizer\Message\Content\AudioNormalizer;
2022
use Symfony\AI\Platform\Exception\InvalidArgumentException;
2123
use Symfony\AI\Platform\Message\Content\Audio;
2224
use Symfony\AI\Platform\Model;
2325
use Symfony\Component\HttpClient\MockHttpClient;
26+
use Symfony\Component\HttpClient\Response\JsonMockResponse;
27+
use Symfony\Component\HttpClient\Response\MockResponse;
2428

2529
#[CoversClass(ElevenLabsClient::class)]
2630
#[UsesClass(ElevenLabs::class)]
@@ -43,18 +47,27 @@ public function testSupportsModel()
4347

4448
public function testClientCannotPerformWithInvalidModel()
4549
{
50+
$mockHttpClient = new MockHttpClient([
51+
new JsonMockResponse([
52+
[
53+
'model_id' => 'bar',
54+
'can_do_text_to_speech' => false,
55+
]
56+
]),
57+
new JsonMockResponse([]),
58+
]);
4659
$normalizer = new AudioNormalizer();
4760

4861
$client = new ElevenLabsClient(
49-
new MockHttpClient(),
62+
$mockHttpClient,
5063
'my-api-key',
5164
'https://api.elevenlabs.io/v1',
5265
);
5366

5467
$payload = $normalizer->normalize(Audio::fromFile(\dirname(__DIR__, 5).'/fixtures/audio.mp3'));
5568

5669
$this->expectException(InvalidArgumentException::class);
57-
$this->expectExceptionMessage('The model option is required.');
70+
$this->expectExceptionMessage('The model information could not be retrieved from the ElevenLabs API. Your model might not be supported. Try to use another one.');
5871
$this->expectExceptionCode(0);
5972
$client->request(new ElevenLabs('foo'), $payload);
6073
}
@@ -70,14 +83,16 @@ public function testClientCannotPerformSpeechToTextRequestWithInvalidPayload()
7083
$this->expectException(InvalidArgumentException::class);
7184
$this->expectExceptionMessage('The payload must be an array, received "string".');
7285
$this->expectExceptionCode(0);
73-
$client->request(new ElevenLabs(ElevenLabs::SPEECH_TO_TEXT, options: [
74-
'model' => 'bar',
75-
]), 'foo');
86+
$client->request(new ElevenLabs(ElevenLabs::ELEVEN_MULTILINGUAL_V2), 'foo');
7687
}
7788

7889
public function testClientCanPerformSpeechToTextRequest()
7990
{
80-
$httpClient = new MockHttpClient();
91+
$httpClient = new MockHttpClient([
92+
new JsonMockResponse([
93+
'text' => 'foo',
94+
]),
95+
]);
8196
$normalizer = new AudioNormalizer();
8297

8398
$client = new ElevenLabsClient(
@@ -88,49 +103,25 @@ public function testClientCanPerformSpeechToTextRequest()
88103

89104
$payload = $normalizer->normalize(Audio::fromFile(\dirname(__DIR__, 5).'/fixtures/audio.mp3'));
90105

91-
$client->request(new ElevenLabs(ElevenLabs::SPEECH_TO_TEXT, options: [
92-
'model' => 'bar',
93-
]), $payload);
106+
$client->request(new ElevenLabs(ElevenLabs::SCRIBE_V1), $payload);
94107

95108
$this->assertSame(1, $httpClient->getRequestsCount());
96109
}
97110

98-
public function testClientCannotPerformTextToSpeechRequestWithoutModel()
99-
{
100-
$client = new ElevenLabsClient(
101-
new MockHttpClient(),
102-
'https://api.elevenlabs.io/v1',
103-
'my-api-key',
104-
);
105-
106-
$this->expectException(InvalidArgumentException::class);
107-
$this->expectExceptionMessage('The model option is required.');
108-
$this->expectExceptionCode(0);
109-
$client->request(new ElevenLabs(), []);
110-
}
111-
112-
public function testClientCannotPerformTextToSpeechRequestWithInvalidPayload()
113-
{
114-
$client = new ElevenLabsClient(
115-
new MockHttpClient(),
116-
'https://api.elevenlabs.io/v1',
117-
'my-api-key',
118-
);
119-
120-
$this->expectException(InvalidArgumentException::class);
121-
$this->expectExceptionMessage('The payload must be an array, received "string".');
122-
$this->expectExceptionCode(0);
123-
$client->request(new ElevenLabs(options: [
124-
'model' => 'bar',
125-
]), 'foo');
126-
}
127-
128111
public function testClientCannotPerformTextToSpeechRequestWithoutValidPayload()
129112
{
130-
$normalizer = new AudioNormalizer();
113+
$mockHttpClient = new MockHttpClient([
114+
new JsonMockResponse([
115+
[
116+
'model_id' => ElevenLabs::ELEVEN_MULTILINGUAL_V2,
117+
'can_do_text_to_speech' => true,
118+
],
119+
]),
120+
new JsonMockResponse([]),
121+
]);
131122

132123
$client = new ElevenLabsClient(
133-
new MockHttpClient(),
124+
$mockHttpClient,
134125
'https://api.elevenlabs.io/v1',
135126
'my-api-key',
136127
);
@@ -139,13 +130,24 @@ public function testClientCannotPerformTextToSpeechRequestWithoutValidPayload()
139130
$this->expectExceptionMessage('The payload must contain a "text" key');
140131
$this->expectExceptionCode(0);
141132
$client->request(new ElevenLabs(options: [
142-
'model' => 'bar',
133+
'voice' => 'Dslrhjl3ZpzrctukrQSN',
143134
]), []);
144135
}
145136

137+
#[Group('foo')]
146138
public function testClientCanPerformTextToSpeechRequest()
147139
{
148-
$httpClient = new MockHttpClient();
140+
$payload = Audio::fromFile(\dirname(__DIR__, 5).'/fixtures/audio.mp3');
141+
142+
$httpClient = new MockHttpClient([
143+
new JsonMockResponse([
144+
[
145+
'model_id' => ElevenLabs::ELEVEN_MULTILINGUAL_V2,
146+
'can_do_text_to_speech' => true,
147+
],
148+
]),
149+
new MockResponse($payload->asBinary()),
150+
]);
149151

150152
$client = new ElevenLabsClient(
151153
$httpClient,
@@ -154,11 +156,11 @@ public function testClientCanPerformTextToSpeechRequest()
154156
);
155157

156158
$client->request(new ElevenLabs(options: [
157-
'model' => 'bar',
159+
'voice' => 'Dslrhjl3ZpzrctukrQSN',
158160
]), [
159161
'text' => 'foo',
160162
]);
161163

162-
$this->assertSame(1, $httpClient->getRequestsCount());
164+
$this->assertSame(2, $httpClient->getRequestsCount());
163165
}
164166
}

src/platform/tests/Bridge/ElevenLabs/ElevenLabsConverterTest.php

Lines changed: 4 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -17,15 +17,15 @@
1717
use Symfony\AI\Platform\Bridge\ElevenLabs\ElevenLabs;
1818
use Symfony\AI\Platform\Bridge\ElevenLabs\ElevenLabsResultConverter;
1919
use Symfony\AI\Platform\Model;
20-
use Symfony\AI\Platform\Result\AudioResult;
20+
use Symfony\AI\Platform\Result\BinaryResult;
2121
use Symfony\AI\Platform\Result\InMemoryRawResult;
2222
use Symfony\AI\Platform\Result\TextResult;
2323

2424
#[CoversClass(ElevenLabsResultConverter::class)]
2525
#[UsesClass(ElevenLabs::class)]
2626
#[UsesClass(Model::class)]
2727
#[UsesClass(TextResult::class)]
28-
#[UsesClass(AudioResult::class)]
28+
#[UsesClass(BinaryResult::class)]
2929
#[UsesClass(InMemoryRawResult::class)]
3030
final class ElevenLabsConverterTest extends TestCase
3131
{
@@ -72,7 +72,7 @@ public function getContent(): string
7272

7373
$result = $converter->convert($rawResult);
7474

75-
$this->assertInstanceOf(AudioResult::class, $result);
76-
$this->assertSame('audio/mpeg', $result->getMimeType());
75+
$this->assertInstanceOf(BinaryResult::class, $result);
76+
$this->assertSame('audio/mpeg', $result->mimeType);
7777
}
7878
}

0 commit comments

Comments
 (0)