Skip to content

Commit befc6a8

Browse files
committed
ref
1 parent 4b85630 commit befc6a8

File tree

19 files changed

+443
-90
lines changed

19 files changed

+443
-90
lines changed

examples/venice/chat-as-stream.php

Lines changed: 32 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,32 @@
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+
use Symfony\AI\Platform\Bridge\Venice\PlatformFactory;
13+
use Symfony\AI\Platform\Message\Message;
14+
use Symfony\AI\Platform\Message\MessageBag;
15+
16+
require_once dirname(__DIR__).'/bootstrap.php';
17+
18+
$platform = PlatformFactory::create(env('VENICE_API_KEY'), httpClient: http_client());
19+
20+
$messages = new MessageBag(
21+
Message::forSystem('You are a helpful assistant.'),
22+
Message::ofUser('Tina has one brother and one sister. How many sisters do Tina\'s siblings have?'),
23+
);
24+
25+
$result = $platform->invoke('venice-uncensored', $messages, [
26+
'stream' => true,
27+
]);
28+
29+
foreach ($result->asStream() as $word) {
30+
echo $word;
31+
}
32+
echo \PHP_EOL;
Lines changed: 24 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,24 @@
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+
use Symfony\AI\Platform\Bridge\Venice\PlatformFactory;
13+
14+
require_once dirname(__DIR__).'/bootstrap.php';
15+
16+
$platform = PlatformFactory::create(env('VENICE_API_KEY'), httpClient: http_client());
17+
18+
try {
19+
$result = $platform->invoke('venice-uncensored', 'A beautiful sunset over a mountain range');
20+
21+
echo $result->asText().\PHP_EOL;
22+
} catch (InvalidArgumentException $e) {
23+
echo $e->getMessage()."\nMaybe use a different model?\n";
24+
}

src/ai-bundle/config/options.php

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -52,6 +52,7 @@
5252
->append($import('platform/perplexity'))
5353
->append($import('platform/scaleway'))
5454
->append($import('platform/transformersphp'))
55+
->append($import('platform/venice'))
5556
->append($import('platform/vertexai'))
5657
->append($import('platform/voyage'))
5758
->end()
Lines changed: 26 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,26 @@
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\Component\Config\Definition\Configurator;
13+
14+
use Symfony\Component\Config\Definition\Builder\ArrayNodeDefinition;
15+
16+
return (new ArrayNodeDefinition('voyage'))
17+
->children()
18+
->stringNode('api_key')->end()
19+
->stringNode('endpoint')
20+
->defaultValue('https://api.venice.ai/api/v1/')
21+
->end()
22+
->stringNode('http_client')
23+
->defaultValue('http_client')
24+
->info('Service ID of the HTTP client to use')
25+
->end()
26+
->end();

src/ai-bundle/config/services.php

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -56,6 +56,8 @@
5656
use Symfony\AI\Platform\Bridge\Replicate\ModelCatalog as ReplicateModelCatalog;
5757
use Symfony\AI\Platform\Bridge\Scaleway\ModelCatalog as ScalewayModelCatalog;
5858
use Symfony\AI\Platform\Bridge\TransformersPhp\ModelCatalog as TransformersPhpModelCatalog;
59+
use Symfony\AI\Platform\Bridge\Venice\Contract\Contract as VeniceContract;
60+
use Symfony\AI\Platform\Bridge\Venice\ModelCatalog as VeniceModelCatalog;
5961
use Symfony\AI\Platform\Bridge\VertexAi\Contract\GeminiContract as VertexAiGeminiContract;
6062
use Symfony\AI\Platform\Bridge\VertexAi\ModelCatalog as VertexAiModelCatalog;
6163
use Symfony\AI\Platform\Bridge\Voyage\ModelCatalog as VoyageModelCatalog;
@@ -90,6 +92,8 @@
9092
->factory([GeminiContract::class, 'create'])
9193
->set('ai.platform.contract.huggingface', Contract::class)
9294
->factory([HuggingFaceContract::class, 'create'])
95+
->set('ai.platform.contract.venice', Contract::class)
96+
->factory([VeniceContract::class, 'create'])
9397
->set('ai.platform.contract.vertexai.gemini', Contract::class)
9498
->factory([VertexAiGeminiContract::class, 'create'])
9599
->set('ai.platform.contract.ollama', Contract::class)

src/ai-bundle/src/AiBundle.php

