Skip to content
Open
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
61 changes: 61 additions & 0 deletions .github/scripts/validate-bridge-type.sh
Original file line number Diff line number Diff line change
@@ -0,0 +1,61 @@
#!/bin/bash
#
# Validates that all bridges have the correct "type" field in composer.json.
#
# Usage: validate-bridge-type.sh <bridge_type> [component]
#
# Arguments:
# bridge_type Type of bridge (e.g., "store", "tool", "platform", "message-store")
# This determines the expected composer.json type: symfony-ai-{bridge_type}
# component Name of the parent component (e.g., agent, platform, store, chat)
# If not provided, defaults to bridge_type
#
# Example:
# validate-bridge-type.sh store
# validate-bridge-type.sh tool agent
# validate-bridge-type.sh message-store chat
#
# The script builds the bridge path internally as: src/${component}/src/Bridge/*

set -e

BRIDGE_TYPE="${1:?Bridge type is required (e.g., store, tool, platform, message-store)}"
COMPONENT="${2:-$BRIDGE_TYPE}"
BRIDGE_PATH="src/${COMPONENT}/src/Bridge/*"

EXPECTED_TYPE="symfony-ai-${BRIDGE_TYPE}"
ERRORS=0

echo "Validating ${BRIDGE_TYPE} bridges have correct type (${BRIDGE_PATH})..."
echo "Expected type: ${EXPECTED_TYPE}"
echo ""

for composer_file in ${BRIDGE_PATH}/composer.json; do
if [[ ! -f "$composer_file" ]]; then
continue
fi

bridge_dir=$(dirname "$composer_file")
bridge_name=$(basename "$bridge_dir")

actual_type=$(jq -r '.type // empty' "$composer_file")

if [[ -z "$actual_type" ]]; then
echo "::error file=$composer_file::${BRIDGE_TYPE} bridge '$bridge_name' is missing 'type' field in composer.json"
ERRORS=$((ERRORS + 1))
elif [[ "$actual_type" != "$EXPECTED_TYPE" ]]; then
echo "::error file=$composer_file::${BRIDGE_TYPE} bridge '$bridge_name' has incorrect type '$actual_type', expected '$EXPECTED_TYPE'"
ERRORS=$((ERRORS + 1))
else
echo "✓ $bridge_name: type '$actual_type' is correct"
fi
done

if [[ $ERRORS -gt 0 ]]; then
echo ""
echo "::error::Found $ERRORS type validation error(s) in ${BRIDGE_TYPE} bridges"
exit 1
fi

echo ""
echo "All ${BRIDGE_TYPE} bridges have the correct type!"
14 changes: 14 additions & 0 deletions .github/workflows/validation.yaml
Original file line number Diff line number Diff line change
Expand Up @@ -10,6 +10,7 @@ on:
- '.github/scripts/validate-bridge-naming.sh'
- '.github/scripts/validate-bridge-splitsh.sh'
- '.github/scripts/validate-bridge-files.sh'
- '.github/scripts/validate-bridge-type.sh'
pull_request:
paths:
- 'src/*/src/Bridge/**/*'
Expand All @@ -19,6 +20,7 @@ on:
- '.github/scripts/validate-bridge-naming.sh'
- '.github/scripts/validate-bridge-splitsh.sh'
- '.github/scripts/validate-bridge-files.sh'
- '.github/scripts/validate-bridge-type.sh'

concurrency:
group: ${{ github.workflow }}-${{ github.head_ref || github.run_id }}
Expand All @@ -41,6 +43,9 @@ jobs:
- name: Validate store bridges have required files
run: .github/scripts/validate-bridge-files.sh store

- name: Validate store bridges have correct type
run: .github/scripts/validate-bridge-type.sh store

validate_tools:
name: Tool Bridges
runs-on: ubuntu-latest
Expand All @@ -57,6 +62,9 @@ jobs:
- name: Validate tool bridges have required files
run: .github/scripts/validate-bridge-files.sh tool agent

- name: Validate tool bridges have correct type
run: .github/scripts/validate-bridge-type.sh tool agent

validate_message_stores:
name: Message Store Bridges
runs-on: ubuntu-latest
Expand All @@ -73,6 +81,9 @@ jobs:
- name: Validate message store bridges have required files
run: .github/scripts/validate-bridge-files.sh message-store chat

- name: Validate message store bridges have correct type
run: .github/scripts/validate-bridge-type.sh message-store chat

