Skip to content

Commit 6ac9274

Browse files
llupacodebachOskarStark
committed
Add DeepSeek API support
Co-authored-by: Ahmet Akbana <[email protected]> Co-authored-by: Oskar Stark <[email protected]>
1 parent 5f78725 commit 6ac9274

21 files changed

+980
-0
lines changed

examples/.env

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -153,3 +153,6 @@ WEAVIATE_API_KEY=symfony
153153

154154
# For using Scaleway
155155
SCALEWAY_SECRET_KEY=
156+
157+
# For using DeepSeek
158+
DEEPSEEK_API_KEY=

examples/deepseek/chat.php

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 <[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+
use Symfony\AI\Platform\Bridge\DeepSeek\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('DEEPSEEK_API_KEY'), http_client());
19+
20+
$messages = new MessageBag(
21+
Message::forSystem('You are an in-universe Matrix programme, always make hints at the Matrix.'),
22+
Message::ofUser('Yesterday I had a Déjà vu. It is a funny feeling, no?'),
23+
);
24+
$result = $platform->invoke('deepseek-chat', $messages);
25+
26+
echo $result->asText().\PHP_EOL;

examples/deepseek/reason.php

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 <[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+
use Symfony\AI\Platform\Bridge\DeepSeek\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('DEEPSEEK_API_KEY'), http_client());
19+
20+
$messages = new MessageBag(
21+
Message::forSystem('You are an elementary school teacher.'),
22+
Message::ofUser('Why can I see the moon at night?'),
23+
);
24+
$result = $platform->invoke('deepseek-reasoner', $messages);
25+
26+
echo $result->asText().\PHP_EOL;

