From a741f682a75451102cbbae9c9a040d3c2145c77f Mon Sep 17 00:00:00 2001 From: Guillaume Loulier Date: Mon, 16 Feb 2026 13:49:55 +0100 Subject: [PATCH] refactor(platform): ElevenLabs improvement --- UPGRADE.md | 10 +++ examples/elevenlabs/speech-to-text.php | 5 +- .../elevenlabs/text-to-speech-as-stream.php | 5 +- examples/elevenlabs/text-to-speech.php | 5 +- src/ai-bundle/CHANGELOG.md | 5 ++ src/ai-bundle/config/platform/elevenlabs.php | 4 +- src/ai-bundle/config/services.php | 5 +- src/ai-bundle/src/AiBundle.php | 28 ++++++-- .../DependencyInjection/AiBundleTest.php | 49 ++++++------- .../src/Bridge/ElevenLabs/CHANGELOG.md | 7 ++ .../ElevenLabs/ElevenLabsApiCatalog.php | 8 +-- .../Bridge/ElevenLabs/ElevenLabsClient.php | 30 +++----- .../ElevenLabs/ElevenLabsResultConverter.php | 4 +- .../src/Bridge/ElevenLabs/PlatformFactory.php | 13 +++- src/platform/src/Bridge/ElevenLabs/README.md | 8 +++ .../Tests/ElevenLabsApiCatalogTest.php | 10 +-- .../ElevenLabs/Tests/ElevenLabsClientTest.php | 67 ++++++------------ .../Tests/ElevenLabsConverterTest.php | 16 +++++ .../ElevenLabs/Tests/Fixtures/audio.mp3 | Bin 0 -> 51019 bytes 19 files changed, 146 insertions(+), 133 deletions(-) create mode 100644 src/platform/src/Bridge/ElevenLabs/Tests/Fixtures/audio.mp3 diff --git a/UPGRADE.md b/UPGRADE.md index 4584df87..4409c125 100644 --- a/UPGRADE.md +++ b/UPGRADE.md @@ -1,3 +1,13 @@ +UPGRADE FROM 0.4 to 0.5 +======================= + +Platform +-------- + + * The `hostUrl` parameter for `ElevenLabsClient` has been removed + * The `host` parameter for `ElevenLabsApiCatalog` has been removed + * The `hostUrl` parameter for `PlatformFactory::create()` in `ElevenLabs` has been renamed to `endpoint` + UPGRADE FROM 0.3 to 0.4 ======================= diff --git a/examples/elevenlabs/speech-to-text.php b/examples/elevenlabs/speech-to-text.php index 2490c9da..5f76015a 100644 --- a/examples/elevenlabs/speech-to-text.php +++ b/examples/elevenlabs/speech-to-text.php @@ -14,10 +14,7 @@ use Symfony\AI\Platform\Message\Content\Audio; require_once dirname(__DIR__).'/bootstrap.php'; -$platform = PlatformFactory::create( - apiKey: env('ELEVEN_LABS_API_KEY'), - httpClient: http_client() -); +$platform = PlatformFactory::create(env('ELEVEN_LABS_API_KEY'), httpClient: http_client()); $result = $platform->invoke('scribe_v1', Audio::fromFile(dirname(__DIR__, 2).'/fixtures/audio.mp3')); diff --git a/examples/elevenlabs/text-to-speech-as-stream.php b/examples/elevenlabs/text-to-speech-as-stream.php index 27e78971..757aceb2 100644 --- a/examples/elevenlabs/text-to-speech-as-stream.php +++ b/examples/elevenlabs/text-to-speech-as-stream.php @@ -14,10 +14,7 @@ use Symfony\AI\Platform\Message\Content\Text; require_once dirname(__DIR__).'/bootstrap.php'; -$platform = PlatformFactory::create( - apiKey: env('ELEVEN_LABS_API_KEY'), - httpClient: http_client(), -); +$platform = PlatformFactory::create(env('ELEVEN_LABS_API_KEY'), httpClient: http_client()); $result = $platform->invoke('eleven_multilingual_v2', new Text('The first move is what sets everything in motion.'), [ 'voice' => 'Dslrhjl3ZpzrctukrQSN', // Brad (https://elevenlabs.io/app/voice-library?voiceId=Dslrhjl3ZpzrctukrQSN) diff --git a/examples/elevenlabs/text-to-speech.php b/examples/elevenlabs/text-to-speech.php index da899419..8318932f 100644 --- a/examples/elevenlabs/text-to-speech.php +++ b/examples/elevenlabs/text-to-speech.php @@ -14,10 +14,7 @@ use Symfony\AI\Platform\Message\Content\Text; require_once dirname(__DIR__).'/bootstrap.php'; -$platform = PlatformFactory::create( - apiKey: env('ELEVEN_LABS_API_KEY'), - httpClient: http_client(), -); +$platform = PlatformFactory::create(env('ELEVEN_LABS_API_KEY'), httpClient: http_client()); $result = $platform->invoke('eleven_multilingual_v2', new Text('Hello world'), [ 'voice' => 'Dslrhjl3ZpzrctukrQSN', // Brad (https://elevenlabs.io/app/voice-library?voiceId=Dslrhjl3ZpzrctukrQSN) diff --git a/src/ai-bundle/CHANGELOG.md b/src/ai-bundle/CHANGELOG.md index b3f36786..14fba9c1 100644 --- a/src/ai-bundle/CHANGELOG.md +++ b/src/ai-bundle/CHANGELOG.md @@ -1,6 +1,11 @@ CHANGELOG ========= +0.5 +--- + + * [BC BREAK] The `host_url` configuration key for `ElevenLabs` has been renamed `endpoint` + 0.4 --- diff --git a/src/ai-bundle/config/platform/elevenlabs.php b/src/ai-bundle/config/platform/elevenlabs.php index 945a2de2..9b2bd1c9 100644 --- a/src/ai-bundle/config/platform/elevenlabs.php +++ b/src/ai-bundle/config/platform/elevenlabs.php @@ -16,8 +16,8 @@ use Symfony\Component\Config\Definition\Builder\ArrayNodeDefinition; return (new ArrayNodeDefinition('elevenlabs')) ->children() ->stringNode('api_key')->isRequired()->end() - ->stringNode('host') - ->defaultValue('https://api.elevenlabs.io/v1') + ->stringNode('endpoint') + ->defaultValue('https://api.elevenlabs.io/v1/') ->end() ->stringNode('http_client') ->defaultValue('http_client') diff --git a/src/ai-bundle/config/services.php b/src/ai-bundle/config/services.php index 718c612d..36c4b6c0 100644 --- a/src/ai-bundle/config/services.php +++ b/src/ai-bundle/config/services.php @@ -36,6 +36,7 @@ use Symfony\AI\Platform\Bridge\Cerebras\ModelCatalog as CerebrasModelCatalog; use Symfony\AI\Platform\Bridge\Decart\ModelCatalog as DecartModelCatalog; use Symfony\AI\Platform\Bridge\DeepSeek\ModelCatalog as DeepSeekModelCatalog; use Symfony\AI\Platform\Bridge\DockerModelRunner\ModelCatalog as DockerModelRunnerModelCatalog; +use Symfony\AI\Platform\Bridge\ElevenLabs\Contract\ElevenLabsContract; use Symfony\AI\Platform\Bridge\ElevenLabs\ModelCatalog as ElevenLabsModelCatalog; use Symfony\AI\Platform\Bridge\Gemini\Contract\GeminiContract; use Symfony\AI\Platform\Bridge\Gemini\ModelCatalog as GeminiModelCatalog; @@ -83,6 +84,8 @@ return static function (ContainerConfigurator $container): void { ->factory([OpenAiContract::class, 'create']) ->set('ai.platform.contract.anthropic', Contract::class) ->factory([AnthropicContract::class, 'create']) + ->set('ai.platform.contract.elevenlabs', Contract::class) + ->factory([ElevenLabsContract::class, 'create']) ->set('ai.platform.contract.gemini', Contract::class) ->factory([GeminiContract::class, 'create']) ->set('ai.platform.contract.huggingface', Contract::class) @@ -107,7 +110,7 @@ return static function (ContainerConfigurator $container): void { ->set('ai.platform.model_catalog.deepseek', DeepSeekModelCatalog::class) ->set('ai.platform.model_catalog.dockermodelrunner', DockerModelRunnerModelCatalog::class) ->set('ai.platform.model_catalog.elevenlabs', ElevenLabsModelCatalog::class) - ->lazy(true) + ->lazy() ->tag('proxy', ['interface' => ModelCatalogInterface::class]) ->set('ai.platform.model_catalog.gemini', GeminiModelCatalog::class) ->set('ai.platform.model_catalog.huggingface', HuggingFaceModelCatalog::class) diff --git a/src/ai-bundle/src/AiBundle.php b/src/ai-bundle/src/AiBundle.php index 18d658d9..45ae22d2 100644 --- a/src/ai-bundle/src/AiBundle.php +++ b/src/ai-bundle/src/AiBundle.php @@ -605,13 +605,29 @@ final class AiBundle extends AbstractBundle throw new RuntimeException('ElevenLabs platform configuration requires "symfony/ai-eleven-labs-platform" package. Try running "composer require symfony/ai-eleven-labs-platform".'); } + $httpClientReference = new Reference($platform['http_client']); + + $scopedHttpClientDefinition = (new Definition(ScopingHttpClient::class)) + ->setFactory([ScopingHttpClient::class, 'forBaseUri']) + ->setArguments([ + $httpClientReference, + $platform['endpoint'], + [ + 'headers' => [ + 'x-api-key' => $platform['api_key'], + ], + ], + ]); + + $container->setDefinition('ai.platform.elevenlabs.scoped_http_client', $scopedHttpClientDefinition); + + $httpClientReference = new Reference('ai.platform.elevenlabs.scoped_http_client'); + if (\array_key_exists('api_catalog', $platform) && $platform['api_catalog']) { $catalogDefinition = (new Definition(ElevenLabsApiCatalog::class)) ->setLazy(true) ->setArguments([ - new Reference($platform['http_client']), - $platform['api_key'], - $platform['host'], + $httpClientReference, ]) ->addTag('proxy', ['interface' => ModelCatalogInterface::class]); @@ -623,10 +639,10 @@ final class AiBundle extends AbstractBundle ->setLazy(true) ->setArguments([ $platform['api_key'], - $platform['host'], - new Reference($platform['http_client'], ContainerInterface::NULL_ON_INVALID_REFERENCE), + $platform['endpoint'], + $httpClientReference, new Reference('ai.platform.model_catalog.'.$type), - null, + new Reference('ai.platform.contract.'.$type), new Reference('event_dispatcher'), ]) ->addTag('proxy', ['interface' => PlatformInterface::class]) diff --git a/src/ai-bundle/tests/DependencyInjection/AiBundleTest.php b/src/ai-bundle/tests/DependencyInjection/AiBundleTest.php index cc21e5a0..3797a29f 100644 --- a/src/ai-bundle/tests/DependencyInjection/AiBundleTest.php +++ b/src/ai-bundle/tests/DependencyInjection/AiBundleTest.php @@ -3895,7 +3895,7 @@ class AiBundleTest extends TestCase $this->assertTrue($foundOutput, 'Default tool processor should have output tag with full agent ID'); } - public function testElevenLabsPlatformCanBeRegistered() + public function testElevenLabsPlatformCanBeConfigured() { $container = $this->buildContainer([ 'ai' => [ @@ -3910,18 +3910,18 @@ class AiBundleTest extends TestCase $this->assertTrue($container->hasDefinition('ai.platform.elevenlabs')); $definition = $container->getDefinition('ai.platform.elevenlabs'); - $this->assertTrue($definition->isLazy()); $this->assertSame([ElevenLabsPlatformFactory::class, 'create'], $definition->getFactory()); $this->assertCount(6, $definition->getArguments()); $this->assertSame('foo', $definition->getArgument(0)); - $this->assertSame('https://api.elevenlabs.io/v1', $definition->getArgument(1)); + $this->assertSame('https://api.elevenlabs.io/v1/', $definition->getArgument(1)); $this->assertInstanceOf(Reference::class, $definition->getArgument(2)); - $this->assertSame('http_client', (string) $definition->getArgument(2)); + $this->assertSame('ai.platform.elevenlabs.scoped_http_client', (string) $definition->getArgument(2)); $this->assertInstanceOf(Reference::class, $definition->getArgument(3)); $this->assertSame('ai.platform.model_catalog.elevenlabs', (string) $definition->getArgument(3)); - $this->assertNull($definition->getArgument(4)); + $this->assertInstanceOf(Reference::class, $definition->getArgument(4)); + $this->assertSame('ai.platform.contract.elevenlabs', (string) $definition->getArgument(4)); $this->assertInstanceOf(Reference::class, $definition->getArgument(5)); $this->assertSame('event_dispatcher', (string) $definition->getArgument(5)); @@ -3940,16 +3940,13 @@ class AiBundleTest extends TestCase $this->assertTrue($modelCatalogDefinition->hasTag('proxy')); $this->assertSame([['interface' => ModelCatalogInterface::class]], $modelCatalogDefinition->getTag('proxy')); - } - public function testElevenLabsPlatformWithCustomEndpointCanBeRegistered() - { $container = $this->buildContainer([ 'ai' => [ 'platform' => [ 'elevenlabs' => [ + 'endpoint' => 'https://api.elevenlabs.io/v2', 'api_key' => 'foo', - 'host' => 'https://api.elevenlabs.io/v2', ], ], ], @@ -3958,7 +3955,6 @@ class AiBundleTest extends TestCase $this->assertTrue($container->hasDefinition('ai.platform.elevenlabs')); $definition = $container->getDefinition('ai.platform.elevenlabs'); - $this->assertTrue($definition->isLazy()); $this->assertSame([ElevenLabsPlatformFactory::class, 'create'], $definition->getFactory()); @@ -3966,10 +3962,11 @@ class AiBundleTest extends TestCase $this->assertSame('foo', $definition->getArgument(0)); $this->assertSame('https://api.elevenlabs.io/v2', $definition->getArgument(1)); $this->assertInstanceOf(Reference::class, $definition->getArgument(2)); - $this->assertSame('http_client', (string) $definition->getArgument(2)); + $this->assertSame('ai.platform.elevenlabs.scoped_http_client', (string) $definition->getArgument(2)); $this->assertInstanceOf(Reference::class, $definition->getArgument(3)); $this->assertSame('ai.platform.model_catalog.elevenlabs', (string) $definition->getArgument(3)); - $this->assertNull($definition->getArgument(4)); + $this->assertInstanceOf(Reference::class, $definition->getArgument(4)); + $this->assertSame('ai.platform.contract.elevenlabs', (string) $definition->getArgument(4)); $this->assertInstanceOf(Reference::class, $definition->getArgument(5)); $this->assertSame('event_dispatcher', (string) $definition->getArgument(5)); @@ -3988,10 +3985,7 @@ class AiBundleTest extends TestCase $this->assertTrue($modelCatalogDefinition->hasTag('proxy')); $this->assertSame([['interface' => ModelCatalogInterface::class]], $modelCatalogDefinition->getTag('proxy')); - } - public function testElevenLabsPlatformWithCustomHttpClientCanBeRegistered() - { $container = $this->buildContainer([ 'ai' => [ 'platform' => [ @@ -4012,12 +4006,13 @@ class AiBundleTest extends TestCase $this->assertCount(6, $definition->getArguments()); $this->assertSame('foo', $definition->getArgument(0)); - $this->assertSame('https://api.elevenlabs.io/v1', $definition->getArgument(1)); + $this->assertSame('https://api.elevenlabs.io/v1/', $definition->getArgument(1)); $this->assertInstanceOf(Reference::class, $definition->getArgument(2)); - $this->assertSame('foo', (string) $definition->getArgument(2)); + $this->assertSame('ai.platform.elevenlabs.scoped_http_client', (string) $definition->getArgument(2)); $this->assertInstanceOf(Reference::class, $definition->getArgument(3)); $this->assertSame('ai.platform.model_catalog.elevenlabs', (string) $definition->getArgument(3)); - $this->assertNull($definition->getArgument(4)); + $this->assertInstanceOf(Reference::class, $definition->getArgument(4)); + $this->assertSame('ai.platform.contract.elevenlabs', (string) $definition->getArgument(4)); $this->assertInstanceOf(Reference::class, $definition->getArgument(5)); $this->assertSame('event_dispatcher', (string) $definition->getArgument(5)); @@ -4036,10 +4031,7 @@ class AiBundleTest extends TestCase $this->assertTrue($modelCatalogDefinition->hasTag('proxy')); $this->assertSame([['interface' => ModelCatalogInterface::class]], $modelCatalogDefinition->getTag('proxy')); - } - public function testElevenLabsPlatformWithApiCatalogCanBeRegistered() - { $container = $this->buildContainer([ 'ai' => [ 'platform' => [ @@ -4061,12 +4053,13 @@ class AiBundleTest extends TestCase $this->assertCount(6, $definition->getArguments()); $this->assertSame('foo', $definition->getArgument(0)); - $this->assertSame('https://api.elevenlabs.io/v1', $definition->getArgument(1)); + $this->assertSame('https://api.elevenlabs.io/v1/', $definition->getArgument(1)); $this->assertInstanceOf(Reference::class, $definition->getArgument(2)); - $this->assertSame('http_client', (string) $definition->getArgument(2)); + $this->assertSame('ai.platform.elevenlabs.scoped_http_client', (string) $definition->getArgument(2)); $this->assertInstanceOf(Reference::class, $definition->getArgument(3)); $this->assertSame('ai.platform.model_catalog.elevenlabs', (string) $definition->getArgument(3)); - $this->assertNull($definition->getArgument(4)); + $this->assertInstanceOf(Reference::class, $definition->getArgument(4)); + $this->assertSame('ai.platform.contract.elevenlabs', (string) $definition->getArgument(4)); $this->assertInstanceOf(Reference::class, $definition->getArgument(5)); $this->assertSame('event_dispatcher', (string) $definition->getArgument(5)); @@ -4082,11 +4075,9 @@ class AiBundleTest extends TestCase $this->assertSame(ElevenLabsApiCatalog::class, $modelCatalogDefinition->getClass()); $this->assertTrue($modelCatalogDefinition->isLazy()); - $this->assertCount(3, $modelCatalogDefinition->getArguments()); + $this->assertCount(1, $modelCatalogDefinition->getArguments()); $this->assertInstanceOf(Reference::class, $modelCatalogDefinition->getArgument(0)); - $this->assertSame('http_client', (string) $modelCatalogDefinition->getArgument(0)); - $this->assertSame('foo', $modelCatalogDefinition->getArgument(1)); - $this->assertSame('https://api.elevenlabs.io/v1', $modelCatalogDefinition->getArgument(2)); + $this->assertSame('ai.platform.elevenlabs.scoped_http_client', (string) $modelCatalogDefinition->getArgument(0)); $this->assertTrue($modelCatalogDefinition->hasTag('proxy')); $this->assertSame([['interface' => ModelCatalogInterface::class]], $modelCatalogDefinition->getTag('proxy')); @@ -7602,7 +7593,7 @@ class AiBundleTest extends TestCase 'api_key' => 'foo', ], 'elevenlabs' => [ - 'host' => 'https://api.elevenlabs.io/v1', + 'endpoint' => 'https://api.elevenlabs.io/v1', 'api_key' => 'elevenlabs_key_full', ], 'failover' => [ diff --git a/src/platform/src/Bridge/ElevenLabs/CHANGELOG.md b/src/platform/src/Bridge/ElevenLabs/CHANGELOG.md index ff3d5727..4354635b 100644 --- a/src/platform/src/Bridge/ElevenLabs/CHANGELOG.md +++ b/src/platform/src/Bridge/ElevenLabs/CHANGELOG.md @@ -1,6 +1,13 @@ CHANGELOG ========= +0.5 +--- + + * [BC BREAK] The `hostUrl` parameter for `ElevenLabsClient` has been removed + * [BC BREAK] The `host` parameter for `ElevenLabsApiCatalog` has been removed + * [BC BREAK] The `hostUrl` parameter for `PlatformFactory::create()` has been renamed to `endpoint` + 0.3 --- diff --git a/src/platform/src/Bridge/ElevenLabs/ElevenLabsApiCatalog.php b/src/platform/src/Bridge/ElevenLabs/ElevenLabsApiCatalog.php index 625535ba..7f625387 100644 --- a/src/platform/src/Bridge/ElevenLabs/ElevenLabsApiCatalog.php +++ b/src/platform/src/Bridge/ElevenLabs/ElevenLabsApiCatalog.php @@ -23,8 +23,6 @@ final class ElevenLabsApiCatalog implements ModelCatalogInterface { public function __construct( private readonly HttpClientInterface $httpClient, - #[\SensitiveParameter] private readonly string $apiKey, - private readonly string $hostUrl = 'https://api.elevenlabs.io/v1', ) { } @@ -45,11 +43,7 @@ final class ElevenLabsApiCatalog implements ModelCatalogInterface public function getModels(): array { - $response = $this->httpClient->request('GET', \sprintf('%s/models', $this->hostUrl), [ - 'headers' => [ - 'xi-api-key' => $this->apiKey, - ], - ]); + $response = $this->httpClient->request('GET', '/models'); $models = $response->toArray(); diff --git a/src/platform/src/Bridge/ElevenLabs/ElevenLabsClient.php b/src/platform/src/Bridge/ElevenLabs/ElevenLabsClient.php index a56fefc5..8e21ffc9 100644 --- a/src/platform/src/Bridge/ElevenLabs/ElevenLabsClient.php +++ b/src/platform/src/Bridge/ElevenLabs/ElevenLabsClient.php @@ -26,8 +26,6 @@ final class ElevenLabsClient implements ModelClientInterface { public function __construct( private readonly HttpClientInterface $httpClient, - #[\SensitiveParameter] private readonly string $apiKey, - private readonly string $hostUrl = 'https://api.elevenlabs.io/v1', ) { } @@ -42,18 +40,14 @@ final class ElevenLabsClient implements ModelClientInterface throw new InvalidArgumentException(\sprintf('The payload must be an array, received "%s".', get_debug_type($payload))); } - if ($model->supports(Capability::SPEECH_TO_TEXT)) { - return $this->doSpeechToTextRequest($model, $payload); - } - - if ($model->supports(Capability::TEXT_TO_SPEECH)) { - return $this->doTextToSpeechRequest($model, $payload, [ + return match (true) { + $model->supports(Capability::SPEECH_TO_TEXT) => $this->doSpeechToTextRequest($model, $payload), + $model->supports(Capability::TEXT_TO_SPEECH) => $this->doTextToSpeechRequest($model, $payload, [ ...$options, ...$model->getOptions(), - ]); - } - - throw new InvalidArgumentException(\sprintf('The model "%s" does not support text-to-speech or speech-to-text, please check the model information.', $model->getName())); + ]), + default => throw new InvalidArgumentException(\sprintf('The model "%s" does not support text-to-speech or speech-to-text, please check the model information.', $model->getName())), + }; } /** @@ -61,10 +55,7 @@ final class ElevenLabsClient implements ModelClientInterface */ private function doSpeechToTextRequest(Model $model, array|string $payload): RawHttpResult { - return new RawHttpResult($this->httpClient->request('POST', \sprintf('%s/speech-to-text', $this->hostUrl), [ - 'headers' => [ - 'xi-api-key' => $this->apiKey, - ], + return new RawHttpResult($this->httpClient->request('POST', 'speech-to-text', [ 'body' => [ 'file' => fopen($payload['input_audio']['path'], 'r'), 'model_id' => $model->getName(), @@ -90,15 +81,12 @@ final class ElevenLabsClient implements ModelClientInterface $stream = $options['stream'] ?? false; $url = $stream - ? \sprintf('%s/text-to-speech/%s/stream', $this->hostUrl, $voice) - : \sprintf('%s/text-to-speech/%s', $this->hostUrl, $voice); + ? \sprintf('text-to-speech/%s/stream', $voice) + : \sprintf('text-to-speech/%s', $voice); unset($options['voice'], $options['stream']); return new RawHttpResult($this->httpClient->request('POST', $url, [ - 'headers' => [ - 'xi-api-key' => $this->apiKey, - ], 'json' => [ 'text' => $payload['text'], 'model_id' => $model->getName(), diff --git a/src/platform/src/Bridge/ElevenLabs/ElevenLabsResultConverter.php b/src/platform/src/Bridge/ElevenLabs/ElevenLabsResultConverter.php index 9625193b..a21e9692 100644 --- a/src/platform/src/Bridge/ElevenLabs/ElevenLabsResultConverter.php +++ b/src/platform/src/Bridge/ElevenLabs/ElevenLabsResultConverter.php @@ -43,9 +43,9 @@ final class ElevenLabsResultConverter implements ResultConverterInterface $response = $result->getObject(); return match (true) { - \array_key_exists('stream', $options) && $options['stream'] => new StreamResult($this->convertToGenerator($response)), - str_contains($response->getInfo('url'), 'speech-to-text') => new TextResult($result->getData()['text']), + str_contains($response->getInfo('url'), 'text-to-speech') && \array_key_exists('stream', $options) && $options['stream'] => new StreamResult($this->convertToGenerator($response)), str_contains($response->getInfo('url'), 'text-to-speech') => new BinaryResult($result->getObject()->getContent(), 'audio/mpeg'), + str_contains($response->getInfo('url'), 'speech-to-text') => new TextResult($result->getData()['text']), default => throw new RuntimeException('Unsupported ElevenLabs response.'), }; } diff --git a/src/platform/src/Bridge/ElevenLabs/PlatformFactory.php b/src/platform/src/Bridge/ElevenLabs/PlatformFactory.php index a1ed7249..19d5b6da 100644 --- a/src/platform/src/Bridge/ElevenLabs/PlatformFactory.php +++ b/src/platform/src/Bridge/ElevenLabs/PlatformFactory.php @@ -17,6 +17,7 @@ use Symfony\AI\Platform\Contract; use Symfony\AI\Platform\ModelCatalog\ModelCatalogInterface; use Symfony\AI\Platform\Platform; use Symfony\Component\HttpClient\EventSourceHttpClient; +use Symfony\Component\HttpClient\ScopingHttpClient; use Symfony\Contracts\HttpClient\HttpClientInterface; /** @@ -25,8 +26,8 @@ use Symfony\Contracts\HttpClient\HttpClientInterface; final class PlatformFactory { public static function create( - string $apiKey, - string $hostUrl = 'https://api.elevenlabs.io/v1', + #[\SensitiveParameter] string $apiKey, + string $endpoint = 'https://api.elevenlabs.io/v1/', ?HttpClientInterface $httpClient = null, ModelCatalogInterface $modelCatalog = new ModelCatalog(), ?Contract $contract = null, @@ -34,8 +35,14 @@ final class PlatformFactory ): Platform { $httpClient = $httpClient instanceof EventSourceHttpClient ? $httpClient : new EventSourceHttpClient($httpClient); + $httpClient = ScopingHttpClient::forBaseUri($httpClient, $endpoint, [ + 'headers' => [ + 'xi-api-key' => $apiKey, + ], + ]); + return new Platform( - [new ElevenLabsClient($httpClient, $apiKey, $hostUrl)], + [new ElevenLabsClient($httpClient)], [new ElevenLabsResultConverter($httpClient)], $modelCatalog, $contract ?? ElevenLabsContract::create(), diff --git a/src/platform/src/Bridge/ElevenLabs/README.md b/src/platform/src/Bridge/ElevenLabs/README.md index 75cf019a..8993ac73 100644 --- a/src/platform/src/Bridge/ElevenLabs/README.md +++ b/src/platform/src/Bridge/ElevenLabs/README.md @@ -3,6 +3,14 @@ ElevenLabs Platform ElevenLabs platform bridge for Symfony AI. + +Test Fixtures +------------- + +The test fixtures in `Tests/Fixtures/` contain binary media content with the following owners and licenses: + +* `audio.mp3`: davidbain, Creative Commons, see [freesound.org](https://freesound.org/people/davidbain/sounds/136777/) + Resources --------- diff --git a/src/platform/src/Bridge/ElevenLabs/Tests/ElevenLabsApiCatalogTest.php b/src/platform/src/Bridge/ElevenLabs/Tests/ElevenLabsApiCatalogTest.php index 8ce9ff12..4e807d51 100644 --- a/src/platform/src/Bridge/ElevenLabs/Tests/ElevenLabsApiCatalogTest.php +++ b/src/platform/src/Bridge/ElevenLabs/Tests/ElevenLabsApiCatalogTest.php @@ -27,7 +27,7 @@ final class ElevenLabsApiCatalogTest extends TestCase new JsonMockResponse([]), ]); - $modelCatalog = new ElevenLabsApiCatalog($httpClient, 'foo'); + $modelCatalog = new ElevenLabsApiCatalog($httpClient); $this->expectException(InvalidArgumentException::class); $this->expectExceptionMessage('The model "foo" cannot be retrieved from the API.'); @@ -48,7 +48,7 @@ final class ElevenLabsApiCatalogTest extends TestCase ]), ]); - $modelCatalog = new ElevenLabsApiCatalog($httpClient, 'foo'); + $modelCatalog = new ElevenLabsApiCatalog($httpClient); $this->expectException(InvalidArgumentException::class); $this->expectExceptionMessage('The model "foo" is not supported, please check the ElevenLabs API.'); @@ -75,7 +75,7 @@ final class ElevenLabsApiCatalogTest extends TestCase ]), ]); - $modelCatalog = new ElevenLabsApiCatalog($httpClient, 'foo'); + $modelCatalog = new ElevenLabsApiCatalog($httpClient); $model = $modelCatalog->getModel('foo'); @@ -102,7 +102,7 @@ final class ElevenLabsApiCatalogTest extends TestCase ]), ]); - $modelCatalog = new ElevenLabsApiCatalog($httpClient, 'foo'); + $modelCatalog = new ElevenLabsApiCatalog($httpClient); $model = $modelCatalog->getModel('foo'); @@ -135,7 +135,7 @@ final class ElevenLabsApiCatalogTest extends TestCase ]), ]); - $modelCatalog = new ElevenLabsApiCatalog($httpClient, 'foo'); + $modelCatalog = new ElevenLabsApiCatalog($httpClient); $models = $modelCatalog->getModels(); diff --git a/src/platform/src/Bridge/ElevenLabs/Tests/ElevenLabsClientTest.php b/src/platform/src/Bridge/ElevenLabs/Tests/ElevenLabsClientTest.php index 31be2b06..aeaa4d48 100644 --- a/src/platform/src/Bridge/ElevenLabs/Tests/ElevenLabsClientTest.php +++ b/src/platform/src/Bridge/ElevenLabs/Tests/ElevenLabsClientTest.php @@ -28,10 +28,7 @@ final class ElevenLabsClientTest extends TestCase { public function testSupportsModel() { - $client = new ElevenLabsClient( - new MockHttpClient(), - 'my-api-key', - ); + $client = new ElevenLabsClient(new MockHttpClient()); $this->assertTrue($client->supports(new ElevenLabs('eleven_multilingual_v2'))); $this->assertFalse($client->supports(new Model('any-model'))); @@ -51,10 +48,7 @@ final class ElevenLabsClientTest extends TestCase ]); $normalizer = new AudioNormalizer(); - $client = new ElevenLabsClient( - $mockHttpClient, - 'my-api-key', - ); + $client = new ElevenLabsClient($mockHttpClient); $payload = $normalizer->normalize(Audio::fromFile(\dirname(__DIR__, 6).'/fixtures/audio.mp3')); @@ -68,7 +62,6 @@ final class ElevenLabsClientTest extends TestCase { $client = new ElevenLabsClient( new MockHttpClient(), - 'my-api-key', ); $this->expectException(InvalidArgumentException::class); @@ -86,14 +79,15 @@ final class ElevenLabsClientTest extends TestCase ]); $normalizer = new AudioNormalizer(); - $client = new ElevenLabsClient( - $httpClient, - 'my-api-key', - ); + $client = new ElevenLabsClient($httpClient); $payload = $normalizer->normalize(Audio::fromFile(\dirname(__DIR__, 6).'/fixtures/audio.mp3')); - $client->request(new ElevenLabs('scribe_v1', [Capability::INPUT_AUDIO, Capability::OUTPUT_TEXT, Capability::SPEECH_TO_TEXT]), $payload); + $client->request(new ElevenLabs('scribe_v1', [ + Capability::INPUT_AUDIO, + Capability::OUTPUT_TEXT, + Capability::SPEECH_TO_TEXT, + ]), $payload); $this->assertSame(1, $httpClient->getRequestsCount()); } @@ -107,14 +101,15 @@ final class ElevenLabsClientTest extends TestCase ]); $normalizer = new AudioNormalizer(); - $client = new ElevenLabsClient( - $httpClient, - 'my-api-key', - ); + $client = new ElevenLabsClient($httpClient); $payload = $normalizer->normalize(Audio::fromFile(\dirname(__DIR__, 6).'/fixtures/audio.mp3')); - $client->request(new ElevenLabs('scribe_v1_experimental', [Capability::INPUT_AUDIO, Capability::OUTPUT_TEXT, Capability::SPEECH_TO_TEXT]), $payload); + $client->request(new ElevenLabs('scribe_v1_experimental', [ + Capability::INPUT_AUDIO, + Capability::OUTPUT_TEXT, + Capability::SPEECH_TO_TEXT, + ]), $payload); $this->assertSame(1, $httpClient->getRequestsCount()); } @@ -125,10 +120,7 @@ final class ElevenLabsClientTest extends TestCase new JsonMockResponse([]), ]); - $client = new ElevenLabsClient( - $mockHttpClient, - 'my-api-key', - ); + $client = new ElevenLabsClient($mockHttpClient); $this->expectException(InvalidArgumentException::class); $this->expectExceptionMessage('The payload must contain a "text" key'); @@ -146,12 +138,9 @@ final class ElevenLabsClientTest extends TestCase new MockResponse($payload->asBinary()), ]); - $client = new ElevenLabsClient( - $httpClient, - 'my-api-key', - ); + $client = new ElevenLabsClient($httpClient); - $client->request(new ElevenLabs('eleven_multilingual_v2', [Capability::TEXT_TO_SPEECH], options: [ + $client->request(new ElevenLabs('eleven_multilingual_v2', [Capability::TEXT_TO_SPEECH], [ 'voice' => 'Dslrhjl3ZpzrctukrQSN', ]), [ 'text' => 'foo', @@ -168,10 +157,7 @@ final class ElevenLabsClientTest extends TestCase new MockResponse($payload->asBinary()), ]); - $client = new ElevenLabsClient( - $httpClient, - 'my-api-key', - ); + $client = new ElevenLabsClient($httpClient); $client->request(new ElevenLabs('eleven_multilingual_v2', [Capability::TEXT_TO_SPEECH]), [ 'text' => 'foo', @@ -190,12 +176,9 @@ final class ElevenLabsClientTest extends TestCase new MockResponse($payload->asBinary()), ]); - $client = new ElevenLabsClient( - $httpClient, - 'my-api-key', - ); + $client = new ElevenLabsClient($httpClient); - $result = $client->request(new ElevenLabs('eleven_multilingual_v2', capabilities: [Capability::TEXT_TO_SPEECH], options: [ + $result = $client->request(new ElevenLabs('eleven_multilingual_v2', [Capability::TEXT_TO_SPEECH], [ 'voice' => 'Dslrhjl3ZpzrctukrQSN', 'stream' => true, ]), [ @@ -214,10 +197,7 @@ final class ElevenLabsClientTest extends TestCase new MockResponse($payload->asBinary()), ]); - $client = new ElevenLabsClient( - $httpClient, - 'my-api-key', - ); + $client = new ElevenLabsClient($httpClient); $result = $client->request(new ElevenLabs('eleven_multilingual_v2', [Capability::TEXT_TO_SPEECH]), [ 'text' => 'foo', @@ -252,10 +232,7 @@ final class ElevenLabsClientTest extends TestCase return new MockResponse($payload->asBinary()); }); - $client = new ElevenLabsClient( - $httpClient, - 'my-api-key', - ); + $client = new ElevenLabsClient($httpClient); $client->request( new ElevenLabs('eleven_multilingual_v2', [Capability::TEXT_TO_SPEECH]), diff --git a/src/platform/src/Bridge/ElevenLabs/Tests/ElevenLabsConverterTest.php b/src/platform/src/Bridge/ElevenLabs/Tests/ElevenLabsConverterTest.php index 9890043c..593dd7b7 100644 --- a/src/platform/src/Bridge/ElevenLabs/Tests/ElevenLabsConverterTest.php +++ b/src/platform/src/Bridge/ElevenLabs/Tests/ElevenLabsConverterTest.php @@ -17,8 +17,10 @@ use Symfony\AI\Platform\Bridge\ElevenLabs\ElevenLabsResultConverter; use Symfony\AI\Platform\Model; use Symfony\AI\Platform\Result\BinaryResult; use Symfony\AI\Platform\Result\InMemoryRawResult; +use Symfony\AI\Platform\Result\StreamResult; use Symfony\AI\Platform\Result\TextResult; use Symfony\Component\HttpClient\MockHttpClient; +use Symfony\Component\HttpClient\Response\MockResponse; final class ElevenLabsConverterTest extends TestCase { @@ -48,6 +50,20 @@ final class ElevenLabsConverterTest extends TestCase $this->assertSame('Hello there', $result->getContent()); } + public function testConvertTextToSpeechAsStreamResponse() + { + $converter = new ElevenLabsResultConverter(new MockHttpClient([], 'https://api.elevenlabs.io/v1/text-to-speech/JBFqnCBsd6RMkjVDRZzb/stream')); + $rawResult = new InMemoryRawResult([], [], MockResponse::fromFile(\dirname(__DIR__).'/Tests/Fixtures/audio.mp3', [ + 'url' => 'https://api.elevenlabs.io/v1/text-to-speech/JBFqnCBsd6RMkjVDRZzb/stream', + ])); + + $result = $converter->convert($rawResult, [ + 'stream' => true, + ]); + + $this->assertInstanceOf(StreamResult::class, $result); + } + public function testConvertTextToSpeechResponse() { $converter = new ElevenLabsResultConverter(new MockHttpClient()); diff --git a/src/platform/src/Bridge/ElevenLabs/Tests/Fixtures/audio.mp3 b/src/platform/src/Bridge/ElevenLabs/Tests/Fixtures/audio.mp3 new file mode 100644 index 0000000000000000000000000000000000000000..509aa0fc4cfb7766ea92936a78d2796d8b966e6f GIT binary patch literal 51019 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 z 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 Q3cz-@2@tbjQ%Ip00E9Or6951J literal 0 HcmV?d00001