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
59 changes: 59 additions & 0 deletions .github/workflows/deptrac.yaml
Original file line number Diff line number Diff line change
@@ -0,0 +1,59 @@
name: deptrac

on:
push:
paths-ignore:
- 'src/*/doc/**'
- 'src/**/*.md'
pull_request:
paths-ignore:
- 'src/*/doc/**'
- 'src/**/*.md'

concurrency:
group: ${{ github.workflow }}-${{ github.head_ref || github.run_id }}
cancel-in-progress: true

jobs:
deptrac:
name: deptrac
runs-on: ubuntu-latest
strategy:
fail-fast: false
matrix:
php-version: [ '8.4' ]
steps:
- name: Checkout
uses: actions/checkout@v5

- name: Configure environment
run: |
echo COLUMNS=120 >> $GITHUB_ENV
echo COMPOSER_UP='composer update --no-progress --no-interaction --ansi --ignore-platform-req=ext-mongodb' >> $GITHUB_ENV

- name: Setup PHP
uses: shivammathur/setup-php@v2
with:
php-version: ${{ matrix.php-version }}

- name: Get composer cache directory
id: composer-cache
run: |
echo "dir=$(composer config cache-files-dir)" >> $GITHUB_OUTPUT

- name: Cache packages dependencies
uses: actions/cache@v4
with:
path: ${{ steps.composer-cache.outputs.dir }}
key: ${{ runner.os }}-composer-packages-${{ matrix.php-version }}-${{ hashFiles('src/**/composer.json') }}
restore-keys: |
${{ runner.os }}-composer-packages-${{ matrix.php-version }}

- name: Install root dependencies
uses: ramsey/composer-install@v3

- name: Build root packages
run: php .github/build-packages.php

