Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
3 changes: 3 additions & 0 deletions examples/.env
Original file line number Diff line number Diff line change
Expand Up @@ -153,3 +153,6 @@ WEAVIATE_API_KEY=symfony

# For using Scaleway
SCALEWAY_SECRET_KEY=

# For using DeepSeek
DEEPSEEK_API_KEY=
26 changes: 26 additions & 0 deletions examples/deepseek/chat.php
Original file line number Diff line number Diff line change
@@ -0,0 +1,26 @@
<?php

/*
* This file is part of the Symfony package.
*
* (c) Fabien Potencier <fabien@symfony.com>
*
* For the full copyright and license information, please view the LICENSE
* file that was distributed with this source code.
*/

use Symfony\AI\Platform\Bridge\DeepSeek\PlatformFactory;
use Symfony\AI\Platform\Message\Message;
use Symfony\AI\Platform\Message\MessageBag;

require_once dirname(__DIR__).'/bootstrap.php';

$platform = PlatformFactory::create(env('DEEPSEEK_API_KEY'), http_client());

$messages = new MessageBag(
Message::forSystem('You are an in-universe Matrix programme, always make hints at the Matrix.'),
Message::ofUser('Yesterday I had a Déjà vu. It is a funny feeling, no?'),
);
$result = $platform->invoke('deepseek-chat', $messages);

echo $result->asText().\PHP_EOL;
26 changes: 26 additions & 0 deletions examples/deepseek/reason.php
Original file line number Diff line number Diff line change
@@ -0,0 +1,26 @@
<?php

/*
* This file is part of the Symfony package.
*
* (c) Fabien Potencier <fabien@symfony.com>
*
* For the full copyright and license information, please view the LICENSE
* file that was distributed with this source code.
*/

use Symfony\AI\Platform\Bridge\DeepSeek\PlatformFactory;
use Symfony\AI\Platform\Message\Message;
use Symfony\AI\Platform\Message\MessageBag;

require_once dirname(__DIR__).'/bootstrap.php';

$platform = PlatformFactory::create(env('DEEPSEEK_API_KEY'), http_client());

$messages = new MessageBag(
Message::forSystem('You are an elementary school teacher.'),
Message::ofUser('Why can I see the moon at night?'),
);
$result = $platform->invoke('deepseek-reasoner', $messages);

echo $result->asText().\PHP_EOL;
26 changes: 26 additions & 0 deletions examples/deepseek/stream.php
Original file line number Diff line number Diff line change
@@ -0,0 +1,26 @@
<?php

/*
* This file is part of the Symfony package.
*
* (c) Fabien Potencier <fabien@symfony.com>
*
* For the full copyright and license information, please view the LICENSE
* file that was distributed with this source code.
*/

use Symfony\AI\Platform\Bridge\DeepSeek\PlatformFactory;
use Symfony\AI\Platform\Message\Message;
use Symfony\AI\Platform\Message\MessageBag;

require_once dirname(__DIR__).'/bootstrap.php';

$platform = PlatformFactory::create(env('DEEPSEEK_API_KEY'), http_client());

$messages = new MessageBag(
Message::forSystem('You are a thoughtful philosopher.'),
Message::ofUser('What is the purpose of an ant?'),
);
$result = $platform->invoke('deepseek-chat', $messages, ['stream' => true]);

print_stream($result);
54 changes: 54 additions & 0 deletions examples/deepseek/structured-output-clock.php
Original file line number Diff line number Diff line change
@@ -0,0 +1,54 @@
<?php

/*
* This file is part of the Symfony package.
*
* (c) Fabien Potencier <fabien@symfony.com>
*
* For the full copyright and license information, please view the LICENSE
* file that was distributed with this source code.
*/

