Skip to content

Commit c3ac16c

Browse files
committed
feature #771 [AI Bundle][Demo] Add config options for keeping tool call messages and sources + expose metadata in profiler (chr-hertel)
This PR was merged into the main branch. Discussion ---------- [AI Bundle][Demo] Add config options for keeping tool call messages and sources + expose metadata in profiler | Q | A | ------------- | --- | Bug fix? | no | New feature? | yes | Docs? | no | Issues | | License | MIT <img width="1346" height="602" alt="image" src="https://github.com/user-attachments/assets/e68b4ace-321e-484a-9d39-63bbc672d2f7" /> <img width="1346" height="602" alt="image" src="https://github.com/user-attachments/assets/d09819a1-5081-428e-abf9-57d02bf7fe28" /> Commits ------- cbf0629 Add config options for keeping tool call messages and sources + expose metadata in profiler
2 parents 7990461 + cbf0629 commit c3ac16c

File tree

13 files changed

+58
-18
lines changed

13 files changed

+58
-18
lines changed

.github/workflows/code-quality.yaml

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -29,7 +29,7 @@ jobs:
2929
- name: Configure environment
3030
run: |
3131
echo COLUMNS=120 >> $GITHUB_ENV
32-
echo COMPOSER_UP='composer update --no-progress --no-interaction --ansi --ignore-platform-req=ext-mongodb' >> $GITHUB_ENV
32+
echo COMPOSER_UP='composer update --no-progress --no-interaction --no-scripts --ansi --ignore-platform-req=ext-mongodb' >> $GITHUB_ENV
3333
echo PHPSTAN='vendor/bin/phpstan' >> $GITHUB_ENV
3434
3535
PACKAGES=$(find src/ -mindepth 2 -type f -name composer.json -not -path "*/vendor/*" -printf '%h\n' | sed 's/^src\///' | grep -Ev "examples" | sort | tr '\n' ' ')

demo/config/packages/ai.yaml

Lines changed: 3 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -25,10 +25,11 @@ ai:
2525
options:
2626
temperature: 0.5
2727
prompt:
28-
text: 'Please answer the users question based on Wikipedia and provide a link to the article.'
28+
text: 'Please answer the users question based on Wikipedia, only use information provided in the messages.'
2929
include_tools: true
3030
tools:
3131
- 'Symfony\AI\Agent\Toolbox\Tool\Wikipedia'
32+
include_sources: true
3233
audio:
3334
model: 'gpt-4o-mini?temperature=1.0'
3435
prompt: 'You are a friendly chatbot that likes to have a conversation with users and asks them some questions.'
@@ -89,7 +90,7 @@ services:
8990

9091
Symfony\AI\Store\Document\Loader\RssFeedLoader: ~
9192
Symfony\AI\Store\Document\Transformer\TextTrimTransformer: ~
92-
93+
9394
app.filter.week_of_symfony:
9495
class: 'Symfony\AI\Store\Document\Filter\TextContainsFilter'
9596
arguments:

demo/src/Wikipedia/Chat.php

Lines changed: 3 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -43,7 +43,9 @@ public function submitMessage(string $message): void
4343

4444
\assert($result instanceof TextResult);
4545

46-
$messages->add(Message::ofAssistant($result->getContent()));
46+
$response = Message::ofAssistant($result->getContent());
47+
$response->getMetadata()->add('sources', $result->getMetadata()->get('sources', []));
48+
$messages->add($response);
4749

4850
$this->saveMessages($messages);
4951
}

demo/templates/components/wikipedia.html.twig

Lines changed: 13 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -1,4 +1,4 @@
1-
{% import "_message.html.twig" as message %}
1+
{% import "_message.html.twig" as msg %}
22

33
<div class="card mx-auto shadow-lg" {{ attributes.defaults(stimulus_controller('wikipedia')) }}>
44
<div class="card-header p-2">
@@ -9,6 +9,16 @@
99
<div id="chat-body" class="card-body p-4 overflow-auto">
1010
{% for message in this.messages %}
1111
{% include '_message.html.twig' with { message, latest: loop.last } %}
12+
{% if message.metadata.has('sources') %}
13+
<div class="ms-5">
14+
<h6>Sources:</h6>
15+
<ol>
16+
{% for source in message.metadata.get('sources') %}
17+
<li><a class="text-black-50" href="{{ source.reference }}" target="_blank" rel="noopener">{{ source.name }}</a></li>
18+
{% endfor %}
19+
</ol>
20+
</div>
21+
{% endif %}
1222
{% else %}
1323
<div id="welcome" class="text-center mt-5 py-5 bg-white rounded-5 shadow-sm w-75 mx-auto">
1424
{{ ux_icon('mdi:wikipedia', { height: '200px', width: '200px' }) }}
@@ -17,8 +27,8 @@
1727
</div>
1828
{% endfor %}
1929
<div id="loading-message" class="d-none">
20-
{{ message.user([{text:''}]) }}
21-
{{ message.bot('The Wikipedia Bot is doing some research ...', true) }}
30+
{{ msg.user([{text:''}]) }}
31+
{{ msg.bot('The Wikipedia Bot is doing some research ...', true) }}
2232
</div>
2333
</div>
2434
<div class="card-footer p-2">