examples/deepseek/stream.php

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 <[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+
use Symfony\AI\Platform\Bridge\DeepSeek\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('DEEPSEEK_API_KEY'), http_client());
19+
20+
$messages = new MessageBag(
21+
Message::forSystem('You are a thoughtful philosopher.'),
22+
Message::ofUser('What is the purpose of an ant?'),
23+
);
24+
$result = $platform->invoke('deepseek-chat', $messages, ['stream' => true]);
25+
26+
print_stream($result);
Lines changed: 54 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,54 @@
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+
use Symfony\AI\Agent\Agent;
13+
use Symfony\AI\Agent\StructuredOutput\AgentProcessor as StructuredOutputProcessor;
14+
use Symfony\AI\Agent\Toolbox\AgentProcessor as ToolProcessor;
15+
use Symfony\AI\Agent\Toolbox\Tool\Clock;
16+
use Symfony\AI\Agent\Toolbox\Toolbox;
17+
use Symfony\AI\Platform\Bridge\DeepSeek\PlatformFactory;
18+
use Symfony\AI\Platform\Message\Message;
19+
use Symfony\AI\Platform\Message\MessageBag;
20+
use Symfony\Component\Clock\Clock as SymfonyClock;
21+
22+
require_once dirname(__DIR__).'/bootstrap.php';
23+
24+
$platform = PlatformFactory::create(env('DEEPSEEK_API_KEY'), http_client());
25+
26+
$clock = new Clock(new SymfonyClock());
27+
$toolbox = new Toolbox([$clock]);
28+
$toolProcessor = new ToolProcessor($toolbox);
29+
$structuredOutputProcessor = new StructuredOutputProcessor();
30+
$agent = new Agent($platform, 'deepseek-chat', [$toolProcessor, $structuredOutputProcessor], [$toolProcessor, $structuredOutputProcessor]);
31+
32+
$messages = new MessageBag(
33+
// for DeepSeek it is *mandatory* to mention JSON anywhere in the prompt when using structured output
34+
Message::forSystem('Respond in JSON as instructed in the response format.'),
35+
Message::ofUser('What date and time is it?')
36+
);
37+
$result = $agent->call($messages, ['response_format' => [
38+
'type' => 'json_object',
39+
'json_object' => [
40+
'name' => 'clock',
41+
'strict' => true,
42+
'schema' => [
43+
'type' => 'object',
44+
'properties' => [
45+
'date' => ['type' => 'string', 'description' => 'The current date in the format YYYY-MM-DD.'],
46+
'time' => ['type' => 'string', 'description' => 'The current time in the format HH:MM:SS.'],
47+
],
48+
'required' => ['date', 'time'],
49+
'additionalProperties' => false,
50+
],
51+
],
52+
]]);
53+
54+
dump($result->getContent());
Lines changed: 29 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,29 @@
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+
use Symfony\AI\Agent\Agent;
13+
use Symfony\AI\Platform\Bridge\DeepSeek\PlatformFactory;
14+
use Symfony\AI\Platform\Bridge\DeepSeek\TokenOutputProcessor;
15+
use Symfony\AI\Platform\Message\Message;
16+
use Symfony\AI\Platform\Message\MessageBag;
17+
18+
require_once dirname(__DIR__).'/bootstrap.php';
19+
20+
$platform = PlatformFactory::create(env('DEEPSEEK_API_KEY'), http_client());
21+
22+
$agent = new Agent($platform, 'deepseek-chat', outputProcessors: [new TokenOutputProcessor()]);
23+
$messages = new MessageBag(
24+
Message::forSystem('You are a pirate and you write funny.'),
25+
Message::ofUser('What is the Symfony framework?'),
26+
);
27+
$result = $agent->call($messages);
28+
29+
print_token_usage($result->getMetadata());
Lines changed: 41 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,41 @@
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+
use Symfony\AI\Agent\Agent;
13+
use Symfony\AI\Agent\Toolbox\AgentProcessor;
14+
use Symfony\AI\Agent\Toolbox\Tool\Wikipedia;
15+
use Symfony\AI\Agent\Toolbox\Toolbox;
16+
use Symfony\AI\Platform\Bridge\DeepSeek\PlatformFactory;
17+
use Symfony\AI\Platform\Message\Message;
18+
use Symfony\AI\Platform\Message\MessageBag;
19+
20+
require_once dirname(__DIR__).'/bootstrap.php';
21+
22+
$platform = PlatformFactory::create(env('DEEPSEEK_API_KEY'), http_client());
23+
24+
$wikipedia = new Wikipedia(http_client());
25+
$toolbox = new Toolbox([$wikipedia]);
26+
$processor = new AgentProcessor($toolbox);
27+
$agent = new Agent($platform, 'deepseek-chat', [$processor], [$processor]);
28+
$messages = new MessageBag(Message::ofUser(<<<TXT
29+
First, define unicorn in 30 words.
30+
Then lookup at Wikipedia what the irish history looks like in 2 sentences.
31+
Please tell me before you call tools.
32+
TXT));
33+
$result = $agent->call($messages, [
34+
'stream' => true, // enable streaming of response text
35+
]);
36+
37+
foreach ($result->getContent() as $word) {
38+
echo $word;
39+
}
40+
41+
echo \PHP_EOL;