Lines changed: 25 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -77,6 +77,7 @@
7777
use Symfony\AI\Platform\Bridge\Perplexity\PlatformFactory as PerplexityPlatformFactory;
7878
use Symfony\AI\Platform\Bridge\Scaleway\PlatformFactory as ScalewayPlatformFactory;
7979
use Symfony\AI\Platform\Bridge\TransformersPhp\PlatformFactory as TransformersPhpPlatformFactory;
80+
use Symfony\AI\Platform\Bridge\Venice\PlatformFactory as VenicePlatformFactory;
8081
use Symfony\AI\Platform\Bridge\VertexAi\PlatformFactory as VertexAiPlatformFactory;
8182
use Symfony\AI\Platform\Bridge\Voyage\PlatformFactory as VoyagePlatformFactory;
8283
use Symfony\AI\Platform\Capability;
@@ -722,6 +723,30 @@ private function processPlatformConfig(string $type, array $platform, ContainerB
722723
return;
723724
}
724725

726+
if ('venice' === $type) {
727+
if (!ContainerBuilder::willBeAvailable('symfony/ai-venice-platform', VoyagePlatformFactory::class, ['symfony/ai-bundle'])) {
728+
throw new RuntimeException('Voyage platform configuration requires "symfony/ai-venice-platform" package. Try running "composer require symfony/ai-venice-platform".');
729+
}
730+
731+
$definition = (new Definition(Platform::class))
732+
->setFactory(VenicePlatformFactory::class.'::create')
733+
->setLazy(true)
734+
->setArguments([
735+
$platform['api_key'] ?? null,
736+
$platform['endpoint'],
737+
new Reference($platform['http_client']),
738+
new Reference('ai.platform.contract.'.$type),
739+
new Reference('event_dispatcher'),
740+
])
741+
->addTag('proxy', ['interface' => PlatformInterface::class])
742+
->addTag('ai.platform', ['name' => $type]);
743+
744+
$container->setDefinition('ai.platform.'.$type, $definition);
745+
$container->registerAliasForArgument('ai.platform.'.$type, PlatformInterface::class, $type);
746+
747+
return;
748+
}
749+
725750
if ('vertexai' === $type && isset($platform['location'], $platform['project_id'])) {
726751
if (!ContainerBuilder::willBeAvailable('symfony/ai-vertex-ai-platform', VertexAiPlatformFactory::class, ['symfony/ai-bundle'])) {
727752
throw new RuntimeException('VertexAI platform configuration requires "symfony/ai-vertex-ai-platform" package. Try running "composer require symfony/ai-vertex-ai-platform".');

src/ai-bundle/tests/DependencyInjection/AiBundleTest.php

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -7872,6 +7872,9 @@ private function getFullConfig(): array
78727872
'voyage' => [
78737873
'api_key' => 'voyage_key_full',
78747874
],
7875+
'venice' => [
7876+
'api_key' => 'venice_api_key',
7877+
],
78757878
'vertexai' => [
78767879
'location' => 'global',
78777880
'project_id' => '123',

src/platform/src/Bridge/Venice/ModelCatalog.php

Lines changed: 58 additions & 23 deletions
Original file line numberDiff line numberDiff line change
@@ -12,55 +12,90 @@
1212
namespace Symfony\AI\Platform\Bridge\Venice;
1313

1414
use Symfony\AI\Platform\Capability;
15-
use Symfony\AI\Platform\Model;
16-
use Symfony\AI\Platform\ModelCatalog\AbstractModelCatalog;
15+
use Symfony\AI\Platform\Exception\InvalidArgumentException;
16+
use Symfony\AI\Platform\ModelCatalog\ModelCatalogInterface;
17+
use Symfony\Contracts\HttpClient\HttpClientInterface;
1718

1819
/**
1920
* @author Guillaume Loulier <personal@guillaumeloulier.fr>
2021
*/
21-
final class ModelCatalog extends AbstractModelCatalog
22+
final class ModelCatalog implements ModelCatalogInterface
2223
{
23-
/**
24-
* @param array<string, array{class: class-string<Model>, capabilities: list<Capability>}> $additionalModels
25-
*/
26-
public function __construct(array $additionalModels = [])
24+
public function __construct(
25+
private readonly HttpClientInterface $httpClient,
26+
) {
27+
}
28+
29+
public function getModel(string $modelName): Venice
2730
{
28-
$defaultModels = [
29-
'venice-uncensored' => [
31+
$models = $this->getModels();
32+
33+
if (!\array_key_exists($modelName, $models)) {
34+
throw new InvalidArgumentException(\sprintf('The model "%s" cannot be retrieved from the API.', $modelName));
35+
}
36+
37+
if ([] === $models[$modelName]['capabilities']) {
38+
throw new InvalidArgumentException(\sprintf('The model "%s" is not supported, please check the Venice API.', $modelName));
39+
}
40+
41+
return new Venice($modelName, $models[$modelName]['capabilities']);
42+
}
43+
44+
public function getModels(): array
45+
{
46+
$results = $this->httpClient->request('GET', 'models', [
47+
'query' => [
48+
'type' => 'all',
49+
],
50+
]);
51+
52+
$models = $results->toArray();
53+
54+
if ([] === $models['data']) {
55+
return [];
56+
}
57+
58+
$payload = static fn (array $model): array => match ($model['type']) {
59+
'asr' => [
3060
'class' => Venice::class,
3161
'capabilities' => [
32-
Capability::INPUT_MESSAGES,
62+
Capability::SPEECH_RECOGNITION,
63+
Capability::INPUT_TEXT,
3364
],
3465
],
35-
'tts-kokoro' => [
66+
'embedding' => [
3667
'class' => Venice::class,
3768
'capabilities' => [
38-
Capability::TEXT_TO_SPEECH,
69+
Capability::EMBEDDINGS,
70+
Capability::INPUT_TEXT,
3971
],
4072
],
41-
'nvidia/parakeet-tdt-0.6b-v3' => [
73+
'text' => [
4274
'class' => Venice::class,
4375
'capabilities' => [
44-
Capability::SPEECH_TO_TEXT,
76+
Capability::INPUT_TEXT,
77+
Capability::INPUT_MESSAGES,
4578
],
4679
],
47-
'openai/whisper-large-v3' => [
80+
'tts' => [
4881
'class' => Venice::class,
4982
'capabilities' => [
50-
Capability::SPEECH_TO_TEXT,
83+
Capability::TEXT_TO_SPEECH,
84+
Capability::INPUT_TEXT,
5185
],
5286
],
53-
'text-embedding-bge-m3' => [
87+
'video' => [
5488
'class' => Venice::class,
5589
'capabilities' => [
56-
Capability::EMBEDDINGS,
90+
Capability::IMAGE_TO_VIDEO,
91+
Capability::INPUT_IMAGE,
5792
],
5893
],
59-
];
94+
};
6095

61-
$this->models = [
62-
...$defaultModels,
63-
...$additionalModels,
64-
];
96+
return array_combine(
97+
array_map(static fn (array $model): string => $model['id'], $models['data']),
98+
array_map(static fn (array $model): array => $payload($model), $models['data']),
99+
);
65100
}
66101
}

src/platform/src/Bridge/Venice/PlatformFactory.php

Lines changed: 7 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -27,23 +27,24 @@
2727
final class PlatformFactory
2828
{
2929
public static function create(
30-
#[\SensitiveParameter] string $apiKey,
30+
#[\SensitiveParameter] ?string $apiKey = null,
3131
string $endpoint = 'https://api.venice.ai/api/v1/',
3232
?HttpClientInterface $httpClient = null,
33-
ModelCatalogInterface $modelCatalog = new ModelCatalog(),
3433
?Contract $contract = null,
3534
?EventDispatcherInterface $eventDispatcher = null,
3635
): PlatformInterface {
3736
$httpClient = $httpClient instanceof EventSourceHttpClient ? $httpClient : new EventSourceHttpClient($httpClient);
3837

39-
$httpClient = ScopingHttpClient::forBaseUri($httpClient, $endpoint, [
40-
'auth_bearer' => $apiKey,
41-
]);
38+
if (null !== $apiKey) {
39+
$httpClient = ScopingHttpClient::forBaseUri($httpClient, $endpoint, [
40+
'auth_bearer' => $apiKey,
41+
]);
42+
}
4243

4344
return new Platform(
4445
[new VeniceClient($httpClient)],
4546
[new ResultConverter()],
46-
$modelCatalog ?? new VeniceApiModelCatalog($httpClient),
47+
new ModelCatalog($httpClient),
4748
$contract ?? VeniceContract::create(),
4849
$eventDispatcher,
4950
);

src/platform/src/Bridge/Venice/README.md

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -1,7 +1,7 @@
1-
Ollama Platform
1+
Venice Platform
22
===============
33

4-
Ollama platform bridge for Symfony AI.
4+
Venice platform bridge for Symfony AI.
55

66
Resources
77
---------

0 commit comments

Comments
 (0)