docs/components/agent.rst

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -318,13 +318,13 @@ Tool Sources
318318
~~~~~~~~~~~~
319319

320320
Some tools bring in data to the agent from external sources, like search engines or APIs. Those sources can be exposed
321-
by enabling `keepToolSources` as argument of the :class:`Symfony\\AI\\Agent\\Toolbox\\AgentProcessor`::
321+
by enabling `includeSources` as argument of the :class:`Symfony\\AI\\Agent\\Toolbox\\AgentProcessor`::
322322

323323
use Symfony\AI\Agent\Toolbox\AgentProcessor;
324324
use Symfony\AI\Agent\Toolbox\Toolbox;
325325

326326
$toolbox = new Toolbox([new MyTool()]);
327-
$toolProcessor = new AgentProcessor($toolbox, keepToolSources: true);
327+
$toolProcessor = new AgentProcessor($toolbox, includeSources: true);
328328

329329
In the tool implementation sources can be added by implementing the
330330
:class:`Symfony\\AI\\Agent\\Toolbox\\Source\\HasSourcesInterface` in combination with the trait

examples/anthropic/toolcall.php

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

2525
$wikipedia = new Wikipedia(http_client());
2626
$toolbox = new Toolbox([$wikipedia], logger: logger());
27-
$processor = new AgentProcessor($toolbox, keepToolSources: true);
27+
$processor = new AgentProcessor($toolbox, includeSources: true);
2828
$agent = new Agent($platform, 'claude-3-5-sonnet-20241022', [$processor], [$processor]);
2929

3030
$messages = new MessageBag(Message::ofUser('Who is the current chancellor of Germany?'));

src/agent/src/Toolbox/AgentProcessor.php

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -53,7 +53,7 @@ public function __construct(
5353
private readonly ToolResultConverter $resultConverter = new ToolResultConverter(),
5454
private readonly ?EventDispatcherInterface $eventDispatcher = null,
5555
private readonly bool $keepToolMessages = false,
56-
private readonly bool $keepToolSources = false,
56+
private readonly bool $includeSources = false,
5757
) {
5858
}
5959

@@ -127,7 +127,7 @@ private function handleToolCallsCallback(Output $output): \Closure
127127
} while ($result instanceof ToolCallResult);
128128

129129
--$this->nestingLevel;
130-
if ($this->keepToolSources && 0 === $this->nestingLevel) {
130+
if ($this->includeSources && 0 === $this->nestingLevel) {
131131
$result->getMetadata()->add('sources', $this->sources);
132132
$this->sources = [];
133133
}

src/agent/tests/Toolbox/AgentProcessorTest.php

Lines changed: 3 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -148,7 +148,7 @@ public function testSourcesEndUpInResultMetadataWithSettingOn()
148148
->method('call')
149149
->willReturn(new TextResult('Final response based on the two articles.'));
150150

151-
$processor = new AgentProcessor($toolbox, keepToolSources: true);
151+
$processor = new AgentProcessor($toolbox, includeSources: true);
152152
$processor->setAgent($agent);
153153

154154
$output = new Output('gpt-4', $result, $messageBag);
@@ -181,7 +181,7 @@ public function testSourcesDoNotEndUpInResultMetadataWithSettingOff()
181181
->method('call')
182182
->willReturn(new TextResult('Final response based on the two articles.'));
183183

184-
$processor = new AgentProcessor($toolbox, keepToolSources: false);
184+
$processor = new AgentProcessor($toolbox, includeSources: false);
185185
$processor->setAgent($agent);
186186

187187
$output = new Output('gpt-4', $result, $messageBag);
@@ -220,7 +220,7 @@ public function testSourcesGetCollectedAcrossConsecutiveToolCalls()
220220
new DeferredResult(new PlainConverter(new TextResult('Final response based on both articles.')), new InMemoryRawResult())
221221
);
222222

223-
$processor = new AgentProcessor($toolbox, keepToolSources: true);
223+
$processor = new AgentProcessor($toolbox, includeSources: true);
224224
$agent = new Agent($platform, 'foo-bar', [$processor], [$processor]);
225225
$processor->setAgent($agent);
226226

src/ai-bundle/config/options.php

Lines changed: 12 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -409,7 +409,18 @@
409409
->end()
410410
->end()
411411
->end()
412-
->booleanNode('fault_tolerant_toolbox')->defaultTrue()->end()
412+
->booleanNode('keep_tool_messages')
413+
->info('Keep tool messages in the conversation history')
414+
->defaultFalse()
415+
->end()
416+
->booleanNode('include_sources')
417+
->info('Include sources exposed by tools as part of the tool result metadata')
418+
->defaultFalse()
419+
->end()
420+
->booleanNode('fault_tolerant_toolbox')
421+
->info('Continue the agent run even if a tool call fails')
422+
->defaultTrue()
423+
->end()
413424
->end()
414425
->end()
415426
->end()

src/ai-bundle/config/services.php

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -157,6 +157,7 @@
157157
service('ai.tool_result_converter'),
158158
service('event_dispatcher')->nullOnInvalid(),
159159
false,
160+
false,
160161
])
161162
->set('ai.security.is_granted_attribute_listener', IsGrantedToolAttributeListener::class)
162163
->args([

0 commit comments

Comments
 (0)