use Symfony\AI\Agent\Agent;
use Symfony\AI\Agent\StructuredOutput\AgentProcessor as StructuredOutputProcessor;
use Symfony\AI\Agent\Toolbox\AgentProcessor as ToolProcessor;
use Symfony\AI\Agent\Toolbox\Tool\Clock;
use Symfony\AI\Agent\Toolbox\Toolbox;
use Symfony\AI\Platform\Bridge\DeepSeek\PlatformFactory;
use Symfony\AI\Platform\Message\Message;
use Symfony\AI\Platform\Message\MessageBag;
use Symfony\Component\Clock\Clock as SymfonyClock;

require_once dirname(__DIR__).'/bootstrap.php';

$platform = PlatformFactory::create(env('DEEPSEEK_API_KEY'), http_client());

$clock = new Clock(new SymfonyClock());
$toolbox = new Toolbox([$clock]);
$toolProcessor = new ToolProcessor($toolbox);
$structuredOutputProcessor = new StructuredOutputProcessor();
$agent = new Agent($platform, 'deepseek-chat', [$toolProcessor, $structuredOutputProcessor], [$toolProcessor, $structuredOutputProcessor]);

$messages = new MessageBag(
// for DeepSeek it is *mandatory* to mention JSON anywhere in the prompt when using structured output
Message::forSystem('Respond in JSON as instructed in the response format.'),
Message::ofUser('What date and time is it?')
);
$result = $agent->call($messages, ['response_format' => [
'type' => 'json_object',
'json_object' => [
'name' => 'clock',
'strict' => true,
'schema' => [
'type' => 'object',
'properties' => [
'date' => ['type' => 'string', 'description' => 'The current date in the format YYYY-MM-DD.'],
'time' => ['type' => 'string', 'description' => 'The current time in the format HH:MM:SS.'],
],
'required' => ['date', 'time'],
'additionalProperties' => false,
],
],
]]);

dump($result->getContent());
29 changes: 29 additions & 0 deletions examples/deepseek/token-metadata.php
Original file line number Diff line number Diff line change
@@ -0,0 +1,29 @@
<?php

/*
* This file is part of the Symfony package.
*
* (c) Fabien Potencier <fabien@symfony.com>
*
* For the full copyright and license information, please view the LICENSE
* file that was distributed with this source code.
*/

use Symfony\AI\Agent\Agent;
use Symfony\AI\Platform\Bridge\DeepSeek\PlatformFactory;
use Symfony\AI\Platform\Bridge\DeepSeek\TokenOutputProcessor;
use Symfony\AI\Platform\Message\Message;
use Symfony\AI\Platform\Message\MessageBag;

require_once dirname(__DIR__).'/bootstrap.php';

$platform = PlatformFactory::create(env('DEEPSEEK_API_KEY'), http_client());

$agent = new Agent($platform, 'deepseek-chat', outputProcessors: [new TokenOutputProcessor()]);
$messages = new MessageBag(
Message::forSystem('You are a pirate and you write funny.'),
Message::ofUser('What is the Symfony framework?'),
);
$result = $agent->call($messages);

print_token_usage($result->getMetadata());
41 changes: 41 additions & 0 deletions examples/deepseek/toolcall-stream.php
Original file line number Diff line number Diff line change
@@ -0,0 +1,41 @@
<?php

/*
* This file is part of the Symfony package.
*
* (c) Fabien Potencier <fabien@symfony.com>
*
* For the full copyright and license information, please view the LICENSE
* file that was distributed with this source code.
*/

use Symfony\AI\Agent\Agent;
use Symfony\AI\Agent\Toolbox\AgentProcessor;
use Symfony\AI\Agent\Toolbox\Tool\Wikipedia;
use Symfony\AI\Agent\Toolbox\Toolbox;
use Symfony\AI\Platform\Bridge\DeepSeek\PlatformFactory;
use Symfony\AI\Platform\Message\Message;
use Symfony\AI\Platform\Message\MessageBag;

require_once dirname(__DIR__).'/bootstrap.php';

$platform = PlatformFactory::create(env('DEEPSEEK_API_KEY'), http_client());

