Skip to content

Commit 86d6946

Browse files
committed
Merge remote-tracking branch 'origin/main' into feature/meilisearch-configurable-semantic-ratio
2 parents 084cac1 + ce9af3b commit 86d6946

File tree

329 files changed

+6128
-1555
lines changed

Some content is hidden

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

329 files changed

+6128
-1555
lines changed

.github/workflows/integration-tests.yaml

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -15,7 +15,7 @@ concurrency:
1515
cancel-in-progress: true
1616

1717
env:
18-
REQUIRED_PHP_EXTENSIONS: 'mongodb'
18+
REQUIRED_PHP_EXTENSIONS: 'mongodb, redis'
1919

2020
jobs:
2121
examples:

CLAUDE.md

Lines changed: 3 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -30,7 +30,7 @@ Each component has its own test suite. Run tests for specific components:
3030
# Platform component
3131
cd src/platform && vendor/bin/phpunit
3232

33-
# Agent component
33+
# Agent component
3434
cd src/agent && vendor/bin/phpunit
3535

3636
# AI Bundle
@@ -111,10 +111,10 @@ Each component uses:
111111
- Do not use void return type for testcase methods
112112
- Always run PHP-CS-Fixer to ensure proper code style
113113
- Always add a newline at the end of the file
114-
- Prefer self::assert* oder $this->assert* in tests
114+
- Prefer self::assert* over $this->assert* in tests
115115
- Never add Claude as co-author in the commits
116116
- Add @author tags to newly introduced classes by the user
117117
- Prefer classic if statements over short-circuit evaluation when possible
118118
- Define array shapes for parameters and return types
119119
- Use project specific exceptions instead of global exception classes like \RuntimeException, \InvalidArgumentException etc.
120-
- NEVER mention Claude as co-author in commits
120+
- NEVER mention Claude as co-author in commits

demo/config/packages/ai.yaml

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -70,6 +70,7 @@ ai:
7070
filters:
7171
- 'app.filter.week_of_symfony'
7272
transformers:
73+
- 'Symfony\AI\Store\Document\Transformer\TextSplitTransformer'
7374
- 'Symfony\AI\Store\Document\Transformer\TextTrimTransformer'
7475
vectorizer: 'ai.vectorizer.openai'
7576
store: 'ai.store.chroma_db.symfonycon'
@@ -89,6 +90,7 @@ services:
8990
$store: '@ai.store.chroma_db.symfonycon'
9091

9192
Symfony\AI\Store\Document\Loader\RssFeedLoader: ~
93+
Symfony\AI\Store\Document\Transformer\TextSplitTransformer: ~
9294
Symfony\AI\Store\Document\Transformer\TextTrimTransformer: ~
9395

9496
app.filter.week_of_symfony:

demo/src/Mcp/Tools/CurrentTimeTool.php

Lines changed: 8 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -12,12 +12,18 @@
1212
namespace App\Mcp\Tools;
1313

1414
use Mcp\Capability\Attribute\McpTool;
15+
use Psr\Log\LoggerInterface;
1516