validate_platforms:
name: Platform Bridges
runs-on: ubuntu-latest
Expand All @@ -89,3 +100,6 @@ jobs:
- name: Validate platform bridges have required files
run: .github/scripts/validate-bridge-files.sh platform

- name: Validate platform bridges have correct type
run: .github/scripts/validate-bridge-type.sh platform

1 change: 0 additions & 1 deletion demo/composer.json
Original file line number Diff line number Diff line change
Expand Up @@ -12,7 +12,6 @@
"mrmysql/youtube-transcript": "^0.0.5",
"nyholm/psr7": "^1.8",
"php-http/discovery": "^1.20",
"symfony/ai-azure-platform": "@dev",
"symfony/ai-bundle": "@dev",
"symfony/ai-chroma-db-store": "@dev",
"symfony/ai-clock-tool": "@dev",
Expand Down
15 changes: 14 additions & 1 deletion demo/config/reference.php
Original file line number Diff line number Diff line change
Expand Up @@ -159,10 +159,16 @@
* version: string,
* http_client?: string, // Service ID of the HTTP client to use // Default: "http_client"
* },
* decart?: array{
* api_key: string,
* host?: string, // Default: "https://api.decart.ai/v1"
* http_client?: string, // Service ID of the HTTP client to use // Default: "http_client"
* },
* elevenlabs?: array{
* api_key: string,
* host?: string, // Default: "https://api.elevenlabs.io/v1"
* http_client?: string, // Service ID of the HTTP client to use // Default: "http_client"
* api_catalog?: bool, // If set, the ElevenLabs API will be used to build the catalog and retrieve models information, using this option leads to additional HTTP calls
* },
* gemini?: array{
* api_key: string,
Expand Down Expand Up @@ -236,7 +242,6 @@
* }>>,
* agent?: array<string, array{ // Default: []
* platform?: string, // Service name of platform // Default: "Symfony\\AI\\Platform\\PlatformInterface"
* track_token_usage?: bool, // Enable tracking of token usage for the agent // Default: true
* model?: mixed,
* memory?: mixed, // Memory configuration: string for static memory, or array with "service" key for service reference // Default: null
* prompt?: string|array{ // The system prompt configuration
Expand Down Expand Up @@ -355,6 +360,14 @@
* distance?: string, // Default: "cosine"
* quantization?: bool,
* }>,
* elasticsearch?: array<string, array{ // Default: []
* endpoint?: string,
* index_name?: string,
* vectors_field?: string, // Default: "_vectors"
* dimensions?: int, // Default: 1536
* similarity?: string, // Default: "cosine"
* http_client?: string, // Default: "http_client"
* }>,
* opensearch?: array<string, array{ // Default: []
* endpoint?: string,
* index_name?: string,
Expand Down
2 changes: 1 addition & 1 deletion docs/components/agent.rst
Original file line number Diff line number Diff line change
Expand Up @@ -37,7 +37,7 @@ array of options::
// Platform instantiation

$agent = new Agent($platform, $model);
$input = new MessageBag(
$messages = new MessageBag(
Message::forSystem('You are a helpful chatbot answering questions about LLM agent.'),
Message::ofUser('Hello, how are you?'),
);
Expand Down
2 changes: 1 addition & 1 deletion examples/aimlapi/image-input-binary.php
Original file line number Diff line number Diff line change
Expand Up @@ -25,6 +25,6 @@
Image::fromFile(dirname(__DIR__, 2).'/fixtures/image.jpg'),
),
);
$result = $platform->invoke('google/gemma-3-27b-it', $messages);
$result = $platform->invoke('google/gemini-2.5-pro', $messages);

echo $result->asText().\PHP_EOL;
2 changes: 1 addition & 1 deletion examples/albert/chat.php
Original file line number Diff line number Diff line change
Expand Up @@ -39,6 +39,6 @@
Message::ofUser('Summarize the main objectives of France\'s AI strategy in one sentence.'),
);

$result = $platform->invoke('albert-small', $messages);
$result = $platform->invoke('openweight-small', $messages);

echo $result->asText().\PHP_EOL;
2 changes: 1 addition & 1 deletion examples/albert/embeddings.php
Original file line number Diff line number Diff line change
Expand Up @@ -15,7 +15,7 @@

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