$wikipedia = new Wikipedia(http_client());
$toolbox = new Toolbox([$wikipedia]);
$processor = new AgentProcessor($toolbox);
$agent = new Agent($platform, 'deepseek-chat', [$processor], [$processor]);
$messages = new MessageBag(Message::ofUser(<<<TXT
First, define unicorn in 30 words.
Then lookup at Wikipedia what the irish history looks like in 2 sentences.
Please tell me before you call tools.
TXT));
$result = $agent->call($messages, [
'stream' => true, // enable streaming of response text
]);

foreach ($result->getContent() as $word) {
echo $word;
}

echo \PHP_EOL;
32 changes: 32 additions & 0 deletions examples/deepseek/toolcall.php
Original file line number Diff line number Diff line change
@@ -0,0 +1,32 @@
<?php

/*
* This file is part of the Symfony package.
*
* (c) Fabien Potencier <fabien@symfony.com>
*
* For the full copyright and license information, please view the LICENSE
* file that was distributed with this source code.
*/

use Symfony\AI\Agent\Agent;
use Symfony\AI\Agent\Toolbox\AgentProcessor;
use Symfony\AI\Agent\Toolbox\Tool\Clock;
use Symfony\AI\Agent\Toolbox\Toolbox;
use Symfony\AI\Platform\Bridge\DeepSeek\PlatformFactory;
use Symfony\AI\Platform\Message\Message;
use Symfony\AI\Platform\Message\MessageBag;

require_once dirname(__DIR__).'/bootstrap.php';

$platform = PlatformFactory::create(env('DEEPSEEK_API_KEY'), http_client());

$clock = new Clock();
$toolbox = new Toolbox([$clock]);
$processor = new AgentProcessor($toolbox);
$agent = new Agent($platform, 'deepseek-chat', [$processor], [$processor]);

$messages = new MessageBag(Message::ofUser('How many days until next Christmas?'));
$result = $agent->call($messages);

echo $result->getContent().\PHP_EOL;
2 changes: 2 additions & 0 deletions src/ai-bundle/config/services.php
Original file line number Diff line number Diff line change
Expand Up @@ -33,6 +33,7 @@
use Symfony\AI\Platform\Bridge\Azure\Meta\ModelCatalog as AzureMetaModelCatalog;
use Symfony\AI\Platform\Bridge\Azure\OpenAi\ModelCatalog as AzureOpenAiModelCatalog;
use Symfony\AI\Platform\Bridge\Cerebras\ModelCatalog as CerebrasModelCatalog;
use Symfony\AI\Platform\Bridge\DeepSeek\ModelCatalog as DeepSeekModelCatalog;
use Symfony\AI\Platform\Bridge\DockerModelRunner\ModelCatalog as DockerModelRunnerModelCatalog;
use Symfony\AI\Platform\Bridge\ElevenLabs\ModelCatalog as ElevenLabsModelCatalog;
use Symfony\AI\Platform\Bridge\Gemini\Contract\GeminiContract;
Expand Down Expand Up @@ -89,6 +90,7 @@
->set('ai.platform.model_catalog.azure.meta', AzureMetaModelCatalog::class)
->set('ai.platform.model_catalog.azure.openai', AzureOpenAiModelCatalog::class)
->set('ai.platform.model_catalog.cerebras', CerebrasModelCatalog::class)
->set('ai.platform.model_catalog.deepseek', DeepSeekModelCatalog::class)
->set('ai.platform.model_catalog.dockermodelrunner', DockerModelRunnerModelCatalog::class)
->set('ai.platform.model_catalog.elevenlabs', ElevenLabsModelCatalog::class)
->set('ai.platform.model_catalog.gemini', GeminiModelCatalog::class)
Expand Down
20 changes: 20 additions & 0 deletions src/ai-bundle/src/AiBundle.php
Original file line number Diff line number Diff line change
Expand Up @@ -37,6 +37,7 @@
use Symfony\AI\Platform\Bridge\Anthropic\PlatformFactory as AnthropicPlatformFactory;
use Symfony\AI\Platform\Bridge\Azure\OpenAi\PlatformFactory as AzureOpenAiPlatformFactory;
use Symfony\AI\Platform\Bridge\Cerebras\PlatformFactory as CerebrasPlatformFactory;
use Symfony\AI\Platform\Bridge\DeepSeek\PlatformFactory as DeepSeekPlatformFactory;
use Symfony\AI\Platform\Bridge\DockerModelRunner\PlatformFactory as DockerModelRunnerPlatformFactory;
use Symfony\AI\Platform\Bridge\ElevenLabs\PlatformFactory as ElevenLabsPlatformFactory;
use Symfony\AI\Platform\Bridge\Gemini\PlatformFactory as GeminiPlatformFactory;
Expand Down Expand Up @@ -461,6 +462,25 @@ private function processPlatformConfig(string $type, array $platform, ContainerB
return;
}

