Skip to content

Commit 8722e07

Browse files
authored
Merge branch 'main' into feature/680-tool-events
2 parents d8c8a9e + 0b2a28c commit 8722e07

Some content is hidden

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

44 files changed

+2691
-202
lines changed

demo/config/packages/ai.yaml

Lines changed: 20 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -13,11 +13,8 @@ ai:
1313
method: 'now'
1414
stream:
1515
model: 'gpt-4o-mini'
16-
prompt: |
17-
You are an example chat application where messages from the LLM are streamed to the user using
18-
Server-Sent Events via `symfony/ux-turbo` / Turbo Streams. This example does not use any custom
19-
javascript and solely relies on the built-in `live` & `turbo_stream` Stimulus controllers.
20-
Whatever the user asks, tell them about the application & used technologies.
16+
prompt:
17+
file: '%kernel.project_dir%/prompts/stream-chat.txt'
2118
tools: false
2219
youtube:
2320
model: 'gpt-4o-mini'
@@ -40,6 +37,24 @@ ai:
4037
- agent: 'blog'
4138
name: 'symfony_blog'
4239
description: 'Can answer questions based on the Symfony blog.'
40+
orchestrator:
41+
model: 'gpt-4o-mini'
42+
prompt: 'You are an intelligent agent orchestrator that routes user questions to specialized agents.'
43+
tools: false
44+
technical:
45+
model: 'gpt-4o-mini'
46+
prompt: 'You are a technical support specialist. Help users resolve bugs, problems, and technical errors.'
47+
tools: false
48+
fallback:
49+
model: 'gpt-4o-mini'
50+
prompt: 'You are a helpful general assistant. Assist users with any questions or tasks they may have.'
51+
tools: false
52+
multi_agent:
53+
support:
54+
orchestrator: 'orchestrator'
55+
handoffs:
56+
technical: ['bug', 'problem', 'technical', 'error', 'code', 'debug']
57+
fallback: 'fallback'
4358
store:
4459
chroma_db:
4560
symfonycon:

demo/prompts/stream-chat.txt

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,4 @@
1+
You are an example chat application where messages from the LLM are streamed to the user using
2+
Server-Sent Events via `symfony/ux-turbo` / Turbo Streams. This example does not use any custom
3+
javascript and solely relies on the built-in `live` & `turbo_stream` Stimulus controllers.
4+
Whatever the user asks, tell them about the application & used technologies.

examples/bootstrap.php

Lines changed: 33 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -50,7 +50,39 @@ function http_client(): HttpClientInterface
5050

5151
function logger(): LoggerInterface
5252
{
53-
return new ConsoleLogger(output());
53+
$output = output();
54+
55+
return new class($output) extends ConsoleLogger {
56+
private ConsoleOutput $output;
57+
58+
public function __construct(ConsoleOutput $output)
59+
{
60+
parent::__construct($output);
61+
$this->output = $output;
62+
}
63+
64+
/**
65+
* @param Stringable|string $message
66+
*/
67+
public function log($level, $message, array $context = []): void
68+
{
69+
// Call parent to handle the base logging
70+
parent::log($level, $message, $context);
71+
72+
// Add context display for debug verbosity
73+
if ($this->output->getVerbosity() >= ConsoleOutput::VERBOSITY_DEBUG && [] !== $context) {
74+
// Filter out special keys that are already handled
75+
$displayContext = array_filter($context, function ($key) {
76+
return !in_array($key, ['exception', 'error', 'object'], true);
77+
}, \ARRAY_FILTER_USE_KEY);
78+
79+
if ([] !== $displayContext) {
80+
$contextMessage = ' '.json_encode($displayContext, \JSON_UNESCAPED_SLASHES | \JSON_UNESCAPED_UNICODE);
81+
$this->output->writeln(sprintf('<comment>%s</comment>', $contextMessage));
82+
}
83+
}
84+
}
85+
};
5486
}
5587

5688
function output(): ConsoleOutput

examples/misc/prompt-json-file.php

Lines changed: 31 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,31 @@
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\InputProcessor\SystemPromptInputProcessor;
14+
use Symfony\AI\Platform\Bridge\OpenAi\PlatformFactory;
15+
use Symfony\AI\Platform\Message\Content\File;
16+
use Symfony\AI\Platform\Message\Message;
17+
use Symfony\AI\Platform\Message\MessageBag;
18+
19+
require_once dirname(__DIR__).'/bootstrap.php';
20+
21+
$platform = PlatformFactory::create($_ENV['OPENAI_API_KEY'], http_client());
22+
23+
// Load system prompt from a JSON file
24+
$promptFile = File::fromFile(dirname(__DIR__, 2).'/fixtures/prompts/code-reviewer.json');
25+
$systemPromptProcessor = new SystemPromptInputProcessor($promptFile);
26+
27+
$agent = new Agent($platform, 'gpt-4o-mini', [$systemPromptProcessor], logger: logger());
28+
$messages = new MessageBag(Message::ofUser('Review this code: function add($a, $b) { return $a + $b; }'));
29+
$result = $agent->call($messages);
30+
31+
echo $result->getContent().\PHP_EOL;