examples/deepseek/toolcall.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 <[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+
use Symfony\AI\Agent\Agent;
13+
use Symfony\AI\Agent\Toolbox\AgentProcessor;
14+
use Symfony\AI\Agent\Toolbox\Tool\Clock;
15+
use Symfony\AI\Agent\Toolbox\Toolbox;
16+
use Symfony\AI\Platform\Bridge\DeepSeek\PlatformFactory;
17+
use Symfony\AI\Platform\Message\Message;
18+
use Symfony\AI\Platform\Message\MessageBag;
19+
20+
require_once dirname(__DIR__).'/bootstrap.php';
21+
22+
$platform = PlatformFactory::create(env('DEEPSEEK_API_KEY'), http_client());
23+
24+
$clock = new Clock();
25+
$toolbox = new Toolbox([$clock]);
26+
$processor = new AgentProcessor($toolbox);
27+
$agent = new Agent($platform, 'deepseek-chat', [$processor], [$processor]);
28+
29+
$messages = new MessageBag(Message::ofUser('How many days until next Christmas?'));
30+
$result = $agent->call($messages);
31+
32+
echo $result->getContent().\PHP_EOL;

src/ai-bundle/config/services.php

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -33,6 +33,7 @@
3333
use Symfony\AI\Platform\Bridge\Azure\Meta\ModelCatalog as AzureMetaModelCatalog;
3434
use Symfony\AI\Platform\Bridge\Azure\OpenAi\ModelCatalog as AzureOpenAiModelCatalog;
3535
use Symfony\AI\Platform\Bridge\Cerebras\ModelCatalog as CerebrasModelCatalog;
36+
use Symfony\AI\Platform\Bridge\DeepSeek\ModelCatalog as DeepSeekModelCatalog;
3637
use Symfony\AI\Platform\Bridge\DockerModelRunner\ModelCatalog as DockerModelRunnerModelCatalog;
3738
use Symfony\AI\Platform\Bridge\ElevenLabs\ModelCatalog as ElevenLabsModelCatalog;
3839
use Symfony\AI\Platform\Bridge\Gemini\Contract\GeminiContract;
@@ -89,6 +90,7 @@
8990
->set('ai.platform.model_catalog.azure.meta', AzureMetaModelCatalog::class)
9091
->set('ai.platform.model_catalog.azure.openai', AzureOpenAiModelCatalog::class)
9192
->set('ai.platform.model_catalog.cerebras', CerebrasModelCatalog::class)
93+
->set('ai.platform.model_catalog.deepseek', DeepSeekModelCatalog::class)
9294
->set('ai.platform.model_catalog.dockermodelrunner', DockerModelRunnerModelCatalog::class)
9395
->set('ai.platform.model_catalog.elevenlabs', ElevenLabsModelCatalog::class)
9496
->set('ai.platform.model_catalog.gemini', GeminiModelCatalog::class)

src/ai-bundle/src/AiBundle.php

Lines changed: 20 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -37,6 +37,7 @@
3737
use Symfony\AI\Platform\Bridge\Anthropic\PlatformFactory as AnthropicPlatformFactory;
3838
use Symfony\AI\Platform\Bridge\Azure\OpenAi\PlatformFactory as AzureOpenAiPlatformFactory;
3939
use Symfony\AI\Platform\Bridge\Cerebras\PlatformFactory as CerebrasPlatformFactory;
40+
use Symfony\AI\Platform\Bridge\DeepSeek\PlatformFactory as DeepSeekPlatformFactory;
4041
use Symfony\AI\Platform\Bridge\DockerModelRunner\PlatformFactory as DockerModelRunnerPlatformFactory;
4142
use Symfony\AI\Platform\Bridge\ElevenLabs\PlatformFactory as ElevenLabsPlatformFactory;
4243
use Symfony\AI\Platform\Bridge\Gemini\PlatformFactory as GeminiPlatformFactory;
@@ -461,6 +462,25 @@ private function processPlatformConfig(string $type, array $platform, ContainerB
461462
return;
462463
}
463464

465+
if ('deepseek' === $type) {
466+
$platformId = 'ai.platform.deepseek';
467+
$definition = (new Definition(Platform::class))
468+
->setFactory(DeepSeekPlatformFactory::class.'::create')
469+
->setLazy(true)
470+
->addTag('proxy', ['interface' => PlatformInterface::class])
471+
->setArguments([
472+
$platform['api_key'],
473+
new Reference($platform['http_client'], ContainerInterface::NULL_ON_INVALID_REFERENCE),
474+
new Reference('ai.platform.model_catalog.deepseek'),
475+
new Reference('ai.platform.contract.default'),
476+
])
477+
->addTag('ai.platform', ['name' => 'deepseek']);
478+
479+
$container->setDefinition($platformId, $definition);
480+
481+
return;
482+
}
483+
464484
if ('voyage' === $type) {
465485
$platformId = 'ai.platform.voyage';
466486
$definition = (new Definition(Platform::class))

0 commit comments

Comments
 (0)