if ('deepseek' === $type) {
$platformId = 'ai.platform.deepseek';
$definition = (new Definition(Platform::class))
->setFactory(DeepSeekPlatformFactory::class.'::create')
->setLazy(true)
->addTag('proxy', ['interface' => PlatformInterface::class])
->setArguments([
$platform['api_key'],
new Reference($platform['http_client'], ContainerInterface::NULL_ON_INVALID_REFERENCE),
new Reference('ai.platform.model_catalog.deepseek'),
new Reference('ai.platform.contract.default'),
])
->addTag('ai.platform', ['name' => 'deepseek']);

$container->setDefinition($platformId, $definition);

return;
}

if ('voyage' === $type) {
$platformId = 'ai.platform.voyage';
$definition = (new Definition(Platform::class))
Expand Down
18 changes: 18 additions & 0 deletions src/platform/src/Bridge/DeepSeek/DeepSeek.php
Original file line number Diff line number Diff line change
@@ -0,0 +1,18 @@
<?php

/*
* This file is part of the Symfony package.
*
* (c) Fabien Potencier <fabien@symfony.com>
*
* For the full copyright and license information, please view the LICENSE
* file that was distributed with this source code.
*/

namespace Symfony\AI\Platform\Bridge\DeepSeek;

use Symfony\AI\Platform\Model;

final class DeepSeek extends Model
{
}
49 changes: 49 additions & 0 deletions src/platform/src/Bridge/DeepSeek/ModelCatalog.php
Original file line number Diff line number Diff line change
@@ -0,0 +1,49 @@
<?php

/*
* This file is part of the Symfony package.
*
* (c) Fabien Potencier <fabien@symfony.com>
*
* For the full copyright and license information, please view the LICENSE
* file that was distributed with this source code.
*/

namespace Symfony\AI\Platform\Bridge\DeepSeek;

use Symfony\AI\Platform\Capability;
use Symfony\AI\Platform\ModelCatalog\AbstractModelCatalog;

/**
* @author Oskar Stark <oskarstark@googlemail.com>
*/
final class ModelCatalog extends AbstractModelCatalog
{
/**
* @param array<string, array{class: string, capabilities: list<Capability>}> $additionalModels
*/
public function __construct(array $additionalModels = [])
{
$defaultModels = [
'deepseek-chat' => [
'class' => DeepSeek::class,
'capabilities' => [
Capability::INPUT_MESSAGES,
Capability::OUTPUT_TEXT,
Capability::OUTPUT_STREAMING,
Capability::TOOL_CALLING,
],
],
'deepseek-reasoner' => [
'class' => DeepSeek::class,
'capabilities' => [
Capability::INPUT_MESSAGES,
Capability::OUTPUT_TEXT,
Capability::OUTPUT_STREAMING,
],
],
];

$this->models = array_merge($defaultModels, $additionalModels);
}
}
Loading