examples/misc/prompt-text-file.php

Lines changed: 31 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,31 @@
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\InputProcessor\SystemPromptInputProcessor;
14+
use Symfony\AI\Platform\Bridge\OpenAi\PlatformFactory;
15+
use Symfony\AI\Platform\Message\Content\File;
16+
use Symfony\AI\Platform\Message\Message;
17+
use Symfony\AI\Platform\Message\MessageBag;
18+
19+
require_once dirname(__DIR__).'/bootstrap.php';
20+
21+
$platform = PlatformFactory::create($_ENV['OPENAI_API_KEY'], http_client());
22+
23+
// Load system prompt from a plain text file (.txt)
24+
$promptFile = File::fromFile(dirname(__DIR__, 2).'/fixtures/prompts/helpful-assistant.txt');
25+
$systemPromptProcessor = new SystemPromptInputProcessor($promptFile);
26+
27+
$agent = new Agent($platform, 'gpt-4o-mini', [$systemPromptProcessor], logger: logger());
28+
$messages = new MessageBag(Message::ofUser('Can you explain what dependency injection is?'));
29+
$result = $agent->call($messages);
30+
31+
echo $result->getContent().\PHP_EOL;
Lines changed: 76 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,76 @@
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\InputProcessor\SystemPromptInputProcessor;
14+
use Symfony\AI\Agent\MultiAgent\Handoff;
15+
use Symfony\AI\Agent\MultiAgent\MultiAgent;
16+
use Symfony\AI\Agent\StructuredOutput\AgentProcessor;
17+
use Symfony\AI\Platform\Bridge\OpenAi\PlatformFactory;
18+
use Symfony\AI\Platform\Message\Message;
19+
use Symfony\AI\Platform\Message\MessageBag;
20+
21+
require_once dirname(__DIR__).'/bootstrap.php';
22+
23+
$platform = PlatformFactory::create(env('OPENAI_API_KEY'), http_client());
24+
25+
// Create structured output processor for the orchestrator
26+
$structuredOutputProcessor = new AgentProcessor();
27+
28+
// Create orchestrator agent for routing decisions
29+
$orchestrator = new Agent(
30+
$platform,
31+
'gpt-4o-mini',
32+
[new SystemPromptInputProcessor('You are an intelligent agent orchestrator that routes user questions to specialized agents.'), $structuredOutputProcessor],
33+
[$structuredOutputProcessor],
34+
logger: logger()
35+
);
36+
37+
// Create technical agent for handling technical issues
38+
$technical = new Agent(
39+
$platform,
40+
'gpt-4o-mini?max_tokens=150', // set max_tokens here to be faster and cheaper
41+
[new SystemPromptInputProcessor('You are a technical support specialist. Help users resolve bugs, problems, and technical errors.')],
42+
name: 'technical',
43+
logger: logger()
44+
);
45+
46+
// Create general agent for handling any other questions
47+
$fallback = new Agent(
48+
$platform,
49+
'gpt-4o-mini',
50+
[new SystemPromptInputProcessor('You are a helpful general assistant. Assist users with any questions or tasks they may have. You should never ever answer technical question.')],
51+
name: 'fallback',
52+
logger: logger()
53+
);
54+
55+
$multiAgent = new MultiAgent(
56+
orchestrator: $orchestrator,
57+
handoffs: [
58+
new Handoff(to: $technical, when: ['bug', 'problem', 'technical', 'error']),
59+
],
60+
fallback: $fallback,
61+
logger: logger()
62+
);
63+
64+
echo "=== Technical Question ===\n";
65+
$technicalQuestion = 'I get this error in my php code: "Call to undefined method App\Controller\UserController::getName()" - this is my line of code: $user->getName() where $user is an instance of User entity.';
66+
echo "Question: $technicalQuestion\n\n";
67+
$messages = new MessageBag(Message::ofUser($technicalQuestion));
68+
$result = $multiAgent->call($messages);
69+
echo 'Answer: '.substr($result->getContent(), 0, 300).'...'.\PHP_EOL.\PHP_EOL;
70+
71+
echo "=== General Question ===\n";
72+
$generalQuestion = 'Can you give me a lasagne recipe?';
73+
echo "Question: $generalQuestion\n\n";
74+
$messages = new MessageBag(Message::ofUser($generalQuestion));
75+
$result = $multiAgent->call($messages);
76+
echo 'Answer: '.substr($result->getContent(), 0, 300).'...'.\PHP_EOL;

