Skip to content

Commit be04280

Browse files
committed
ref
1 parent cec0635 commit be04280

Some content is hidden

Large Commits have some content hidden by default. Use the searchbox below for content that may be hidden.

45 files changed

+293
-64
lines changed

examples/voice/agent-eleven-labs-voice.php renamed to examples/speech/agent-eleven-labs-speech.php

Lines changed: 12 additions & 12 deletions
Original file line numberDiff line numberDiff line change
@@ -12,6 +12,7 @@
1212
use Symfony\AI\Agent\Agent;
1313
use Symfony\AI\Platform\Bridge\ElevenLabs\ElevenLabsSpeechProvider;
1414
use Symfony\AI\Platform\Bridge\ElevenLabs\PlatformFactory;
15+
use Symfony\AI\Platform\Bridge\OpenAi\PlatformFactory as OpenAiPlatformFactory;
1516
use Symfony\AI\Platform\Message\Message;
1617
use Symfony\AI\Platform\Message\MessageBag;
1718
use Symfony\AI\Platform\Speech\SpeechConfiguration;
@@ -25,20 +26,19 @@
2526
new ElevenLabsSpeechProvider(PlatformFactory::create(
2627
apiKey: env('ELEVEN_LABS_API_KEY'),
2728
httpClient: http_client(),
28-
), new SpeechConfiguration(
29-
'eleven_multilingual_v2',
30-
'Dslrhjl3ZpzrctukrQSN', // Brad (https://elevenlabs.io/app/voice-library?voiceId=Dslrhjl3ZpzrctukrQSN)
31-
'eleven_multilingual_v2'
32-
)),
33-
]));
29+
speechConfiguration: new SpeechConfiguration(
30+
'eleven_multilingual_v2',
31+
'Dslrhjl3ZpzrctukrQSN', // Brad (https://elevenlabs.io/app/voice-library?voiceId=Dslrhjl3ZpzrctukrQSN)
32+
'eleven_multilingual_v2'
33+
)),
34+
),
35+
], []));
3436

35-
$platform = PlatformFactory::create(env('OPENAI_API_KEY'), httpClient: http_client());
37+
$platform = OpenAiPlatformFactory::create(env('OPENAI_API_KEY'), httpClient: http_client(), eventDispatcher: $eventDispatcher);
3638

3739
$agent = new Agent($platform, 'gpt-4o');
3840
$answer = $agent->call(new MessageBag(
39-
Message::ofUser('Hello'),
40-
), [
41-
ElevenLabsSpeechProvider::ELEVEN_LABS_STT_MODEL => true,
42-
]);
41+
Message::ofUser('Tina has one brother and one sister. How many sisters do Tina\'s siblings have?'),
42+
));
4343

44-
echo $answer->getSpeech();
44+
echo $answer->getSpeech()->asBinary();

src/ai-bundle/config/options.php

Lines changed: 6 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -960,13 +960,17 @@
960960
->end()
961961
->end()
962962
->end()
963-
->arrayNode('voice')
963+
->arrayNode('speech')
964964
->children()
965965
->arrayNode('eleven_labs')
966966
->useAttributeAsKey('name')
967967
->arrayPrototype()
968968
->children()
969-
->stringNode('model')->cannotBeEmpty()->end()
969+
->stringNode('tts_model')->end()
970+
->stringNode('tts_voice')->end()
971+
->arrayNode('tts_extra_options')->end()
972+
->stringNode('stt_model')->end()
973+
->arrayNode('stt_extra_options')->end()
970974
->end()
971975
->end()
972976
->end()

src/ai-bundle/src/AiBundle.php

Lines changed: 39 additions & 12 deletions
Original file line numberDiff line numberDiff line change
@@ -54,6 +54,7 @@
5454
use Symfony\AI\Platform\Bridge\Cerebras\PlatformFactory as CerebrasPlatformFactory;
5555
use Symfony\AI\Platform\Bridge\DeepSeek\PlatformFactory as DeepSeekPlatformFactory;
5656
use Symfony\AI\Platform\Bridge\DockerModelRunner\PlatformFactory as DockerModelRunnerPlatformFactory;
57+
use Symfony\AI\Platform\Bridge\ElevenLabs\ElevenLabsSpeechListener;
5758
use Symfony\AI\Platform\Bridge\ElevenLabs\ElevenLabsSpeechProvider;
5859
use Symfony\AI\Platform\Bridge\ElevenLabs\PlatformFactory as ElevenLabsPlatformFactory;
5960
use Symfony\AI\Platform\Bridge\Gemini\PlatformFactory as GeminiPlatformFactory;
@@ -77,6 +78,7 @@
7778
use Symfony\AI\Platform\PlatformInterface;
7879
use Symfony\AI\Platform\ResultConverterInterface;
7980
use Symfony\AI\Platform\Speech\SpeechConfiguration;
81+
use Symfony\AI\Platform\Speech\SpeechListenerInterface;
8082
use Symfony\AI\Platform\Speech\SpeechProviderInterface;
8183
use Symfony\AI\Store\Bridge\Azure\SearchStore as AzureSearchStore;
8284
use Symfony\AI\Store\Bridge\ChromaDb\Store as ChromaDbStore;
@@ -260,6 +262,11 @@ public function loadExtension(array $config, ContainerConfigurator $container, C
260262
$builder->removeDefinition('ai.speech_provider.listener');
261263
}
262264