$response = $platform->invoke('embeddings-small', <<<TEXT
$response = $platform->invoke('openweight-embeddings', <<<TEXT
Once upon a time, there was a country called Japan. It was a beautiful country with a lot of mountains and rivers.
The people of Japan were very kind and hardworking. They loved their country very much and took care of it. The
country was very peaceful and prosperous. The people lived happily ever after.
Expand Down
5 changes: 4 additions & 1 deletion examples/bootstrap.php
Original file line number Diff line number Diff line change
Expand Up @@ -101,7 +101,10 @@ function print_token_usage(Metadata $metadata): void
{
$tokenUsage = $metadata->get('token_usage');

assert($tokenUsage instanceof TokenUsage);
if (!$tokenUsage instanceof TokenUsage) {
output()->writeln('<error>No token usage information available.</error>');
exit(1);
}

$na = '<comment>n/a</comment>';
$table = new Table(output());
Expand Down
39 changes: 0 additions & 39 deletions examples/composer.json
Original file line number Diff line number Diff line change
Expand Up @@ -19,42 +19,6 @@
{
"type": "path",
"url": "../src/store"
},
{
"type": "path",
"url": "../src/chat/src/Bridge/Cache"
},
{
"type": "path",
"url": "../src/chat/src/Bridge/Cloudflare"
},
{
"type": "path",
"url": "../src/chat/src/Bridge/Doctrine"
},
{
"type": "path",
"url": "../src/chat/src/Bridge/Session"
},
{
"type": "path",
"url": "../src/chat/src/Bridge/Meilisearch"
},
{
"type": "path",
"url": "../src/chat/src/Bridge/MongoDb"
},
{
"type": "path",
"url": "../src/chat/src/Bridge/Pogocache"
},
{
"type": "path",
"url": "../src/chat/src/Bridge/Redis"
},
{
"type": "path",
"url": "../src/chat/src/Bridge/SurrealDb"
}
],
"require": {
Expand Down Expand Up @@ -138,9 +102,6 @@
"phpstan/phpstan": "^2.1",
"phpstan/phpstan-strict-rules": "^2.0"
},
"conflict": {
"mongodb/mongodb": "<1.21"
},
"minimum-stability": "dev",
"autoload": {
"psr-4": {
Expand Down
6 changes: 4 additions & 2 deletions examples/indexer/index-with-filters.php
Original file line number Diff line number Diff line change
Expand Up @@ -72,16 +72,18 @@
$vector = $vectorizer->vectorize('technology artificial intelligence');
$results = $store->query($vector);

$filteredDocuments = 0;
foreach ($results as $i => $document) {
$title = $document->metadata['title'] ?? 'Unknown';
$category = $document->metadata['category'] ?? 'Unknown';
echo sprintf("%d. %s [%s]\n", $i + 1, $title, $category);
echo sprintf(" Content: %s\n", substr($document->metadata->getText() ?? 'No content', 0, 80).'...');
echo sprintf(" ID: %s\n\n", substr($document->id, 0, 8).'...');
++$filteredDocuments;
}

echo "=== Results Summary ===\n";
echo sprintf("Original documents: %d\n", count($documents));
echo sprintf("Documents after filtering: %d\n", count($results));
echo sprintf("Filtered out: %d documents\n", count($documents) - count($results));
echo sprintf("Documents after filtering: %d\n", ++$filteredDocuments);
echo sprintf("Filtered out: %d documents\n", count($documents) - $filteredDocuments);
echo "\nThe 'Week of Symfony' newsletter and SPAM advertisement were successfully filtered out!\n";
4 changes: 2 additions & 2 deletions examples/mistral/chat-multiple.php
Original file line number Diff line number Diff line change
Expand Up @@ -21,9 +21,9 @@
Message::forSystem('Just give short answers.'),
Message::ofUser('What is your favorite color?'),
);
$result = $platform->invoke('mistral-large-latest', $messages, [
$result = $platform->invoke('mistral-small-latest', $messages, [
'temperature' => 1.5,
'n' => 10,
'n' => 5,
]);

foreach ($result->getResult()->getContent() as $key => $choice) {
Expand Down
2 changes: 1 addition & 1 deletion examples/mistral/token-metadata.php
Original file line number Diff line number Diff line change
Expand Up @@ -21,7 +21,7 @@
$agent = new Agent($platform, 'mistral-large-latest');

$messages = new MessageBag(
Message::forSystem('You are a pirate and you write funny.'),
Message::forSystem('You are a pirate, you write funny and only with one sentence.'),
Message::ofUser('What is the best French cuisine?'),
);

Expand Down
54 changes: 1 addition & 53 deletions src/agent/CHANGELOG.md
Original file line number Diff line number Diff line change
Expand Up @@ -4,56 +4,4 @@ CHANGELOG
0.1
---

* Add support for union types and polymorphic types via DiscriminatorMap
* Add Agent class as central orchestrator for AI interactions through the Platform component
* Add input/output processing pipeline:
- `InputProcessorInterface` for pre-processing messages and options
- `OutputProcessorInterface` for post-processing LLM responses
- `AgentAwareInterface` for processors requiring agent access
- `SystemPromptInputProcessor` for system prompt injection
- `ModelOverrideInputProcessor` for dynamic model switching
* Add comprehensive tool system:
- `#[AsTool]` attribute for simple tool registration
- `ReflectionToolFactory` for auto-discovering tools with attributes
- `MemoryToolFactory` for manual tool registration
- `ChainFactory` for combining multiple factories
- Automatic JSON Schema generation for parameter validation
- Tool call execution with argument resolution
- `ToolCallsExecuted` and `ToolCallArgumentsResolved` events
- `FaultTolerantToolbox` for graceful error handling
* Add built-in tools:
- `SimilaritySearch` for RAG/vector store searches
- `Agent` allowing agents to use other agents as tools
- `Clock` for current date/time
- `Crawler` for web page crawling
- `Mapbox` for geocoding addresses to coordinates and reverse geocoding
- `OpenMeteo` for weather information
- `SerpApi` for search engine results
- `Wikipedia` for Wikipedia content retrieval
- `YouTubeTranscriber` for YouTube video transcription
* Add bridges:
- `Brave` for web search integration (`symfony/ai-brave-tool`)
- `Tavily` for AI-powered search (`symfony/ai-tavily-tool`)
* Add structured output support:
- PHP class output with automatic conversion from LLM responses
- Array structure output with JSON schema validation
- `ResponseFormatFactory` for schema generation
- Symfony Serializer integration
* Add memory management system:
- `MemoryInputProcessor` for injecting contextual memory
- `StaticMemoryProvider` for fixed contextual information
- `EmbeddingProvider` for vector-based memory retrieval
- Dynamic memory control with `use_memory` option
- Extensible `MemoryInterface` for custom providers
* Add advanced features:
- Tool filtering to limit available tools per agent call
- Tool message retention option for context preservation
- Multi-method tools support in single classes
- Tool parameter validation with `#[With]` attribute
- Stream response support for real-time output
- PSR-3 logger integration throughout
- Symfony EventDispatcher integration
* Add model capability detection before processing
* Add comprehensive type safety with full PHP type hints
* Add clear exception hierarchy for different error scenarios
* Add translation support for system prompts
* Add the component
31 changes: 1 addition & 30 deletions src/ai-bundle/CHANGELOG.md
Original file line number Diff line number Diff line change
Expand Up @@ -4,33 +4,4 @@ CHANGELOG
0.1
---

* Add Symfony bundle for integrating Platform, Agent, and Store components
* Add memory provider configuration support for agents. Symfony AI was bootstrapped by Christopher Hertel and Oskar Stark
* Add Perplexity platform support with API key configuration
* Add service configuration:
- Agent services with configurable platforms and system prompts
- Tool registration via `#[AsTool]` attribute and `ai.tool` tag
- Input/Output processor registration via `ai.agent.input_processor` and `ai.agent.output_processor` tags
- Abstract service definitions for extensibility
* Add Symfony Profiler integration for monitoring AI interactions
* Add security integration:
- `#[IsGrantedTool]` attribute for tool-level authorization
- Security voter integration for runtime permission checks
* Add configuration options:
- Multiple agents configuration with different platforms
- Platform credentials (API keys, endpoints)
- Model configurations per agent
- Vector store configurations
* Add dependency injection integration:
- Autoconfiguration for tools and processors
- Service aliases for default agent and platform
- Factory services for creating platforms
* Add bundle configuration with semantic validation
* Add support for fault-tolerant tool execution
* Add structured output configuration support
* Add token usage tracking:
- `track_token_usage` option for agents to monitor AI model consumption
- Automatic registration of token output processors for Mistral, OpenAI and Vertex AI
- Token usage metadata in agent results including prompt, completion, total, cached, and thinking tokens
- Rate limit information tracking for supported platforms
* Add support for configuring chats and message stores
* Add the bundle
Loading
Loading