examples/openai/agent-as-tool.php

Lines changed: 58 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,58 @@
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\InputProcessor\SystemPromptInputProcessor;
14+
use Symfony\AI\Agent\Toolbox\AgentProcessor;
15+
use Symfony\AI\Agent\Toolbox\Tool\Agent as AgentTool;
16+
use Symfony\AI\Agent\Toolbox\ToolFactory\ChainFactory;
17+
use Symfony\AI\Agent\Toolbox\ToolFactory\MemoryToolFactory;
18+
use Symfony\AI\Agent\Toolbox\ToolFactory\ReflectionToolFactory;
19+
use Symfony\AI\Agent\Toolbox\Toolbox;
20+
use Symfony\AI\Platform\Bridge\OpenAi\PlatformFactory;
21+
use Symfony\AI\Platform\Message\Message;
22+
use Symfony\AI\Platform\Message\MessageBag;
23+
24+
require_once dirname(__DIR__).'/bootstrap.php';
25+
26+
$platform = PlatformFactory::create(env('OPENAI_API_KEY'), http_client());
27+
28+
// Create a specialized agent for mathematical calculations
29+
$mathSystemPrompt = new SystemPromptInputProcessor('You are a mathematical calculator. When given a math problem, solve it and return only the numerical result with a brief explanation.');
30+
$mathAgent = new Agent($platform, 'gpt-4o', [$mathSystemPrompt], logger: logger());
31+
32+
// Wrap the math agent as a tool
33+
$mathTool = new AgentTool($mathAgent);
34+
35+
// Use MemoryToolFactory to register the tool with metadata
36+
$memoryFactory = new MemoryToolFactory();
37+
$memoryFactory->addTool(
38+
$mathTool,
39+
'calculate',
40+
'Performs mathematical calculations. Use this when you need to solve math problems or do arithmetic.',
41+
);
42+
43+
// Combine with ReflectionToolFactory using ChainFactory
44+
$chainFactory = new ChainFactory([
45+
$memoryFactory,
46+
new ReflectionToolFactory(),
47+
]);
48+
49+
// Create the main agent with the math agent as a tool
50+
$toolbox = new Toolbox([$mathTool], toolFactory: $chainFactory, logger: logger());
51+
$processor = new AgentProcessor($toolbox);
52+
$agent = new Agent($platform, 'gpt-4o-mini', [$processor], [$processor], logger: logger());
53+
54+
// Ask a question that requires mathematical calculation
55+
$messages = new MessageBag(Message::ofUser('I have 15 apples and I want to share them equally among 4 friends. How many apples does each friend get and how many are left over?'));
56+
$result = $agent->call($messages);
57+
58+
echo $result->getContent().\PHP_EOL;

examples/vertexai/toolcall.php

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -23,7 +23,7 @@
2323

2424
$toolbox = new Toolbox([new Clock()], logger: logger());
2525
$processor = new AgentProcessor($toolbox);
26-
$agent = new Agent($platform, 'gemini-2.0-flash-lite', [$processor], [$processor], logger: logger());
26+
$agent = new Agent($platform, 'gemini-2.5-flash-lite', [$processor], [$processor], logger: logger());
2727

2828
$messages = new MessageBag(Message::ofUser('What time is it?'));
2929
$result = $agent->call($messages);
Lines changed: 12 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,12 @@
1+
{
2+
"role": "You are an expert code reviewer with deep knowledge of software engineering best practices, design patterns, and code quality.",
3+
"responsibilities": [
4+
"Review code for bugs and potential issues",
5+
"Suggest improvements for code quality and maintainability",
6+
"Identify security vulnerabilities",
7+
"Recommend better design patterns when appropriate",
8+
"Ensure code follows language-specific best practices"
9+
],
10+
"tone": "constructive and educational",
11+
"approach": "Provide thorough but concise feedback with specific suggestions and examples when helpful"
12+
}
Lines changed: 8 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,8 @@
1+
You are a helpful and knowledgeable assistant. Your goal is to provide accurate, concise, and useful responses to user queries.
2+
3+
Guidelines:
4+
- Be clear and direct in your responses
5+
- Provide examples when appropriate
6+
- If you're unsure about something, say so
7+
- Be respectful and professional at all times
8+
- Break down complex topics into understandable explanations

0 commit comments

Comments
 (0)