1617
/**
1718
* @author Tom Hart <tom.hart.221@gmail.com>
1819
*/
1920
class CurrentTimeTool
2021
{
22+
public function __construct(
23+
private readonly LoggerInterface $logger,
24+
) {
25+
}
26+
2127
/**
2228
* Returns the current time in UTC.
2329
*
@@ -26,6 +32,8 @@ class CurrentTimeTool
2632
#[McpTool(name: 'current-time')]
2733
public function getCurrentTime(string $format = 'Y-m-d H:i:s'): string
2834
{
35+
$this->logger->info('CurrentTimeTool called', ['format' => $format]);
36+
2937
return (new \DateTime('now', new \DateTimeZone('UTC')))->format($format);
3038
}
3139
}

demo/templates/components/wikipedia.html.twig

Lines changed: 8 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -9,14 +9,14 @@
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>
12+
{% if message.metadata.has('sources') and 0 != message.metadata.get('sources')|length %}
13+
<div class="ms-5 ps-4" style="margin-top: -1.5em;">
14+
<span class="text-muted">Sources:</span>
15+
{% for source in message.metadata.get('sources') %}
16+
<a class="text-black-50" href="{{ source.reference }}" target="_blank" rel="noopener">
17+
<span class="badge text-bg-secondary">{{ source.name }}</span>
18+
</a>
19+
{% endfor %}
2020
</div>
2121
{% endif %}
2222
{% else %}

docs/bundles/ai-bundle.rst

Lines changed: 42 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -67,7 +67,6 @@ Advanced Example with Multiple Agents
6767
agent:
6868
rag:
6969
platform: 'ai.platform.azure.gpt_deployment'
70-
structured_output: false # Disables support for "output_structure" option, default is true
7170
track_token_usage: true # Enable tracking of token usage for the agent, default is true
7271
model: 'gpt-4o-mini'
7372
memory: 'You have access to conversation history and user preferences' # Optional: static memory content
@@ -513,11 +512,6 @@ Configuration
513512
# Fallback agent for unmatched requests (required)
514513
fallback: 'general'
515514
516-
.. important::
517-
518-
The orchestrator agent MUST have ``structured_output: true`` (the default) to work correctly.
519-
The multi-agent system uses structured output to reliably parse agent selection decisions.
520-
521515
Each multi-agent configuration automatically registers a service with the ID pattern ``ai.multi_agent.{name}``.
522516

523517
For the example above, the service ``ai.multi_agent.support`` is registered and can be injected::
@@ -956,6 +950,48 @@ The profiler panel provides insights into the agent's execution:
956950
.. image:: profiler.png
957951
:alt: Profiler Panel
958952

953+
Message stores
954+
--------------
955+
956+
Message stores are critical to store messages sent to agents in the short / long term, they can be configured
957+
and reused in multiple chats, providing the capacity to agents to keep previous interactions.
958+
959+
Configuring message stores
960+
~~~~~~~~~~~~~~~~~~~~~~~~~~
961+
962+
Message stores are defined in the ``message_store`` section of your configuration:
963+
964+
.. code-block:: yaml
965+
966+
ai:
967+
# ...
968+
message_store:
969+
youtube:
970+
cache:
971+
service: 'cache.app'
972+
key: 'youtube'
973+
974+
Chats
975+
-----
976+
977+
Chats are the entrypoint when it comes to sending messages to agents and retrieving content (mostly text)
978+
that contains the response from the agent.
979+
980+
Each chat requires to define an agent and a message store.
981+
982+
Configuring Chats
983+
~~~~~~~~~~~~~~~~~
984+
985+
Chats are defined in the ``chat`` section of your configuration:
986+
987+
.. code-block:: yaml
988+
989+
ai:
990+
# ...
991+
chat:
992+
youtube:
993+
agent: 'ai.agent.youtube'
994+
message_store: 'ai.message_store.cache.youtube'
959995
960996
.. _`Symfony AI Agent`: https://github.com/symfony/ai-agent
961997
.. _`Symfony AI Chat`: https://github.com/symfony/ai-chat

docs/bundles/mcp-bundle.rst

Lines changed: 27 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -113,6 +113,33 @@ Dynamic resources with parameters:
113113

114114
All capabilities are automatically discovered in the ``src/`` directory when the server starts.
115115

116+
Attribute Placement Patterns
117+
^^^^^^^^^^^^^^^^^^^^^^^^^^^^
118+
119+
The MCP SDK, and therefore the MCP Bundle, supports two patterns for placing attributes on your capabilities:
120+
121+
**Invokable Pattern** - Attribute on a class with ``__invoke()`` method::
122+
123+
#[McpTool(name: 'my-tool')]
124+
class MyTool
125+
{
126+
public function __invoke(string $param): string
127+
{
128+
// Implementation
129+
}
130+
}
131+
132+
**Method-Based Pattern** - Multiple attributes on individual methods::
133+
134+
class MyTools
135+
{
136+
#[McpTool(name: 'tool-one')]
137+
public function toolOne(): string { }
138+
139+
#[McpTool(name: 'tool-two')]
140+
public function toolTwo(): string { }
141+
}
142+
116143
Transport Types
117144
...............
118145

docs/components/agent.rst

Lines changed: 0 additions & 76 deletions
Original file line numberDiff line numberDiff line change
@@ -483,80 +483,6 @@ Code Examples
483483
* `RAG with MongoDB`_
484484
* `RAG with Pinecone`_
485485

486-
Structured Output
487-
-----------------
488-
489-
A typical use-case of LLMs is to classify and extract data from unstructured sources, which is supported by some models
490-
by features like Structured Output or providing a Response Format.
491-
492-
PHP Classes as Output
493-
~~~~~~~~~~~~~~~~~~~~~
494-
495-
Symfony AI supports that use-case by abstracting the hustle of defining and providing schemas to the LLM and converting
496-
the result back to PHP objects.
497-
498-
To achieve this, a specific agent processor needs to be registered::
499-
500-
use Symfony\AI\Agent\Agent;
501-
use Symfony\AI\Agent\StructuredOutput\AgentProcessor;
502-
use Symfony\AI\Agent\StructuredOutput\ResponseFormatFactory;
503-
use Symfony\AI\Fixtures\StructuredOutput\MathReasoning;
504-
use Symfony\AI\Platform\Message\Message;
505-
use Symfony\AI\Platform\Message\MessageBag;
506-
use Symfony\Component\Serializer\Encoder\JsonEncoder;
507-
use Symfony\Component\Serializer\Normalizer\ObjectNormalizer;
508-
use Symfony\Component\Serializer\Serializer;
509-
510-
// Initialize Platform and LLM
511-
512-
$serializer = new Serializer([new ObjectNormalizer()], [new JsonEncoder()]);
513-
$processor = new AgentProcessor(new ResponseFormatFactory(), $serializer);
514-
$agent = new Agent($platform, $model, [$processor], [$processor]);
515-
516-
$messages = new MessageBag(
517-
Message::forSystem('You are a helpful math tutor. Guide the user through the solution step by step.'),
518-
Message::ofUser('how can I solve 8x + 7 = -23'),
519-
);
520-
$result = $agent->call($messages, ['output_structure' => MathReasoning::class]);
521-
522-
dump($result->getContent()); // returns an instance of `MathReasoning` class
523-
524-
Array Structures as Output
525-
~~~~~~~~~~~~~~~~~~~~~~~~~~
526-
527-
Also PHP array structures as response_format are supported, which also requires the agent processor mentioned above::
528-
529-
use Symfony\AI\Platform\Message\Message;
530-
use Symfony\AI\Platform\Message\MessageBag;
531-
532-
// Initialize Platform, LLM and agent with processors and Clock tool
533-
534-
$messages = new MessageBag(Message::ofUser('What date and time is it?'));
535-
$result = $agent->call($messages, ['response_format' => [
536-
'type' => 'json_schema',
537-
'json_schema' => [
538-
'name' => 'clock',
539-
'strict' => true,
540-
'schema' => [
541-
'type' => 'object',
542-
'properties' => [
543-
'date' => ['type' => 'string', 'description' => 'The current date in the format YYYY-MM-DD.'],
544-
'time' => ['type' => 'string', 'description' => 'The current time in the format HH:MM:SS.'],
545-
],
546-
'required' => ['date', 'time'],
547-
'additionalProperties' => false,
548-
],
549-
],
550-
]]);
551-
552-
dump($result->getContent()); // returns an array
553-
554-
Code Examples
555-
~~~~~~~~~~~~~
556-
557-
* `Structured Output with PHP class`_
558-
* `Structured Output with array`_
559-
560486
Input & Output Processing
561487
-------------------------
562488

@@ -825,7 +751,5 @@ Code Examples
825751
.. _`Store Component`: https://github.com/symfony/ai-store
826752
.. _`RAG with MongoDB`: https://github.com/symfony/ai/blob/main/examples/rag/mongodb.php
827753
.. _`RAG with Pinecone`: https://github.com/symfony/ai/blob/main/examples/rag/pinecone.php
828-
.. _`Structured Output with PHP class`: https://github.com/symfony/ai/blob/main/examples/openai/structured-output-math.php
829-
.. _`Structured Output with array`: https://github.com/symfony/ai/blob/main/examples/openai/structured-output-clock.php
830754
.. _`Chat with static memory`: https://github.com/symfony/ai/blob/main/examples/memory/static.php
831755
.. _`Chat with embedding search memory`: https://github.com/symfony/ai/blob/main/examples/memory/mariadb.php

docs/components/chat.rst

Lines changed: 31 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -31,6 +31,24 @@ with a ``Symfony\AI\Agent\AgentInterface`` and a ``Symfony\AI\Chat\MessageStoreI
3131

3232
$chat->submit(Message::ofUser('Hello'));
3333

34+
You can find more advanced usage in combination with an Agent using the store for long-term context:
35+
36+
* `External services storage with Cache`_
37+
* `Current session context storage with HttpFoundation session`_
38+
* `Current process context storage with InMemory`_
39+
* `Long-term context with Meilisearch`_
40+
* `Long-term context with Pogocache`_
41+
* `Long-term context with Redis`_
42+
43+
Supported Message stores
44+
------------------------
45+
46+
* `Cache`_
47+
* `HttpFoundation session`_
48+
* `InMemory`_
49+
* `Meilisearch`_
50+
* `Pogocache`_
51+
* `Redis`_
3452

3553
Implementing a Bridge
3654
---------------------
@@ -105,3 +123,16 @@ store and ``bin/console ai:message-store:drop`` to clean up the message store:
105123
106124
$ php bin/console ai:message-store:setup symfonycon
107125
$ php bin/console ai:message-store:drop symfonycon
126+
127+
.. _`External services storage with Cache`: https://github.com/symfony/ai/blob/main/examples/chat/persistent-chat-cache.php
128+
.. _`Current session context storage with HttpFoundation session`: https://github.com/symfony/ai/blob/main/examples/chat/persistent-chat-session.php
129+
.. _`Current process context storage with InMemory`: https://github.com/symfony/ai/blob/main/examples/chat/persistent-chat.php
130+
.. _`Long-term context with Meilisearch`: https://github.com/symfony/ai/blob/main/examples/chat/persistent-chat-meilisearch.php
131+
.. _`Long-term context with Pogocache`: https://github.com/symfony/ai/blob/main/examples/chat/persistent-chat-pogocache.php
132+
.. _`Long-term context with Redis`: https://github.com/symfony/ai/blob/main/examples/chat/persistent-chat-redis.php
133+
.. _`Cache`: https://symfony.com/doc/current/components/cache.html
134+
.. _`InMemory`: https://www.php.net/manual/en/language.types.array.php
135+
.. _`HttpFoundation session`: https://developers.cloudflare.com/vectorize/
136+
.. _`Meilisearch`: https://www.meilisearch.com/
137+
.. _`Pogocache`: https://pogocache.com/
138+
.. _`Redis`: https://redis.io/

0 commit comments

Comments
 (0)