- name: Run DEPTRAC
run: $COMPOSER_UP && vendor/bin/deptrac
5 changes: 3 additions & 2 deletions composer.json
Original file line number Diff line number Diff line change
Expand Up @@ -7,9 +7,10 @@
],
"require-dev": {
"php": ">=8.2",
"deptrac/deptrac": "^4.2",
"php-cs-fixer/shim": "^3.75",
"symfony/finder": "^6.4 || ^7.0",
"symfony/filesystem": "^6.4 || ^7.0"
"symfony/filesystem": "^6.4 || ^7.0",
"symfony/finder": "^6.4 || ^7.0"
},
"config": {
"sort-packages": true
Expand Down
26 changes: 26 additions & 0 deletions deptrac.yaml
Original file line number Diff line number Diff line change
@@ -0,0 +1,26 @@
deptrac:
paths:
- ./src
exclude_files:
- '#.*test.*#'
layers:
- name: Agent
collectors:
- type: classLike
value: Symfony\\AI\\Agent.*
- name: Platform
collectors:
- type: classLike
value: Symfony\\AI\\Platform.*
- name: Store
collectors:
- type: classLike
value: Symfony\\AI\\Store.*
ruleset:
Platform: ~
Agent:
- Platform
- orm
- Store
Store:
- Platform
5 changes: 3 additions & 2 deletions examples/anthropic/token-metadata.php
Original file line number Diff line number Diff line change
Expand Up @@ -10,9 +10,10 @@
*/

use Symfony\AI\Agent\Agent;
use Symfony\AI\Agent\OutputProcessor\ResultOutputProcessor;
use Symfony\AI\Platform\Bridge\Anthropic\Claude;
use Symfony\AI\Platform\Bridge\Anthropic\PlatformFactory;
use Symfony\AI\Platform\Bridge\Anthropic\TokenOutputProcessor;
use Symfony\AI\Platform\Bridge\Anthropic\TokenUsageResultHandler;
use Symfony\AI\Platform\Message\Message;
use Symfony\AI\Platform\Message\MessageBag;

Expand All @@ -21,7 +22,7 @@
$platform = PlatformFactory::create(env('ANTHROPIC_API_KEY'), http_client());
$model = new Claude(Claude::SONNET_37);

$agent = new Agent($platform, $model, outputProcessors: [new TokenOutputProcessor()], logger: logger());
$agent = new Agent($platform, $model, outputProcessors: [new ResultOutputProcessor(new TokenUsageResultHandler())], logger: logger());
$messages = new MessageBag(
Message::forSystem('You are a pirate and you write funny.'),
Message::ofUser('What is the Symfony framework?'),
Expand Down
5 changes: 3 additions & 2 deletions examples/gemini/token-metadata.php
Original file line number Diff line number Diff line change
Expand Up @@ -10,9 +10,10 @@
*/

use Symfony\AI\Agent\Agent;
use Symfony\AI\Agent\OutputProcessor\ResultOutputProcessor;
use Symfony\AI\Platform\Bridge\Gemini\Gemini;
use Symfony\AI\Platform\Bridge\Gemini\PlatformFactory;
use Symfony\AI\Platform\Bridge\Gemini\TokenOutputProcessor;
use Symfony\AI\Platform\Bridge\Gemini\TokenUsageResultHandler;
use Symfony\AI\Platform\Message\Message;
use Symfony\AI\Platform\Message\MessageBag;

Expand All @@ -21,7 +22,7 @@
$platform = PlatformFactory::create(env('GEMINI_API_KEY'), http_client());
$model = new Gemini(Gemini::GEMINI_2_FLASH);

$agent = new Agent($platform, $model, outputProcessors: [new TokenOutputProcessor()], logger: logger());
$agent = new Agent($platform, $model, outputProcessors: [new ResultOutputProcessor(new TokenUsageResultHandler())], logger: logger());
$messages = new MessageBag(
Message::forSystem('You are a pirate and you write funny.'),
Message::ofUser('What is the Symfony framework?'),
Expand Down
5 changes: 3 additions & 2 deletions examples/mistral/token-metadata.php
Original file line number Diff line number Diff line change
Expand Up @@ -10,9 +10,10 @@
*/

use Symfony\AI\Agent\Agent;
use Symfony\AI\Agent\OutputProcessor\ResultOutputProcessor;
use Symfony\AI\Platform\Bridge\Mistral\Mistral;
use Symfony\AI\Platform\Bridge\Mistral\PlatformFactory;
use Symfony\AI\Platform\Bridge\Mistral\TokenOutputProcessor;
use Symfony\AI\Platform\Bridge\Mistral\TokenUsageResultHandler;
use Symfony\AI\Platform\Message\Message;
use Symfony\AI\Platform\Message\MessageBag;

Expand All @@ -21,7 +22,7 @@
$platform = PlatformFactory::create(env('MISTRAL_API_KEY'), http_client());
$model = new Mistral();

$agent = new Agent($platform, $model, outputProcessors: [new TokenOutputProcessor()], logger: logger());
$agent = new Agent($platform, $model, outputProcessors: [new ResultOutputProcessor(new TokenUsageResultHandler())], logger: logger());

$messages = new MessageBag(
Message::forSystem('You are a pirate and you write funny.'),
Expand Down
5 changes: 3 additions & 2 deletions examples/openai/token-metadata.php
Original file line number Diff line number Diff line change
Expand Up @@ -10,9 +10,10 @@
*/

use Symfony\AI\Agent\Agent;
use Symfony\AI\Agent\OutputProcessor\ResultOutputProcessor;
use Symfony\AI\Platform\Bridge\OpenAi\Gpt;
use Symfony\AI\Platform\Bridge\OpenAi\PlatformFactory;
use Symfony\AI\Platform\Bridge\OpenAi\TokenOutputProcessor;
use Symfony\AI\Platform\Bridge\OpenAi\TokenUsageResultHandler;
use Symfony\AI\Platform\Message\Message;
use Symfony\AI\Platform\Message\MessageBag;

Expand All @@ -21,7 +22,7 @@
$platform = PlatformFactory::create(env('OPENAI_API_KEY'), http_client());
$model = new Gpt(Gpt::GPT_4O_MINI);

$agent = new Agent($platform, $model, outputProcessors: [new TokenOutputProcessor()], logger: logger());
$agent = new Agent($platform, $model, outputProcessors: [new ResultOutputProcessor(new TokenUsageResultHandler())], logger: logger());
$messages = new MessageBag(
Message::forSystem('You are a pirate and you write funny.'),
Message::ofUser('What is the Symfony framework?'),
Expand Down
6 changes: 4 additions & 2 deletions examples/perplexity/academic-search.php
Original file line number Diff line number Diff line change
Expand Up @@ -10,17 +10,19 @@
*/

use Symfony\AI\Agent\Agent;
use Symfony\AI\Agent\OutputProcessor\ResultOutputProcessor;
use Symfony\AI\Platform\Bridge\Perplexity\Perplexity;
use Symfony\AI\Platform\Bridge\Perplexity\PlatformFactory;
use Symfony\AI\Platform\Bridge\Perplexity\SearchResultProcessor;
use Symfony\AI\Platform\Bridge\Perplexity\SearchResultHandler;
use Symfony\AI\Platform\Message\Message;
use Symfony\AI\Platform\Message\MessageBag;

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

$platform = PlatformFactory::create(env('PERPLEXITY_API_KEY'), http_client());
$model = new Perplexity();
$agent = new Agent($platform, $model, outputProcessors: [new SearchResultProcessor()], logger: logger());

$agent = new Agent($platform, $model, outputProcessors: [new ResultOutputProcessor(new SearchResultHandler())], logger: logger());

$messages = new MessageBag(Message::ofUser('What is the best French cheese of the first quarter-century of 21st century?'));
$response = $agent->call($messages, [
Expand Down
6 changes: 4 additions & 2 deletions examples/perplexity/image-input-url.php
Original file line number Diff line number Diff line change
Expand Up @@ -10,9 +10,10 @@
*/

use Symfony\AI\Agent\Agent;
use Symfony\AI\Agent\OutputProcessor\ResultOutputProcessor;
use Symfony\AI\Platform\Bridge\Perplexity\Perplexity;
use Symfony\AI\Platform\Bridge\Perplexity\PlatformFactory;
use Symfony\AI\Platform\Bridge\Perplexity\SearchResultProcessor;
use Symfony\AI\Platform\Bridge\Perplexity\SearchResultHandler;
use Symfony\AI\Platform\Message\Content\ImageUrl;
use Symfony\AI\Platform\Message\Message;
use Symfony\AI\Platform\Message\MessageBag;
Expand All @@ -21,7 +22,8 @@

$platform = PlatformFactory::create(env('PERPLEXITY_API_KEY'), http_client());
$model = new Perplexity();
$agent = new Agent($platform, $model, outputProcessors: [new SearchResultProcessor()], logger: logger());

$agent = new Agent($platform, $model, outputProcessors: [new ResultOutputProcessor(new SearchResultHandler())], logger: logger());

$messages = new MessageBag(
Message::forSystem('You are an image analyzer bot that helps identify the content of images.'),
Expand Down
6 changes: 4 additions & 2 deletions examples/perplexity/pdf-input-url.php
Original file line number Diff line number Diff line change
Expand Up @@ -10,9 +10,10 @@
*/

use Symfony\AI\Agent\Agent;
use Symfony\AI\Agent\OutputProcessor\ResultOutputProcessor;
use Symfony\AI\Platform\Bridge\Perplexity\Perplexity;
use Symfony\AI\Platform\Bridge\Perplexity\PlatformFactory;
use Symfony\AI\Platform\Bridge\Perplexity\SearchResultProcessor;
use Symfony\AI\Platform\Bridge\Perplexity\SearchResultHandler;
use Symfony\AI\Platform\Message\Content\DocumentUrl;
use Symfony\AI\Platform\Message\Message;
use Symfony\AI\Platform\Message\MessageBag;
Expand All @@ -21,7 +22,8 @@

$platform = PlatformFactory::create(env('PERPLEXITY_API_KEY'), http_client());
$model = new Perplexity();
$agent = new Agent($platform, $model, outputProcessors: [new SearchResultProcessor()], logger: logger());

$agent = new Agent($platform, $model, outputProcessors: [new ResultOutputProcessor(new SearchResultHandler())], logger: logger());

$messages = new MessageBag(
Message::ofUser(
Expand Down
6 changes: 4 additions & 2 deletions examples/perplexity/stream.php
Original file line number Diff line number Diff line change
Expand Up @@ -10,17 +10,19 @@
*/

use Symfony\AI\Agent\Agent;
use Symfony\AI\Agent\OutputProcessor\ResultOutputProcessor;
use Symfony\AI\Platform\Bridge\Perplexity\Perplexity;
use Symfony\AI\Platform\Bridge\Perplexity\PlatformFactory;
use Symfony\AI\Platform\Bridge\Perplexity\SearchResultProcessor;
use Symfony\AI\Platform\Bridge\Perplexity\SearchResultHandler;
use Symfony\AI\Platform\Message\Message;
use Symfony\AI\Platform\Message\MessageBag;

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

$platform = PlatformFactory::create(env('PERPLEXITY_API_KEY'), http_client());
$model = new Perplexity();
$agent = new Agent($platform, $model, outputProcessors: [new SearchResultProcessor()], logger: logger());

$agent = new Agent($platform, $model, outputProcessors: [new ResultOutputProcessor(new SearchResultHandler())], logger: logger());

$messages = new MessageBag(
Message::forSystem('You are a thoughtful philosopher.'),
Expand Down
6 changes: 4 additions & 2 deletions examples/perplexity/token-metadata.php
Original file line number Diff line number Diff line change
Expand Up @@ -10,17 +10,19 @@
*/

use Symfony\AI\Agent\Agent;
use Symfony\AI\Agent\OutputProcessor\ResultOutputProcessor;
use Symfony\AI\Platform\Bridge\Perplexity\Perplexity;
use Symfony\AI\Platform\Bridge\Perplexity\PlatformFactory;
use Symfony\AI\Platform\Bridge\Perplexity\TokenOutputProcessor;
use Symfony\AI\Platform\Bridge\Perplexity\TokenUsageResultHandler;
use Symfony\AI\Platform\Message\Message;
use Symfony\AI\Platform\Message\MessageBag;

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

$platform = PlatformFactory::create(env('PERPLEXITY_API_KEY'), http_client());
$model = new Perplexity();
$agent = new Agent($platform, $model, outputProcessors: [new TokenOutputProcessor()], logger: logger());

$agent = new Agent($platform, $model, outputProcessors: [new ResultOutputProcessor(new TokenUsageResultHandler())], logger: logger());

$messages = new MessageBag(
Message::forSystem('You are a pirate and you write funny.'),
Expand Down
4 changes: 3 additions & 1 deletion examples/vertexai/token-metadata.php
Original file line number Diff line number Diff line change
Expand Up @@ -10,8 +10,10 @@
*/

use Symfony\AI\Agent\Agent;
use Symfony\AI\Agent\OutputProcessor\ResultOutputProcessor;
use Symfony\AI\Platform\Bridge\VertexAi\Gemini\Model;
use Symfony\AI\Platform\Bridge\VertexAi\PlatformFactory;
use Symfony\AI\Platform\Bridge\VertexAi\TokenUsageResultHandler;
use Symfony\AI\Platform\Message\Message;
use Symfony\AI\Platform\Message\MessageBag;

Expand All @@ -20,7 +22,7 @@
$platform = PlatformFactory::create(env('GOOGLE_CLOUD_LOCATION'), env('GOOGLE_CLOUD_PROJECT'), adc_aware_http_client());
$model = new Model(Model::GEMINI_2_0_FLASH_LITE);

$agent = new Agent($platform, $model, outputProcessors: [new Symfony\AI\Platform\Bridge\VertexAi\TokenOutputProcessor()], logger: logger());
$agent = new Agent($platform, $model, outputProcessors: [new ResultOutputProcessor(new TokenUsageResultHandler())], logger: logger());
$messages = new MessageBag(
Message::forSystem('You are an expert assistant in animal study.'),
Message::ofUser('What does a cat usually eat?'),
Expand Down
29 changes: 29 additions & 0 deletions src/agent/src/OutputProcessor/ResultOutputProcessor.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.
*/

namespace Symfony\AI\Agent\OutputProcessor;

use Symfony\AI\Agent\Output;
use Symfony\AI\Agent\OutputProcessorInterface;
use Symfony\AI\Platform\Result\ResultHandlerInterface;

readonly class ResultOutputProcessor implements OutputProcessorInterface
{
public function __construct(
private ResultHandlerInterface $resultProcessor,
) {
}

public function processOutput(Output $output): void
{
$this->resultProcessor->handleResult($output->result);
}
}
28 changes: 14 additions & 14 deletions src/ai-bundle/config/services.php
Original file line number Diff line number Diff line change
Expand Up @@ -26,18 +26,18 @@
use Symfony\AI\AiBundle\Profiler\TraceableToolbox;
use Symfony\AI\AiBundle\Security\EventListener\IsGrantedToolAttributeListener;
use Symfony\AI\Platform\Bridge\Anthropic\Contract\AnthropicContract;
use Symfony\AI\Platform\Bridge\Anthropic\TokenOutputProcessor as AnthropicTokenOutputProcessor;
use Symfony\AI\Platform\Bridge\Anthropic\TokenUsageResultHandler as AnthropicTokenUsageResultHandler;
use Symfony\AI\Platform\Bridge\Gemini\Contract\GeminiContract;
use Symfony\AI\Platform\Bridge\Gemini\TokenOutputProcessor as GeminiTokenOutputProcessor;
use Symfony\AI\Platform\Bridge\Mistral\TokenOutputProcessor as MistralTokenOutputProcessor;
use Symfony\AI\Platform\Bridge\Gemini\TokenUsageResultHandler as GeminiTokenUsageResultHandler;
use Symfony\AI\Platform\Bridge\Mistral\TokenUsageResultHandler as MistralTokenUsageResultHandler;
use Symfony\AI\Platform\Bridge\Ollama\Contract\OllamaContract;
use Symfony\AI\Platform\Bridge\OpenAi\Contract\OpenAiContract;
use Symfony\AI\Platform\Bridge\OpenAi\TokenOutputProcessor as OpenAiTokenOutputProcessor;
use Symfony\AI\Platform\Bridge\OpenAi\TokenUsageResultHandler as OpenAiTokenUsageResultHandler;
use Symfony\AI\Platform\Bridge\Perplexity\Contract\PerplexityContract;
use Symfony\AI\Platform\Bridge\Perplexity\SearchResultProcessor as PerplexitySearchResultProcessor;
use Symfony\AI\Platform\Bridge\Perplexity\TokenOutputProcessor as PerplexityTokenOutputProcessor;
use Symfony\AI\Platform\Bridge\Perplexity\SearchResultHandler as PerplexitySearchResultHandler;
use Symfony\AI\Platform\Bridge\Perplexity\TokenUsageResultHandler as PerplexityTokenUsageResultHandler;
use Symfony\AI\Platform\Bridge\VertexAi\Contract\GeminiContract as VertexAiGeminiContract;
use Symfony\AI\Platform\Bridge\VertexAi\TokenOutputProcessor as VertexAiTokenOutputProcessor;
use Symfony\AI\Platform\Bridge\VertexAi\TokenUsageResultHandler as VertexAiTokenUsageResultHandler;
use Symfony\AI\Platform\Contract;
use Symfony\AI\Platform\Contract\JsonSchema\DescriptionParser;
use Symfony\AI\Platform\Contract\JsonSchema\Factory as SchemaFactory;
Expand Down Expand Up @@ -143,15 +143,15 @@
->tag('ai.traceable_toolbox')

// token usage processors
->set('ai.platform.token_usage_processor.anthropic', AnthropicTokenOutputProcessor::class)
->set('ai.platform.token_usage_processor.gemini', GeminiTokenOutputProcessor::class)
->set('ai.platform.token_usage_processor.mistral', MistralTokenOutputProcessor::class)
->set('ai.platform.token_usage_processor.openai', OpenAiTokenOutputProcessor::class)
->set('ai.platform.token_usage_processor.perplexity', PerplexityTokenOutputProcessor::class)
->set('ai.platform.token_usage_processor.vertexai', VertexAiTokenOutputProcessor::class)
->set('ai.platform.token_usage_result_handler.mistral', MistralTokenUsageResultHandler::class)
->set('ai.platform.token_usage_result_handler.gemini', GeminiTokenUsageResultHandler::class)
->set('ai.platform.token_usage_result_handler.openai', OpenAiTokenUsageResultHandler::class)
->set('ai.platform.token_usage_result_handler.perplexity', PerplexityTokenUsageResultHandler::class)
->set('ai.platform.token_usage_result_handler.vertexai', VertexAiTokenUsageResultHandler::class)
->set('ai.platform.token_usage_result_handler.anthropic', AnthropicTokenUsageResultHandler::class)

// search result processors
->set('ai.platform.search_result_processor.perplexity', PerplexitySearchResultProcessor::class)
->set('ai.platform.search_result_processor.perplexity', PerplexitySearchResultHandler::class)

// commands
->set('ai.command.chat', ChatCommand::class)
Expand Down
Loading
Loading