265+
$speechListeners = array_keys($builder->findTaggedServiceIds('ai.speech_listener'));
266+
if ([] === $speechListeners) {
267+
$builder->removeDefinition('ai.speech_listener.listener');
268+
}
269+
263270
foreach ($config['vectorizer'] ?? [] as $vectorizerName => $vectorizer) {
264271
$this->processVectorizerConfig($vectorizerName, $vectorizer, $builder);
265272
}
@@ -435,6 +442,7 @@ private function processPlatformConfig(string $type, array $platform, ContainerB
435442
new Reference($platform['http_client'], ContainerInterface::NULL_ON_INVALID_REFERENCE),
436443
new Reference('ai.platform.model_catalog.elevenlabs'),
437444
null,
445+
new Reference('ai.speech.eleven_labs.configuration'),
438446
new Reference('event_dispatcher'),
439447
])
440448
->addTag('proxy', ['interface' => PlatformInterface::class])
@@ -1817,30 +1825,49 @@ private function processChatConfig(string $name, array $configuration, Container
18171825
private function processSpeechConfig(string $name, array $providers, ContainerBuilder $container): void
18181826
{
18191827
if ('eleven_labs' === $name) {
1820-
foreach ($providers as $config) {
1828+
foreach ($providers as $type => $config) {
18211829
$configurationDefinition = new Definition(SpeechConfiguration::class);
18221830
$configurationDefinition
18231831
->setLazy(true)
18241832
->setArguments([
18251833
$config['tts_model'],
18261834
$config['tts_voice'],
1835+
$config['tts_extra_options'],
18271836
$config['stt_model'],
1837+
$config['stt_extra_options'],
18281838
]);
18291839

18301840
$container->setDefinition('ai.speech.eleven_labs.configuration', $configurationDefinition);
18311841

1832-
$definition = new Definition(ElevenLabsSpeechProvider::class);
1833-
$definition
1834-
->setLazy(true)
1835-
->setArguments([
1836-
new Reference('ai.platform.eleven_labs'),
1837-
new Reference('ai.speech.eleven_labs.configuration'),
1838-
])
1839-
->addTag('proxy', ['interface' => SpeechProviderInterface::class])
1840-
->addTag('kernel.event_subscriber')
1841-
->addTag('ai.speech_provider');
1842+
if (\array_key_exists('tts_model', $config)) {
1843+
$definition = new Definition(ElevenLabsSpeechProvider::class);
1844+
$definition
1845+
->setLazy(true)
1846+
->setArguments([
1847+
new Reference('ai.platform.eleven_labs'),
1848+
])
1849+
->addTag('proxy', ['interface' => SpeechProviderInterface::class])
1850+
->addTag('ai.speech_provider');
1851+
1852+
$container->setDefinition('ai.speech_provider.'.$type.'.'.$name, $definition);
1853+
$container->registerAliasForArgument('ai.speech_provider.'.$type.'.'.$name, SpeechProviderInterface::class, $name);
1854+
$container->registerAliasForArgument('ai.speech_provider.'.$type.'.'.$name, SpeechProviderInterface::class, $type.'_'.$name);
1855+
}
18421856

1843-
$container->setDefinition('ai.speech.eleven_labs.'.$name, $definition);
1857+
if (\array_key_exists('stt_model', $config)) {
1858+
$definition = new Definition(ElevenLabsSpeechListener::class);
1859+
$definition
1860+
->setLazy(true)
1861+
->setArguments([
1862+
new Reference('ai.platform.eleven_labs'),
1863+
])
1864+
->addTag('proxy', ['interface' => SpeechListenerInterface::class])
1865+
->addTag('ai.speech_listener');
1866+
1867+
$container->setDefinition('ai.speech_listener.'.$type.'.'.$name, $definition);
1868+
$container->registerAliasForArgument('ai.speech_listener.'.$type.'.'.$name, SpeechListenerInterface::class, $name);
1869+
$container->registerAliasForArgument('ai.speech_listener.'.$type.'.'.$name, SpeechListenerInterface::class, $type.'_'.$name);
1870+
}
18441871
}
18451872
}
18461873
}

src/ai-bundle/src/Profiler/TraceablePlatform.php

Lines changed: 6 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -12,12 +12,12 @@
1212
namespace Symfony\AI\AiBundle\Profiler;
1313

1414
use Symfony\AI\Platform\Message\Content\File;
15-
use Symfony\AI\Platform\Model;
1615
use Symfony\AI\Platform\ModelCatalog\ModelCatalogInterface;
1716
use Symfony\AI\Platform\PlatformInterface;
1817
use Symfony\AI\Platform\Result\DeferredResult;
1918
use Symfony\AI\Platform\Result\ResultInterface;
2019
use Symfony\AI\Platform\Result\StreamResult;
20+
use Symfony\AI\Platform\Speech\SpeechConfiguration;
2121
use Symfony\AI\Platform\Test\PlainConverter;
2222

2323
/**
@@ -75,6 +75,11 @@ public function getModelCatalog(): ModelCatalogInterface
7575
return $this->platform->getModelCatalog();
7676
}
7777

78+
public function getSpeechConfiguration(): ?SpeechConfiguration
79+
{
80+
return $this->platform->getSpeechConfiguration();
81+
}
82+
7883
private function createTraceableStreamResult(\Generator $originalStream): StreamResult
7984
{
8085
return $result = new StreamResult((function () use (&$result, $originalStream) {

src/platform/src/Bridge/AiMlApi/PlatformFactory.php

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -15,6 +15,7 @@
1515
use Symfony\AI\Platform\Bridge\AiMlApi\Embeddings\ModelClient;
1616
use Symfony\AI\Platform\Contract;
1717
use Symfony\AI\Platform\Platform;
18+
use Symfony\AI\Platform\Speech\SpeechConfiguration;
1819
use Symfony\Contracts\HttpClient\HttpClientInterface;
1920

2021
/**
@@ -27,6 +28,7 @@ public static function create(
2728
?HttpClientInterface $httpClient = null,
2829
?Contract $contract = null,
2930
string $hostUrl = 'https://api.aimlapi.com',
31+
?SpeechConfiguration $speechConfiguration = null,
3032
?EventDispatcherInterface $eventDispatcher = null,
3133
): Platform {
3234
return new Platform(
@@ -40,6 +42,7 @@ public static function create(
4042
],
4143
new ModelCatalog(),
4244
$contract,
45+
$speechConfiguration,
4346
$eventDispatcher,
4447
);
4548
}

src/platform/src/Bridge/Albert/PlatformFactory.php

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -18,6 +18,7 @@
1818
use Symfony\AI\Platform\Exception\InvalidArgumentException;
1919
use Symfony\AI\Platform\ModelCatalog\ModelCatalogInterface;
2020
use Symfony\AI\Platform\Platform;
21+
use Symfony\AI\Platform\Speech\SpeechConfiguration;
2122
use Symfony\Component\HttpClient\EventSourceHttpClient;
2223
use Symfony\Contracts\HttpClient\HttpClientInterface;
2324

@@ -31,6 +32,7 @@ public static function create(
3132
string $baseUrl,
3233
?HttpClientInterface $httpClient = null,
3334
ModelCatalogInterface $modelCatalog = new ModelCatalog(),
35+
?SpeechConfiguration $speechConfiguration = null,
3436
?EventDispatcherInterface $eventDispatcher = null,
3537
): Platform {
3638
if (!str_starts_with($baseUrl, 'https://')) {
@@ -56,6 +58,7 @@ public static function create(
5658
[new Gpt\ResultConverter(), new Embeddings\ResultConverter()],
5759
$modelCatalog,
5860
Contract::create(),
61+
$speechConfiguration,
5962
$eventDispatcher,
6063
);
6164
}

src/platform/src/Bridge/Anthropic/PlatformFactory.php

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -16,6 +16,7 @@
1616
use Symfony\AI\Platform\Contract;
1717
use Symfony\AI\Platform\ModelCatalog\ModelCatalogInterface;
1818
use Symfony\AI\Platform\Platform;
19+
use Symfony\AI\Platform\Speech\SpeechConfiguration;
1920
use Symfony\Component\HttpClient\EventSourceHttpClient;
2021
use Symfony\Contracts\HttpClient\HttpClientInterface;
2122

@@ -29,6 +30,7 @@ public static function create(
2930
?HttpClientInterface $httpClient = null,
3031
ModelCatalogInterface $modelCatalog = new ModelCatalog(),
3132
?Contract $contract = null,
33+
?SpeechConfiguration $speechConfiguration = null,
3234
?EventDispatcherInterface $eventDispatcher = null,
3335
): Platform {
3436
$httpClient = $httpClient instanceof EventSourceHttpClient ? $httpClient : new EventSourceHttpClient($httpClient);
@@ -38,6 +40,7 @@ public static function create(
3840
[new ResultConverter()],
3941
$modelCatalog,
4042
$contract ?? AnthropicContract::create(),
43+
$speechConfiguration,
4144
$eventDispatcher,
4245
);
4346
}

src/platform/src/Bridge/Azure/Meta/PlatformFactory.php

Lines changed: 3 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -16,6 +16,7 @@
1616
use Symfony\AI\Platform\Contract;
1717
use Symfony\AI\Platform\ModelCatalog\ModelCatalogInterface;
1818
use Symfony\AI\Platform\Platform;
19+
use Symfony\AI\Platform\Speech\SpeechConfiguration;
1920
use Symfony\Component\HttpClient\HttpClient;
2021
use Symfony\Contracts\HttpClient\HttpClientInterface;
2122

@@ -30,10 +31,11 @@ public static function create(
3031
?HttpClientInterface $httpClient = null,
3132
ModelCatalogInterface $modelCatalog = new ModelCatalog(),
3233
?Contract $contract = null,
34+
?SpeechConfiguration $speechConfiguration = null,
3335
?EventDispatcherInterface $eventDispatcher = null,
3436
): Platform {
3537
$modelClient = new LlamaModelClient($httpClient ?? HttpClient::create(), $baseUrl, $apiKey);
3638

37-
return new Platform([$modelClient], [new LlamaResultConverter()], $modelCatalog, $contract, $eventDispatcher);
39+
return new Platform([$modelClient], [new LlamaResultConverter()], $modelCatalog, $contract, $speechConfiguration, $eventDispatcher);
3840
}
3941
}

src/platform/src/Bridge/Azure/OpenAi/PlatformFactory.php

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -20,6 +20,7 @@
2020
use Symfony\AI\Platform\Contract;
2121
use Symfony\AI\Platform\ModelCatalog\ModelCatalogInterface;
2222
use Symfony\AI\Platform\Platform;
23+
use Symfony\AI\Platform\Speech\SpeechConfiguration;
2324
use Symfony\Component\HttpClient\EventSourceHttpClient;
2425
use Symfony\Contracts\HttpClient\HttpClientInterface;
2526

@@ -36,6 +37,7 @@ public static function create(
3637
?HttpClientInterface $httpClient = null,
3738
ModelCatalogInterface $modelCatalog = new ModelCatalog(),
3839
?Contract $contract = null,
40+
?SpeechConfiguration $speechConfiguration = null,
3941
?EventDispatcherInterface $eventDispatcher = null,
4042
): Platform {
4143
$httpClient = $httpClient instanceof EventSourceHttpClient ? $httpClient : new EventSourceHttpClient($httpClient);
@@ -48,6 +50,7 @@ public static function create(
4850
[new Gpt\ResultConverter(), new Embeddings\ResultConverter(), new Whisper\ResultConverter()],
4951
$modelCatalog,
5052
$contract ?? Contract::create(new AudioNormalizer()),
53+
$speechConfiguration,
5154
$eventDispatcher,
5255
);
5356
}

src/platform/src/Bridge/Bedrock/PlatformFactory.php

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -26,6 +26,7 @@
2626
use Symfony\AI\Platform\Exception\RuntimeException;
2727
use Symfony\AI\Platform\ModelCatalog\ModelCatalogInterface;
2828
use Symfony\AI\Platform\Platform;
29+
use Symfony\AI\Platform\Speech\SpeechConfiguration;
2930

3031
/**
3132
* @author Björn Altmann
@@ -36,6 +37,7 @@ public static function create(
3637
BedrockRuntimeClient $bedrockRuntimeClient = new BedrockRuntimeClient(),
3738
ModelCatalogInterface $modelCatalog = new ModelCatalog(),
3839
?Contract $contract = null,
40+
?SpeechConfiguration $speechConfiguration = null,
3941
?EventDispatcherInterface $eventDispatcher = null,
4042
): Platform {
4143
if (!class_exists(BedrockRuntimeClient::class)) {
@@ -70,6 +72,7 @@ public static function create(
7072
new NovaContract\ToolNormalizer(),
7173
new NovaContract\UserMessageNormalizer(),
7274
),
75+
$speechConfiguration,
7376
$eventDispatcher,
7477
);
7578
}

0 commit comments

Comments
 (0)