diff --git a/.github/workflows/code-quality.yaml b/.github/workflows/code-quality.yaml
index 8648e20e3..cad408551 100644
--- a/.github/workflows/code-quality.yaml
+++ b/.github/workflows/code-quality.yaml
@@ -51,12 +51,14 @@ jobs:
done
echo "packages=$PACKAGES" >> $GITHUB_OUTPUT
- # Bridges (store and tool)
+ # Bridges (store, tool, and platform)
STORE_BRIDGES=$(find src/store/src/Bridge/ -mindepth 1 -maxdepth 1 -type d -printf '%f\n' | sort \
| jq -R -s -c 'split("\n") | map(select(length > 0)) | map({component: "store", type: "Store", bridge: .})')
TOOL_BRIDGES=$(find src/agent/src/Bridge/ -mindepth 1 -maxdepth 1 -type d -printf '%f\n' | sort \
| jq -R -s -c 'split("\n") | map(select(length > 0)) | map({component: "agent", type: "Tool", bridge: .})')
- BRIDGES=$(jq -n -c --argjson store "$STORE_BRIDGES" --argjson tool "$TOOL_BRIDGES" '$store + $tool')
+ PLATFORM_BRIDGES=$(find src/platform/src/Bridge/ -mindepth 1 -maxdepth 1 -type d -printf '%f\n' | sort \
+ | jq -R -s -c 'split("\n") | map(select(length > 0)) | map({component: "platform", type: "Platform", bridge: .})')
+ BRIDGES=$(jq -n -c --argjson store "$STORE_BRIDGES" --argjson tool "$TOOL_BRIDGES" --argjson platform "$PLATFORM_BRIDGES" '$store + $tool + $platform')
echo "bridges=$BRIDGES" >> $GITHUB_OUTPUT
# Pretty print for info
@@ -172,6 +174,19 @@ jobs:
php-version: ${{ env.PHP_VERSION }}
extensions: ${{ env.REQUIRED_PHP_EXTENSIONS }}
+ - name: Install root dependencies (platform bridges only)
+ if: matrix.bridge.component == 'platform'
+ uses: ramsey/composer-install@v3
+
+ - name: Build root packages (platform bridges only)
+ if: matrix.bridge.component == 'platform'
+ run: php .github/build-packages.php
+
+ # Remove root vendor and bridge vendor to avoid circular symlinks when installing bridge dependencies
+ - name: Clean vendor folders (platform bridges only)
+ if: matrix.bridge.component == 'platform'
+ run: rm -rf vendor src/platform/src/Bridge/${{ matrix.bridge.bridge }}/vendor
+
- name: Install dependencies
uses: ramsey/composer-install@v3
with:
diff --git a/.github/workflows/unit-tests.yaml b/.github/workflows/unit-tests.yaml
index 0c7ae85a4..570619a86 100644
--- a/.github/workflows/unit-tests.yaml
+++ b/.github/workflows/unit-tests.yaml
@@ -28,6 +28,8 @@ jobs:
store-bridges-include: ${{ steps.set-matrix.outputs.store-bridges-include }}
tool-bridges: ${{ steps.set-matrix.outputs.tool-bridges }}
tool-bridges-include: ${{ steps.set-matrix.outputs.tool-bridges-include }}
+ platform-bridges: ${{ steps.set-matrix.outputs.platform-bridges }}
+ platform-bridges-include: ${{ steps.set-matrix.outputs.platform-bridges-include }}
steps:
- name: Checkout
uses: actions/checkout@v6
@@ -103,6 +105,24 @@ jobs:
')
echo "tool-bridges-include=$TOOL_BRIDGES_INCLUDE" >> $GITHUB_OUTPUT
+ # Platform bridges
+ PLATFORM_BRIDGES=$(ls -1 src/platform/src/Bridge/ | sort \
+ | jq -R -s -c 'split("\n") | map(select(length > 0)) | map({bridge: .})')
+ echo "platform-bridges=$PLATFORM_BRIDGES" >> $GITHUB_OUTPUT
+
+ # Generate platform bridge includes (lowest, Symfony 7.4, Symfony 8.0)
+ PLATFORM_BRIDGES_INCLUDE=$(echo "$PLATFORM_BRIDGES" | jq -c '
+ . as $bridges |
+ # lowest deps with PHP 8.2
+ ($bridges | map(. + {"php-version": "8.2", "dependency-version": "lowest"})) +
+ # Symfony 7.4 LTS with PHP 8.2
+ ($bridges | map(. + {"php-version": "8.2", "symfony-version": "7.4.*"})) +
+ # Symfony 8.0 with PHP 8.5
+ ($bridges | map(. + {"php-version": "8.5", "symfony-version": "8.0.*"}))
+ | map({bridge: {bridge: .bridge}} + (. | del(.bridge)))
+ ')
+ echo "platform-bridges-include=$PLATFORM_BRIDGES_INCLUDE" >> $GITHUB_OUTPUT
+
# Pretty print for info
echo "::group::Packages"
echo "$PACKAGES" | jq .
@@ -113,6 +133,9 @@ jobs:
echo "::group::Tool Bridges"
echo "$TOOL_BRIDGES" | jq .
echo "::endgroup::"
+ echo "::group::Platform Bridges"
+ echo "$PLATFORM_BRIDGES" | jq .
+ echo "::endgroup::"
package:
name: ${{ matrix.package.type }} / ${{ matrix.package.name }} / PHP ${{ matrix.php-version }}${{ matrix.dependency-version == 'lowest' && ' / lowest' || '' }}${{ matrix.symfony-version && format(' / Symfony {0}', matrix.symfony-version) || '' }}
@@ -236,3 +259,59 @@ jobs:
- name: Run PHPUnit
run: cd src/${{ matrix.bridge.component }}/src/Bridge/${{ matrix.bridge.bridge }} && vendor/bin/phpunit
+
+ platform-bridge:
+ name: Platform / ${{ matrix.bridge.bridge }} / PHP ${{ matrix.php-version }}${{ matrix.dependency-version == 'lowest' && ' / lowest' || '' }}${{ matrix.symfony-version && format(' / Symfony {0}', matrix.symfony-version) || '' }}
+ needs: matrix
+ runs-on: ubuntu-latest
+ strategy:
+ fail-fast: false
+ matrix:
+ bridge: ${{ fromJson(needs.matrix.outputs.platform-bridges) }}
+ php-version: ['8.2', '8.5']
+ dependency-version: ['']
+ symfony-version: ['']
+ include: ${{ fromJson(needs.matrix.outputs.platform-bridges-include) }}
+
+ env:
+ SYMFONY_REQUIRE: ${{ matrix.symfony-version || '>=7.4' }}
+
+ steps:
+ - name: Checkout
+ uses: actions/checkout@v6
+
+ - name: Configure environment
+ run: |
+ echo COLUMNS=120 >> $GITHUB_ENV
+ [ 'lowest' = '${{ matrix.dependency-version }}' ] && echo SYMFONY_DEPRECATIONS_HELPER=weak >> $GITHUB_ENV || true
+
+ - name: Setup PHP
+ uses: shivammathur/setup-php@v2
+ with:
+ php-version: ${{ matrix.php-version }}
+ tools: flex
+ extensions: ${{ env.REQUIRED_PHP_EXTENSIONS }}
+
+ # Deptrac does not support Symfony 8.0 yet
+ - name: Remove deptrac (Symfony 8.0)
+ if: matrix.symfony-version == '8.0.*'
+ run: composer remove --dev deptrac/deptrac --no-update
+
+ - name: Install root dependencies
+ uses: ramsey/composer-install@v3
+
+ - name: Build packages
+ run: php .github/build-packages.php
+
+ # Remove root vendor and bridge vendor to avoid circular symlinks when installing bridge dependencies
+ - name: Clean vendor folders
+ run: rm -rf vendor src/platform/src/Bridge/${{ matrix.bridge.bridge }}/vendor
+
+ - name: Install dependencies
+ uses: ramsey/composer-install@v3
+ with:
+ working-directory: src/platform/src/Bridge/${{ matrix.bridge.bridge }}
+ dependency-versions: ${{ matrix.dependency-version || 'highest' }}
+
+ - name: Run PHPUnit
+ run: cd src/platform/src/Bridge/${{ matrix.bridge.bridge }} && vendor/bin/phpunit
diff --git a/.github/workflows/validation.yaml b/.github/workflows/validation.yaml
index a2bbe284d..4a34bf3c9 100644
--- a/.github/workflows/validation.yaml
+++ b/.github/workflows/validation.yaml
@@ -56,3 +56,19 @@ jobs:
- name: Validate tool bridges have required files
run: .github/scripts/validate-bridge-files.sh tool agent
+
+ validate_platforms:
+ name: Platform Bridges
+ runs-on: ubuntu-latest
+ steps:
+ - name: Checkout
+ uses: actions/checkout@v6
+
+ - name: Validate platform bridge naming conventions
+ run: .github/scripts/validate-bridge-naming.sh platform platform
+
+ - name: Validate platform bridges are in splitsh.json
+ run: .github/scripts/validate-bridge-splitsh.sh platform
+
+ - name: Validate platform bridges have required files
+ run: .github/scripts/validate-bridge-files.sh platform
diff --git a/demo/composer.json b/demo/composer.json
index d2c657782..5e0f1701a 100644
--- a/demo/composer.json
+++ b/demo/composer.json
@@ -15,6 +15,8 @@
"symfony/ai-bundle": "@dev",
"symfony/ai-chroma-db-store": "@dev",
"symfony/ai-clock-tool": "@dev",
+ "symfony/ai-hugging-face-platform": "@dev",
+ "symfony/ai-open-ai-platform": "@dev",
"symfony/ai-similarity-search-tool": "@dev",
"symfony/ai-wikipedia-tool": "@dev",
"symfony/asset": "^8.0",
diff --git a/examples/composer.json b/examples/composer.json
index c7fa7a63b..59b72cb9a 100644
--- a/examples/composer.json
+++ b/examples/composer.json
@@ -19,44 +19,165 @@
{
"type": "path",
"url": "../src/store"
+ },
+ {
+ "type": "path",
+ "url": "../src/platform/src/Bridge/AiMlApi"
+ },
+ {
+ "type": "path",
+ "url": "../src/platform/src/Bridge/Albert"
+ },
+ {
+ "type": "path",
+ "url": "../src/platform/src/Bridge/Anthropic"
+ },
+ {
+ "type": "path",
+ "url": "../src/platform/src/Bridge/Azure"
+ },
+ {
+ "type": "path",
+ "url": "../src/platform/src/Bridge/Bedrock"
+ },
+ {
+ "type": "path",
+ "url": "../src/platform/src/Bridge/Cartesia"
+ },
+ {
+ "type": "path",
+ "url": "../src/platform/src/Bridge/Cerebras"
+ },
+ {
+ "type": "path",
+ "url": "../src/platform/src/Bridge/Decart"
+ },
+ {
+ "type": "path",
+ "url": "../src/platform/src/Bridge/DeepSeek"
+ },
+ {
+ "type": "path",
+ "url": "../src/platform/src/Bridge/DockerModelRunner"
+ },
+ {
+ "type": "path",
+ "url": "../src/platform/src/Bridge/ElevenLabs"
+ },
+ {
+ "type": "path",
+ "url": "../src/platform/src/Bridge/Gemini"
+ },
+ {
+ "type": "path",
+ "url": "../src/platform/src/Bridge/Generic"
+ },
+ {
+ "type": "path",
+ "url": "../src/platform/src/Bridge/HuggingFace"
+ },
+ {
+ "type": "path",
+ "url": "../src/platform/src/Bridge/LmStudio"
+ },
+ {
+ "type": "path",
+ "url": "../src/platform/src/Bridge/Meta"
+ },
+ {
+ "type": "path",
+ "url": "../src/platform/src/Bridge/Mistral"
+ },
+ {
+ "type": "path",
+ "url": "../src/platform/src/Bridge/Ollama"
+ },
+ {
+ "type": "path",
+ "url": "../src/platform/src/Bridge/OpenAi"
+ },
+ {
+ "type": "path",
+ "url": "../src/platform/src/Bridge/OpenRouter"
+ },
+ {
+ "type": "path",
+ "url": "../src/platform/src/Bridge/Perplexity"
+ },
+ {
+ "type": "path",
+ "url": "../src/platform/src/Bridge/Scaleway"
+ },
+ {
+ "type": "path",
+ "url": "../src/platform/src/Bridge/TransformersPhp"
+ },
+ {
+ "type": "path",
+ "url": "../src/platform/src/Bridge/VertexAi"
+ },
+ {
+ "type": "path",
+ "url": "../src/platform/src/Bridge/Voyage"
}
],
"require": {
"php": ">=8.2",
- "async-aws/bedrock-runtime": "^1.1",
- "codewithkyrian/transformers": "^0.6.2",
"doctrine/dbal": "^3.3|^4.0",
- "google/auth": "^1.47",
"symfony/ai-agent": "@dev",
+ "symfony/ai-ai-ml-api-platform": "@dev",
+ "symfony/ai-albert-platform": "@dev",
+ "symfony/ai-anthropic-platform": "@dev",
+ "symfony/ai-azure-platform": "@dev",
"symfony/ai-azure-search-store": "@dev",
+ "symfony/ai-bedrock-platform": "@dev",
"symfony/ai-brave-tool": "@dev",
"symfony/ai-cache-store": "@dev",
+ "symfony/ai-cartesia-platform": "@dev",
+ "symfony/ai-cerebras-platform": "@dev",
"symfony/ai-chat": "@dev",
"symfony/ai-chroma-db-store": "@dev",
"symfony/ai-click-house-store": "@dev",
"symfony/ai-clock-tool": "@dev",
"symfony/ai-cloudflare-store": "@dev",
+ "symfony/ai-decart-platform": "@dev",
+ "symfony/ai-deep-seek-platform": "@dev",
+ "symfony/ai-docker-model-runner-platform": "@dev",
"symfony/ai-elasticsearch-store": "@dev",
+ "symfony/ai-eleven-labs-platform": "@dev",
+ "symfony/ai-gemini-platform": "@dev",
+ "symfony/ai-generic-platform": "@dev",
+ "symfony/ai-hugging-face-platform": "@dev",
+ "symfony/ai-lm-studio-platform": "@dev",
"symfony/ai-manticore-search-store": "@dev",
"symfony/ai-maria-db-store": "@dev",
"symfony/ai-meilisearch-store": "@dev",
+ "symfony/ai-meta-platform": "@dev",
"symfony/ai-milvus-store": "@dev",
+ "symfony/ai-mistral-platform": "@dev",
"symfony/ai-mongo-db-store": "@dev",
"symfony/ai-neo4j-store": "@dev",
+ "symfony/ai-ollama-platform": "@dev",
+ "symfony/ai-open-ai-platform": "@dev",
"symfony/ai-open-meteo-tool": "@dev",
+ "symfony/ai-open-router-platform": "@dev",
"symfony/ai-open-search-store": "@dev",
+ "symfony/ai-perplexity-platform": "@dev",
"symfony/ai-pinecone-store": "@dev",
- "symfony/ai-platform": "@dev",
"symfony/ai-postgres-store": "@dev",
"symfony/ai-qdrant-store": "@dev",
"symfony/ai-redis-store": "@dev",
+ "symfony/ai-scaleway-platform": "@dev",
"symfony/ai-scraper-tool": "@dev",
"symfony/ai-serp-api-tool": "@dev",
"symfony/ai-similarity-search-tool": "@dev",
"symfony/ai-supabase-store": "@dev",
"symfony/ai-surreal-db-store": "@dev",
"symfony/ai-tavily-tool": "@dev",
+ "symfony/ai-transformers-php-platform": "@dev",
"symfony/ai-typesense-store": "@dev",
+ "symfony/ai-vertex-ai-platform": "@dev",
+ "symfony/ai-voyage-platform": "@dev",
"symfony/ai-weaviate-store": "@dev",
"symfony/ai-wikipedia-tool": "@dev",
"symfony/ai-youtube-tool": "@dev",
diff --git a/splitsh.json b/splitsh.json
index 1cdc98665..7366ecb2f 100644
--- a/splitsh.json
+++ b/splitsh.json
@@ -18,7 +18,35 @@
"ai-bundle": "src/ai-bundle",
"ai-chat": "src/chat",
"mcp-bundle": "src/mcp-bundle",
- "ai-platform": "src/platform",
+ "ai-platform": {
+ "prefixes": [{ "from": "src/platform", "to": "", "excludes": ["src/Bridge"] }]
+ },
+ "ai-ai-ml-api-platform": "src/platform/src/Bridge/AiMlApi",
+ "ai-albert-platform": "src/platform/src/Bridge/Albert",
+ "ai-anthropic-platform": "src/platform/src/Bridge/Anthropic",
+ "ai-azure-platform": "src/platform/src/Bridge/Azure",
+ "ai-bedrock-platform": "src/platform/src/Bridge/Bedrock",
+ "ai-cartesia-platform": "src/platform/src/Bridge/Cartesia",
+ "ai-cerebras-platform": "src/platform/src/Bridge/Cerebras",
+ "ai-decart-platform": "src/platform/src/Bridge/Decart",
+ "ai-deep-seek-platform": "src/platform/src/Bridge/DeepSeek",
+ "ai-docker-model-runner-platform": "src/platform/src/Bridge/DockerModelRunner",
+ "ai-eleven-labs-platform": "src/platform/src/Bridge/ElevenLabs",
+ "ai-gemini-platform": "src/platform/src/Bridge/Gemini",
+ "ai-generic-platform": "src/platform/src/Bridge/Generic",
+ "ai-hugging-face-platform": "src/platform/src/Bridge/HuggingFace",
+ "ai-lm-studio-platform": "src/platform/src/Bridge/LmStudio",
+ "ai-meta-platform": "src/platform/src/Bridge/Meta",
+ "ai-mistral-platform": "src/platform/src/Bridge/Mistral",
+ "ai-ollama-platform": "src/platform/src/Bridge/Ollama",
+ "ai-open-ai-platform": "src/platform/src/Bridge/OpenAi",
+ "ai-open-router-platform": "src/platform/src/Bridge/OpenRouter",
+ "ai-perplexity-platform": "src/platform/src/Bridge/Perplexity",
+ "ai-replicate-platform": "src/platform/src/Bridge/Replicate",
+ "ai-scaleway-platform": "src/platform/src/Bridge/Scaleway",
+ "ai-transformers-php-platform": "src/platform/src/Bridge/TransformersPhp",
+ "ai-vertex-ai-platform": "src/platform/src/Bridge/VertexAi",
+ "ai-voyage-platform": "src/platform/src/Bridge/Voyage",
"ai-store": {
"prefixes": [{ "from": "src/store", "to": "", "excludes": ["src/Bridge"] }]
},
diff --git a/src/ai-bundle/composer.json b/src/ai-bundle/composer.json
index f4167a1c8..b4e01cbdc 100644
--- a/src/ai-bundle/composer.json
+++ b/src/ai-bundle/composer.json
@@ -73,10 +73,7 @@
}
},
"config": {
- "sort-packages": true,
- "allow-plugins": {
- "php-http/discovery": true
- }
+ "sort-packages": true
},
"extra": {
"branch-alias": {
diff --git a/src/ai-bundle/src/AiBundle.php b/src/ai-bundle/src/AiBundle.php
index 4f63f29c0..de37b29ea 100644
--- a/src/ai-bundle/src/AiBundle.php
+++ b/src/ai-bundle/src/AiBundle.php
@@ -332,6 +332,10 @@ public function loadExtension(array $config, ContainerConfigurator $container, C
private function processPlatformConfig(string $type, array $platform, ContainerBuilder $container): void
{
if ('albert' === $type) {
+ if (!ContainerBuilder::willBeAvailable('symfony/ai-albert-platform', AlbertPlatformFactory::class, ['symfony/ai-bundle'])) {
+ throw new RuntimeException('Albert platform configuration requires "symfony/ai-albert-platform" package. Try running "composer require symfony/ai-albert-platform".');
+ }
+
$platformId = 'ai.platform.albert';
$definition = (new Definition(Platform::class))
->setFactory(AlbertPlatformFactory::class.'::create')
@@ -352,6 +356,10 @@ private function processPlatformConfig(string $type, array $platform, ContainerB
}
if ('anthropic' === $type) {
+ if (!ContainerBuilder::willBeAvailable('symfony/ai-anthropic-platform', AnthropicPlatformFactory::class, ['symfony/ai-bundle'])) {
+ throw new RuntimeException('Anthropic platform configuration requires "symfony/ai-anthropic-platform" package. Try running "composer require symfony/ai-anthropic-platform".');
+ }
+
$platformId = 'ai.platform.anthropic';
$definition = (new Definition(Platform::class))
->setFactory(AnthropicPlatformFactory::class.'::create')
@@ -372,6 +380,10 @@ private function processPlatformConfig(string $type, array $platform, ContainerB
}
if ('azure' === $type) {
+ if (!ContainerBuilder::willBeAvailable('symfony/ai-azure-platform', AzureOpenAiPlatformFactory::class, ['symfony/ai-bundle'])) {
+ throw new RuntimeException('Azure platform configuration requires "symfony/ai-azure-platform" package. Try running "composer require symfony/ai-azure-platform".');
+ }
+
foreach ($platform as $name => $config) {
$platformId = 'ai.platform.azure.'.$name;
$definition = (new Definition(Platform::class))
@@ -417,6 +429,10 @@ private function processPlatformConfig(string $type, array $platform, ContainerB
}
if ('cartesia' === $type) {
+ if (!ContainerBuilder::willBeAvailable('symfony/ai-cartesia-platform', CartesiaPlatformFactory::class, ['symfony/ai-bundle'])) {
+ throw new RuntimeException('Cartesia platform configuration requires "symfony/ai-cartesia-platform" package. Try running "composer require symfony/ai-cartesia-platform".');
+ }
+
$definition = (new Definition(Platform::class))
->setFactory(CartesiaPlatformFactory::class.'::create')
->setLazy(true)
@@ -458,6 +474,10 @@ private function processPlatformConfig(string $type, array $platform, ContainerB
}
if ('elevenlabs' === $type) {
+ if (!ContainerBuilder::willBeAvailable('symfony/ai-eleven-labs-platform', ElevenLabsPlatformFactory::class, ['symfony/ai-bundle'])) {
+ throw new RuntimeException('ElevenLabs platform configuration requires "symfony/ai-eleven-labs-platform" package. Try running "composer require symfony/ai-eleven-labs-platform".');
+ }
+
if (\array_key_exists('api_catalog', $platform) && $platform['api_catalog']) {
$catalogDefinition = (new Definition(ElevenLabsApiCatalog::class))
->setLazy(true)
@@ -492,6 +512,10 @@ private function processPlatformConfig(string $type, array $platform, ContainerB
}
if ('gemini' === $type) {
+ if (!ContainerBuilder::willBeAvailable('symfony/ai-gemini-platform', GeminiPlatformFactory::class, ['symfony/ai-bundle'])) {
+ throw new RuntimeException('Gemini platform configuration requires "symfony/ai-gemini-platform" package. Try running "composer require symfony/ai-gemini-platform".');
+ }
+
$platformId = 'ai.platform.gemini';
$definition = (new Definition(Platform::class))
->setFactory(GeminiPlatformFactory::class.'::create')
@@ -512,6 +536,10 @@ private function processPlatformConfig(string $type, array $platform, ContainerB
}
if ('generic' === $type) {
+ if (!ContainerBuilder::willBeAvailable('symfony/ai-generic-platform', GenericPlatformFactory::class, ['symfony/ai-bundle'])) {
+ throw new RuntimeException('Generic platform configuration requires "symfony/ai-generic-platform" package. Try running "composer require symfony/ai-generic-platform".');
+ }
+
foreach ($platform as $name => $config) {
$platformId = 'ai.platform.generic.'.$name;
$definition = (new Definition(Platform::class))
@@ -539,6 +567,10 @@ private function processPlatformConfig(string $type, array $platform, ContainerB
}
if ('huggingface' === $type) {
+ if (!ContainerBuilder::willBeAvailable('symfony/ai-hugging-face-platform', HuggingFacePlatformFactory::class, ['symfony/ai-bundle'])) {
+ throw new RuntimeException('HuggingFace platform configuration requires "symfony/ai-hugging-face-platform" package. Try running "composer require symfony/ai-hugging-face-platform".');
+ }
+
$platformId = 'ai.platform.huggingface';
$definition = (new Definition(Platform::class))
->setFactory(HuggingFacePlatformFactory::class.'::create')
@@ -560,6 +592,10 @@ private function processPlatformConfig(string $type, array $platform, ContainerB
}
if ('vertexai' === $type && isset($platform['location'], $platform['project_id'])) {
+ if (!ContainerBuilder::willBeAvailable('symfony/ai-vertex-ai-platform', VertexAiPlatformFactory::class, ['symfony/ai-bundle'])) {
+ throw new RuntimeException('VertexAI platform configuration requires "symfony/ai-vertex-ai-platform" package. Try running "composer require symfony/ai-vertex-ai-platform".');
+ }
+
if (!class_exists(ApplicationDefaultCredentials::class)) {
throw new RuntimeException('For using the Vertex AI platform, google/auth package is required. Try running "composer require google/auth".');
}
@@ -601,6 +637,10 @@ private function processPlatformConfig(string $type, array $platform, ContainerB
}
if ('openai' === $type) {
+ if (!ContainerBuilder::willBeAvailable('symfony/ai-open-ai-platform', OpenAiPlatformFactory::class, ['symfony/ai-bundle'])) {
+ throw new RuntimeException('OpenAI platform configuration requires "symfony/ai-open-ai-platform" package. Try running "composer require symfony/ai-open-ai-platform".');
+ }
+
$platformId = 'ai.platform.openai';
$definition = (new Definition(Platform::class))
->setFactory(OpenAiPlatformFactory::class.'::create')
@@ -622,6 +662,10 @@ private function processPlatformConfig(string $type, array $platform, ContainerB
}
if ('openrouter' === $type) {
+ if (!ContainerBuilder::willBeAvailable('symfony/ai-open-router-platform', OpenRouterPlatformFactory::class, ['symfony/ai-bundle'])) {
+ throw new RuntimeException('OpenRouter platform configuration requires "symfony/ai-open-router-platform" package. Try running "composer require symfony/ai-open-router-platform".');
+ }
+
$platformId = 'ai.platform.openrouter';
$definition = (new Definition(Platform::class))
->setFactory(OpenRouterPlatformFactory::class.'::create')
@@ -642,6 +686,10 @@ private function processPlatformConfig(string $type, array $platform, ContainerB
}
if ('mistral' === $type) {
+ if (!ContainerBuilder::willBeAvailable('symfony/ai-mistral-platform', MistralPlatformFactory::class, ['symfony/ai-bundle'])) {
+ throw new RuntimeException('Mistral platform configuration requires "symfony/ai-mistral-platform" package. Try running "composer require symfony/ai-mistral-platform".');
+ }
+
$platformId = 'ai.platform.mistral';
$definition = (new Definition(Platform::class))
->setFactory(MistralPlatformFactory::class.'::create')
@@ -662,6 +710,10 @@ private function processPlatformConfig(string $type, array $platform, ContainerB
}
if ('lmstudio' === $type) {
+ if (!ContainerBuilder::willBeAvailable('symfony/ai-lm-studio-platform', LmStudioPlatformFactory::class, ['symfony/ai-bundle'])) {
+ throw new RuntimeException('LmStudio platform configuration requires "symfony/ai-lm-studio-platform" package. Try running "composer require symfony/ai-lm-studio-platform".');
+ }
+
$platformId = 'ai.platform.lmstudio';
$definition = (new Definition(Platform::class))
->setFactory(LmStudioPlatformFactory::class.'::create')
@@ -682,6 +734,10 @@ private function processPlatformConfig(string $type, array $platform, ContainerB
}
if ('ollama' === $type) {
+ if (!ContainerBuilder::willBeAvailable('symfony/ai-ollama-platform', OllamaPlatformFactory::class, ['symfony/ai-bundle'])) {
+ throw new RuntimeException('Ollama platform configuration requires "symfony/ai-ollama-platform" package. Try running "composer require symfony/ai-ollama-platform".');
+ }
+
if (\array_key_exists('api_catalog', $platform)) {
$catalogDefinition = (new Definition(OllamaApiCatalog::class))
->setLazy(true)
@@ -714,6 +770,10 @@ private function processPlatformConfig(string $type, array $platform, ContainerB
}
if ('cerebras' === $type) {
+ if (!ContainerBuilder::willBeAvailable('symfony/ai-cerebras-platform', CerebrasPlatformFactory::class, ['symfony/ai-bundle'])) {
+ throw new RuntimeException('Cerebras platform configuration requires "symfony/ai-cerebras-platform" package. Try running "composer require symfony/ai-cerebras-platform".');
+ }
+
$platformId = 'ai.platform.cerebras';
$definition = (new Definition(Platform::class))
->setFactory(CerebrasPlatformFactory::class.'::create')
@@ -734,6 +794,10 @@ private function processPlatformConfig(string $type, array $platform, ContainerB
}
if ('deepseek' === $type) {
+ if (!ContainerBuilder::willBeAvailable('symfony/ai-deep-seek-platform', DeepSeekPlatformFactory::class, ['symfony/ai-bundle'])) {
+ throw new RuntimeException('DeepSeek platform configuration requires "symfony/ai-deep-seek-platform" package. Try running "composer require symfony/ai-deep-seek-platform".');
+ }
+
$platformId = 'ai.platform.deepseek';
$definition = (new Definition(Platform::class))
->setFactory(DeepSeekPlatformFactory::class.'::create')
@@ -754,6 +818,10 @@ private function processPlatformConfig(string $type, array $platform, ContainerB
}
if ('voyage' === $type) {
+ if (!ContainerBuilder::willBeAvailable('symfony/ai-voyage-platform', VoyagePlatformFactory::class, ['symfony/ai-bundle'])) {
+ throw new RuntimeException('Voyage platform configuration requires "symfony/ai-voyage-platform" package. Try running "composer require symfony/ai-voyage-platform".');
+ }
+
$platformId = 'ai.platform.voyage';
$definition = (new Definition(Platform::class))
->setFactory(VoyagePlatformFactory::class.'::create')
@@ -774,6 +842,10 @@ private function processPlatformConfig(string $type, array $platform, ContainerB
}
if ('perplexity' === $type) {
+ if (!ContainerBuilder::willBeAvailable('symfony/ai-perplexity-platform', PerplexityPlatformFactory::class, ['symfony/ai-bundle'])) {
+ throw new RuntimeException('Perplexity platform configuration requires "symfony/ai-perplexity-platform" package. Try running "composer require symfony/ai-perplexity-platform".');
+ }
+
$platformId = 'ai.platform.perplexity';
$definition = (new Definition(Platform::class))
->setFactory(PerplexityPlatformFactory::class.'::create')
@@ -794,6 +866,10 @@ private function processPlatformConfig(string $type, array $platform, ContainerB
}
if ('dockermodelrunner' === $type) {
+ if (!ContainerBuilder::willBeAvailable('symfony/ai-docker-model-runner-platform', DockerModelRunnerPlatformFactory::class, ['symfony/ai-bundle'])) {
+ throw new RuntimeException('Docker Model Runner platform configuration requires "symfony/ai-docker-model-runner-platform" package. Try running "composer require symfony/ai-docker-model-runner-platform".');
+ }
+
$platformId = 'ai.platform.dockermodelrunner';
$definition = (new Definition(Platform::class))
->setFactory(DockerModelRunnerPlatformFactory::class.'::create')
@@ -814,6 +890,10 @@ private function processPlatformConfig(string $type, array $platform, ContainerB
}
if ('scaleway' === $type && isset($platform['api_key'])) {
+ if (!ContainerBuilder::willBeAvailable('symfony/ai-scaleway-platform', ScalewayPlatformFactory::class, ['symfony/ai-bundle'])) {
+ throw new RuntimeException('Scaleway platform configuration requires "symfony/ai-scaleway-platform" package. Try running "composer require symfony/ai-scaleway-platform".');
+ }
+
$platformId = 'ai.platform.scaleway';
$definition = (new Definition(Platform::class))
->setFactory(ScalewayPlatformFactory::class.'::create')
diff --git a/src/platform/README.md b/src/platform/README.md
index bf45c979e..5e988a714 100644
--- a/src/platform/README.md
+++ b/src/platform/README.md
@@ -13,6 +13,39 @@ are not covered by Symfony's
composer require symfony/ai-platform
```
+## Platform Bridges
+
+To use a specific AI platform, install the corresponding bridge package:
+
+| Platform | Package |
+|----------|---------|
+| AI.ML API | `symfony/ai-ai-ml-api-platform` |
+| Albert | `symfony/ai-albert-platform` |
+| Anthropic | `symfony/ai-anthropic-platform` |
+| Azure OpenAI | `symfony/ai-azure-platform` |
+| AWS Bedrock | `symfony/ai-bedrock-platform` |
+| Cartesia | `symfony/ai-cartesia-platform` |
+| Cerebras | `symfony/ai-cerebras-platform` |
+| Decart | `symfony/ai-decart-platform` |
+| DeepSeek | `symfony/ai-deep-seek-platform` |
+| Docker Model Runner | `symfony/ai-docker-model-runner-platform` |
+| ElevenLabs | `symfony/ai-eleven-labs-platform` |
+| Generic | `symfony/ai-generic-platform` |
+| Google Gemini | `symfony/ai-gemini-platform` |
+| Hugging Face | `symfony/ai-hugging-face-platform` |
+| LM Studio | `symfony/ai-lm-studio-platform` |
+| Meta Llama | `symfony/ai-meta-platform` |
+| Mistral | `symfony/ai-mistral-platform` |
+| Ollama | `symfony/ai-ollama-platform` |
+| OpenAI | `symfony/ai-open-ai-platform` |
+| OpenRouter | `symfony/ai-open-router-platform` |
+| Perplexity | `symfony/ai-perplexity-platform` |
+| Replicate | `symfony/ai-replicate-platform` |
+| Scaleway | `symfony/ai-scaleway-platform` |
+| TransformersPHP | `symfony/ai-transformers-php-platform` |
+| Google Vertex AI | `symfony/ai-vertex-ai-platform` |
+| Voyage | `symfony/ai-voyage-platform` |
+
**This repository is a READ-ONLY sub-tree split**. See
https://github.com/symfony/ai to create issues or submit pull requests.
diff --git a/src/platform/composer.json b/src/platform/composer.json
index 9c9bfb89e..c0a852cd8 100644
--- a/src/platform/composer.json
+++ b/src/platform/composer.json
@@ -54,7 +54,6 @@
"psr/log": "^3.0",
"symfony/clock": "^7.3|^8.0",
"symfony/event-dispatcher": "^7.3|^8.0",
- "symfony/http-client": "^7.3|^8.0",
"symfony/property-access": "^7.3|^8.0",
"symfony/property-info": "^7.3|^8.0",
"symfony/serializer": "^7.3|^8.0",
@@ -62,19 +61,16 @@
"symfony/uid": "^7.3|^8.0"
},
"require-dev": {
- "async-aws/bedrock-runtime": "^0.1|^1.0",
- "symfony/ai-agent": "@dev",
- "codewithkyrian/transformers": "^0.6.2",
- "google/auth": "^1.47",
"phpstan/phpstan": "^2.1.17",
"phpstan/phpstan-strict-rules": "^2.0",
- "phpstan/phpstan-symfony": "^2.0.6",
"phpunit/phpunit": "^11.5.46",
"symfony/cache": "^7.3|^8.0",
"symfony/console": "^7.3|^8.0",
"symfony/dotenv": "^7.3|^8.0",
"symfony/expression-language": "^7.3|^8.0",
"symfony/finder": "^7.3|^8.0",
+ "symfony/http-client": "^7.3|^8.0",
+ "symfony/http-client-contracts": "^3.5",
"symfony/process": "^7.3|^8.0",
"symfony/var-dumper": "^7.3|^8.0"
},
@@ -93,10 +89,6 @@
}
},
"config": {
- "allow-plugins": {
- "codewithkyrian/platform-package-installer": true,
- "codewithkyrian/transformers-libsloader": true
- },
"sort-packages": true
},
"extra": {
diff --git a/src/platform/phpstan.dist.neon b/src/platform/phpstan.dist.neon
index f544eee10..fd87fc6dc 100644
--- a/src/platform/phpstan.dist.neon
+++ b/src/platform/phpstan.dist.neon
@@ -1,12 +1,13 @@
includes:
- ../../.phpstan/extension.neon
- - vendor/phpstan/phpstan-symfony/extension.neon
parameters:
level: 6
paths:
- src/
- tests/
+ excludePaths:
+ - src/Bridge/
treatPhpDocTypesAsCertain: false
ignoreErrors:
-
@@ -23,15 +24,7 @@ parameters:
identifier: missingType.iterableValue
path: tests/*
reportUnmatched: false
- -
- identifier: missingType.iterableValue
- path: src/Bridge/**/Tests/*
- reportUnmatched: false
-
identifier: 'symfonyAi.forbidNativeException'
path: tests/*
reportUnmatched: false
- -
- identifier: 'symfonyAi.forbidNativeException'
- path: src/Bridge/**/Tests/*
- reportUnmatched: false
diff --git a/src/platform/src/Bridge/AiMlApi/README.md b/src/platform/src/Bridge/AiMlApi/README.md
new file mode 100644
index 000000000..9414a2390
--- /dev/null
+++ b/src/platform/src/Bridge/AiMlApi/README.md
@@ -0,0 +1,12 @@
+AiMlApi Platform
+================
+
+AiML API platform bridge for Symfony AI.
+
+Resources
+---------
+
+ * [Contributing](https://symfony.com/doc/current/contributing/index.html)
+ * [Report issues](https://github.com/symfony/ai/issues) and
+ [send Pull Requests](https://github.com/symfony/ai/pulls)
+ in the [main Symfony AI repository](https://github.com/symfony/ai)
diff --git a/src/platform/tests/Bridge/AiMlApi/ModelCatalogTest.php b/src/platform/src/Bridge/AiMlApi/Tests/ModelCatalogTest.php
similarity index 99%
rename from src/platform/tests/Bridge/AiMlApi/ModelCatalogTest.php
rename to src/platform/src/Bridge/AiMlApi/Tests/ModelCatalogTest.php
index f4ab7af30..5b2fbab8a 100644
--- a/src/platform/tests/Bridge/AiMlApi/ModelCatalogTest.php
+++ b/src/platform/src/Bridge/AiMlApi/Tests/ModelCatalogTest.php
@@ -9,7 +9,7 @@
* file that was distributed with this source code.
*/
-namespace Symfony\AI\Platform\Tests\Bridge\AiMlApi;
+namespace Symfony\AI\Platform\Bridge\AiMlApi\Tests;
use Symfony\AI\Platform\Bridge\AiMlApi\ModelCatalog;
use Symfony\AI\Platform\Bridge\Generic\CompletionsModel;
diff --git a/src/platform/src/Bridge/AiMlApi/composer.json b/src/platform/src/Bridge/AiMlApi/composer.json
new file mode 100644
index 000000000..6f8b6284c
--- /dev/null
+++ b/src/platform/src/Bridge/AiMlApi/composer.json
@@ -0,0 +1,61 @@
+{
+ "name": "symfony/ai-ai-ml-api-platform",
+ "description": "AiML API platform bridge for Symfony AI",
+ "license": "MIT",
+ "type": "symfony-ai-platform",
+ "keywords": [
+ "ai",
+ "aimlapi",
+ "bridge",
+ "platform"
+ ],
+ "authors": [
+ {
+ "name": "Christopher Hertel",
+ "email": "mail@christopher-hertel.de"
+ },
+ {
+ "name": "Oskar Stark",
+ "email": "oskarstark@googlemail.com"
+ },
+ {
+ "name": "Symfony Community",
+ "homepage": "https://symfony.com/contributors"
+ }
+ ],
+ "require": {
+ "php": ">=8.2",
+ "symfony/ai-generic-platform": "@dev",
+ "symfony/ai-platform": "@dev",
+ "symfony/http-client": "^7.3|^8.0"
+ },
+ "require-dev": {
+ "phpstan/phpstan": "^2.1",
+ "phpstan/phpstan-strict-rules": "^2.0",
+ "phpunit/phpunit": "^11.5.46"
+ },
+ "minimum-stability": "dev",
+ "autoload": {
+ "psr-4": {
+ "Symfony\\AI\\Platform\\Bridge\\AiMlApi\\": ""
+ }
+ },
+ "autoload-dev": {
+ "psr-4": {
+ "Symfony\\AI\\PHPStan\\": "../../../../../.phpstan/",
+ "Symfony\\AI\\Platform\\Bridge\\AiMlApi\\Tests\\": "Tests/"
+ }
+ },
+ "config": {
+ "sort-packages": true
+ },
+ "extra": {
+ "branch-alias": {
+ "dev-main": "0.x-dev"
+ },
+ "thanks": {
+ "name": "symfony/ai",
+ "url": "https://github.com/symfony/ai"
+ }
+ }
+}
diff --git a/src/platform/src/Bridge/AiMlApi/phpstan.dist.neon b/src/platform/src/Bridge/AiMlApi/phpstan.dist.neon
new file mode 100644
index 000000000..5503dac38
--- /dev/null
+++ b/src/platform/src/Bridge/AiMlApi/phpstan.dist.neon
@@ -0,0 +1,23 @@
+includes:
+ - ../../../../../.phpstan/extension.neon
+
+parameters:
+ level: 6
+ paths:
+ - .
+ - Tests/
+ excludePaths:
+ - vendor/
+ treatPhpDocTypesAsCertain: false
+ ignoreErrors:
+ -
+ message: "#^Method .*::test.*\\(\\) has no return type specified\\.$#"
+ reportUnmatched: false
+ -
+ identifier: missingType.iterableValue
+ path: Tests/*
+ reportUnmatched: false
+ -
+ identifier: 'symfonyAi.forbidNativeException'
+ path: Tests/*
+ reportUnmatched: false
diff --git a/src/platform/src/Bridge/AiMlApi/phpunit.xml.dist b/src/platform/src/Bridge/AiMlApi/phpunit.xml.dist
new file mode 100644
index 000000000..a79b6f515
--- /dev/null
+++ b/src/platform/src/Bridge/AiMlApi/phpunit.xml.dist
@@ -0,0 +1,32 @@
+
+
+
+
+
+
+
+
+
+ ./Tests/
+
+
+
+
+
+ ./
+
+
+ ./Resources
+ ./Tests
+ ./vendor
+
+
+
diff --git a/src/platform/src/Bridge/Albert/README.md b/src/platform/src/Bridge/Albert/README.md
new file mode 100644
index 000000000..b997a4fc2
--- /dev/null
+++ b/src/platform/src/Bridge/Albert/README.md
@@ -0,0 +1,12 @@
+Albert Platform
+===============
+
+Albert platform bridge for Symfony AI.
+
+Resources
+---------
+
+ * [Contributing](https://symfony.com/doc/current/contributing/index.html)
+ * [Report issues](https://github.com/symfony/ai/issues) and
+ [send Pull Requests](https://github.com/symfony/ai/pulls)
+ in the [main Symfony AI repository](https://github.com/symfony/ai)
diff --git a/src/platform/tests/Bridge/Albert/ModelCatalogTest.php b/src/platform/src/Bridge/Albert/Tests/ModelCatalogTest.php
similarity index 96%
rename from src/platform/tests/Bridge/Albert/ModelCatalogTest.php
rename to src/platform/src/Bridge/Albert/Tests/ModelCatalogTest.php
index 6aafba68e..6e3a3e8fc 100644
--- a/src/platform/tests/Bridge/Albert/ModelCatalogTest.php
+++ b/src/platform/src/Bridge/Albert/Tests/ModelCatalogTest.php
@@ -9,7 +9,7 @@
* file that was distributed with this source code.
*/
-namespace Symfony\AI\Platform\Tests\Bridge\Albert;
+namespace Symfony\AI\Platform\Bridge\Albert\Tests;
use Symfony\AI\Platform\Bridge\Albert\ModelCatalog;
use Symfony\AI\Platform\Bridge\Generic\CompletionsModel;
diff --git a/src/platform/tests/Bridge/Albert/PlatformFactoryTest.php b/src/platform/src/Bridge/Albert/Tests/PlatformFactoryTest.php
similarity index 98%
rename from src/platform/tests/Bridge/Albert/PlatformFactoryTest.php
rename to src/platform/src/Bridge/Albert/Tests/PlatformFactoryTest.php
index d8c02c9b0..c59c3fc11 100644
--- a/src/platform/tests/Bridge/Albert/PlatformFactoryTest.php
+++ b/src/platform/src/Bridge/Albert/Tests/PlatformFactoryTest.php
@@ -9,7 +9,7 @@
* file that was distributed with this source code.
*/
-namespace Symfony\AI\Platform\Tests\Bridge\Albert;
+namespace Symfony\AI\Platform\Bridge\Albert\Tests;
use PHPUnit\Framework\Attributes\DataProvider;
use PHPUnit\Framework\TestCase;
diff --git a/src/platform/src/Bridge/Albert/composer.json b/src/platform/src/Bridge/Albert/composer.json
new file mode 100644
index 000000000..bd5337e9a
--- /dev/null
+++ b/src/platform/src/Bridge/Albert/composer.json
@@ -0,0 +1,61 @@
+{
+ "name": "symfony/ai-albert-platform",
+ "description": "Albert platform bridge for Symfony AI",
+ "license": "MIT",
+ "type": "symfony-ai-platform",
+ "keywords": [
+ "ai",
+ "albert",
+ "bridge",
+ "platform"
+ ],
+ "authors": [
+ {
+ "name": "Christopher Hertel",
+ "email": "mail@christopher-hertel.de"
+ },
+ {
+ "name": "Oskar Stark",
+ "email": "oskarstark@googlemail.com"
+ },
+ {
+ "name": "Symfony Community",
+ "homepage": "https://symfony.com/contributors"
+ }
+ ],
+ "require": {
+ "php": ">=8.2",
+ "symfony/ai-generic-platform": "@dev",
+ "symfony/ai-platform": "@dev",
+ "symfony/http-client": "^7.3|^8.0"
+ },
+ "require-dev": {
+ "phpstan/phpstan": "^2.1",
+ "phpstan/phpstan-strict-rules": "^2.0",
+ "phpunit/phpunit": "^11.5.46"
+ },
+ "minimum-stability": "dev",
+ "autoload": {
+ "psr-4": {
+ "Symfony\\AI\\Platform\\Bridge\\Albert\\": ""
+ }
+ },
+ "autoload-dev": {
+ "psr-4": {
+ "Symfony\\AI\\PHPStan\\": "../../../../../.phpstan/",
+ "Symfony\\AI\\Platform\\Bridge\\Albert\\Tests\\": "Tests/"
+ }
+ },
+ "config": {
+ "sort-packages": true
+ },
+ "extra": {
+ "branch-alias": {
+ "dev-main": "0.x-dev"
+ },
+ "thanks": {
+ "name": "symfony/ai",
+ "url": "https://github.com/symfony/ai"
+ }
+ }
+}
diff --git a/src/platform/src/Bridge/Albert/phpstan.dist.neon b/src/platform/src/Bridge/Albert/phpstan.dist.neon
new file mode 100644
index 000000000..5503dac38
--- /dev/null
+++ b/src/platform/src/Bridge/Albert/phpstan.dist.neon
@@ -0,0 +1,23 @@
+includes:
+ - ../../../../../.phpstan/extension.neon
+
+parameters:
+ level: 6
+ paths:
+ - .
+ - Tests/
+ excludePaths:
+ - vendor/
+ treatPhpDocTypesAsCertain: false
+ ignoreErrors:
+ -
+ message: "#^Method .*::test.*\\(\\) has no return type specified\\.$#"
+ reportUnmatched: false
+ -
+ identifier: missingType.iterableValue
+ path: Tests/*
+ reportUnmatched: false
+ -
+ identifier: 'symfonyAi.forbidNativeException'
+ path: Tests/*
+ reportUnmatched: false
diff --git a/src/platform/src/Bridge/Albert/phpunit.xml.dist b/src/platform/src/Bridge/Albert/phpunit.xml.dist
new file mode 100644
index 000000000..efd487c71
--- /dev/null
+++ b/src/platform/src/Bridge/Albert/phpunit.xml.dist
@@ -0,0 +1,32 @@
+
+
+
+
+
+
+
+
+
+ ./Tests/
+
+
+
+
+
+ ./
+
+
+ ./Resources
+ ./Tests
+ ./vendor
+
+
+
diff --git a/src/platform/src/Bridge/Anthropic/README.md b/src/platform/src/Bridge/Anthropic/README.md
new file mode 100644
index 000000000..88475b758
--- /dev/null
+++ b/src/platform/src/Bridge/Anthropic/README.md
@@ -0,0 +1,12 @@
+Anthropic Platform
+==================
+
+Anthropic (Claude) platform bridge for Symfony AI.
+
+Resources
+---------
+
+ * [Contributing](https://symfony.com/doc/current/contributing/index.html)
+ * [Report issues](https://github.com/symfony/ai/issues) and
+ [send Pull Requests](https://github.com/symfony/ai/pulls)
+ in the [main Symfony AI repository](https://github.com/symfony/ai)
diff --git a/src/platform/tests/Bridge/Anthropic/ClaudeTest.php b/src/platform/src/Bridge/Anthropic/Tests/ClaudeTest.php
similarity index 96%
rename from src/platform/tests/Bridge/Anthropic/ClaudeTest.php
rename to src/platform/src/Bridge/Anthropic/Tests/ClaudeTest.php
index a0b69bcbc..ced7d786b 100644
--- a/src/platform/tests/Bridge/Anthropic/ClaudeTest.php
+++ b/src/platform/src/Bridge/Anthropic/Tests/ClaudeTest.php
@@ -9,7 +9,7 @@
* file that was distributed with this source code.
*/
-namespace Symfony\AI\Platform\Tests\Bridge\Anthropic;
+namespace Symfony\AI\Platform\Bridge\Anthropic\Tests;
use PHPUnit\Framework\TestCase;
use Symfony\AI\Platform\Bridge\Anthropic\Claude;
diff --git a/src/platform/tests/Bridge/Anthropic/Contract/AssistantMessageNormalizerTest.php b/src/platform/src/Bridge/Anthropic/Tests/Contract/AssistantMessageNormalizerTest.php
similarity index 98%
rename from src/platform/tests/Bridge/Anthropic/Contract/AssistantMessageNormalizerTest.php
rename to src/platform/src/Bridge/Anthropic/Tests/Contract/AssistantMessageNormalizerTest.php
index a523652fb..031b5b2b0 100644
--- a/src/platform/tests/Bridge/Anthropic/Contract/AssistantMessageNormalizerTest.php
+++ b/src/platform/src/Bridge/Anthropic/Tests/Contract/AssistantMessageNormalizerTest.php
@@ -9,7 +9,7 @@
* file that was distributed with this source code.
*/
-namespace Symfony\AI\Platform\Tests\Bridge\Anthropic\Contract;
+namespace Symfony\AI\Platform\Bridge\Anthropic\Tests\Contract;
use PHPUnit\Framework\Attributes\DataProvider;
use PHPUnit\Framework\TestCase;
diff --git a/src/platform/tests/Bridge/Anthropic/ModelCatalogTest.php b/src/platform/src/Bridge/Anthropic/Tests/ModelCatalogTest.php
similarity index 98%
rename from src/platform/tests/Bridge/Anthropic/ModelCatalogTest.php
rename to src/platform/src/Bridge/Anthropic/Tests/ModelCatalogTest.php
index 1845f166a..a80710fa9 100644
--- a/src/platform/tests/Bridge/Anthropic/ModelCatalogTest.php
+++ b/src/platform/src/Bridge/Anthropic/Tests/ModelCatalogTest.php
@@ -9,7 +9,7 @@
* file that was distributed with this source code.
*/
-namespace Symfony\AI\Platform\Tests\Bridge\Anthropic;
+namespace Symfony\AI\Platform\Bridge\Anthropic\Tests;
use Symfony\AI\Platform\Bridge\Anthropic\Claude;
use Symfony\AI\Platform\Bridge\Anthropic\ModelCatalog;
diff --git a/src/platform/tests/Bridge/Anthropic/ModelClientTest.php b/src/platform/src/Bridge/Anthropic/Tests/ModelClientTest.php
similarity index 97%
rename from src/platform/tests/Bridge/Anthropic/ModelClientTest.php
rename to src/platform/src/Bridge/Anthropic/Tests/ModelClientTest.php
index d15870b5c..b924e4f31 100644
--- a/src/platform/tests/Bridge/Anthropic/ModelClientTest.php
+++ b/src/platform/src/Bridge/Anthropic/Tests/ModelClientTest.php
@@ -97,6 +97,11 @@ public function testAnthropicBetaHeaderIsNotSetWhenBetaFeaturesIsNotProvided()
$this->modelClient->request($this->model, ['message' => 'test'], $options);
}
+ /**
+ * @param list $headers
+ *
+ * @return array
+ */
private function parseHeaders(array $headers): array
{
$parsed = [];
diff --git a/src/platform/tests/Bridge/Anthropic/ResultConverterRateLimitTest.php b/src/platform/src/Bridge/Anthropic/Tests/ResultConverterRateLimitTest.php
similarity index 97%
rename from src/platform/tests/Bridge/Anthropic/ResultConverterRateLimitTest.php
rename to src/platform/src/Bridge/Anthropic/Tests/ResultConverterRateLimitTest.php
index e88873cd6..6f96e2fea 100644
--- a/src/platform/tests/Bridge/Anthropic/ResultConverterRateLimitTest.php
+++ b/src/platform/src/Bridge/Anthropic/Tests/ResultConverterRateLimitTest.php
@@ -9,7 +9,7 @@
* file that was distributed with this source code.
*/
-namespace Symfony\AI\Platform\Tests\Bridge\Anthropic;
+namespace Symfony\AI\Platform\Bridge\Anthropic\Tests;
use PHPUnit\Framework\TestCase;
use Symfony\AI\Platform\Bridge\Anthropic\ResultConverter;
diff --git a/src/platform/tests/Bridge/Anthropic/ResultConverterTest.php b/src/platform/src/Bridge/Anthropic/Tests/ResultConverterTest.php
similarity index 98%
rename from src/platform/tests/Bridge/Anthropic/ResultConverterTest.php
rename to src/platform/src/Bridge/Anthropic/Tests/ResultConverterTest.php
index d64be5e8a..abd723be5 100644
--- a/src/platform/tests/Bridge/Anthropic/ResultConverterTest.php
+++ b/src/platform/src/Bridge/Anthropic/Tests/ResultConverterTest.php
@@ -9,7 +9,7 @@
* file that was distributed with this source code.
*/
-namespace Symfony\AI\Platform\Tests\Bridge\Anthropic;
+namespace Symfony\AI\Platform\Bridge\Anthropic\Tests;
use PHPUnit\Framework\TestCase;
use Symfony\AI\Platform\Bridge\Anthropic\ResultConverter;
diff --git a/src/platform/tests/Bridge/Anthropic/TokenUsageExtractorTest.php b/src/platform/src/Bridge/Anthropic/Tests/TokenUsageExtractorTest.php
similarity index 100%
rename from src/platform/tests/Bridge/Anthropic/TokenUsageExtractorTest.php
rename to src/platform/src/Bridge/Anthropic/Tests/TokenUsageExtractorTest.php
diff --git a/src/platform/src/Bridge/Anthropic/composer.json b/src/platform/src/Bridge/Anthropic/composer.json
new file mode 100644
index 000000000..917ec49d8
--- /dev/null
+++ b/src/platform/src/Bridge/Anthropic/composer.json
@@ -0,0 +1,61 @@
+{
+ "name": "symfony/ai-anthropic-platform",
+ "description": "Anthropic (Claude) platform bridge for Symfony AI",
+ "license": "MIT",
+ "type": "symfony-ai-platform",
+ "keywords": [
+ "ai",
+ "anthropic",
+ "bridge",
+ "claude",
+ "platform"
+ ],
+ "authors": [
+ {
+ "name": "Christopher Hertel",
+ "email": "mail@christopher-hertel.de"
+ },
+ {
+ "name": "Oskar Stark",
+ "email": "oskarstark@googlemail.com"
+ },
+ {
+ "name": "Symfony Community",
+ "homepage": "https://symfony.com/contributors"
+ }
+ ],
+ "require": {
+ "php": ">=8.2",
+ "symfony/ai-platform": "@dev",
+ "symfony/http-client": "^7.3|^8.0"
+ },
+ "require-dev": {
+ "phpstan/phpstan": "^2.1",
+ "phpstan/phpstan-strict-rules": "^2.0",
+ "phpunit/phpunit": "^11.5.46"
+ },
+ "minimum-stability": "dev",
+ "autoload": {
+ "psr-4": {
+ "Symfony\\AI\\Platform\\Bridge\\Anthropic\\": ""
+ }
+ },
+ "autoload-dev": {
+ "psr-4": {
+ "Symfony\\AI\\PHPStan\\": "../../../../../.phpstan/",
+ "Symfony\\AI\\Platform\\Bridge\\Anthropic\\Tests\\": "Tests/"
+ }
+ },
+ "config": {
+ "sort-packages": true
+ },
+ "extra": {
+ "branch-alias": {
+ "dev-main": "0.x-dev"
+ },
+ "thanks": {
+ "name": "symfony/ai",
+ "url": "https://github.com/symfony/ai"
+ }
+ }
+}
diff --git a/src/platform/src/Bridge/Anthropic/phpstan.dist.neon b/src/platform/src/Bridge/Anthropic/phpstan.dist.neon
new file mode 100644
index 000000000..5503dac38
--- /dev/null
+++ b/src/platform/src/Bridge/Anthropic/phpstan.dist.neon
@@ -0,0 +1,23 @@
+includes:
+ - ../../../../../.phpstan/extension.neon
+
+parameters:
+ level: 6
+ paths:
+ - .
+ - Tests/
+ excludePaths:
+ - vendor/
+ treatPhpDocTypesAsCertain: false
+ ignoreErrors:
+ -
+ message: "#^Method .*::test.*\\(\\) has no return type specified\\.$#"
+ reportUnmatched: false
+ -
+ identifier: missingType.iterableValue
+ path: Tests/*
+ reportUnmatched: false
+ -
+ identifier: 'symfonyAi.forbidNativeException'
+ path: Tests/*
+ reportUnmatched: false
diff --git a/src/platform/src/Bridge/Anthropic/phpunit.xml.dist b/src/platform/src/Bridge/Anthropic/phpunit.xml.dist
new file mode 100644
index 000000000..9bfcfd2bd
--- /dev/null
+++ b/src/platform/src/Bridge/Anthropic/phpunit.xml.dist
@@ -0,0 +1,32 @@
+
+
+
+
+
+
+
+
+
+ ./Tests/
+
+
+
+
+
+ ./
+
+
+ ./Resources
+ ./Tests
+ ./vendor
+
+
+
diff --git a/src/platform/src/Bridge/Azure/README.md b/src/platform/src/Bridge/Azure/README.md
new file mode 100644
index 000000000..a2294b689
--- /dev/null
+++ b/src/platform/src/Bridge/Azure/README.md
@@ -0,0 +1,12 @@
+Azure Platform
+==============
+
+Azure AI platform bridge for Symfony AI.
+
+Resources
+---------
+
+ * [Contributing](https://symfony.com/doc/current/contributing/index.html)
+ * [Report issues](https://github.com/symfony/ai/issues) and
+ [send Pull Requests](https://github.com/symfony/ai/pulls)
+ in the [main Symfony AI repository](https://github.com/symfony/ai)
diff --git a/src/platform/tests/Bridge/Azure/OpenAi/CompletionsModelClientTest.php b/src/platform/src/Bridge/Azure/Tests/OpenAi/CompletionsModelClientTest.php
similarity index 98%
rename from src/platform/tests/Bridge/Azure/OpenAi/CompletionsModelClientTest.php
rename to src/platform/src/Bridge/Azure/Tests/OpenAi/CompletionsModelClientTest.php
index 935abec3b..e3f8dc680 100644
--- a/src/platform/tests/Bridge/Azure/OpenAi/CompletionsModelClientTest.php
+++ b/src/platform/src/Bridge/Azure/Tests/OpenAi/CompletionsModelClientTest.php
@@ -9,7 +9,7 @@
* file that was distributed with this source code.
*/
-namespace Symfony\AI\Platform\Tests\Bridge\Azure\OpenAi;
+namespace Symfony\AI\Platform\Bridge\Azure\Tests\OpenAi;
use PHPUnit\Framework\Attributes\TestWith;
use PHPUnit\Framework\TestCase;
diff --git a/src/platform/tests/Bridge/Azure/OpenAi/EmbeddingsModelClientTest.php b/src/platform/src/Bridge/Azure/Tests/OpenAi/EmbeddingsModelClientTest.php
similarity index 98%
rename from src/platform/tests/Bridge/Azure/OpenAi/EmbeddingsModelClientTest.php
rename to src/platform/src/Bridge/Azure/Tests/OpenAi/EmbeddingsModelClientTest.php
index 1b46e0f4a..37a9ed8fb 100644
--- a/src/platform/tests/Bridge/Azure/OpenAi/EmbeddingsModelClientTest.php
+++ b/src/platform/src/Bridge/Azure/Tests/OpenAi/EmbeddingsModelClientTest.php
@@ -9,7 +9,7 @@
* file that was distributed with this source code.
*/
-namespace Symfony\AI\Platform\Tests\Bridge\Azure\OpenAi;
+namespace Symfony\AI\Platform\Bridge\Azure\Tests\OpenAi;
use PHPUnit\Framework\Attributes\TestWith;
use PHPUnit\Framework\TestCase;
diff --git a/src/platform/tests/Bridge/Azure/OpenAi/WhisperModelClientTest.php b/src/platform/src/Bridge/Azure/Tests/OpenAi/WhisperModelClientTest.php
similarity index 98%
rename from src/platform/tests/Bridge/Azure/OpenAi/WhisperModelClientTest.php
rename to src/platform/src/Bridge/Azure/Tests/OpenAi/WhisperModelClientTest.php
index 40084b314..86179dbb3 100644
--- a/src/platform/tests/Bridge/Azure/OpenAi/WhisperModelClientTest.php
+++ b/src/platform/src/Bridge/Azure/Tests/OpenAi/WhisperModelClientTest.php
@@ -9,7 +9,7 @@
* file that was distributed with this source code.
*/
-namespace Symfony\AI\Platform\Tests\Bridge\Azure\OpenAi;
+namespace Symfony\AI\Platform\Bridge\Azure\Tests\OpenAi;
use PHPUnit\Framework\Attributes\TestWith;
use PHPUnit\Framework\TestCase;
diff --git a/src/platform/src/Bridge/Azure/composer.json b/src/platform/src/Bridge/Azure/composer.json
new file mode 100644
index 000000000..d5c45a3dd
--- /dev/null
+++ b/src/platform/src/Bridge/Azure/composer.json
@@ -0,0 +1,64 @@
+{
+ "name": "symfony/ai-azure-platform",
+ "description": "Azure AI platform bridge for Symfony AI",
+ "license": "MIT",
+ "type": "symfony-ai-platform",
+ "keywords": [
+ "ai",
+ "azure",
+ "azure-openai",
+ "bridge",
+ "platform"
+ ],
+ "authors": [
+ {
+ "name": "Christopher Hertel",
+ "email": "mail@christopher-hertel.de"
+ },
+ {
+ "name": "Oskar Stark",
+ "email": "oskarstark@googlemail.com"
+ },
+ {
+ "name": "Symfony Community",
+ "homepage": "https://symfony.com/contributors"
+ }
+ ],
+ "require": {
+ "php": ">=8.2",
+ "symfony/ai-generic-platform": "@dev",
+ "symfony/ai-meta-platform": "@dev",
+ "symfony/ai-open-ai-platform": "@dev",
+ "symfony/ai-platform": "@dev",
+ "symfony/http-client": "^7.3|^8.0"
+ },
+ "require-dev": {
+ "phpstan/phpstan": "^2.1",
+ "phpstan/phpstan-strict-rules": "^2.0",
+ "phpunit/phpunit": "^11.5.46"
+ },
+ "minimum-stability": "dev",
+ "autoload": {
+ "psr-4": {
+ "Symfony\\AI\\Platform\\Bridge\\Azure\\": ""
+ }
+ },
+ "autoload-dev": {
+ "psr-4": {
+ "Symfony\\AI\\PHPStan\\": "../../../../../.phpstan/",
+ "Symfony\\AI\\Platform\\Bridge\\Azure\\Tests\\": "Tests/"
+ }
+ },
+ "config": {
+ "sort-packages": true
+ },
+ "extra": {
+ "branch-alias": {
+ "dev-main": "0.x-dev"
+ },
+ "thanks": {
+ "name": "symfony/ai",
+ "url": "https://github.com/symfony/ai"
+ }
+ }
+}
diff --git a/src/platform/src/Bridge/Azure/phpstan.dist.neon b/src/platform/src/Bridge/Azure/phpstan.dist.neon
new file mode 100644
index 000000000..5503dac38
--- /dev/null
+++ b/src/platform/src/Bridge/Azure/phpstan.dist.neon
@@ -0,0 +1,23 @@
+includes:
+ - ../../../../../.phpstan/extension.neon
+
+parameters:
+ level: 6
+ paths:
+ - .
+ - Tests/
+ excludePaths:
+ - vendor/
+ treatPhpDocTypesAsCertain: false
+ ignoreErrors:
+ -
+ message: "#^Method .*::test.*\\(\\) has no return type specified\\.$#"
+ reportUnmatched: false
+ -
+ identifier: missingType.iterableValue
+ path: Tests/*
+ reportUnmatched: false
+ -
+ identifier: 'symfonyAi.forbidNativeException'
+ path: Tests/*
+ reportUnmatched: false
diff --git a/src/platform/src/Bridge/Azure/phpunit.xml.dist b/src/platform/src/Bridge/Azure/phpunit.xml.dist
new file mode 100644
index 000000000..25a6d800b
--- /dev/null
+++ b/src/platform/src/Bridge/Azure/phpunit.xml.dist
@@ -0,0 +1,32 @@
+
+
+
+
+
+
+
+
+
+ ./Tests/
+
+
+
+
+
+ ./
+
+
+ ./Resources
+ ./Tests
+ ./vendor
+
+
+
diff --git a/src/platform/src/Bridge/Bedrock/README.md b/src/platform/src/Bridge/Bedrock/README.md
new file mode 100644
index 000000000..ed76288eb
--- /dev/null
+++ b/src/platform/src/Bridge/Bedrock/README.md
@@ -0,0 +1,12 @@
+Bedrock Platform
+================
+
+AWS Bedrock platform bridge for Symfony AI.
+
+Resources
+---------
+
+ * [Contributing](https://symfony.com/doc/current/contributing/index.html)
+ * [Report issues](https://github.com/symfony/ai/issues) and
+ [send Pull Requests](https://github.com/symfony/ai/pulls)
+ in the [main Symfony AI repository](https://github.com/symfony/ai)
diff --git a/src/platform/tests/Bridge/Bedrock/Anthropic/ClaudeResultConverterTest.php b/src/platform/src/Bridge/Bedrock/Tests/Anthropic/ClaudeResultConverterTest.php
similarity index 99%
rename from src/platform/tests/Bridge/Bedrock/Anthropic/ClaudeResultConverterTest.php
rename to src/platform/src/Bridge/Bedrock/Tests/Anthropic/ClaudeResultConverterTest.php
index fd26e0b16..5c5c1536e 100644
--- a/src/platform/tests/Bridge/Bedrock/Anthropic/ClaudeResultConverterTest.php
+++ b/src/platform/src/Bridge/Bedrock/Tests/Anthropic/ClaudeResultConverterTest.php
@@ -9,7 +9,7 @@
* file that was distributed with this source code.
*/
-namespace Symfony\AI\Platform\Tests\Bridge\Bedrock\Anthropic;
+namespace Symfony\AI\Platform\Bridge\Bedrock\Tests\Anthropic;
use AsyncAws\BedrockRuntime\Result\InvokeModelResponse;
use AsyncAws\Core\Test\ResultMockFactory;
diff --git a/src/platform/tests/Bridge/Bedrock/Meta/LlamaResultConverterTest.php b/src/platform/src/Bridge/Bedrock/Tests/Meta/LlamaResultConverterTest.php
similarity index 99%
rename from src/platform/tests/Bridge/Bedrock/Meta/LlamaResultConverterTest.php
rename to src/platform/src/Bridge/Bedrock/Tests/Meta/LlamaResultConverterTest.php
index 97c392da8..9964ce30d 100644
--- a/src/platform/tests/Bridge/Bedrock/Meta/LlamaResultConverterTest.php
+++ b/src/platform/src/Bridge/Bedrock/Tests/Meta/LlamaResultConverterTest.php
@@ -9,7 +9,7 @@
* file that was distributed with this source code.
*/
-namespace Symfony\AI\Platform\Tests\Bridge\Bedrock\Meta;
+namespace Symfony\AI\Platform\Bridge\Bedrock\Tests\Meta;
use AsyncAws\BedrockRuntime\Result\InvokeModelResponse;
use AsyncAws\Core\Test\ResultMockFactory;
diff --git a/src/platform/tests/Bridge/Bedrock/ModelCatalogTest.php b/src/platform/src/Bridge/Bedrock/Tests/ModelCatalogTest.php
similarity index 97%
rename from src/platform/tests/Bridge/Bedrock/ModelCatalogTest.php
rename to src/platform/src/Bridge/Bedrock/Tests/ModelCatalogTest.php
index afaf68ad2..ada8f6e33 100644
--- a/src/platform/tests/Bridge/Bedrock/ModelCatalogTest.php
+++ b/src/platform/src/Bridge/Bedrock/Tests/ModelCatalogTest.php
@@ -9,7 +9,7 @@
* file that was distributed with this source code.
*/
-namespace Symfony\AI\Platform\Tests\Bridge\Bedrock;
+namespace Symfony\AI\Platform\Bridge\Bedrock\Tests;
use Symfony\AI\Platform\Bridge\Anthropic\Claude;
use Symfony\AI\Platform\Bridge\Bedrock\ModelCatalog;
diff --git a/src/platform/tests/Bridge/Bedrock/Nova/ContractTest.php b/src/platform/src/Bridge/Bedrock/Tests/Nova/ContractTest.php
similarity index 98%
rename from src/platform/tests/Bridge/Bedrock/Nova/ContractTest.php
rename to src/platform/src/Bridge/Bedrock/Tests/Nova/ContractTest.php
index 505fa3483..33a285fe3 100644
--- a/src/platform/tests/Bridge/Bedrock/Nova/ContractTest.php
+++ b/src/platform/src/Bridge/Bedrock/Tests/Nova/ContractTest.php
@@ -9,7 +9,7 @@
* file that was distributed with this source code.
*/
-namespace Symfony\AI\Platform\Tests\Bridge\Bedrock\Nova;
+namespace Symfony\AI\Platform\Bridge\Bedrock\Tests\Nova;
use PHPUnit\Framework\Attributes\DataProvider;
use PHPUnit\Framework\TestCase;
diff --git a/src/platform/tests/Bridge/Bedrock/Nova/NovaResultConverterTest.php b/src/platform/src/Bridge/Bedrock/Tests/Nova/NovaResultConverterTest.php
similarity index 99%
rename from src/platform/tests/Bridge/Bedrock/Nova/NovaResultConverterTest.php
rename to src/platform/src/Bridge/Bedrock/Tests/Nova/NovaResultConverterTest.php
index 34e8900cf..897c6dc86 100644
--- a/src/platform/tests/Bridge/Bedrock/Nova/NovaResultConverterTest.php
+++ b/src/platform/src/Bridge/Bedrock/Tests/Nova/NovaResultConverterTest.php
@@ -9,7 +9,7 @@
* file that was distributed with this source code.
*/
-namespace Symfony\AI\Platform\Tests\Bridge\Bedrock\Nova;
+namespace Symfony\AI\Platform\Bridge\Bedrock\Tests\Nova;
use AsyncAws\BedrockRuntime\Result\InvokeModelResponse;
use AsyncAws\Core\Test\ResultMockFactory;
diff --git a/src/platform/src/Bridge/Bedrock/composer.json b/src/platform/src/Bridge/Bedrock/composer.json
new file mode 100644
index 000000000..9775023b6
--- /dev/null
+++ b/src/platform/src/Bridge/Bedrock/composer.json
@@ -0,0 +1,63 @@
+{
+ "name": "symfony/ai-bedrock-platform",
+ "description": "AWS Bedrock platform bridge for Symfony AI",
+ "license": "MIT",
+ "type": "symfony-ai-platform",
+ "keywords": [
+ "ai",
+ "aws",
+ "bedrock",
+ "bridge",
+ "platform"
+ ],
+ "authors": [
+ {
+ "name": "Christopher Hertel",
+ "email": "mail@christopher-hertel.de"
+ },
+ {
+ "name": "Oskar Stark",
+ "email": "oskarstark@googlemail.com"
+ },
+ {
+ "name": "Symfony Community",
+ "homepage": "https://symfony.com/contributors"
+ }
+ ],
+ "require": {
+ "async-aws/bedrock-runtime": "^0.1|^1.0",
+ "php": ">=8.2",
+ "symfony/ai-anthropic-platform": "@dev",
+ "symfony/ai-meta-platform": "@dev",
+ "symfony/ai-platform": "@dev"
+ },
+ "require-dev": {
+ "phpstan/phpstan": "^2.1",
+ "phpstan/phpstan-strict-rules": "^2.0",
+ "phpunit/phpunit": "^11.5.46"
+ },
+ "minimum-stability": "dev",
+ "autoload": {
+ "psr-4": {
+ "Symfony\\AI\\Platform\\Bridge\\Bedrock\\": ""
+ }
+ },
+ "autoload-dev": {
+ "psr-4": {
+ "Symfony\\AI\\PHPStan\\": "../../../../../.phpstan/",
+ "Symfony\\AI\\Platform\\Bridge\\Bedrock\\Tests\\": "Tests/"
+ }
+ },
+ "config": {
+ "sort-packages": true
+ },
+ "extra": {
+ "branch-alias": {
+ "dev-main": "0.x-dev"
+ },
+ "thanks": {
+ "name": "symfony/ai",
+ "url": "https://github.com/symfony/ai"
+ }
+ }
+}
diff --git a/src/platform/src/Bridge/Bedrock/phpstan.dist.neon b/src/platform/src/Bridge/Bedrock/phpstan.dist.neon
new file mode 100644
index 000000000..5503dac38
--- /dev/null
+++ b/src/platform/src/Bridge/Bedrock/phpstan.dist.neon
@@ -0,0 +1,23 @@
+includes:
+ - ../../../../../.phpstan/extension.neon
+
+parameters:
+ level: 6
+ paths:
+ - .
+ - Tests/
+ excludePaths:
+ - vendor/
+ treatPhpDocTypesAsCertain: false
+ ignoreErrors:
+ -
+ message: "#^Method .*::test.*\\(\\) has no return type specified\\.$#"
+ reportUnmatched: false
+ -
+ identifier: missingType.iterableValue
+ path: Tests/*
+ reportUnmatched: false
+ -
+ identifier: 'symfonyAi.forbidNativeException'
+ path: Tests/*
+ reportUnmatched: false
diff --git a/src/platform/src/Bridge/Bedrock/phpunit.xml.dist b/src/platform/src/Bridge/Bedrock/phpunit.xml.dist
new file mode 100644
index 000000000..b3e1c8b2b
--- /dev/null
+++ b/src/platform/src/Bridge/Bedrock/phpunit.xml.dist
@@ -0,0 +1,32 @@
+
+
+
+
+
+
+
+
+
+ ./Tests/
+
+
+
+
+
+ ./
+
+
+ ./Resources
+ ./Tests
+ ./vendor
+
+
+
diff --git a/src/platform/src/Bridge/Cartesia/README.md b/src/platform/src/Bridge/Cartesia/README.md
new file mode 100644
index 000000000..9c9d3fcf4
--- /dev/null
+++ b/src/platform/src/Bridge/Cartesia/README.md
@@ -0,0 +1,12 @@
+Cartesia Platform
+=================
+
+Cartesia platform bridge for Symfony AI.
+
+Resources
+---------
+
+ * [Contributing](https://symfony.com/doc/current/contributing/index.html)
+ * [Report issues](https://github.com/symfony/ai/issues) and
+ [send Pull Requests](https://github.com/symfony/ai/pulls)
+ in the [main Symfony AI repository](https://github.com/symfony/ai)
diff --git a/src/platform/tests/Bridge/Cartesia/CartesiaClientTest.php b/src/platform/src/Bridge/Cartesia/Tests/CartesiaClientTest.php
similarity index 95%
rename from src/platform/tests/Bridge/Cartesia/CartesiaClientTest.php
rename to src/platform/src/Bridge/Cartesia/Tests/CartesiaClientTest.php
index 6ae2e3045..271022a61 100644
--- a/src/platform/tests/Bridge/Cartesia/CartesiaClientTest.php
+++ b/src/platform/src/Bridge/Cartesia/Tests/CartesiaClientTest.php
@@ -9,7 +9,7 @@
* file that was distributed with this source code.
*/
-namespace Symfony\AI\Platform\Tests\Bridge\Cartesia;
+namespace Symfony\AI\Platform\Bridge\Cartesia\Tests;
use PHPUnit\Framework\TestCase;
use Symfony\AI\Platform\Bridge\Cartesia\Cartesia;
@@ -87,7 +87,7 @@ public function testClientCannotPerformTextToSpeechOnInvalidResponse()
public function testClientCanPerformTextToSpeech()
{
- $payload = Audio::fromFile(\dirname(__DIR__, 5).'/fixtures/audio.mp3');
+ $payload = Audio::fromFile(\dirname(__DIR__, 6).'/fixtures/audio.mp3');
$httpClient = new MockHttpClient([
new MockResponse($payload->asBinary()),
@@ -115,7 +115,7 @@ public function testClientCanPerformTextToSpeech()
public function testClientCannotPerformSpeechToTextOnInvalidResponse()
{
- $payload = Audio::fromFile(\dirname(__DIR__, 2).'/Fixtures/audio.mp3');
+ $payload = Audio::fromFile(\dirname(__DIR__, 6).'/fixtures/audio.mp3');
$normalizer = new AudioNormalizer();
@@ -141,7 +141,7 @@ public function testClientCannotPerformSpeechToTextOnInvalidResponse()
public function testClientCanPerformSpeechToText()
{
- $payload = Audio::fromFile(\dirname(__DIR__, 2).'/Fixtures/audio.mp3');
+ $payload = Audio::fromFile(\dirname(__DIR__, 6).'/fixtures/audio.mp3');
$normalizer = new AudioNormalizer();
diff --git a/src/platform/tests/Bridge/Cartesia/CartesiaResultConverterTest.php b/src/platform/src/Bridge/Cartesia/Tests/CartesiaResultConverterTest.php
similarity index 94%
rename from src/platform/tests/Bridge/Cartesia/CartesiaResultConverterTest.php
rename to src/platform/src/Bridge/Cartesia/Tests/CartesiaResultConverterTest.php
index c1ea9917d..da051c9dd 100644
--- a/src/platform/tests/Bridge/Cartesia/CartesiaResultConverterTest.php
+++ b/src/platform/src/Bridge/Cartesia/Tests/CartesiaResultConverterTest.php
@@ -9,7 +9,7 @@
* file that was distributed with this source code.
*/
-namespace Symfony\AI\Platform\Tests\Bridge\Cartesia;
+namespace Symfony\AI\Platform\Bridge\Cartesia\Tests;
use PHPUnit\Framework\TestCase;
use Symfony\AI\Platform\Bridge\Cartesia\Cartesia;
@@ -58,7 +58,7 @@ public function getInfo(): string
public function getContent(): string
{
- return file_get_contents(\dirname(__DIR__, 5).'/fixtures/audio.mp3');
+ return file_get_contents(\dirname(__DIR__, 6).'/fixtures/audio.mp3');
}
});
diff --git a/src/platform/tests/Bridge/Cartesia/Contract/CartesiaContractTest.php b/src/platform/src/Bridge/Cartesia/Tests/Contract/CartesiaContractTest.php
similarity index 88%
rename from src/platform/tests/Bridge/Cartesia/Contract/CartesiaContractTest.php
rename to src/platform/src/Bridge/Cartesia/Tests/Contract/CartesiaContractTest.php
index ce691da92..8e8d09615 100644
--- a/src/platform/tests/Bridge/Cartesia/Contract/CartesiaContractTest.php
+++ b/src/platform/src/Bridge/Cartesia/Tests/Contract/CartesiaContractTest.php
@@ -9,7 +9,7 @@
* file that was distributed with this source code.
*/
-namespace Symfony\AI\Platform\Tests\Bridge\Cartesia\Contract;
+namespace Symfony\AI\Platform\Bridge\Cartesia\Tests\Contract;
use PHPUnit\Framework\TestCase;
use Symfony\AI\Platform\Bridge\Cartesia\Cartesia;
@@ -20,7 +20,7 @@ final class CartesiaContractTest extends TestCase
{
public function testItCanCreatePayloadWithAudio()
{
- $audio = Audio::fromFile(\dirname(__DIR__, 6).'/fixtures/audio.mp3');
+ $audio = Audio::fromFile(\dirname(__DIR__, 7).'/fixtures/audio.mp3');
$contract = CartesiaContract::create();
diff --git a/src/platform/tests/Bridge/Cartesia/ModelCatalogTest.php b/src/platform/src/Bridge/Cartesia/Tests/ModelCatalogTest.php
similarity index 94%
rename from src/platform/tests/Bridge/Cartesia/ModelCatalogTest.php
rename to src/platform/src/Bridge/Cartesia/Tests/ModelCatalogTest.php
index 80930d525..cc81c1b92 100644
--- a/src/platform/tests/Bridge/Cartesia/ModelCatalogTest.php
+++ b/src/platform/src/Bridge/Cartesia/Tests/ModelCatalogTest.php
@@ -9,7 +9,7 @@
* file that was distributed with this source code.
*/
-namespace Symfony\AI\Platform\Tests\Bridge\Cartesia;
+namespace Symfony\AI\Platform\Bridge\Cartesia\Tests;
use Symfony\AI\Platform\Bridge\Cartesia\Cartesia;
use Symfony\AI\Platform\Bridge\Cartesia\ModelCatalog;
diff --git a/src/platform/src/Bridge/Cartesia/composer.json b/src/platform/src/Bridge/Cartesia/composer.json
new file mode 100644
index 000000000..6392f3394
--- /dev/null
+++ b/src/platform/src/Bridge/Cartesia/composer.json
@@ -0,0 +1,61 @@
+{
+ "name": "symfony/ai-cartesia-platform",
+ "description": "Cartesia platform bridge for Symfony AI",
+ "license": "MIT",
+ "type": "symfony-ai-platform",
+ "keywords": [
+ "ai",
+ "bridge",
+ "cartesia",
+ "platform",
+ "voice"
+ ],
+ "authors": [
+ {
+ "name": "Christopher Hertel",
+ "email": "mail@christopher-hertel.de"
+ },
+ {
+ "name": "Oskar Stark",
+ "email": "oskarstark@googlemail.com"
+ },
+ {
+ "name": "Symfony Community",
+ "homepage": "https://symfony.com/contributors"
+ }
+ ],
+ "require": {
+ "php": ">=8.2",
+ "symfony/ai-platform": "@dev",
+ "symfony/http-client": "^7.3|^8.0"
+ },
+ "require-dev": {
+ "phpstan/phpstan": "^2.1",
+ "phpstan/phpstan-strict-rules": "^2.0",
+ "phpunit/phpunit": "^11.5.46"
+ },
+ "minimum-stability": "dev",
+ "autoload": {
+ "psr-4": {
+ "Symfony\\AI\\Platform\\Bridge\\Cartesia\\": ""
+ }
+ },
+ "autoload-dev": {
+ "psr-4": {
+ "Symfony\\AI\\PHPStan\\": "../../../../../.phpstan/",
+ "Symfony\\AI\\Platform\\Bridge\\Cartesia\\Tests\\": "Tests/"
+ }
+ },
+ "config": {
+ "sort-packages": true
+ },
+ "extra": {
+ "branch-alias": {
+ "dev-main": "0.x-dev"
+ },
+ "thanks": {
+ "name": "symfony/ai",
+ "url": "https://github.com/symfony/ai"
+ }
+ }
+}
diff --git a/src/platform/src/Bridge/Cartesia/phpstan.dist.neon b/src/platform/src/Bridge/Cartesia/phpstan.dist.neon
new file mode 100644
index 000000000..5503dac38
--- /dev/null
+++ b/src/platform/src/Bridge/Cartesia/phpstan.dist.neon
@@ -0,0 +1,23 @@
+includes:
+ - ../../../../../.phpstan/extension.neon
+
+parameters:
+ level: 6
+ paths:
+ - .
+ - Tests/
+ excludePaths:
+ - vendor/
+ treatPhpDocTypesAsCertain: false
+ ignoreErrors:
+ -
+ message: "#^Method .*::test.*\\(\\) has no return type specified\\.$#"
+ reportUnmatched: false
+ -
+ identifier: missingType.iterableValue
+ path: Tests/*
+ reportUnmatched: false
+ -
+ identifier: 'symfonyAi.forbidNativeException'
+ path: Tests/*
+ reportUnmatched: false
diff --git a/src/platform/src/Bridge/Cartesia/phpunit.xml.dist b/src/platform/src/Bridge/Cartesia/phpunit.xml.dist
new file mode 100644
index 000000000..bab284a12
--- /dev/null
+++ b/src/platform/src/Bridge/Cartesia/phpunit.xml.dist
@@ -0,0 +1,32 @@
+
+
+
+
+
+
+
+
+
+ ./Tests/
+
+
+
+
+
+ ./
+
+
+ ./Resources
+ ./Tests
+ ./vendor
+
+
+
diff --git a/src/platform/src/Bridge/Cerebras/README.md b/src/platform/src/Bridge/Cerebras/README.md
new file mode 100644
index 000000000..21182aa74
--- /dev/null
+++ b/src/platform/src/Bridge/Cerebras/README.md
@@ -0,0 +1,12 @@
+Cerebras Platform
+=================
+
+Cerebras platform bridge for Symfony AI.
+
+Resources
+---------
+
+ * [Contributing](https://symfony.com/doc/current/contributing/index.html)
+ * [Report issues](https://github.com/symfony/ai/issues) and
+ [send Pull Requests](https://github.com/symfony/ai/pulls)
+ in the [main Symfony AI repository](https://github.com/symfony/ai)
diff --git a/src/platform/tests/Bridge/Cerebras/ModelCatalogTest.php b/src/platform/src/Bridge/Cerebras/Tests/ModelCatalogTest.php
similarity index 97%
rename from src/platform/tests/Bridge/Cerebras/ModelCatalogTest.php
rename to src/platform/src/Bridge/Cerebras/Tests/ModelCatalogTest.php
index 0da88e1d9..b73c3dc08 100644
--- a/src/platform/tests/Bridge/Cerebras/ModelCatalogTest.php
+++ b/src/platform/src/Bridge/Cerebras/Tests/ModelCatalogTest.php
@@ -9,7 +9,7 @@
* file that was distributed with this source code.
*/
-namespace Symfony\AI\Platform\Tests\Bridge\Cerebras;
+namespace Symfony\AI\Platform\Bridge\Cerebras\Tests;
use Symfony\AI\Platform\Bridge\Cerebras\ModelCatalog;
use Symfony\AI\Platform\Capability;
diff --git a/src/platform/tests/Bridge/Cerebras/ModelClientTest.php b/src/platform/src/Bridge/Cerebras/Tests/ModelClientTest.php
similarity index 98%
rename from src/platform/tests/Bridge/Cerebras/ModelClientTest.php
rename to src/platform/src/Bridge/Cerebras/Tests/ModelClientTest.php
index f420dde73..f397da2e6 100644
--- a/src/platform/tests/Bridge/Cerebras/ModelClientTest.php
+++ b/src/platform/src/Bridge/Cerebras/Tests/ModelClientTest.php
@@ -9,7 +9,7 @@
* file that was distributed with this source code.
*/
-namespace Symfony\AI\Platform\Tests\Bridge\Cerebras;
+namespace Symfony\AI\Platform\Bridge\Cerebras\Tests;
use PHPUnit\Framework\Attributes\TestWith;
use PHPUnit\Framework\TestCase;
diff --git a/src/platform/tests/Bridge/Cerebras/ResultConverterTest.php b/src/platform/src/Bridge/Cerebras/Tests/ResultConverterTest.php
similarity index 93%
rename from src/platform/tests/Bridge/Cerebras/ResultConverterTest.php
rename to src/platform/src/Bridge/Cerebras/Tests/ResultConverterTest.php
index 864e14aef..8ee372f77 100644
--- a/src/platform/tests/Bridge/Cerebras/ResultConverterTest.php
+++ b/src/platform/src/Bridge/Cerebras/Tests/ResultConverterTest.php
@@ -9,7 +9,7 @@
* file that was distributed with this source code.
*/
-namespace Symfony\AI\Platform\Tests\Bridge\Cerebras;
+namespace Symfony\AI\Platform\Bridge\Cerebras\Tests;
use PHPUnit\Framework\TestCase;
use Symfony\AI\Platform\Bridge\Cerebras\Model;
diff --git a/src/platform/src/Bridge/Cerebras/composer.json b/src/platform/src/Bridge/Cerebras/composer.json
new file mode 100644
index 000000000..7bbd0b99b
--- /dev/null
+++ b/src/platform/src/Bridge/Cerebras/composer.json
@@ -0,0 +1,60 @@
+{
+ "name": "symfony/ai-cerebras-platform",
+ "description": "Cerebras platform bridge for Symfony AI",
+ "license": "MIT",
+ "type": "symfony-ai-platform",
+ "keywords": [
+ "ai",
+ "bridge",
+ "cerebras",
+ "platform"
+ ],
+ "authors": [
+ {
+ "name": "Christopher Hertel",
+ "email": "mail@christopher-hertel.de"
+ },
+ {
+ "name": "Oskar Stark",
+ "email": "oskarstark@googlemail.com"
+ },
+ {
+ "name": "Symfony Community",
+ "homepage": "https://symfony.com/contributors"
+ }
+ ],
+ "require": {
+ "php": ">=8.2",
+ "symfony/ai-platform": "@dev",
+ "symfony/http-client": "^7.3|^8.0"
+ },
+ "require-dev": {
+ "phpstan/phpstan": "^2.1",
+ "phpstan/phpstan-strict-rules": "^2.0",
+ "phpunit/phpunit": "^11.5.46"
+ },
+ "minimum-stability": "dev",
+ "autoload": {
+ "psr-4": {
+ "Symfony\\AI\\Platform\\Bridge\\Cerebras\\": ""
+ }
+ },
+ "autoload-dev": {
+ "psr-4": {
+ "Symfony\\AI\\PHPStan\\": "../../../../../.phpstan/",
+ "Symfony\\AI\\Platform\\Bridge\\Cerebras\\Tests\\": "Tests/"
+ }
+ },
+ "config": {
+ "sort-packages": true
+ },
+ "extra": {
+ "branch-alias": {
+ "dev-main": "0.x-dev"
+ },
+ "thanks": {
+ "name": "symfony/ai",
+ "url": "https://github.com/symfony/ai"
+ }
+ }
+}
diff --git a/src/platform/src/Bridge/Cerebras/phpstan.dist.neon b/src/platform/src/Bridge/Cerebras/phpstan.dist.neon
new file mode 100644
index 000000000..5503dac38
--- /dev/null
+++ b/src/platform/src/Bridge/Cerebras/phpstan.dist.neon
@@ -0,0 +1,23 @@
+includes:
+ - ../../../../../.phpstan/extension.neon
+
+parameters:
+ level: 6
+ paths:
+ - .
+ - Tests/
+ excludePaths:
+ - vendor/
+ treatPhpDocTypesAsCertain: false
+ ignoreErrors:
+ -
+ message: "#^Method .*::test.*\\(\\) has no return type specified\\.$#"
+ reportUnmatched: false
+ -
+ identifier: missingType.iterableValue
+ path: Tests/*
+ reportUnmatched: false
+ -
+ identifier: 'symfonyAi.forbidNativeException'
+ path: Tests/*
+ reportUnmatched: false
diff --git a/src/platform/src/Bridge/Cerebras/phpunit.xml.dist b/src/platform/src/Bridge/Cerebras/phpunit.xml.dist
new file mode 100644
index 000000000..e59d59ed4
--- /dev/null
+++ b/src/platform/src/Bridge/Cerebras/phpunit.xml.dist
@@ -0,0 +1,32 @@
+
+
+
+
+
+
+
+
+
+ ./Tests/
+
+
+
+
+
+ ./
+
+
+ ./Resources
+ ./Tests
+ ./vendor
+
+
+
diff --git a/src/platform/src/Bridge/Decart/README.md b/src/platform/src/Bridge/Decart/README.md
new file mode 100644
index 000000000..e0f480ae8
--- /dev/null
+++ b/src/platform/src/Bridge/Decart/README.md
@@ -0,0 +1,12 @@
+Decart Platform
+===============
+
+Decart platform bridge for Symfony AI.
+
+Resources
+---------
+
+ * [Contributing](https://symfony.com/doc/current/contributing/index.html)
+ * [Report issues](https://github.com/symfony/ai/issues) and
+ [send Pull Requests](https://github.com/symfony/ai/pulls)
+ in the [main Symfony AI repository](https://github.com/symfony/ai)
diff --git a/src/platform/tests/Bridge/Decart/Contract/DecartContractTest.php b/src/platform/src/Bridge/Decart/Tests/Contract/DecartContractTest.php
similarity index 88%
rename from src/platform/tests/Bridge/Decart/Contract/DecartContractTest.php
rename to src/platform/src/Bridge/Decart/Tests/Contract/DecartContractTest.php
index 4dbec2e3a..ad8bed38a 100644
--- a/src/platform/tests/Bridge/Decart/Contract/DecartContractTest.php
+++ b/src/platform/src/Bridge/Decart/Tests/Contract/DecartContractTest.php
@@ -9,7 +9,7 @@
* file that was distributed with this source code.
*/
-namespace Symfony\AI\Platform\Tests\Bridge\Decart\Contract;
+namespace Symfony\AI\Platform\Bridge\Decart\Tests\Contract;
use PHPUnit\Framework\TestCase;
use Symfony\AI\Platform\Bridge\Decart\Contract\DecartContract;
@@ -21,7 +21,7 @@ final class DecartContractTest extends TestCase
{
public function testItCanCreatePayloadWithImage()
{
- $image = Image::fromFile(\dirname(__DIR__, 6).'/fixtures/image.jpg');
+ $image = Image::fromFile(\dirname(__DIR__, 7).'/fixtures/image.jpg');
$contract = DecartContract::create();
@@ -39,7 +39,7 @@ public function testItCanCreatePayloadWithImage()
public function testItCanCreatePayloadWithVideo()
{
- $image = Video::fromFile(\dirname(__DIR__, 6).'/fixtures/ocean.mp4');
+ $image = Video::fromFile(\dirname(__DIR__, 7).'/fixtures/ocean.mp4');
$contract = DecartContract::create();
diff --git a/src/platform/tests/Bridge/Decart/DecartClientTest.php b/src/platform/src/Bridge/Decart/Tests/DecartClientTest.php
similarity index 78%
rename from src/platform/tests/Bridge/Decart/DecartClientTest.php
rename to src/platform/src/Bridge/Decart/Tests/DecartClientTest.php
index 13ae8e019..1f833a159 100644
--- a/src/platform/tests/Bridge/Decart/DecartClientTest.php
+++ b/src/platform/src/Bridge/Decart/Tests/DecartClientTest.php
@@ -9,7 +9,7 @@
* file that was distributed with this source code.
*/
-namespace Symfony\AI\Platform\Tests\Bridge\Decart;
+namespace Symfony\AI\Platform\Bridge\Decart\Tests;
use PHPUnit\Framework\TestCase;
use Symfony\AI\Platform\Bridge\Decart\Contract\ImageNormalizer;
@@ -52,12 +52,10 @@ public function testClientCannotGenerateOnInvalidModel()
public function testClientCanGenerateTextToImage()
{
- $normalizer = new ImageNormalizer();
-
- $payload = $normalizer->normalize(Image::fromFile(\dirname(__DIR__, 5).'/fixtures/image.jpg'));
+ $imageContent = file_get_contents(\dirname(__DIR__, 6).'/fixtures/image.jpg');
$httpClient = new MockHttpClient([
- new MockResponse($payload),
+ new MockResponse($imageContent, ['response_headers' => ['content-type' => 'image/jpeg']]),
]);
$client = new DecartClient(
@@ -74,12 +72,10 @@ public function testClientCanGenerateTextToImage()
public function testClientCanGenerateTextToVideo()
{
- $normalizer = new VideoNormalizer();
-
- $payload = $normalizer->normalize(Video::fromFile(\dirname(__DIR__, 5).'/fixtures/ocean.mp4'));
+ $videoContent = file_get_contents(\dirname(__DIR__, 6).'/fixtures/ocean.mp4');
$httpClient = new MockHttpClient([
- new MockResponse($payload),
+ new MockResponse($videoContent, ['response_headers' => ['content-type' => 'video/mp4']]),
]);
$client = new DecartClient(
@@ -97,11 +93,12 @@ public function testClientCanGenerateTextToVideo()
public function testClientCanGenerateImageToImage()
{
$normalizer = new ImageNormalizer();
+ $imageContent = file_get_contents(\dirname(__DIR__, 6).'/fixtures/image.jpg');
- $payload = $normalizer->normalize(Image::fromFile(\dirname(__DIR__, 5).'/fixtures/image.jpg'));
+ $payload = $normalizer->normalize(Image::fromFile(\dirname(__DIR__, 6).'/fixtures/image.jpg'));
$httpClient = new MockHttpClient([
- new MockResponse($payload),
+ new MockResponse($imageContent, ['response_headers' => ['content-type' => 'image/jpeg']]),
]);
$client = new DecartClient(
@@ -119,13 +116,12 @@ public function testClientCanGenerateImageToImage()
public function testClientCanGenerateImageToVideo()
{
$normalizer = new ImageNormalizer();
- $videoNormalizer = new VideoNormalizer();
+ $videoContent = file_get_contents(\dirname(__DIR__, 6).'/fixtures/ocean.mp4');
- $payload = $normalizer->normalize(Image::fromFile(\dirname(__DIR__, 5).'/fixtures/image.jpg'));
- $responsePayload = $videoNormalizer->normalize(Video::fromFile(\dirname(__DIR__, 5).'/fixtures/ocean.mp4'));
+ $payload = $normalizer->normalize(Image::fromFile(\dirname(__DIR__, 6).'/fixtures/image.jpg'));
$httpClient = new MockHttpClient([
- new MockResponse($responsePayload),
+ new MockResponse($videoContent, ['response_headers' => ['content-type' => 'video/mp4']]),
]);
$client = new DecartClient(
@@ -143,11 +139,12 @@ public function testClientCanGenerateImageToVideo()
public function testClientCanGenerateVideoToVideo()
{
$normalizer = new VideoNormalizer();
+ $videoContent = file_get_contents(\dirname(__DIR__, 6).'/fixtures/ocean.mp4');
- $payload = $normalizer->normalize(Video::fromFile(\dirname(__DIR__, 5).'/fixtures/ocean.mp4'));
+ $payload = $normalizer->normalize(Video::fromFile(\dirname(__DIR__, 6).'/fixtures/ocean.mp4'));
$httpClient = new MockHttpClient([
- new MockResponse($payload),
+ new MockResponse($videoContent, ['response_headers' => ['content-type' => 'video/mp4']]),
]);
$client = new DecartClient(
diff --git a/src/platform/tests/Bridge/Decart/ModelCatalogTest.php b/src/platform/src/Bridge/Decart/Tests/ModelCatalogTest.php
similarity index 96%
rename from src/platform/tests/Bridge/Decart/ModelCatalogTest.php
rename to src/platform/src/Bridge/Decart/Tests/ModelCatalogTest.php
index cc28f99d3..df6bcaef8 100644
--- a/src/platform/tests/Bridge/Decart/ModelCatalogTest.php
+++ b/src/platform/src/Bridge/Decart/Tests/ModelCatalogTest.php
@@ -9,7 +9,7 @@
* file that was distributed with this source code.
*/
-namespace Symfony\AI\Platform\Tests\Bridge\Decart;
+namespace Symfony\AI\Platform\Bridge\Decart\Tests;
use Symfony\AI\Platform\Bridge\Decart\Decart;
use Symfony\AI\Platform\Bridge\Decart\ModelCatalog;
diff --git a/src/platform/src/Bridge/Decart/composer.json b/src/platform/src/Bridge/Decart/composer.json
new file mode 100644
index 000000000..f3fb49c0e
--- /dev/null
+++ b/src/platform/src/Bridge/Decart/composer.json
@@ -0,0 +1,62 @@
+{
+ "name": "symfony/ai-decart-platform",
+ "description": "Decart platform bridge for Symfony AI",
+ "license": "MIT",
+ "type": "symfony-ai-platform",
+ "keywords": [
+ "ai",
+ "bridge",
+ "decart",
+ "image",
+ "platform",
+ "video"
+ ],
+ "authors": [
+ {
+ "name": "Christopher Hertel",
+ "email": "mail@christopher-hertel.de"
+ },
+ {
+ "name": "Oskar Stark",
+ "email": "oskarstark@googlemail.com"
+ },
+ {
+ "name": "Symfony Community",
+ "homepage": "https://symfony.com/contributors"
+ }
+ ],
+ "require": {
+ "php": ">=8.2",
+ "symfony/ai-platform": "@dev",
+ "symfony/http-client": "^7.3|^8.0"
+ },
+ "require-dev": {
+ "phpstan/phpstan": "^2.1",
+ "phpstan/phpstan-strict-rules": "^2.0",
+ "phpunit/phpunit": "^11.5.46"
+ },
+ "minimum-stability": "dev",
+ "autoload": {
+ "psr-4": {
+ "Symfony\\AI\\Platform\\Bridge\\Decart\\": ""
+ }
+ },
+ "autoload-dev": {
+ "psr-4": {
+ "Symfony\\AI\\PHPStan\\": "../../../../../.phpstan/",
+ "Symfony\\AI\\Platform\\Bridge\\Decart\\Tests\\": "Tests/"
+ }
+ },
+ "config": {
+ "sort-packages": true
+ },
+ "extra": {
+ "branch-alias": {
+ "dev-main": "0.x-dev"
+ },
+ "thanks": {
+ "name": "symfony/ai",
+ "url": "https://github.com/symfony/ai"
+ }
+ }
+}
diff --git a/src/platform/src/Bridge/Decart/phpstan.dist.neon b/src/platform/src/Bridge/Decart/phpstan.dist.neon
new file mode 100644
index 000000000..5503dac38
--- /dev/null
+++ b/src/platform/src/Bridge/Decart/phpstan.dist.neon
@@ -0,0 +1,23 @@
+includes:
+ - ../../../../../.phpstan/extension.neon
+
+parameters:
+ level: 6
+ paths:
+ - .
+ - Tests/
+ excludePaths:
+ - vendor/
+ treatPhpDocTypesAsCertain: false
+ ignoreErrors:
+ -
+ message: "#^Method .*::test.*\\(\\) has no return type specified\\.$#"
+ reportUnmatched: false
+ -
+ identifier: missingType.iterableValue
+ path: Tests/*
+ reportUnmatched: false
+ -
+ identifier: 'symfonyAi.forbidNativeException'
+ path: Tests/*
+ reportUnmatched: false
diff --git a/src/platform/src/Bridge/Decart/phpunit.xml.dist b/src/platform/src/Bridge/Decart/phpunit.xml.dist
new file mode 100644
index 000000000..db434eb2f
--- /dev/null
+++ b/src/platform/src/Bridge/Decart/phpunit.xml.dist
@@ -0,0 +1,32 @@
+
+
+
+
+
+
+
+
+
+ ./Tests/
+
+
+
+
+
+ ./
+
+
+ ./Resources
+ ./Tests
+ ./vendor
+
+
+
diff --git a/src/platform/src/Bridge/DeepSeek/README.md b/src/platform/src/Bridge/DeepSeek/README.md
new file mode 100644
index 000000000..5fd5e5c89
--- /dev/null
+++ b/src/platform/src/Bridge/DeepSeek/README.md
@@ -0,0 +1,12 @@
+DeepSeek Platform
+=================
+
+DeepSeek platform bridge for Symfony AI.
+
+Resources
+---------
+
+ * [Contributing](https://symfony.com/doc/current/contributing/index.html)
+ * [Report issues](https://github.com/symfony/ai/issues) and
+ [send Pull Requests](https://github.com/symfony/ai/pulls)
+ in the [main Symfony AI repository](https://github.com/symfony/ai)
diff --git a/src/platform/tests/Bridge/DeepSeek/DeepSeekTest.php b/src/platform/src/Bridge/DeepSeek/Tests/DeepSeekTest.php
similarity index 95%
rename from src/platform/tests/Bridge/DeepSeek/DeepSeekTest.php
rename to src/platform/src/Bridge/DeepSeek/Tests/DeepSeekTest.php
index 988dd2f77..141ce2ccd 100644
--- a/src/platform/tests/Bridge/DeepSeek/DeepSeekTest.php
+++ b/src/platform/src/Bridge/DeepSeek/Tests/DeepSeekTest.php
@@ -9,7 +9,7 @@
* file that was distributed with this source code.
*/
-namespace Symfony\AI\Platform\Tests\Bridge\DeepSeek;
+namespace Symfony\AI\Platform\Bridge\DeepSeek\Tests;
use PHPUnit\Framework\TestCase;
use Symfony\AI\Platform\Bridge\DeepSeek\DeepSeek;
diff --git a/src/platform/tests/Bridge/DeepSeek/ModelCatalogTest.php b/src/platform/src/Bridge/DeepSeek/Tests/ModelCatalogTest.php
similarity index 95%
rename from src/platform/tests/Bridge/DeepSeek/ModelCatalogTest.php
rename to src/platform/src/Bridge/DeepSeek/Tests/ModelCatalogTest.php
index 436b7c440..86f7e5358 100644
--- a/src/platform/tests/Bridge/DeepSeek/ModelCatalogTest.php
+++ b/src/platform/src/Bridge/DeepSeek/Tests/ModelCatalogTest.php
@@ -9,7 +9,7 @@
* file that was distributed with this source code.
*/
-namespace Symfony\AI\Platform\Tests\Bridge\DeepSeek;
+namespace Symfony\AI\Platform\Bridge\DeepSeek\Tests;
use Symfony\AI\Platform\Bridge\DeepSeek\DeepSeek;
use Symfony\AI\Platform\Bridge\DeepSeek\ModelCatalog;
diff --git a/src/platform/tests/Bridge/DeepSeek/ModelClientTest.php b/src/platform/src/Bridge/DeepSeek/Tests/ModelClientTest.php
similarity index 98%
rename from src/platform/tests/Bridge/DeepSeek/ModelClientTest.php
rename to src/platform/src/Bridge/DeepSeek/Tests/ModelClientTest.php
index 904ea0e87..85dd72c25 100644
--- a/src/platform/tests/Bridge/DeepSeek/ModelClientTest.php
+++ b/src/platform/src/Bridge/DeepSeek/Tests/ModelClientTest.php
@@ -9,7 +9,7 @@
* file that was distributed with this source code.
*/
-namespace Symfony\AI\Platform\Tests\Bridge\DeepSeek;
+namespace Symfony\AI\Platform\Bridge\DeepSeek\Tests;
use PHPUnit\Framework\TestCase;
use Symfony\AI\Platform\Bridge\DeepSeek\DeepSeek;
diff --git a/src/platform/tests/Bridge/DeepSeek/ResultConverterTest.php b/src/platform/src/Bridge/DeepSeek/Tests/ResultConverterTest.php
similarity index 98%
rename from src/platform/tests/Bridge/DeepSeek/ResultConverterTest.php
rename to src/platform/src/Bridge/DeepSeek/Tests/ResultConverterTest.php
index 01b7c4d65..90066b8b2 100644
--- a/src/platform/tests/Bridge/DeepSeek/ResultConverterTest.php
+++ b/src/platform/src/Bridge/DeepSeek/Tests/ResultConverterTest.php
@@ -9,7 +9,7 @@
* file that was distributed with this source code.
*/
-namespace Symfony\AI\Platform\Tests\Bridge\DeepSeek;
+namespace Symfony\AI\Platform\Bridge\DeepSeek\Tests;
use PHPUnit\Framework\TestCase;
use Symfony\AI\Platform\Bridge\DeepSeek\DeepSeek;
diff --git a/src/platform/src/Bridge/DeepSeek/composer.json b/src/platform/src/Bridge/DeepSeek/composer.json
new file mode 100644
index 000000000..9739281af
--- /dev/null
+++ b/src/platform/src/Bridge/DeepSeek/composer.json
@@ -0,0 +1,60 @@
+{
+ "name": "symfony/ai-deep-seek-platform",
+ "description": "DeepSeek platform bridge for Symfony AI",
+ "license": "MIT",
+ "type": "symfony-ai-platform",
+ "keywords": [
+ "ai",
+ "bridge",
+ "deepseek",
+ "platform"
+ ],
+ "authors": [
+ {
+ "name": "Christopher Hertel",
+ "email": "mail@christopher-hertel.de"
+ },
+ {
+ "name": "Oskar Stark",
+ "email": "oskarstark@googlemail.com"
+ },
+ {
+ "name": "Symfony Community",
+ "homepage": "https://symfony.com/contributors"
+ }
+ ],
+ "require": {
+ "php": ">=8.2",
+ "symfony/ai-platform": "@dev",
+ "symfony/http-client": "^7.3|^8.0"
+ },
+ "require-dev": {
+ "phpstan/phpstan": "^2.1",
+ "phpstan/phpstan-strict-rules": "^2.0",
+ "phpunit/phpunit": "^11.5.46"
+ },
+ "minimum-stability": "dev",
+ "autoload": {
+ "psr-4": {
+ "Symfony\\AI\\Platform\\Bridge\\DeepSeek\\": ""
+ }
+ },
+ "autoload-dev": {
+ "psr-4": {
+ "Symfony\\AI\\PHPStan\\": "../../../../../.phpstan/",
+ "Symfony\\AI\\Platform\\Bridge\\DeepSeek\\Tests\\": "Tests/"
+ }
+ },
+ "config": {
+ "sort-packages": true
+ },
+ "extra": {
+ "branch-alias": {
+ "dev-main": "0.x-dev"
+ },
+ "thanks": {
+ "name": "symfony/ai",
+ "url": "https://github.com/symfony/ai"
+ }
+ }
+}
diff --git a/src/platform/src/Bridge/DeepSeek/phpstan.dist.neon b/src/platform/src/Bridge/DeepSeek/phpstan.dist.neon
new file mode 100644
index 000000000..5503dac38
--- /dev/null
+++ b/src/platform/src/Bridge/DeepSeek/phpstan.dist.neon
@@ -0,0 +1,23 @@
+includes:
+ - ../../../../../.phpstan/extension.neon
+
+parameters:
+ level: 6
+ paths:
+ - .
+ - Tests/
+ excludePaths:
+ - vendor/
+ treatPhpDocTypesAsCertain: false
+ ignoreErrors:
+ -
+ message: "#^Method .*::test.*\\(\\) has no return type specified\\.$#"
+ reportUnmatched: false
+ -
+ identifier: missingType.iterableValue
+ path: Tests/*
+ reportUnmatched: false
+ -
+ identifier: 'symfonyAi.forbidNativeException'
+ path: Tests/*
+ reportUnmatched: false
diff --git a/src/platform/src/Bridge/DeepSeek/phpunit.xml.dist b/src/platform/src/Bridge/DeepSeek/phpunit.xml.dist
new file mode 100644
index 000000000..d9ed9cafe
--- /dev/null
+++ b/src/platform/src/Bridge/DeepSeek/phpunit.xml.dist
@@ -0,0 +1,32 @@
+
+
+
+
+
+
+
+
+
+ ./Tests/
+
+
+
+
+
+ ./
+
+
+ ./Resources
+ ./Tests
+ ./vendor
+
+
+
diff --git a/src/platform/src/Bridge/DockerModelRunner/README.md b/src/platform/src/Bridge/DockerModelRunner/README.md
new file mode 100644
index 000000000..8942c7fc2
--- /dev/null
+++ b/src/platform/src/Bridge/DockerModelRunner/README.md
@@ -0,0 +1,12 @@
+DockerModelRunner Platform
+==========================
+
+Docker Model Runner platform bridge for Symfony AI.
+
+Resources
+---------
+
+ * [Contributing](https://symfony.com/doc/current/contributing/index.html)
+ * [Report issues](https://github.com/symfony/ai/issues) and
+ [send Pull Requests](https://github.com/symfony/ai/pulls)
+ in the [main Symfony AI repository](https://github.com/symfony/ai)
diff --git a/src/platform/tests/Bridge/DockerModelRunner/Completions/ModelClientTest.php b/src/platform/src/Bridge/DockerModelRunner/Tests/Completions/ModelClientTest.php
similarity index 98%
rename from src/platform/tests/Bridge/DockerModelRunner/Completions/ModelClientTest.php
rename to src/platform/src/Bridge/DockerModelRunner/Tests/Completions/ModelClientTest.php
index 3bb36d0c3..622c41ca9 100644
--- a/src/platform/tests/Bridge/DockerModelRunner/Completions/ModelClientTest.php
+++ b/src/platform/src/Bridge/DockerModelRunner/Tests/Completions/ModelClientTest.php
@@ -9,7 +9,7 @@
* file that was distributed with this source code.
*/
-namespace Symfony\AI\Platform\Tests\Bridge\DockerModelRunner\Completions;
+namespace Symfony\AI\Platform\Bridge\DockerModelRunner\Tests\Completions;
use PHPUnit\Framework\TestCase;
use Symfony\AI\Platform\Bridge\DockerModelRunner\Completions;
diff --git a/src/platform/tests/Bridge/DockerModelRunner/Completions/ResultConverterTest.php b/src/platform/src/Bridge/DockerModelRunner/Tests/Completions/ResultConverterTest.php
similarity index 97%
rename from src/platform/tests/Bridge/DockerModelRunner/Completions/ResultConverterTest.php
rename to src/platform/src/Bridge/DockerModelRunner/Tests/Completions/ResultConverterTest.php
index 67d6815d6..5108778b5 100644
--- a/src/platform/tests/Bridge/DockerModelRunner/Completions/ResultConverterTest.php
+++ b/src/platform/src/Bridge/DockerModelRunner/Tests/Completions/ResultConverterTest.php
@@ -9,7 +9,7 @@
* file that was distributed with this source code.
*/
-namespace Symfony\AI\Platform\Tests\Bridge\DockerModelRunner\Completions;
+namespace Symfony\AI\Platform\Bridge\DockerModelRunner\Tests\Completions;
use PHPUnit\Framework\Attributes\TestWith;
use PHPUnit\Framework\TestCase;
diff --git a/src/platform/tests/Bridge/DockerModelRunner/Embeddings/ModelClientTest.php b/src/platform/src/Bridge/DockerModelRunner/Tests/Embeddings/ModelClientTest.php
similarity index 97%
rename from src/platform/tests/Bridge/DockerModelRunner/Embeddings/ModelClientTest.php
rename to src/platform/src/Bridge/DockerModelRunner/Tests/Embeddings/ModelClientTest.php
index cb853c7e0..7623ead45 100644
--- a/src/platform/tests/Bridge/DockerModelRunner/Embeddings/ModelClientTest.php
+++ b/src/platform/src/Bridge/DockerModelRunner/Tests/Embeddings/ModelClientTest.php
@@ -9,7 +9,7 @@
* file that was distributed with this source code.
*/
-namespace Symfony\AI\Platform\Tests\Bridge\DockerModelRunner\Embeddings;
+namespace Symfony\AI\Platform\Bridge\DockerModelRunner\Tests\Embeddings;
use PHPUnit\Framework\TestCase;
use Symfony\AI\Platform\Bridge\DockerModelRunner\Embeddings;
diff --git a/src/platform/tests/Bridge/DockerModelRunner/Embeddings/ResultConverterTest.php b/src/platform/src/Bridge/DockerModelRunner/Tests/Embeddings/ResultConverterTest.php
similarity index 98%
rename from src/platform/tests/Bridge/DockerModelRunner/Embeddings/ResultConverterTest.php
rename to src/platform/src/Bridge/DockerModelRunner/Tests/Embeddings/ResultConverterTest.php
index 55349a5fd..b33eb905f 100644
--- a/src/platform/tests/Bridge/DockerModelRunner/Embeddings/ResultConverterTest.php
+++ b/src/platform/src/Bridge/DockerModelRunner/Tests/Embeddings/ResultConverterTest.php
@@ -9,7 +9,7 @@
* file that was distributed with this source code.
*/
-namespace Symfony\AI\Platform\Tests\Bridge\DockerModelRunner\Embeddings;
+namespace Symfony\AI\Platform\Bridge\DockerModelRunner\Tests\Embeddings;
use PHPUnit\Framework\Attributes\TestWith;
use PHPUnit\Framework\TestCase;
diff --git a/src/platform/tests/Bridge/DockerModelRunner/ModelCatalogTest.php b/src/platform/src/Bridge/DockerModelRunner/Tests/ModelCatalogTest.php
similarity index 98%
rename from src/platform/tests/Bridge/DockerModelRunner/ModelCatalogTest.php
rename to src/platform/src/Bridge/DockerModelRunner/Tests/ModelCatalogTest.php
index 04c62cb4b..eae4c3310 100644
--- a/src/platform/tests/Bridge/DockerModelRunner/ModelCatalogTest.php
+++ b/src/platform/src/Bridge/DockerModelRunner/Tests/ModelCatalogTest.php
@@ -9,7 +9,7 @@
* file that was distributed with this source code.
*/
-namespace Symfony\AI\Platform\Tests\Bridge\DockerModelRunner;
+namespace Symfony\AI\Platform\Bridge\DockerModelRunner\Tests;
use Symfony\AI\Platform\Bridge\DockerModelRunner\Completions;
use Symfony\AI\Platform\Bridge\DockerModelRunner\Embeddings;
diff --git a/src/platform/src/Bridge/DockerModelRunner/composer.json b/src/platform/src/Bridge/DockerModelRunner/composer.json
new file mode 100644
index 000000000..d9f6499ce
--- /dev/null
+++ b/src/platform/src/Bridge/DockerModelRunner/composer.json
@@ -0,0 +1,60 @@
+{
+ "name": "symfony/ai-docker-model-runner-platform",
+ "description": "Docker Model Runner platform bridge for Symfony AI",
+ "license": "MIT",
+ "type": "symfony-ai-platform",
+ "keywords": [
+ "ai",
+ "bridge",
+ "docker",
+ "platform"
+ ],
+ "authors": [
+ {
+ "name": "Christopher Hertel",
+ "email": "mail@christopher-hertel.de"
+ },
+ {
+ "name": "Oskar Stark",
+ "email": "oskarstark@googlemail.com"
+ },
+ {
+ "name": "Symfony Community",
+ "homepage": "https://symfony.com/contributors"
+ }
+ ],
+ "require": {
+ "php": ">=8.2",
+ "symfony/ai-platform": "@dev",
+ "symfony/http-client": "^7.3|^8.0"
+ },
+ "require-dev": {
+ "phpstan/phpstan": "^2.1",
+ "phpstan/phpstan-strict-rules": "^2.0",
+ "phpunit/phpunit": "^11.5.46"
+ },
+ "minimum-stability": "dev",
+ "autoload": {
+ "psr-4": {
+ "Symfony\\AI\\Platform\\Bridge\\DockerModelRunner\\": ""
+ }
+ },
+ "autoload-dev": {
+ "psr-4": {
+ "Symfony\\AI\\PHPStan\\": "../../../../../.phpstan/",
+ "Symfony\\AI\\Platform\\Bridge\\DockerModelRunner\\Tests\\": "Tests/"
+ }
+ },
+ "config": {
+ "sort-packages": true
+ },
+ "extra": {
+ "branch-alias": {
+ "dev-main": "0.x-dev"
+ },
+ "thanks": {
+ "name": "symfony/ai",
+ "url": "https://github.com/symfony/ai"
+ }
+ }
+}
diff --git a/src/platform/src/Bridge/DockerModelRunner/phpstan.dist.neon b/src/platform/src/Bridge/DockerModelRunner/phpstan.dist.neon
new file mode 100644
index 000000000..5503dac38
--- /dev/null
+++ b/src/platform/src/Bridge/DockerModelRunner/phpstan.dist.neon
@@ -0,0 +1,23 @@
+includes:
+ - ../../../../../.phpstan/extension.neon
+
+parameters:
+ level: 6
+ paths:
+ - .
+ - Tests/
+ excludePaths:
+ - vendor/
+ treatPhpDocTypesAsCertain: false
+ ignoreErrors:
+ -
+ message: "#^Method .*::test.*\\(\\) has no return type specified\\.$#"
+ reportUnmatched: false
+ -
+ identifier: missingType.iterableValue
+ path: Tests/*
+ reportUnmatched: false
+ -
+ identifier: 'symfonyAi.forbidNativeException'
+ path: Tests/*
+ reportUnmatched: false
diff --git a/src/platform/src/Bridge/DockerModelRunner/phpunit.xml.dist b/src/platform/src/Bridge/DockerModelRunner/phpunit.xml.dist
new file mode 100644
index 000000000..3aaa9edf1
--- /dev/null
+++ b/src/platform/src/Bridge/DockerModelRunner/phpunit.xml.dist
@@ -0,0 +1,32 @@
+
+
+
+
+
+
+
+
+
+ ./Tests/
+
+
+
+
+
+ ./
+
+
+ ./Resources
+ ./Tests
+ ./vendor
+
+
+
diff --git a/src/platform/src/Bridge/ElevenLabs/README.md b/src/platform/src/Bridge/ElevenLabs/README.md
new file mode 100644
index 000000000..75cf019a8
--- /dev/null
+++ b/src/platform/src/Bridge/ElevenLabs/README.md
@@ -0,0 +1,12 @@
+ElevenLabs Platform
+===================
+
+ElevenLabs platform bridge for Symfony AI.
+
+Resources
+---------
+
+ * [Contributing](https://symfony.com/doc/current/contributing/index.html)
+ * [Report issues](https://github.com/symfony/ai/issues) and
+ [send Pull Requests](https://github.com/symfony/ai/pulls)
+ in the [main Symfony AI repository](https://github.com/symfony/ai)
diff --git a/src/platform/tests/Bridge/ElevenLabs/Contract/ElevenLabsContractTest.php b/src/platform/src/Bridge/ElevenLabs/Tests/Contract/ElevenLabsContractTest.php
similarity index 88%
rename from src/platform/tests/Bridge/ElevenLabs/Contract/ElevenLabsContractTest.php
rename to src/platform/src/Bridge/ElevenLabs/Tests/Contract/ElevenLabsContractTest.php
index 5fd637065..4a64f32b6 100644
--- a/src/platform/tests/Bridge/ElevenLabs/Contract/ElevenLabsContractTest.php
+++ b/src/platform/src/Bridge/ElevenLabs/Tests/Contract/ElevenLabsContractTest.php
@@ -9,7 +9,7 @@
* file that was distributed with this source code.
*/
-namespace Symfony\AI\Platform\Tests\Bridge\ElevenLabs\Contract;
+namespace Symfony\AI\Platform\Bridge\ElevenLabs\Tests\Contract;
use PHPUnit\Framework\TestCase;
use Symfony\AI\Platform\Bridge\ElevenLabs\Contract\ElevenLabsContract;
@@ -20,7 +20,7 @@ final class ElevenLabsContractTest extends TestCase
{
public function testItCanCreatePayloadWithAudio()
{
- $audio = Audio::fromFile(\dirname(__DIR__, 6).'/fixtures/audio.mp3');
+ $audio = Audio::fromFile(\dirname(__DIR__, 7).'/fixtures/audio.mp3');
$contract = ElevenLabsContract::create();
diff --git a/src/platform/tests/Bridge/ElevenLabs/ElevenLabsApiCatalogTest.php b/src/platform/src/Bridge/ElevenLabs/Tests/ElevenLabsApiCatalogTest.php
similarity index 98%
rename from src/platform/tests/Bridge/ElevenLabs/ElevenLabsApiCatalogTest.php
rename to src/platform/src/Bridge/ElevenLabs/Tests/ElevenLabsApiCatalogTest.php
index db3991244..d4d2eaaea 100644
--- a/src/platform/tests/Bridge/ElevenLabs/ElevenLabsApiCatalogTest.php
+++ b/src/platform/src/Bridge/ElevenLabs/Tests/ElevenLabsApiCatalogTest.php
@@ -9,7 +9,7 @@
* file that was distributed with this source code.
*/
-namespace Symfony\AI\Platform\Tests\Bridge\ElevenLabs;
+namespace Symfony\AI\Platform\Bridge\ElevenLabs\Tests;
use PHPUnit\Framework\TestCase;
use Symfony\AI\Platform\Bridge\ElevenLabs\ElevenLabs;
diff --git a/src/platform/tests/Bridge/ElevenLabs/ElevenLabsClientTest.php b/src/platform/src/Bridge/ElevenLabs/Tests/ElevenLabsClientTest.php
similarity index 94%
rename from src/platform/tests/Bridge/ElevenLabs/ElevenLabsClientTest.php
rename to src/platform/src/Bridge/ElevenLabs/Tests/ElevenLabsClientTest.php
index fca5a1fbe..ac663f8e9 100644
--- a/src/platform/tests/Bridge/ElevenLabs/ElevenLabsClientTest.php
+++ b/src/platform/src/Bridge/ElevenLabs/Tests/ElevenLabsClientTest.php
@@ -9,7 +9,7 @@
* file that was distributed with this source code.
*/
-namespace Symfony\AI\Platform\Tests\Bridge\ElevenLabs;
+namespace Symfony\AI\Platform\Bridge\ElevenLabs\Tests;
use PHPUnit\Framework\TestCase;
use Symfony\AI\Platform\Bridge\ElevenLabs\Contract\AudioNormalizer;
@@ -56,7 +56,7 @@ public function testClientCannotPerformWithInvalidModel()
'my-api-key',
);
- $payload = $normalizer->normalize(Audio::fromFile(\dirname(__DIR__, 5).'/fixtures/audio.mp3'));
+ $payload = $normalizer->normalize(Audio::fromFile(\dirname(__DIR__, 6).'/fixtures/audio.mp3'));
$this->expectException(InvalidArgumentException::class);
$this->expectExceptionMessage('The model "foo" does not support text-to-speech or speech-to-text, please check the model information.');
@@ -91,7 +91,7 @@ public function testClientCanPerformSpeechToTextRequest()
'my-api-key',
);
- $payload = $normalizer->normalize(Audio::fromFile(\dirname(__DIR__, 5).'/fixtures/audio.mp3'));
+ $payload = $normalizer->normalize(Audio::fromFile(\dirname(__DIR__, 6).'/fixtures/audio.mp3'));
$client->request(new ElevenLabs('scribe_v1', [Capability::INPUT_AUDIO, Capability::OUTPUT_TEXT, Capability::SPEECH_TO_TEXT]), $payload);
@@ -112,7 +112,7 @@ public function testClientCanPerformSpeechToTextRequestWithExperimentalModel()
'my-api-key',
);
- $payload = $normalizer->normalize(Audio::fromFile(\dirname(__DIR__, 5).'/fixtures/audio.mp3'));
+ $payload = $normalizer->normalize(Audio::fromFile(\dirname(__DIR__, 6).'/fixtures/audio.mp3'));
$client->request(new ElevenLabs('scribe_v1_experimental', [Capability::INPUT_AUDIO, Capability::OUTPUT_TEXT, Capability::SPEECH_TO_TEXT]), $payload);
@@ -140,7 +140,7 @@ public function testClientCannotPerformTextToSpeechRequestWithoutValidPayload()
public function testClientCanPerformTextToSpeechRequest()
{
- $payload = Audio::fromFile(\dirname(__DIR__, 5).'/fixtures/audio.mp3');
+ $payload = Audio::fromFile(\dirname(__DIR__, 6).'/fixtures/audio.mp3');
$httpClient = new MockHttpClient([
new MockResponse($payload->asBinary()),
@@ -162,7 +162,7 @@ public function testClientCanPerformTextToSpeechRequest()
public function testClientCanPerformTextToSpeechRequestWhenVoiceKeyIsProvidedAsRequestOption()
{
- $payload = Audio::fromFile(\dirname(__DIR__, 5).'/fixtures/audio.mp3');
+ $payload = Audio::fromFile(\dirname(__DIR__, 6).'/fixtures/audio.mp3');
$httpClient = new MockHttpClient([
new MockResponse($payload->asBinary()),
@@ -184,7 +184,7 @@ public function testClientCanPerformTextToSpeechRequestWhenVoiceKeyIsProvidedAsR
public function testClientCanPerformTextToSpeechRequestAsStream()
{
- $payload = Audio::fromFile(\dirname(__DIR__, 5).'/fixtures/audio.mp3');
+ $payload = Audio::fromFile(\dirname(__DIR__, 6).'/fixtures/audio.mp3');
$httpClient = new MockHttpClient([
new MockResponse($payload->asBinary()),
@@ -208,7 +208,7 @@ public function testClientCanPerformTextToSpeechRequestAsStream()
public function testClientCanPerformTextToSpeechRequestAsStreamVoiceKeyIsProvidedAsRequestOption()
{
- $payload = Audio::fromFile(\dirname(__DIR__, 5).'/fixtures/audio.mp3');
+ $payload = Audio::fromFile(\dirname(__DIR__, 6).'/fixtures/audio.mp3');
$httpClient = new MockHttpClient([
new MockResponse($payload->asBinary()),
diff --git a/src/platform/tests/Bridge/ElevenLabs/ElevenLabsConverterTest.php b/src/platform/src/Bridge/ElevenLabs/Tests/ElevenLabsConverterTest.php
similarity index 94%
rename from src/platform/tests/Bridge/ElevenLabs/ElevenLabsConverterTest.php
rename to src/platform/src/Bridge/ElevenLabs/Tests/ElevenLabsConverterTest.php
index 4821bed16..9890043c7 100644
--- a/src/platform/tests/Bridge/ElevenLabs/ElevenLabsConverterTest.php
+++ b/src/platform/src/Bridge/ElevenLabs/Tests/ElevenLabsConverterTest.php
@@ -9,7 +9,7 @@
* file that was distributed with this source code.
*/
-namespace Symfony\AI\Platform\Tests\Bridge\ElevenLabs;
+namespace Symfony\AI\Platform\Bridge\ElevenLabs\Tests;
use PHPUnit\Framework\TestCase;
use Symfony\AI\Platform\Bridge\ElevenLabs\ElevenLabs;
@@ -59,7 +59,7 @@ public function getInfo(): string
public function getContent(): string
{
- return file_get_contents(\dirname(__DIR__, 5).'/fixtures/audio.mp3');
+ return file_get_contents(\dirname(__DIR__, 6).'/fixtures/audio.mp3');
}
});
diff --git a/src/platform/tests/Bridge/ElevenLabs/ModelCatalogTest.php b/src/platform/src/Bridge/ElevenLabs/Tests/ModelCatalogTest.php
similarity index 98%
rename from src/platform/tests/Bridge/ElevenLabs/ModelCatalogTest.php
rename to src/platform/src/Bridge/ElevenLabs/Tests/ModelCatalogTest.php
index ccac7dc7b..1eb8d561b 100644
--- a/src/platform/tests/Bridge/ElevenLabs/ModelCatalogTest.php
+++ b/src/platform/src/Bridge/ElevenLabs/Tests/ModelCatalogTest.php
@@ -9,7 +9,7 @@
* file that was distributed with this source code.
*/
-namespace Symfony\AI\Platform\Tests\Bridge\ElevenLabs;
+namespace Symfony\AI\Platform\Bridge\ElevenLabs\Tests;
use Symfony\AI\Platform\Bridge\ElevenLabs\ElevenLabs;
use Symfony\AI\Platform\Bridge\ElevenLabs\ModelCatalog;
diff --git a/src/platform/src/Bridge/ElevenLabs/composer.json b/src/platform/src/Bridge/ElevenLabs/composer.json
new file mode 100644
index 000000000..369e9bb8d
--- /dev/null
+++ b/src/platform/src/Bridge/ElevenLabs/composer.json
@@ -0,0 +1,62 @@
+{
+ "name": "symfony/ai-eleven-labs-platform",
+ "description": "ElevenLabs platform bridge for Symfony AI",
+ "license": "MIT",
+ "type": "symfony-ai-platform",
+ "keywords": [
+ "ai",
+ "bridge",
+ "elevenlabs",
+ "platform",
+ "text-to-speech",
+ "voice"
+ ],
+ "authors": [
+ {
+ "name": "Christopher Hertel",
+ "email": "mail@christopher-hertel.de"
+ },
+ {
+ "name": "Oskar Stark",
+ "email": "oskarstark@googlemail.com"
+ },
+ {
+ "name": "Symfony Community",
+ "homepage": "https://symfony.com/contributors"
+ }
+ ],
+ "require": {
+ "php": ">=8.2",
+ "symfony/ai-platform": "@dev",
+ "symfony/http-client": "^7.3|^8.0"
+ },
+ "require-dev": {
+ "phpstan/phpstan": "^2.1",
+ "phpstan/phpstan-strict-rules": "^2.0",
+ "phpunit/phpunit": "^11.5.46"
+ },
+ "minimum-stability": "dev",
+ "autoload": {
+ "psr-4": {
+ "Symfony\\AI\\Platform\\Bridge\\ElevenLabs\\": ""
+ }
+ },
+ "autoload-dev": {
+ "psr-4": {
+ "Symfony\\AI\\PHPStan\\": "../../../../../.phpstan/",
+ "Symfony\\AI\\Platform\\Bridge\\ElevenLabs\\Tests\\": "Tests/"
+ }
+ },
+ "config": {
+ "sort-packages": true
+ },
+ "extra": {
+ "branch-alias": {
+ "dev-main": "0.x-dev"
+ },
+ "thanks": {
+ "name": "symfony/ai",
+ "url": "https://github.com/symfony/ai"
+ }
+ }
+}
diff --git a/src/platform/src/Bridge/ElevenLabs/phpstan.dist.neon b/src/platform/src/Bridge/ElevenLabs/phpstan.dist.neon
new file mode 100644
index 000000000..5503dac38
--- /dev/null
+++ b/src/platform/src/Bridge/ElevenLabs/phpstan.dist.neon
@@ -0,0 +1,23 @@
+includes:
+ - ../../../../../.phpstan/extension.neon
+
+parameters:
+ level: 6
+ paths:
+ - .
+ - Tests/
+ excludePaths:
+ - vendor/
+ treatPhpDocTypesAsCertain: false
+ ignoreErrors:
+ -
+ message: "#^Method .*::test.*\\(\\) has no return type specified\\.$#"
+ reportUnmatched: false
+ -
+ identifier: missingType.iterableValue
+ path: Tests/*
+ reportUnmatched: false
+ -
+ identifier: 'symfonyAi.forbidNativeException'
+ path: Tests/*
+ reportUnmatched: false
diff --git a/src/platform/src/Bridge/ElevenLabs/phpunit.xml.dist b/src/platform/src/Bridge/ElevenLabs/phpunit.xml.dist
new file mode 100644
index 000000000..11427a5a8
--- /dev/null
+++ b/src/platform/src/Bridge/ElevenLabs/phpunit.xml.dist
@@ -0,0 +1,32 @@
+
+
+
+
+
+
+
+
+
+ ./Tests/
+
+
+
+
+
+ ./
+
+
+ ./Resources
+ ./Tests
+ ./vendor
+
+
+
diff --git a/src/platform/src/Bridge/Gemini/README.md b/src/platform/src/Bridge/Gemini/README.md
new file mode 100644
index 000000000..a88ba2d9c
--- /dev/null
+++ b/src/platform/src/Bridge/Gemini/README.md
@@ -0,0 +1,12 @@
+Gemini Platform
+===============
+
+Google Gemini platform bridge for Symfony AI.
+
+Resources
+---------
+
+ * [Contributing](https://symfony.com/doc/current/contributing/index.html)
+ * [Report issues](https://github.com/symfony/ai/issues) and
+ [send Pull Requests](https://github.com/symfony/ai/pulls)
+ in the [main Symfony AI repository](https://github.com/symfony/ai)
diff --git a/src/platform/src/Bridge/Gemini/Tests/CodeExecution/Fixtures/code_execution_outcome_deadline_exceeded.json b/src/platform/src/Bridge/Gemini/Tests/CodeExecution/Fixtures/code_execution_outcome_deadline_exceeded.json
new file mode 100644
index 000000000..9b4a592a0
--- /dev/null
+++ b/src/platform/src/Bridge/Gemini/Tests/CodeExecution/Fixtures/code_execution_outcome_deadline_exceeded.json
@@ -0,0 +1,31 @@
+{
+ "candidates": [
+ {
+ "content": {
+ "parts": [
+ {
+ "text": "First text"
+ },
+ {
+ "executableCode": {
+ "language": "PYTHON",
+ "code": "print('Hello, World!')"
+ }
+ },
+ {
+ "codeExecutionResult": {
+ "outcome": "OUTCOME_DEADLINE_EXCEEDED",
+ "output": "An error occurred during code execution."
+ }
+ },
+ {
+ "text": "Last text"
+ }
+ ],
+ "role": "model"
+ },
+ "finishReason": "STOP",
+ "index": 0
+ }
+ ]
+}
diff --git a/src/platform/src/Bridge/Gemini/Tests/CodeExecution/Fixtures/code_execution_outcome_failed.json b/src/platform/src/Bridge/Gemini/Tests/CodeExecution/Fixtures/code_execution_outcome_failed.json
new file mode 100644
index 000000000..8a1580137
--- /dev/null
+++ b/src/platform/src/Bridge/Gemini/Tests/CodeExecution/Fixtures/code_execution_outcome_failed.json
@@ -0,0 +1,31 @@
+{
+ "candidates": [
+ {
+ "content": {
+ "parts": [
+ {
+ "text": "First text"
+ },
+ {
+ "executableCode": {
+ "language": "PYTHON",
+ "code": "print('Hello, World!')"
+ }
+ },
+ {
+ "codeExecutionResult": {
+ "outcome": "OUTCOME_FAILED",
+ "output": "An error occurred during code execution."
+ }
+ },
+ {
+ "text": "Last text"
+ }
+ ],
+ "role": "model"
+ },
+ "finishReason": "STOP",
+ "index": 0
+ }
+ ]
+}
diff --git a/src/platform/src/Bridge/Gemini/Tests/CodeExecution/Fixtures/code_execution_outcome_ok.json b/src/platform/src/Bridge/Gemini/Tests/CodeExecution/Fixtures/code_execution_outcome_ok.json
new file mode 100644
index 000000000..3738f01b2
--- /dev/null
+++ b/src/platform/src/Bridge/Gemini/Tests/CodeExecution/Fixtures/code_execution_outcome_ok.json
@@ -0,0 +1,37 @@
+{
+ "candidates": [
+ {
+ "content": {
+ "parts": [
+ {
+ "text": "First text"
+ },
+ {
+ "executableCode": {
+ "language": "PYTHON",
+ "code": "print('Hello, World!')"
+ }
+ },
+ {
+ "codeExecutionResult": {
+ "outcome": "OUTCOME_OK",
+ "output": "Hello, World!"
+ }
+ },
+ {
+ "text": "Second text\n"
+ },
+ {
+ "text": "Third text\n"
+ },
+ {
+ "text": "Fourth text"
+ }
+ ],
+ "role": "model"
+ },
+ "finishReason": "STOP",
+ "index": 0
+ }
+ ]
+}
diff --git a/src/platform/tests/Bridge/Gemini/CodeExecution/ResultConverterTest.php b/src/platform/src/Bridge/Gemini/Tests/CodeExecution/ResultConverterTest.php
similarity index 88%
rename from src/platform/tests/Bridge/Gemini/CodeExecution/ResultConverterTest.php
rename to src/platform/src/Bridge/Gemini/Tests/CodeExecution/ResultConverterTest.php
index faf3900b6..76db6f359 100644
--- a/src/platform/tests/Bridge/Gemini/CodeExecution/ResultConverterTest.php
+++ b/src/platform/src/Bridge/Gemini/Tests/CodeExecution/ResultConverterTest.php
@@ -9,7 +9,7 @@
* file that was distributed with this source code.
*/
-namespace Symfony\AI\Platform\Tests\Bridge\Gemini\CodeExecution;
+namespace Symfony\AI\Platform\Bridge\Gemini\Tests\CodeExecution;
use PHPUnit\Framework\TestCase;
use Symfony\AI\Platform\Bridge\Gemini\Gemini\ResultConverter;
@@ -22,7 +22,7 @@ final class ResultConverterTest extends TestCase
public function testItReturnsAggregatedTextOnSuccess()
{
$response = $this->createStub(ResponseInterface::class);
- $responseContent = file_get_contents(__DIR__.'/fixtures/code_execution_outcome_ok.json');
+ $responseContent = file_get_contents(__DIR__.'/Fixtures/code_execution_outcome_ok.json');
$response
->method('toArray')
@@ -39,7 +39,7 @@ public function testItReturnsAggregatedTextOnSuccess()
public function testItThrowsExceptionOnFailure()
{
$response = $this->createStub(ResponseInterface::class);
- $responseContent = file_get_contents(__DIR__.'/fixtures/code_execution_outcome_failed.json');
+ $responseContent = file_get_contents(__DIR__.'/Fixtures/code_execution_outcome_failed.json');
$response
->method('toArray')
@@ -54,7 +54,7 @@ public function testItThrowsExceptionOnFailure()
public function testItThrowsExceptionOnTimeout()
{
$response = $this->createStub(ResponseInterface::class);
- $responseContent = file_get_contents(__DIR__.'/fixtures/code_execution_outcome_deadline_exceeded.json');
+ $responseContent = file_get_contents(__DIR__.'/Fixtures/code_execution_outcome_deadline_exceeded.json');
$response
->method('toArray')
diff --git a/src/platform/tests/Bridge/Gemini/Contract/AssistantMessageNormalizerTest.php b/src/platform/src/Bridge/Gemini/Tests/Contract/AssistantMessageNormalizerTest.php
similarity index 97%
rename from src/platform/tests/Bridge/Gemini/Contract/AssistantMessageNormalizerTest.php
rename to src/platform/src/Bridge/Gemini/Tests/Contract/AssistantMessageNormalizerTest.php
index ccf964a83..5f111c011 100644
--- a/src/platform/tests/Bridge/Gemini/Contract/AssistantMessageNormalizerTest.php
+++ b/src/platform/src/Bridge/Gemini/Tests/Contract/AssistantMessageNormalizerTest.php
@@ -9,7 +9,7 @@
* file that was distributed with this source code.
*/
-namespace Symfony\AI\Platform\Tests\Bridge\Gemini\Contract;
+namespace Symfony\AI\Platform\Bridge\Gemini\Tests\Contract;
use PHPUnit\Framework\Attributes\DataProvider;
use PHPUnit\Framework\TestCase;
diff --git a/src/platform/tests/Bridge/Gemini/Contract/MessageBagNormalizerTest.php b/src/platform/src/Bridge/Gemini/Tests/Contract/MessageBagNormalizerTest.php
similarity index 96%
rename from src/platform/tests/Bridge/Gemini/Contract/MessageBagNormalizerTest.php
rename to src/platform/src/Bridge/Gemini/Tests/Contract/MessageBagNormalizerTest.php
index ee2e3f27b..8acdf6ca4 100644
--- a/src/platform/tests/Bridge/Gemini/Contract/MessageBagNormalizerTest.php
+++ b/src/platform/src/Bridge/Gemini/Tests/Contract/MessageBagNormalizerTest.php
@@ -9,7 +9,7 @@
* file that was distributed with this source code.
*/
-namespace Symfony\AI\Platform\Tests\Bridge\Gemini\Contract;
+namespace Symfony\AI\Platform\Bridge\Gemini\Tests\Contract;
use PHPUnit\Framework\Attributes\DataProvider;
use PHPUnit\Framework\TestCase;
@@ -92,13 +92,13 @@ public static function provideMessageBagData(): iterable
yield 'text with image' => [
new MessageBag(
- Message::ofUser('Tell me about this instrument', Image::fromFile(\dirname(__DIR__, 6).'/fixtures/image.jpg'))
+ Message::ofUser('Tell me about this instrument', Image::fromFile(\dirname(__DIR__, 5).'/tests/Fixtures/image.jpg'))
),
[
'contents' => [
['role' => 'user', 'parts' => [
['text' => 'Tell me about this instrument'],
- ['inline_data' => ['mime_type' => 'image/jpeg', 'data' => base64_encode(file_get_contents(\dirname(__DIR__, 6).'/fixtures/image.jpg'))]],
+ ['inline_data' => ['mime_type' => 'image/jpeg', 'data' => base64_encode(file_get_contents(\dirname(__DIR__, 5).'/tests/Fixtures/image.jpg'))]],
]],
],
],
diff --git a/src/platform/tests/Bridge/Gemini/Contract/ToolCallMessageNormalizerTest.php b/src/platform/src/Bridge/Gemini/Tests/Contract/ToolCallMessageNormalizerTest.php
similarity index 97%
rename from src/platform/tests/Bridge/Gemini/Contract/ToolCallMessageNormalizerTest.php
rename to src/platform/src/Bridge/Gemini/Tests/Contract/ToolCallMessageNormalizerTest.php
index 260483840..6b4bbcd75 100644
--- a/src/platform/tests/Bridge/Gemini/Contract/ToolCallMessageNormalizerTest.php
+++ b/src/platform/src/Bridge/Gemini/Tests/Contract/ToolCallMessageNormalizerTest.php
@@ -9,7 +9,7 @@
* file that was distributed with this source code.
*/
-namespace Symfony\AI\Platform\Tests\Bridge\Gemini\Contract;
+namespace Symfony\AI\Platform\Bridge\Gemini\Tests\Contract;
use PHPUnit\Framework\Attributes\DataProvider;
use PHPUnit\Framework\TestCase;
diff --git a/src/platform/tests/Bridge/Gemini/Contract/ToolNormalizerTest.php b/src/platform/src/Bridge/Gemini/Tests/Contract/ToolNormalizerTest.php
similarity index 98%
rename from src/platform/tests/Bridge/Gemini/Contract/ToolNormalizerTest.php
rename to src/platform/src/Bridge/Gemini/Tests/Contract/ToolNormalizerTest.php
index 45dda8a0d..f2c4897b8 100644
--- a/src/platform/tests/Bridge/Gemini/Contract/ToolNormalizerTest.php
+++ b/src/platform/src/Bridge/Gemini/Tests/Contract/ToolNormalizerTest.php
@@ -9,7 +9,7 @@
* file that was distributed with this source code.
*/
-namespace Symfony\AI\Platform\Tests\Bridge\Gemini\Contract;
+namespace Symfony\AI\Platform\Bridge\Gemini\Tests\Contract;
use PHPUnit\Framework\Attributes\DataProvider;
use PHPUnit\Framework\TestCase;
diff --git a/src/platform/tests/Bridge/Gemini/Contract/UserMessageNormalizerTest.php b/src/platform/src/Bridge/Gemini/Tests/Contract/UserMessageNormalizerTest.php
similarity index 88%
rename from src/platform/tests/Bridge/Gemini/Contract/UserMessageNormalizerTest.php
rename to src/platform/src/Bridge/Gemini/Tests/Contract/UserMessageNormalizerTest.php
index 17261a509..4f1d94a52 100644
--- a/src/platform/tests/Bridge/Gemini/Contract/UserMessageNormalizerTest.php
+++ b/src/platform/src/Bridge/Gemini/Tests/Contract/UserMessageNormalizerTest.php
@@ -9,7 +9,7 @@
* file that was distributed with this source code.
*/
-namespace Symfony\AI\Platform\Tests\Bridge\Gemini\Contract;
+namespace Symfony\AI\Platform\Bridge\Gemini\Tests\Contract;
use PHPUnit\Framework\Attributes\DataProvider;
use PHPUnit\Framework\TestCase;
@@ -52,6 +52,16 @@ public function testNormalizeTextContent()
$this->assertSame([['text' => 'Write a story about a magic backpack.']], $normalized);
}
+ /**
+ * @return iterable
+ */
+ public static function binaryContentProvider(): iterable
+ {
+ yield 'image' => [Image::fromFile(\dirname(__DIR__, 5).'/tests/Fixtures/image.jpg'), 'image/jpeg', '/9j/'];
+ yield 'document' => [Document::fromFile(\dirname(__DIR__, 5).'/tests/Fixtures/document.pdf'), 'application/pdf', 'JVBE'];
+ yield 'audio' => [Audio::fromFile(\dirname(__DIR__, 5).'/tests/Fixtures/audio.mp3'), 'audio/mpeg', 'SUQz'];
+ }
+
#[DataProvider('binaryContentProvider')]
public function testNormalizeBinaryContent(File $content, string $expectedMimeType, string $expectedPrefix)
{
@@ -69,14 +79,4 @@ public function testNormalizeBinaryContent(File $content, string $expectedMimeTy
// Verify that the base64 data string starts correctly
$this->assertStringStartsWith($expectedPrefix, $normalized[1]['inline_data']['data']);
}
-
- /**
- * @return iterable
- */
- public static function binaryContentProvider(): iterable
- {
- yield 'image' => [Image::fromFile(\dirname(__DIR__, 6).'/fixtures/image.jpg'), 'image/jpeg', '/9j/'];
- yield 'document' => [Document::fromFile(\dirname(__DIR__, 6).'/fixtures/document.pdf'), 'application/pdf', 'JVBE'];
- yield 'audio' => [Audio::fromFile(\dirname(__DIR__, 6).'/fixtures/audio.mp3'), 'audio/mpeg', 'SUQz'];
- }
}
diff --git a/src/platform/tests/Bridge/Gemini/Embeddings/ModelClientTest.php b/src/platform/src/Bridge/Gemini/Tests/Embeddings/ModelClientTest.php
similarity index 97%
rename from src/platform/tests/Bridge/Gemini/Embeddings/ModelClientTest.php
rename to src/platform/src/Bridge/Gemini/Tests/Embeddings/ModelClientTest.php
index bc61f2f6a..2983b8858 100644
--- a/src/platform/tests/Bridge/Gemini/Embeddings/ModelClientTest.php
+++ b/src/platform/src/Bridge/Gemini/Tests/Embeddings/ModelClientTest.php
@@ -9,7 +9,7 @@
* file that was distributed with this source code.
*/
-namespace Symfony\AI\Platform\Tests\Bridge\Gemini\Embeddings;
+namespace Symfony\AI\Platform\Bridge\Gemini\Tests\Embeddings;
use PHPUnit\Framework\TestCase;
use Symfony\AI\Platform\Bridge\Gemini\Embeddings;
diff --git a/src/platform/tests/Bridge/Gemini/Embeddings/ResultConverterTest.php b/src/platform/src/Bridge/Gemini/Tests/Embeddings/ResultConverterTest.php
similarity index 95%
rename from src/platform/tests/Bridge/Gemini/Embeddings/ResultConverterTest.php
rename to src/platform/src/Bridge/Gemini/Tests/Embeddings/ResultConverterTest.php
index 849884394..9660d75b1 100644
--- a/src/platform/tests/Bridge/Gemini/Embeddings/ResultConverterTest.php
+++ b/src/platform/src/Bridge/Gemini/Tests/Embeddings/ResultConverterTest.php
@@ -9,7 +9,7 @@
* file that was distributed with this source code.
*/
-namespace Symfony\AI\Platform\Tests\Bridge\Gemini\Embeddings;
+namespace Symfony\AI\Platform\Bridge\Gemini\Tests\Embeddings;
use PHPUnit\Framework\TestCase;
use Symfony\AI\Platform\Bridge\Gemini\Embeddings\ResultConverter;
diff --git a/src/platform/tests/Bridge/Gemini/Gemini/ResultConverterRateLimitTest.php b/src/platform/src/Bridge/Gemini/Tests/Gemini/ResultConverterRateLimitTest.php
similarity index 96%
rename from src/platform/tests/Bridge/Gemini/Gemini/ResultConverterRateLimitTest.php
rename to src/platform/src/Bridge/Gemini/Tests/Gemini/ResultConverterRateLimitTest.php
index 2b7c80a90..9263e91c5 100644
--- a/src/platform/tests/Bridge/Gemini/Gemini/ResultConverterRateLimitTest.php
+++ b/src/platform/src/Bridge/Gemini/Tests/Gemini/ResultConverterRateLimitTest.php
@@ -9,7 +9,7 @@
* file that was distributed with this source code.
*/
-namespace Symfony\AI\Platform\Tests\Bridge\Gemini\Gemini;
+namespace Symfony\AI\Platform\Bridge\Gemini\Tests\Gemini;
use PHPUnit\Framework\TestCase;
use Symfony\AI\Platform\Bridge\Gemini\Gemini\ResultConverter;
diff --git a/src/platform/tests/Bridge/Gemini/Gemini/ResultConverterTest.php b/src/platform/src/Bridge/Gemini/Tests/Gemini/ResultConverterTest.php
similarity index 96%
rename from src/platform/tests/Bridge/Gemini/Gemini/ResultConverterTest.php
rename to src/platform/src/Bridge/Gemini/Tests/Gemini/ResultConverterTest.php
index 9f21feaf1..f7a141937 100644
--- a/src/platform/tests/Bridge/Gemini/Gemini/ResultConverterTest.php
+++ b/src/platform/src/Bridge/Gemini/Tests/Gemini/ResultConverterTest.php
@@ -9,7 +9,7 @@
* file that was distributed with this source code.
*/
-namespace Symfony\AI\Platform\Tests\Bridge\Gemini\Gemini;
+namespace Symfony\AI\Platform\Bridge\Gemini\Tests\Gemini;
use PHPUnit\Framework\TestCase;
use Symfony\AI\Platform\Bridge\Gemini\Gemini\ResultConverter;
@@ -84,7 +84,7 @@ public function testConvertsInlineDataToBinaryResult()
$converter = new ResultConverter();
$httpResponse = self::createMock(ResponseInterface::class);
$httpResponse->method('getStatusCode')->willReturn(200);
- $image = Image::fromFile(\dirname(__DIR__, 6).'/fixtures/image.jpg');
+ $image = Image::fromFile(\dirname(__DIR__, 7).'/fixtures/image.jpg');
$httpResponse->method('toArray')->willReturn([
'candidates' => [
[
@@ -114,7 +114,7 @@ public function testConvertsInlineDataWithoutMimeTypeToBinaryResult()
$converter = new ResultConverter();
$httpResponse = self::createMock(ResponseInterface::class);
$httpResponse->method('getStatusCode')->willReturn(200);
- $image = Image::fromFile(\dirname(__DIR__, 6).'/fixtures/image.jpg');
+ $image = Image::fromFile(\dirname(__DIR__, 7).'/fixtures/image.jpg');
$httpResponse->method('toArray')->willReturn([
'candidates' => [
[
diff --git a/src/platform/tests/Bridge/Gemini/ModelCatalogTest.php b/src/platform/src/Bridge/Gemini/Tests/ModelCatalogTest.php
similarity index 98%
rename from src/platform/tests/Bridge/Gemini/ModelCatalogTest.php
rename to src/platform/src/Bridge/Gemini/Tests/ModelCatalogTest.php
index 3f0b2cd85..e582b610b 100644
--- a/src/platform/tests/Bridge/Gemini/ModelCatalogTest.php
+++ b/src/platform/src/Bridge/Gemini/Tests/ModelCatalogTest.php
@@ -9,7 +9,7 @@
* file that was distributed with this source code.
*/
-namespace Symfony\AI\Platform\Tests\Bridge\Gemini;
+namespace Symfony\AI\Platform\Bridge\Gemini\Tests;
use Symfony\AI\Platform\Bridge\Gemini\Embeddings;
use Symfony\AI\Platform\Bridge\Gemini\Gemini;
diff --git a/src/platform/tests/Bridge/Gemini/TokenUsageExtractorTest.php b/src/platform/src/Bridge/Gemini/Tests/TokenUsageExtractorTest.php
similarity index 100%
rename from src/platform/tests/Bridge/Gemini/TokenUsageExtractorTest.php
rename to src/platform/src/Bridge/Gemini/Tests/TokenUsageExtractorTest.php
diff --git a/src/platform/src/Bridge/Gemini/composer.json b/src/platform/src/Bridge/Gemini/composer.json
new file mode 100644
index 000000000..96b951f18
--- /dev/null
+++ b/src/platform/src/Bridge/Gemini/composer.json
@@ -0,0 +1,63 @@
+{
+ "name": "symfony/ai-gemini-platform",
+ "description": "Google Gemini platform bridge for Symfony AI",
+ "license": "MIT",
+ "type": "symfony-ai-platform",
+ "keywords": [
+ "ai",
+ "bridge",
+ "gemini",
+ "google",
+ "platform"
+ ],
+ "authors": [
+ {
+ "name": "Christopher Hertel",
+ "email": "mail@christopher-hertel.de"
+ },
+ {
+ "name": "Oskar Stark",
+ "email": "oskarstark@googlemail.com"
+ },
+ {
+ "name": "Symfony Community",
+ "homepage": "https://symfony.com/contributors"
+ }
+ ],
+ "require": {
+ "php": ">=8.2",
+ "symfony/ai-platform": "@dev",
+ "symfony/http-client": "^7.3|^8.0"
+ },
+ "require-dev": {
+ "phpstan/phpstan": "^2.1",
+ "phpstan/phpstan-strict-rules": "^2.0",
+ "phpunit/phpunit": "^11.5.46",
+ "symfony/ai-agent": "@dev"
+ },
+ "minimum-stability": "dev",
+ "autoload": {
+ "psr-4": {
+ "Symfony\\AI\\Platform\\Bridge\\Gemini\\": ""
+ }
+ },
+ "autoload-dev": {
+ "psr-4": {
+ "Symfony\\AI\\Agent\\Tests\\": "../../../../agent/tests/",
+ "Symfony\\AI\\PHPStan\\": "../../../../../.phpstan/",
+ "Symfony\\AI\\Platform\\Bridge\\Gemini\\Tests\\": "Tests/"
+ }
+ },
+ "config": {
+ "sort-packages": true
+ },
+ "extra": {
+ "branch-alias": {
+ "dev-main": "0.x-dev"
+ },
+ "thanks": {
+ "name": "symfony/ai",
+ "url": "https://github.com/symfony/ai"
+ }
+ }
+}
diff --git a/src/platform/src/Bridge/Gemini/phpstan.dist.neon b/src/platform/src/Bridge/Gemini/phpstan.dist.neon
new file mode 100644
index 000000000..5503dac38
--- /dev/null
+++ b/src/platform/src/Bridge/Gemini/phpstan.dist.neon
@@ -0,0 +1,23 @@
+includes:
+ - ../../../../../.phpstan/extension.neon
+
+parameters:
+ level: 6
+ paths:
+ - .
+ - Tests/
+ excludePaths:
+ - vendor/
+ treatPhpDocTypesAsCertain: false
+ ignoreErrors:
+ -
+ message: "#^Method .*::test.*\\(\\) has no return type specified\\.$#"
+ reportUnmatched: false
+ -
+ identifier: missingType.iterableValue
+ path: Tests/*
+ reportUnmatched: false
+ -
+ identifier: 'symfonyAi.forbidNativeException'
+ path: Tests/*
+ reportUnmatched: false
diff --git a/src/platform/src/Bridge/Gemini/phpunit.xml.dist b/src/platform/src/Bridge/Gemini/phpunit.xml.dist
new file mode 100644
index 000000000..0f990f638
--- /dev/null
+++ b/src/platform/src/Bridge/Gemini/phpunit.xml.dist
@@ -0,0 +1,32 @@
+
+
+
+
+
+
+
+
+
+ ./Tests/
+
+
+
+
+
+ ./
+
+
+ ./Resources
+ ./Tests
+ ./vendor
+
+
+
diff --git a/src/platform/src/Bridge/Generic/README.md b/src/platform/src/Bridge/Generic/README.md
new file mode 100644
index 000000000..6c58756cd
--- /dev/null
+++ b/src/platform/src/Bridge/Generic/README.md
@@ -0,0 +1,12 @@
+Generic Platform
+================
+
+Generic platform bridge for Symfony AI.
+
+Resources
+---------
+
+ * [Contributing](https://symfony.com/doc/current/contributing/index.html)
+ * [Report issues](https://github.com/symfony/ai/issues) and
+ [send Pull Requests](https://github.com/symfony/ai/pulls)
+ in the [main Symfony AI repository](https://github.com/symfony/ai)
diff --git a/src/platform/tests/Bridge/Generic/Completions/ModelClientTest.php b/src/platform/src/Bridge/Generic/Tests/Completions/ModelClientTest.php
similarity index 98%
rename from src/platform/tests/Bridge/Generic/Completions/ModelClientTest.php
rename to src/platform/src/Bridge/Generic/Tests/Completions/ModelClientTest.php
index 59d142161..a2dea9f0e 100644
--- a/src/platform/tests/Bridge/Generic/Completions/ModelClientTest.php
+++ b/src/platform/src/Bridge/Generic/Tests/Completions/ModelClientTest.php
@@ -9,7 +9,7 @@
* file that was distributed with this source code.
*/
-namespace Symfony\AI\Platform\Tests\Bridge\Generic\Completions;
+namespace Symfony\AI\Platform\Bridge\Generic\Tests\Completions;
use PHPUnit\Framework\Attributes\TestWith;
use PHPUnit\Framework\TestCase;
diff --git a/src/platform/tests/Bridge/Generic/Completions/ResultConverterTest.php b/src/platform/src/Bridge/Generic/Tests/Completions/ResultConverterTest.php
similarity index 99%
rename from src/platform/tests/Bridge/Generic/Completions/ResultConverterTest.php
rename to src/platform/src/Bridge/Generic/Tests/Completions/ResultConverterTest.php
index f381a7176..3028b3f1b 100644
--- a/src/platform/tests/Bridge/Generic/Completions/ResultConverterTest.php
+++ b/src/platform/src/Bridge/Generic/Tests/Completions/ResultConverterTest.php
@@ -9,7 +9,7 @@
* file that was distributed with this source code.
*/
-namespace Symfony\AI\Platform\Tests\Bridge\Generic\Completions;
+namespace Symfony\AI\Platform\Bridge\Generic\Tests\Completions;
use PHPUnit\Framework\TestCase;
use Symfony\AI\Platform\Bridge\Generic\Completions\ResultConverter;
diff --git a/src/platform/tests/Bridge/Generic/Embeddings/ModelClientTest.php b/src/platform/src/Bridge/Generic/Tests/Embeddings/ModelClientTest.php
similarity index 98%
rename from src/platform/tests/Bridge/Generic/Embeddings/ModelClientTest.php
rename to src/platform/src/Bridge/Generic/Tests/Embeddings/ModelClientTest.php
index 405ab63a9..e54a73a87 100644
--- a/src/platform/tests/Bridge/Generic/Embeddings/ModelClientTest.php
+++ b/src/platform/src/Bridge/Generic/Tests/Embeddings/ModelClientTest.php
@@ -9,7 +9,7 @@
* file that was distributed with this source code.
*/
-namespace Symfony\AI\Platform\Tests\Bridge\Generic\Embeddings;
+namespace Symfony\AI\Platform\Bridge\Generic\Tests\Embeddings;
use PHPUnit\Framework\Attributes\TestWith;
use PHPUnit\Framework\TestCase;
diff --git a/src/platform/tests/Bridge/Generic/Embeddings/ResultConverterTest.php b/src/platform/src/Bridge/Generic/Tests/Embeddings/ResultConverterTest.php
similarity index 96%
rename from src/platform/tests/Bridge/Generic/Embeddings/ResultConverterTest.php
rename to src/platform/src/Bridge/Generic/Tests/Embeddings/ResultConverterTest.php
index 4831f2274..db2a45794 100644
--- a/src/platform/tests/Bridge/Generic/Embeddings/ResultConverterTest.php
+++ b/src/platform/src/Bridge/Generic/Tests/Embeddings/ResultConverterTest.php
@@ -9,7 +9,7 @@
* file that was distributed with this source code.
*/
-namespace Symfony\AI\Platform\Tests\Bridge\Generic\Embeddings;
+namespace Symfony\AI\Platform\Bridge\Generic\Tests\Embeddings;
use PHPUnit\Framework\TestCase;
use Symfony\AI\Platform\Bridge\Generic\Embeddings\ResultConverter;
diff --git a/src/platform/src/Bridge/Generic/composer.json b/src/platform/src/Bridge/Generic/composer.json
new file mode 100644
index 000000000..64d8376f9
--- /dev/null
+++ b/src/platform/src/Bridge/Generic/composer.json
@@ -0,0 +1,60 @@
+{
+ "name": "symfony/ai-generic-platform",
+ "description": "Generic platform bridge for Symfony AI",
+ "license": "MIT",
+ "type": "symfony-ai-platform",
+ "keywords": [
+ "ai",
+ "bridge",
+ "generic",
+ "platform"
+ ],
+ "authors": [
+ {
+ "name": "Christopher Hertel",
+ "email": "mail@christopher-hertel.de"
+ },
+ {
+ "name": "Oskar Stark",
+ "email": "oskarstark@googlemail.com"
+ },
+ {
+ "name": "Symfony Community",
+ "homepage": "https://symfony.com/contributors"
+ }
+ ],
+ "require": {
+ "php": ">=8.2",
+ "symfony/ai-platform": "@dev",
+ "symfony/http-client": "^7.3|^8.0"
+ },
+ "require-dev": {
+ "phpstan/phpstan": "^2.1",
+ "phpstan/phpstan-strict-rules": "^2.0",
+ "phpunit/phpunit": "^11.5.46"
+ },
+ "minimum-stability": "dev",
+ "autoload": {
+ "psr-4": {
+ "Symfony\\AI\\Platform\\Bridge\\Generic\\": ""
+ }
+ },
+ "autoload-dev": {
+ "psr-4": {
+ "Symfony\\AI\\PHPStan\\": "../../../../../.phpstan/",
+ "Symfony\\AI\\Platform\\Bridge\\Generic\\Tests\\": "Tests/"
+ }
+ },
+ "config": {
+ "sort-packages": true
+ },
+ "extra": {
+ "branch-alias": {
+ "dev-main": "0.x-dev"
+ },
+ "thanks": {
+ "name": "symfony/ai",
+ "url": "https://github.com/symfony/ai"
+ }
+ }
+}
diff --git a/src/platform/src/Bridge/Generic/phpstan.dist.neon b/src/platform/src/Bridge/Generic/phpstan.dist.neon
new file mode 100644
index 000000000..5503dac38
--- /dev/null
+++ b/src/platform/src/Bridge/Generic/phpstan.dist.neon
@@ -0,0 +1,23 @@
+includes:
+ - ../../../../../.phpstan/extension.neon
+
+parameters:
+ level: 6
+ paths:
+ - .
+ - Tests/
+ excludePaths:
+ - vendor/
+ treatPhpDocTypesAsCertain: false
+ ignoreErrors:
+ -
+ message: "#^Method .*::test.*\\(\\) has no return type specified\\.$#"
+ reportUnmatched: false
+ -
+ identifier: missingType.iterableValue
+ path: Tests/*
+ reportUnmatched: false
+ -
+ identifier: 'symfonyAi.forbidNativeException'
+ path: Tests/*
+ reportUnmatched: false
diff --git a/src/platform/src/Bridge/Generic/phpunit.xml.dist b/src/platform/src/Bridge/Generic/phpunit.xml.dist
new file mode 100644
index 000000000..d6c99e72c
--- /dev/null
+++ b/src/platform/src/Bridge/Generic/phpunit.xml.dist
@@ -0,0 +1,32 @@
+
+
+
+
+
+
+
+
+
+ ./Tests/
+
+
+
+
+
+ ./
+
+
+ ./Resources
+ ./Tests
+ ./vendor
+
+
+
diff --git a/src/platform/tests/Bridge/HuggingFace/ApiClientTest.php b/src/platform/src/Bridge/HuggingFace/Tests/ApiClientTest.php
similarity index 98%
rename from src/platform/tests/Bridge/HuggingFace/ApiClientTest.php
rename to src/platform/src/Bridge/HuggingFace/Tests/ApiClientTest.php
index 4ef902cfa..6d195ccf1 100644
--- a/src/platform/tests/Bridge/HuggingFace/ApiClientTest.php
+++ b/src/platform/src/Bridge/HuggingFace/Tests/ApiClientTest.php
@@ -9,7 +9,7 @@
* file that was distributed with this source code.
*/
-namespace Symfony\AI\Platform\Tests\Bridge\HuggingFace;
+namespace Symfony\AI\Platform\Bridge\HuggingFace\Tests;
use PHPUnit\Framework\Attributes\TestDox;
use PHPUnit\Framework\TestCase;
diff --git a/src/platform/tests/Bridge/HuggingFace/Contract/FileNormalizerTest.php b/src/platform/src/Bridge/HuggingFace/Tests/Contract/FileNormalizerTest.php
similarity index 80%
rename from src/platform/tests/Bridge/HuggingFace/Contract/FileNormalizerTest.php
rename to src/platform/src/Bridge/HuggingFace/Tests/Contract/FileNormalizerTest.php
index 31d765768..ef8cc9249 100644
--- a/src/platform/tests/Bridge/HuggingFace/Contract/FileNormalizerTest.php
+++ b/src/platform/src/Bridge/HuggingFace/Tests/Contract/FileNormalizerTest.php
@@ -9,7 +9,7 @@
* file that was distributed with this source code.
*/
-namespace Symfony\AI\Platform\Tests\Bridge\HuggingFace\Contract;
+namespace Symfony\AI\Platform\Bridge\HuggingFace\Tests\Contract;
use PHPUnit\Framework\Attributes\DataProvider;
use PHPUnit\Framework\TestCase;
@@ -54,26 +54,26 @@ public function testNormalize(File $file, array $expected)
public static function normalizeDataProvider(): iterable
{
yield 'image from file' => [
- File::fromFile(\dirname(__DIR__, 3).'/Fixtures/image.jpg'),
+ File::fromFile(\dirname(__DIR__, 7).'/fixtures/image.jpg'),
[
'headers' => ['Content-Type' => 'image/jpeg'],
- 'body' => file_get_contents(\dirname(__DIR__, 3).'/Fixtures/image.jpg'),
+ 'body' => file_get_contents(\dirname(__DIR__, 7).'/fixtures/image.jpg'),
],
];
yield 'pdf document from file' => [
- File::fromFile(\dirname(__DIR__, 3).'/Fixtures/document.pdf'),
+ File::fromFile(\dirname(__DIR__, 7).'/fixtures/document.pdf'),
[
'headers' => ['Content-Type' => 'application/pdf'],
- 'body' => file_get_contents(\dirname(__DIR__, 3).'/Fixtures/document.pdf'),
+ 'body' => file_get_contents(\dirname(__DIR__, 7).'/fixtures/document.pdf'),
],
];
yield 'audio from file' => [
- File::fromFile(\dirname(__DIR__, 3).'/Fixtures/audio.mp3'),
+ File::fromFile(\dirname(__DIR__, 7).'/fixtures/audio.mp3'),
[
'headers' => ['Content-Type' => 'audio/mpeg'],
- 'body' => file_get_contents(\dirname(__DIR__, 3).'/Fixtures/audio.mp3'),
+ 'body' => file_get_contents(\dirname(__DIR__, 7).'/fixtures/audio.mp3'),
],
];
diff --git a/src/platform/tests/Bridge/HuggingFace/Contract/MessageBagNormalizerTest.php b/src/platform/src/Bridge/HuggingFace/Tests/Contract/MessageBagNormalizerTest.php
similarity index 98%
rename from src/platform/tests/Bridge/HuggingFace/Contract/MessageBagNormalizerTest.php
rename to src/platform/src/Bridge/HuggingFace/Tests/Contract/MessageBagNormalizerTest.php
index 09af37150..86d8c499a 100644
--- a/src/platform/tests/Bridge/HuggingFace/Contract/MessageBagNormalizerTest.php
+++ b/src/platform/src/Bridge/HuggingFace/Tests/Contract/MessageBagNormalizerTest.php
@@ -9,7 +9,7 @@
* file that was distributed with this source code.
*/
-namespace Symfony\AI\Platform\Tests\Bridge\HuggingFace\Contract;
+namespace Symfony\AI\Platform\Bridge\HuggingFace\Tests\Contract;
use PHPUnit\Framework\Attributes\DataProvider;
use PHPUnit\Framework\TestCase;
diff --git a/src/platform/tests/Bridge/HuggingFace/ModelClientTest.php b/src/platform/src/Bridge/HuggingFace/Tests/ModelClientTest.php
similarity index 99%
rename from src/platform/tests/Bridge/HuggingFace/ModelClientTest.php
rename to src/platform/src/Bridge/HuggingFace/Tests/ModelClientTest.php
index e7b25bf42..c9520ad01 100644
--- a/src/platform/tests/Bridge/HuggingFace/ModelClientTest.php
+++ b/src/platform/src/Bridge/HuggingFace/Tests/ModelClientTest.php
@@ -9,7 +9,7 @@
* file that was distributed with this source code.
*/
-namespace Symfony\AI\Platform\Tests\Bridge\HuggingFace;
+namespace Symfony\AI\Platform\Bridge\HuggingFace\Tests;
use PHPUnit\Framework\Attributes\DataProvider;
use PHPUnit\Framework\TestCase;
diff --git a/src/platform/tests/Bridge/HuggingFace/Output/ClassificationResultTest.php b/src/platform/src/Bridge/HuggingFace/Tests/Output/ClassificationResultTest.php
similarity index 98%
rename from src/platform/tests/Bridge/HuggingFace/Output/ClassificationResultTest.php
rename to src/platform/src/Bridge/HuggingFace/Tests/Output/ClassificationResultTest.php
index 8de3ad6bd..da624134c 100644
--- a/src/platform/tests/Bridge/HuggingFace/Output/ClassificationResultTest.php
+++ b/src/platform/src/Bridge/HuggingFace/Tests/Output/ClassificationResultTest.php
@@ -9,7 +9,7 @@
* file that was distributed with this source code.
*/
-namespace Symfony\AI\Platform\Tests\Bridge\HuggingFace\Output;
+namespace Symfony\AI\Platform\Bridge\HuggingFace\Tests\Output;
use PHPUnit\Framework\Attributes\TestDox;
use PHPUnit\Framework\Attributes\TestWith;
diff --git a/src/platform/tests/Bridge/HuggingFace/Output/ClassificationTest.php b/src/platform/src/Bridge/HuggingFace/Tests/Output/ClassificationTest.php
similarity index 96%
rename from src/platform/tests/Bridge/HuggingFace/Output/ClassificationTest.php
rename to src/platform/src/Bridge/HuggingFace/Tests/Output/ClassificationTest.php
index e5b7a80c0..1e288f058 100644
--- a/src/platform/tests/Bridge/HuggingFace/Output/ClassificationTest.php
+++ b/src/platform/src/Bridge/HuggingFace/Tests/Output/ClassificationTest.php
@@ -9,7 +9,7 @@
* file that was distributed with this source code.
*/
-namespace Symfony\AI\Platform\Tests\Bridge\HuggingFace\Output;
+namespace Symfony\AI\Platform\Bridge\HuggingFace\Tests\Output;
use PHPUnit\Framework\Attributes\TestDox;
use PHPUnit\Framework\Attributes\TestWith;
diff --git a/src/platform/tests/Bridge/HuggingFace/Output/DetectedObjectTest.php b/src/platform/src/Bridge/HuggingFace/Tests/Output/DetectedObjectTest.php
similarity index 98%
rename from src/platform/tests/Bridge/HuggingFace/Output/DetectedObjectTest.php
rename to src/platform/src/Bridge/HuggingFace/Tests/Output/DetectedObjectTest.php
index b87c9994b..fbfb31c59 100644
--- a/src/platform/tests/Bridge/HuggingFace/Output/DetectedObjectTest.php
+++ b/src/platform/src/Bridge/HuggingFace/Tests/Output/DetectedObjectTest.php
@@ -9,7 +9,7 @@
* file that was distributed with this source code.
*/
-namespace Symfony\AI\Platform\Tests\Bridge\HuggingFace\Output;
+namespace Symfony\AI\Platform\Bridge\HuggingFace\Tests\Output;
use PHPUnit\Framework\Attributes\TestDox;
use PHPUnit\Framework\Attributes\TestWith;
diff --git a/src/platform/tests/Bridge/HuggingFace/Output/FillMaskResultTest.php b/src/platform/src/Bridge/HuggingFace/Tests/Output/FillMaskResultTest.php
similarity index 99%
rename from src/platform/tests/Bridge/HuggingFace/Output/FillMaskResultTest.php
rename to src/platform/src/Bridge/HuggingFace/Tests/Output/FillMaskResultTest.php
index d8f7399cb..ed10663f5 100644
--- a/src/platform/tests/Bridge/HuggingFace/Output/FillMaskResultTest.php
+++ b/src/platform/src/Bridge/HuggingFace/Tests/Output/FillMaskResultTest.php
@@ -9,7 +9,7 @@
* file that was distributed with this source code.
*/
-namespace Symfony\AI\Platform\Tests\Bridge\HuggingFace\Output;
+namespace Symfony\AI\Platform\Bridge\HuggingFace\Tests\Output;
use PHPUnit\Framework\Attributes\TestDox;
use PHPUnit\Framework\TestCase;
diff --git a/src/platform/tests/Bridge/HuggingFace/Output/ImageSegmentTest.php b/src/platform/src/Bridge/HuggingFace/Tests/Output/ImageSegmentTest.php
similarity index 98%
rename from src/platform/tests/Bridge/HuggingFace/Output/ImageSegmentTest.php
rename to src/platform/src/Bridge/HuggingFace/Tests/Output/ImageSegmentTest.php
index 2eeb624f1..af731939d 100644
--- a/src/platform/tests/Bridge/HuggingFace/Output/ImageSegmentTest.php
+++ b/src/platform/src/Bridge/HuggingFace/Tests/Output/ImageSegmentTest.php
@@ -9,7 +9,7 @@
* file that was distributed with this source code.
*/
-namespace Symfony\AI\Platform\Tests\Bridge\HuggingFace\Output;
+namespace Symfony\AI\Platform\Bridge\HuggingFace\Tests\Output;
use PHPUnit\Framework\Attributes\TestDox;
use PHPUnit\Framework\Attributes\TestWith;
diff --git a/src/platform/tests/Bridge/HuggingFace/Output/ImageSegmentationResultTest.php b/src/platform/src/Bridge/HuggingFace/Tests/Output/ImageSegmentationResultTest.php
similarity index 99%
rename from src/platform/tests/Bridge/HuggingFace/Output/ImageSegmentationResultTest.php
rename to src/platform/src/Bridge/HuggingFace/Tests/Output/ImageSegmentationResultTest.php
index 222166a1c..75e5c73be 100644
--- a/src/platform/tests/Bridge/HuggingFace/Output/ImageSegmentationResultTest.php
+++ b/src/platform/src/Bridge/HuggingFace/Tests/Output/ImageSegmentationResultTest.php
@@ -9,7 +9,7 @@
* file that was distributed with this source code.
*/
-namespace Symfony\AI\Platform\Tests\Bridge\HuggingFace\Output;
+namespace Symfony\AI\Platform\Bridge\HuggingFace\Tests\Output;
use PHPUnit\Framework\Attributes\TestDox;
use PHPUnit\Framework\TestCase;
diff --git a/src/platform/tests/Bridge/HuggingFace/Output/MaskFillTest.php b/src/platform/src/Bridge/HuggingFace/Tests/Output/MaskFillTest.php
similarity index 98%
rename from src/platform/tests/Bridge/HuggingFace/Output/MaskFillTest.php
rename to src/platform/src/Bridge/HuggingFace/Tests/Output/MaskFillTest.php
index 465798703..0d51add29 100644
--- a/src/platform/tests/Bridge/HuggingFace/Output/MaskFillTest.php
+++ b/src/platform/src/Bridge/HuggingFace/Tests/Output/MaskFillTest.php
@@ -9,7 +9,7 @@
* file that was distributed with this source code.
*/
-namespace Symfony\AI\Platform\Tests\Bridge\HuggingFace\Output;
+namespace Symfony\AI\Platform\Bridge\HuggingFace\Tests\Output;
use PHPUnit\Framework\Attributes\TestDox;
use PHPUnit\Framework\Attributes\TestWith;
diff --git a/src/platform/tests/Bridge/HuggingFace/Output/ObjectDetectionResultTest.php b/src/platform/src/Bridge/HuggingFace/Tests/Output/ObjectDetectionResultTest.php
similarity index 99%
rename from src/platform/tests/Bridge/HuggingFace/Output/ObjectDetectionResultTest.php
rename to src/platform/src/Bridge/HuggingFace/Tests/Output/ObjectDetectionResultTest.php
index 5e43dd406..4c543072f 100644
--- a/src/platform/tests/Bridge/HuggingFace/Output/ObjectDetectionResultTest.php
+++ b/src/platform/src/Bridge/HuggingFace/Tests/Output/ObjectDetectionResultTest.php
@@ -9,7 +9,7 @@
* file that was distributed with this source code.
*/
-namespace Symfony\AI\Platform\Tests\Bridge\HuggingFace\Output;
+namespace Symfony\AI\Platform\Bridge\HuggingFace\Tests\Output;
use PHPUnit\Framework\Attributes\TestDox;
use PHPUnit\Framework\TestCase;
diff --git a/src/platform/tests/Bridge/HuggingFace/Output/QuestionAnsweringResultTest.php b/src/platform/src/Bridge/HuggingFace/Tests/Output/QuestionAnsweringResultTest.php
similarity index 98%
rename from src/platform/tests/Bridge/HuggingFace/Output/QuestionAnsweringResultTest.php
rename to src/platform/src/Bridge/HuggingFace/Tests/Output/QuestionAnsweringResultTest.php
index 609a566ff..8a67e9850 100644
--- a/src/platform/tests/Bridge/HuggingFace/Output/QuestionAnsweringResultTest.php
+++ b/src/platform/src/Bridge/HuggingFace/Tests/Output/QuestionAnsweringResultTest.php
@@ -9,7 +9,7 @@
* file that was distributed with this source code.
*/
-namespace Symfony\AI\Platform\Tests\Bridge\HuggingFace\Output;
+namespace Symfony\AI\Platform\Bridge\HuggingFace\Tests\Output;
use PHPUnit\Framework\Attributes\TestDox;
use PHPUnit\Framework\Attributes\TestWith;
diff --git a/src/platform/tests/Bridge/HuggingFace/Output/SentenceSimilarityResultTest.php b/src/platform/src/Bridge/HuggingFace/Tests/Output/SentenceSimilarityResultTest.php
similarity index 98%
rename from src/platform/tests/Bridge/HuggingFace/Output/SentenceSimilarityResultTest.php
rename to src/platform/src/Bridge/HuggingFace/Tests/Output/SentenceSimilarityResultTest.php
index 6a39380de..7631f2ae2 100644
--- a/src/platform/tests/Bridge/HuggingFace/Output/SentenceSimilarityResultTest.php
+++ b/src/platform/src/Bridge/HuggingFace/Tests/Output/SentenceSimilarityResultTest.php
@@ -9,7 +9,7 @@
* file that was distributed with this source code.
*/
-namespace Symfony\AI\Platform\Tests\Bridge\HuggingFace\Output;
+namespace Symfony\AI\Platform\Bridge\HuggingFace\Tests\Output;
use PHPUnit\Framework\Attributes\TestDox;
use PHPUnit\Framework\Attributes\TestWith;
diff --git a/src/platform/tests/Bridge/HuggingFace/Output/TableQuestionAnsweringResultTest.php b/src/platform/src/Bridge/HuggingFace/Tests/Output/TableQuestionAnsweringResultTest.php
similarity index 99%
rename from src/platform/tests/Bridge/HuggingFace/Output/TableQuestionAnsweringResultTest.php
rename to src/platform/src/Bridge/HuggingFace/Tests/Output/TableQuestionAnsweringResultTest.php
index 5f0d3e92c..69bdf5a10 100644
--- a/src/platform/tests/Bridge/HuggingFace/Output/TableQuestionAnsweringResultTest.php
+++ b/src/platform/src/Bridge/HuggingFace/Tests/Output/TableQuestionAnsweringResultTest.php
@@ -9,7 +9,7 @@
* file that was distributed with this source code.
*/
-namespace Symfony\AI\Platform\Tests\Bridge\HuggingFace\Output;
+namespace Symfony\AI\Platform\Bridge\HuggingFace\Tests\Output;
use PHPUnit\Framework\Attributes\TestDox;
use PHPUnit\Framework\Attributes\TestWith;
diff --git a/src/platform/tests/Bridge/HuggingFace/Output/TokenClassificationResultTest.php b/src/platform/src/Bridge/HuggingFace/Tests/Output/TokenClassificationResultTest.php
similarity index 99%
rename from src/platform/tests/Bridge/HuggingFace/Output/TokenClassificationResultTest.php
rename to src/platform/src/Bridge/HuggingFace/Tests/Output/TokenClassificationResultTest.php
index c8b9425ce..dc771d92e 100644
--- a/src/platform/tests/Bridge/HuggingFace/Output/TokenClassificationResultTest.php
+++ b/src/platform/src/Bridge/HuggingFace/Tests/Output/TokenClassificationResultTest.php
@@ -9,7 +9,7 @@
* file that was distributed with this source code.
*/
-namespace Symfony\AI\Platform\Tests\Bridge\HuggingFace\Output;
+namespace Symfony\AI\Platform\Bridge\HuggingFace\Tests\Output;
use PHPUnit\Framework\Attributes\TestDox;
use PHPUnit\Framework\Attributes\TestWith;
diff --git a/src/platform/tests/Bridge/HuggingFace/Output/TokenTest.php b/src/platform/src/Bridge/HuggingFace/Tests/Output/TokenTest.php
similarity index 98%
rename from src/platform/tests/Bridge/HuggingFace/Output/TokenTest.php
rename to src/platform/src/Bridge/HuggingFace/Tests/Output/TokenTest.php
index feefd29cd..1ae649787 100644
--- a/src/platform/tests/Bridge/HuggingFace/Output/TokenTest.php
+++ b/src/platform/src/Bridge/HuggingFace/Tests/Output/TokenTest.php
@@ -9,7 +9,7 @@
* file that was distributed with this source code.
*/
-namespace Symfony\AI\Platform\Tests\Bridge\HuggingFace\Output;
+namespace Symfony\AI\Platform\Bridge\HuggingFace\Tests\Output;
use PHPUnit\Framework\Attributes\TestDox;
use PHPUnit\Framework\Attributes\TestWith;
diff --git a/src/platform/tests/Bridge/HuggingFace/Output/ZeroShotClassificationResultTest.php b/src/platform/src/Bridge/HuggingFace/Tests/Output/ZeroShotClassificationResultTest.php
similarity index 99%
rename from src/platform/tests/Bridge/HuggingFace/Output/ZeroShotClassificationResultTest.php
rename to src/platform/src/Bridge/HuggingFace/Tests/Output/ZeroShotClassificationResultTest.php
index 5858f14ee..0377fa827 100644
--- a/src/platform/tests/Bridge/HuggingFace/Output/ZeroShotClassificationResultTest.php
+++ b/src/platform/src/Bridge/HuggingFace/Tests/Output/ZeroShotClassificationResultTest.php
@@ -9,7 +9,7 @@
* file that was distributed with this source code.
*/
-namespace Symfony\AI\Platform\Tests\Bridge\HuggingFace\Output;
+namespace Symfony\AI\Platform\Bridge\HuggingFace\Tests\Output;
use PHPUnit\Framework\Attributes\TestDox;
use PHPUnit\Framework\Attributes\TestWith;
diff --git a/src/platform/tests/Bridge/HuggingFace/PlatformFactoryTest.php b/src/platform/src/Bridge/HuggingFace/Tests/PlatformFactoryTest.php
similarity index 97%
rename from src/platform/tests/Bridge/HuggingFace/PlatformFactoryTest.php
rename to src/platform/src/Bridge/HuggingFace/Tests/PlatformFactoryTest.php
index 559681211..ff5fa6b52 100644
--- a/src/platform/tests/Bridge/HuggingFace/PlatformFactoryTest.php
+++ b/src/platform/src/Bridge/HuggingFace/Tests/PlatformFactoryTest.php
@@ -9,7 +9,7 @@
* file that was distributed with this source code.
*/
-namespace Symfony\AI\Platform\Tests\Bridge\HuggingFace;
+namespace Symfony\AI\Platform\Bridge\HuggingFace\Tests;
use PHPUnit\Framework\Attributes\TestDox;
use PHPUnit\Framework\Attributes\TestWith;
diff --git a/src/platform/tests/Bridge/HuggingFace/ResultConverterTest.php b/src/platform/src/Bridge/HuggingFace/Tests/ResultConverterTest.php
similarity index 99%
rename from src/platform/tests/Bridge/HuggingFace/ResultConverterTest.php
rename to src/platform/src/Bridge/HuggingFace/Tests/ResultConverterTest.php
index 91d055dac..58941b382 100644
--- a/src/platform/tests/Bridge/HuggingFace/ResultConverterTest.php
+++ b/src/platform/src/Bridge/HuggingFace/Tests/ResultConverterTest.php
@@ -9,7 +9,7 @@
* file that was distributed with this source code.
*/
-namespace Symfony\AI\Platform\Tests\Bridge\HuggingFace;
+namespace Symfony\AI\Platform\Bridge\HuggingFace\Tests;
use PHPUnit\Framework\Attributes\TestDox;
use PHPUnit\Framework\Attributes\TestWith;
diff --git a/src/platform/src/Bridge/HuggingFace/composer.json b/src/platform/src/Bridge/HuggingFace/composer.json
new file mode 100644
index 000000000..ae2624541
--- /dev/null
+++ b/src/platform/src/Bridge/HuggingFace/composer.json
@@ -0,0 +1,61 @@
+{
+ "name": "symfony/ai-hugging-face-platform",
+ "description": "HuggingFace platform bridge for Symfony AI",
+ "license": "MIT",
+ "type": "symfony-ai-platform",
+ "keywords": [
+ "ai",
+ "bridge",
+ "huggingface",
+ "platform"
+ ],
+ "authors": [
+ {
+ "name": "Christopher Hertel",
+ "email": "mail@christopher-hertel.de"
+ },
+ {
+ "name": "Oskar Stark",
+ "email": "oskarstark@googlemail.com"
+ },
+ {
+ "name": "Symfony Community",
+ "homepage": "https://symfony.com/contributors"
+ }
+ ],
+ "require": {
+ "php": ">=8.2",
+ "symfony/ai-platform": "@dev",
+ "symfony/console": "^7.3|^8.0",
+ "symfony/http-client": "^7.3|^8.0"
+ },
+ "require-dev": {
+ "phpstan/phpstan": "^2.1",
+ "phpstan/phpstan-strict-rules": "^2.0",
+ "phpunit/phpunit": "^11.5.46"
+ },
+ "minimum-stability": "dev",
+ "autoload": {
+ "psr-4": {
+ "Symfony\\AI\\Platform\\Bridge\\HuggingFace\\": ""
+ }
+ },
+ "autoload-dev": {
+ "psr-4": {
+ "Symfony\\AI\\PHPStan\\": "../../../../../.phpstan/",
+ "Symfony\\AI\\Platform\\Bridge\\HuggingFace\\Tests\\": "Tests/"
+ }
+ },
+ "config": {
+ "sort-packages": true
+ },
+ "extra": {
+ "branch-alias": {
+ "dev-main": "0.x-dev"
+ },
+ "thanks": {
+ "name": "symfony/ai",
+ "url": "https://github.com/symfony/ai"
+ }
+ }
+}
diff --git a/src/platform/src/Bridge/HuggingFace/phpstan.dist.neon b/src/platform/src/Bridge/HuggingFace/phpstan.dist.neon
new file mode 100644
index 000000000..5503dac38
--- /dev/null
+++ b/src/platform/src/Bridge/HuggingFace/phpstan.dist.neon
@@ -0,0 +1,23 @@
+includes:
+ - ../../../../../.phpstan/extension.neon
+
+parameters:
+ level: 6
+ paths:
+ - .
+ - Tests/
+ excludePaths:
+ - vendor/
+ treatPhpDocTypesAsCertain: false
+ ignoreErrors:
+ -
+ message: "#^Method .*::test.*\\(\\) has no return type specified\\.$#"
+ reportUnmatched: false
+ -
+ identifier: missingType.iterableValue
+ path: Tests/*
+ reportUnmatched: false
+ -
+ identifier: 'symfonyAi.forbidNativeException'
+ path: Tests/*
+ reportUnmatched: false
diff --git a/src/platform/src/Bridge/HuggingFace/phpunit.xml.dist b/src/platform/src/Bridge/HuggingFace/phpunit.xml.dist
new file mode 100644
index 000000000..3abdf23e9
--- /dev/null
+++ b/src/platform/src/Bridge/HuggingFace/phpunit.xml.dist
@@ -0,0 +1,32 @@
+
+
+
+
+
+
+
+
+
+ ./Tests/
+
+
+
+
+
+ ./
+
+
+ ./Resources
+ ./Tests
+ ./vendor
+
+
+
diff --git a/src/platform/src/Bridge/LmStudio/README.md b/src/platform/src/Bridge/LmStudio/README.md
new file mode 100644
index 000000000..ef286139d
--- /dev/null
+++ b/src/platform/src/Bridge/LmStudio/README.md
@@ -0,0 +1,12 @@
+LmStudio Platform
+=================
+
+LM Studio platform bridge for Symfony AI.
+
+Resources
+---------
+
+ * [Contributing](https://symfony.com/doc/current/contributing/index.html)
+ * [Report issues](https://github.com/symfony/ai/issues) and
+ [send Pull Requests](https://github.com/symfony/ai/pulls)
+ in the [main Symfony AI repository](https://github.com/symfony/ai)
diff --git a/src/platform/tests/Bridge/LmStudio/ModelCatalogTest.php b/src/platform/src/Bridge/LmStudio/Tests/ModelCatalogTest.php
similarity index 96%
rename from src/platform/tests/Bridge/LmStudio/ModelCatalogTest.php
rename to src/platform/src/Bridge/LmStudio/Tests/ModelCatalogTest.php
index f768f370e..50b14ece2 100644
--- a/src/platform/tests/Bridge/LmStudio/ModelCatalogTest.php
+++ b/src/platform/src/Bridge/LmStudio/Tests/ModelCatalogTest.php
@@ -9,7 +9,7 @@
* file that was distributed with this source code.
*/
-namespace Symfony\AI\Platform\Tests\Bridge\LmStudio;
+namespace Symfony\AI\Platform\Bridge\LmStudio\Tests;
use Symfony\AI\Platform\Bridge\Generic\CompletionsModel;
use Symfony\AI\Platform\Bridge\Generic\EmbeddingsModel;
diff --git a/src/platform/tests/Bridge/LmStudio/PlatformFactoryTest.php b/src/platform/src/Bridge/LmStudio/Tests/PlatformFactoryTest.php
similarity index 96%
rename from src/platform/tests/Bridge/LmStudio/PlatformFactoryTest.php
rename to src/platform/src/Bridge/LmStudio/Tests/PlatformFactoryTest.php
index 8ea4d2a59..d640e8193 100644
--- a/src/platform/tests/Bridge/LmStudio/PlatformFactoryTest.php
+++ b/src/platform/src/Bridge/LmStudio/Tests/PlatformFactoryTest.php
@@ -9,7 +9,7 @@
* file that was distributed with this source code.
*/
-namespace Symfony\AI\Platform\Tests\Bridge\LmStudio;
+namespace Symfony\AI\Platform\Bridge\LmStudio\Tests;
use PHPUnit\Framework\TestCase;
use Symfony\AI\Platform\Bridge\LmStudio\PlatformFactory;
diff --git a/src/platform/src/Bridge/LmStudio/composer.json b/src/platform/src/Bridge/LmStudio/composer.json
new file mode 100644
index 000000000..644244597
--- /dev/null
+++ b/src/platform/src/Bridge/LmStudio/composer.json
@@ -0,0 +1,62 @@
+{
+ "name": "symfony/ai-lm-studio-platform",
+ "description": "LM Studio platform bridge for Symfony AI",
+ "license": "MIT",
+ "type": "symfony-ai-platform",
+ "keywords": [
+ "ai",
+ "bridge",
+ "lmstudio",
+ "local",
+ "platform"
+ ],
+ "authors": [
+ {
+ "name": "Christopher Hertel",
+ "email": "mail@christopher-hertel.de"
+ },
+ {
+ "name": "Oskar Stark",
+ "email": "oskarstark@googlemail.com"
+ },
+ {
+ "name": "Symfony Community",
+ "homepage": "https://symfony.com/contributors"
+ }
+ ],
+ "require": {
+ "php": ">=8.2",
+ "symfony/ai-generic-platform": "@dev",
+ "symfony/ai-platform": "@dev",
+ "symfony/http-client": "^7.3|^8.0"
+ },
+ "require-dev": {
+ "phpstan/phpstan": "^2.1",
+ "phpstan/phpstan-strict-rules": "^2.0",
+ "phpunit/phpunit": "^11.5.46"
+ },
+ "minimum-stability": "dev",
+ "autoload": {
+ "psr-4": {
+ "Symfony\\AI\\Platform\\Bridge\\LmStudio\\": ""
+ }
+ },
+ "autoload-dev": {
+ "psr-4": {
+ "Symfony\\AI\\PHPStan\\": "../../../../../.phpstan/",
+ "Symfony\\AI\\Platform\\Bridge\\LmStudio\\Tests\\": "Tests/"
+ }
+ },
+ "config": {
+ "sort-packages": true
+ },
+ "extra": {
+ "branch-alias": {
+ "dev-main": "0.x-dev"
+ },
+ "thanks": {
+ "name": "symfony/ai",
+ "url": "https://github.com/symfony/ai"
+ }
+ }
+}
diff --git a/src/platform/src/Bridge/LmStudio/phpstan.dist.neon b/src/platform/src/Bridge/LmStudio/phpstan.dist.neon
new file mode 100644
index 000000000..5503dac38
--- /dev/null
+++ b/src/platform/src/Bridge/LmStudio/phpstan.dist.neon
@@ -0,0 +1,23 @@
+includes:
+ - ../../../../../.phpstan/extension.neon
+
+parameters:
+ level: 6
+ paths:
+ - .
+ - Tests/
+ excludePaths:
+ - vendor/
+ treatPhpDocTypesAsCertain: false
+ ignoreErrors:
+ -
+ message: "#^Method .*::test.*\\(\\) has no return type specified\\.$#"
+ reportUnmatched: false
+ -
+ identifier: missingType.iterableValue
+ path: Tests/*
+ reportUnmatched: false
+ -
+ identifier: 'symfonyAi.forbidNativeException'
+ path: Tests/*
+ reportUnmatched: false
diff --git a/src/platform/src/Bridge/LmStudio/phpunit.xml.dist b/src/platform/src/Bridge/LmStudio/phpunit.xml.dist
new file mode 100644
index 000000000..4481a7882
--- /dev/null
+++ b/src/platform/src/Bridge/LmStudio/phpunit.xml.dist
@@ -0,0 +1,32 @@
+
+
+
+
+
+
+
+
+
+ ./Tests/
+
+
+
+
+
+ ./
+
+
+ ./Resources
+ ./Tests
+ ./vendor
+
+
+
diff --git a/src/platform/src/Bridge/Meta/README.md b/src/platform/src/Bridge/Meta/README.md
new file mode 100644
index 000000000..06495c738
--- /dev/null
+++ b/src/platform/src/Bridge/Meta/README.md
@@ -0,0 +1,12 @@
+Meta Platform
+=============
+
+Meta (Llama) platform bridge for Symfony AI.
+
+Resources
+---------
+
+ * [Contributing](https://symfony.com/doc/current/contributing/index.html)
+ * [Report issues](https://github.com/symfony/ai/issues) and
+ [send Pull Requests](https://github.com/symfony/ai/pulls)
+ in the [main Symfony AI repository](https://github.com/symfony/ai)
diff --git a/src/platform/tests/Bridge/Meta/LlamaPromptConverterTest.php b/src/platform/src/Bridge/Meta/Tests/LlamaPromptConverterTest.php
similarity index 98%
rename from src/platform/tests/Bridge/Meta/LlamaPromptConverterTest.php
rename to src/platform/src/Bridge/Meta/Tests/LlamaPromptConverterTest.php
index 0f133be00..3dacf371a 100644
--- a/src/platform/tests/Bridge/Meta/LlamaPromptConverterTest.php
+++ b/src/platform/src/Bridge/Meta/Tests/LlamaPromptConverterTest.php
@@ -9,7 +9,7 @@
* file that was distributed with this source code.
*/
-namespace Symfony\AI\Platform\Tests\Bridge\Meta;
+namespace Symfony\AI\Platform\Bridge\Meta\Tests;
use PHPUnit\Framework\Attributes\DataProvider;
use PHPUnit\Framework\TestCase;
diff --git a/src/platform/tests/Bridge/Meta/ModelCatalogTest.php b/src/platform/src/Bridge/Meta/Tests/ModelCatalogTest.php
similarity index 98%
rename from src/platform/tests/Bridge/Meta/ModelCatalogTest.php
rename to src/platform/src/Bridge/Meta/Tests/ModelCatalogTest.php
index f5e8b922f..26992bbae 100644
--- a/src/platform/tests/Bridge/Meta/ModelCatalogTest.php
+++ b/src/platform/src/Bridge/Meta/Tests/ModelCatalogTest.php
@@ -9,7 +9,7 @@
* file that was distributed with this source code.
*/
-namespace Symfony\AI\Platform\Tests\Bridge\Meta;
+namespace Symfony\AI\Platform\Bridge\Meta\Tests;
use Symfony\AI\Platform\Bridge\Meta\Llama;
use Symfony\AI\Platform\Bridge\Meta\ModelCatalog;
diff --git a/src/platform/src/Bridge/Meta/composer.json b/src/platform/src/Bridge/Meta/composer.json
new file mode 100644
index 000000000..c7da0c71d
--- /dev/null
+++ b/src/platform/src/Bridge/Meta/composer.json
@@ -0,0 +1,60 @@
+{
+ "name": "symfony/ai-meta-platform",
+ "description": "Meta (Llama) platform bridge for Symfony AI",
+ "license": "MIT",
+ "type": "symfony-ai-platform",
+ "keywords": [
+ "ai",
+ "bridge",
+ "llama",
+ "meta",
+ "platform"
+ ],
+ "authors": [
+ {
+ "name": "Christopher Hertel",
+ "email": "mail@christopher-hertel.de"
+ },
+ {
+ "name": "Oskar Stark",
+ "email": "oskarstark@googlemail.com"
+ },
+ {
+ "name": "Symfony Community",
+ "homepage": "https://symfony.com/contributors"
+ }
+ ],
+ "require": {
+ "php": ">=8.2",
+ "symfony/ai-platform": "@dev"
+ },
+ "require-dev": {
+ "phpstan/phpstan": "^2.1",
+ "phpstan/phpstan-strict-rules": "^2.0",
+ "phpunit/phpunit": "^11.5.46"
+ },
+ "minimum-stability": "dev",
+ "autoload": {
+ "psr-4": {
+ "Symfony\\AI\\Platform\\Bridge\\Meta\\": ""
+ }
+ },
+ "autoload-dev": {
+ "psr-4": {
+ "Symfony\\AI\\PHPStan\\": "../../../../../.phpstan/",
+ "Symfony\\AI\\Platform\\Bridge\\Meta\\Tests\\": "Tests/"
+ }
+ },
+ "config": {
+ "sort-packages": true
+ },
+ "extra": {
+ "branch-alias": {
+ "dev-main": "0.x-dev"
+ },
+ "thanks": {
+ "name": "symfony/ai",
+ "url": "https://github.com/symfony/ai"
+ }
+ }
+}
diff --git a/src/platform/src/Bridge/Meta/phpstan.dist.neon b/src/platform/src/Bridge/Meta/phpstan.dist.neon
new file mode 100644
index 000000000..5503dac38
--- /dev/null
+++ b/src/platform/src/Bridge/Meta/phpstan.dist.neon
@@ -0,0 +1,23 @@
+includes:
+ - ../../../../../.phpstan/extension.neon
+
+parameters:
+ level: 6
+ paths:
+ - .
+ - Tests/
+ excludePaths:
+ - vendor/
+ treatPhpDocTypesAsCertain: false
+ ignoreErrors:
+ -
+ message: "#^Method .*::test.*\\(\\) has no return type specified\\.$#"
+ reportUnmatched: false
+ -
+ identifier: missingType.iterableValue
+ path: Tests/*
+ reportUnmatched: false
+ -
+ identifier: 'symfonyAi.forbidNativeException'
+ path: Tests/*
+ reportUnmatched: false
diff --git a/src/platform/src/Bridge/Meta/phpunit.xml.dist b/src/platform/src/Bridge/Meta/phpunit.xml.dist
new file mode 100644
index 000000000..15ddf4779
--- /dev/null
+++ b/src/platform/src/Bridge/Meta/phpunit.xml.dist
@@ -0,0 +1,32 @@
+
+
+
+
+
+
+
+
+
+ ./Tests/
+
+
+
+
+
+ ./
+
+
+ ./Resources
+ ./Tests
+ ./vendor
+
+
+
diff --git a/src/platform/src/Bridge/Mistral/README.md b/src/platform/src/Bridge/Mistral/README.md
new file mode 100644
index 000000000..de50da226
--- /dev/null
+++ b/src/platform/src/Bridge/Mistral/README.md
@@ -0,0 +1,12 @@
+Mistral Platform
+================
+
+Mistral platform bridge for Symfony AI.
+
+Resources
+---------
+
+ * [Contributing](https://symfony.com/doc/current/contributing/index.html)
+ * [Report issues](https://github.com/symfony/ai/issues) and
+ [send Pull Requests](https://github.com/symfony/ai/pulls)
+ in the [main Symfony AI repository](https://github.com/symfony/ai)
diff --git a/src/platform/tests/Bridge/Mistral/Contract/DocumentNormalizerTest.php b/src/platform/src/Bridge/Mistral/Tests/Contract/DocumentNormalizerTest.php
similarity index 88%
rename from src/platform/tests/Bridge/Mistral/Contract/DocumentNormalizerTest.php
rename to src/platform/src/Bridge/Mistral/Tests/Contract/DocumentNormalizerTest.php
index e418e72bc..f53366cfc 100644
--- a/src/platform/tests/Bridge/Mistral/Contract/DocumentNormalizerTest.php
+++ b/src/platform/src/Bridge/Mistral/Tests/Contract/DocumentNormalizerTest.php
@@ -9,7 +9,7 @@
* file that was distributed with this source code.
*/
-namespace Symfony\AI\Platform\Tests\Bridge\Mistral\Contract;
+namespace Symfony\AI\Platform\Bridge\Mistral\Tests\Contract;
use PHPUnit\Framework\Attributes\DataProvider;
use PHPUnit\Framework\TestCase;
@@ -54,11 +54,11 @@ public function testNormalize(Document $file, array $expected)
public static function normalizeDataProvider(): iterable
{
yield 'document from file' => [
- Document::fromFile(\dirname(__DIR__, 3).'/Fixtures/document.pdf'),
+ Document::fromFile(\dirname(__DIR__, 5).'/tests/Fixtures/document.pdf'),
[
'type' => 'document_url',
'document_name' => 'document.pdf',
- 'document_url' => 'data:application/pdf;base64,'.base64_encode(file_get_contents(\dirname(__DIR__, 3).'/Fixtures/document.pdf')),
+ 'document_url' => 'data:application/pdf;base64,'.base64_encode(file_get_contents(\dirname(__DIR__, 5).'/tests/Fixtures/document.pdf')),
],
];
}
diff --git a/src/platform/tests/Bridge/Mistral/Contract/DocumentUrlNormalizerTest.php b/src/platform/src/Bridge/Mistral/Tests/Contract/DocumentUrlNormalizerTest.php
similarity index 96%
rename from src/platform/tests/Bridge/Mistral/Contract/DocumentUrlNormalizerTest.php
rename to src/platform/src/Bridge/Mistral/Tests/Contract/DocumentUrlNormalizerTest.php
index 573e24091..536497866 100644
--- a/src/platform/tests/Bridge/Mistral/Contract/DocumentUrlNormalizerTest.php
+++ b/src/platform/src/Bridge/Mistral/Tests/Contract/DocumentUrlNormalizerTest.php
@@ -9,7 +9,7 @@
* file that was distributed with this source code.
*/
-namespace Symfony\AI\Platform\Tests\Bridge\Mistral\Contract;
+namespace Symfony\AI\Platform\Bridge\Mistral\Tests\Contract;
use PHPUnit\Framework\Attributes\DataProvider;
use PHPUnit\Framework\TestCase;
diff --git a/src/platform/tests/Bridge/Mistral/Contract/ImageUrlNormalizerTest.php b/src/platform/src/Bridge/Mistral/Tests/Contract/ImageUrlNormalizerTest.php
similarity index 100%
rename from src/platform/tests/Bridge/Mistral/Contract/ImageUrlNormalizerTest.php
rename to src/platform/src/Bridge/Mistral/Tests/Contract/ImageUrlNormalizerTest.php
diff --git a/src/platform/tests/Bridge/Mistral/ModelCatalogTest.php b/src/platform/src/Bridge/Mistral/Tests/ModelCatalogTest.php
similarity index 98%
rename from src/platform/tests/Bridge/Mistral/ModelCatalogTest.php
rename to src/platform/src/Bridge/Mistral/Tests/ModelCatalogTest.php
index eea0290df..542d83958 100644
--- a/src/platform/tests/Bridge/Mistral/ModelCatalogTest.php
+++ b/src/platform/src/Bridge/Mistral/Tests/ModelCatalogTest.php
@@ -9,7 +9,7 @@
* file that was distributed with this source code.
*/
-namespace Symfony\AI\Platform\Tests\Bridge\Mistral;
+namespace Symfony\AI\Platform\Bridge\Mistral\Tests;
use Symfony\AI\Platform\Bridge\Mistral\Embeddings;
use Symfony\AI\Platform\Bridge\Mistral\Mistral;
diff --git a/src/platform/tests/Bridge/Mistral/TokenUsageExtractorTest.php b/src/platform/src/Bridge/Mistral/Tests/TokenUsageExtractorTest.php
similarity index 100%
rename from src/platform/tests/Bridge/Mistral/TokenUsageExtractorTest.php
rename to src/platform/src/Bridge/Mistral/Tests/TokenUsageExtractorTest.php
diff --git a/src/platform/src/Bridge/Mistral/composer.json b/src/platform/src/Bridge/Mistral/composer.json
new file mode 100644
index 000000000..bc0bd985e
--- /dev/null
+++ b/src/platform/src/Bridge/Mistral/composer.json
@@ -0,0 +1,60 @@
+{
+ "name": "symfony/ai-mistral-platform",
+ "description": "Mistral platform bridge for Symfony AI",
+ "license": "MIT",
+ "type": "symfony-ai-platform",
+ "keywords": [
+ "ai",
+ "bridge",
+ "mistral",
+ "platform"
+ ],
+ "authors": [
+ {
+ "name": "Christopher Hertel",
+ "email": "mail@christopher-hertel.de"
+ },
+ {
+ "name": "Oskar Stark",
+ "email": "oskarstark@googlemail.com"
+ },
+ {
+ "name": "Symfony Community",
+ "homepage": "https://symfony.com/contributors"
+ }
+ ],
+ "require": {
+ "php": ">=8.2",
+ "symfony/ai-platform": "@dev",
+ "symfony/http-client": "^7.3|^8.0"
+ },
+ "require-dev": {
+ "phpstan/phpstan": "^2.1",
+ "phpstan/phpstan-strict-rules": "^2.0",
+ "phpunit/phpunit": "^11.5.46"
+ },
+ "minimum-stability": "dev",
+ "autoload": {
+ "psr-4": {
+ "Symfony\\AI\\Platform\\Bridge\\Mistral\\": ""
+ }
+ },
+ "autoload-dev": {
+ "psr-4": {
+ "Symfony\\AI\\PHPStan\\": "../../../../../.phpstan/",
+ "Symfony\\AI\\Platform\\Bridge\\Mistral\\Tests\\": "Tests/"
+ }
+ },
+ "config": {
+ "sort-packages": true
+ },
+ "extra": {
+ "branch-alias": {
+ "dev-main": "0.x-dev"
+ },
+ "thanks": {
+ "name": "symfony/ai",
+ "url": "https://github.com/symfony/ai"
+ }
+ }
+}
diff --git a/src/platform/src/Bridge/Mistral/phpstan.dist.neon b/src/platform/src/Bridge/Mistral/phpstan.dist.neon
new file mode 100644
index 000000000..5503dac38
--- /dev/null
+++ b/src/platform/src/Bridge/Mistral/phpstan.dist.neon
@@ -0,0 +1,23 @@
+includes:
+ - ../../../../../.phpstan/extension.neon
+
+parameters:
+ level: 6
+ paths:
+ - .
+ - Tests/
+ excludePaths:
+ - vendor/
+ treatPhpDocTypesAsCertain: false
+ ignoreErrors:
+ -
+ message: "#^Method .*::test.*\\(\\) has no return type specified\\.$#"
+ reportUnmatched: false
+ -
+ identifier: missingType.iterableValue
+ path: Tests/*
+ reportUnmatched: false
+ -
+ identifier: 'symfonyAi.forbidNativeException'
+ path: Tests/*
+ reportUnmatched: false
diff --git a/src/platform/src/Bridge/Mistral/phpunit.xml.dist b/src/platform/src/Bridge/Mistral/phpunit.xml.dist
new file mode 100644
index 000000000..025d8183e
--- /dev/null
+++ b/src/platform/src/Bridge/Mistral/phpunit.xml.dist
@@ -0,0 +1,32 @@
+
+
+
+
+
+
+
+
+
+ ./Tests/
+
+
+
+
+
+ ./
+
+
+ ./Resources
+ ./Tests
+ ./vendor
+
+
+
diff --git a/src/platform/src/Bridge/Ollama/README.md b/src/platform/src/Bridge/Ollama/README.md
new file mode 100644
index 000000000..b711cf4e3
--- /dev/null
+++ b/src/platform/src/Bridge/Ollama/README.md
@@ -0,0 +1,12 @@
+Ollama Platform
+===============
+
+Ollama platform bridge for Symfony AI.
+
+Resources
+---------
+
+ * [Contributing](https://symfony.com/doc/current/contributing/index.html)
+ * [Report issues](https://github.com/symfony/ai/issues) and
+ [send Pull Requests](https://github.com/symfony/ai/pulls)
+ in the [main Symfony AI repository](https://github.com/symfony/ai)
diff --git a/src/platform/tests/Bridge/Ollama/Contract/AssistantMessageNormalizerTest.php b/src/platform/src/Bridge/Ollama/Tests/Contract/AssistantMessageNormalizerTest.php
similarity index 98%
rename from src/platform/tests/Bridge/Ollama/Contract/AssistantMessageNormalizerTest.php
rename to src/platform/src/Bridge/Ollama/Tests/Contract/AssistantMessageNormalizerTest.php
index 6f9ee9eb3..64584a145 100644
--- a/src/platform/tests/Bridge/Ollama/Contract/AssistantMessageNormalizerTest.php
+++ b/src/platform/src/Bridge/Ollama/Tests/Contract/AssistantMessageNormalizerTest.php
@@ -9,7 +9,7 @@
* file that was distributed with this source code.
*/
-namespace Symfony\AI\Platform\Tests\Bridge\Ollama\Contract;
+namespace Symfony\AI\Platform\Bridge\Ollama\Tests\Contract;
use PHPUnit\Framework\Attributes\DataProvider;
use PHPUnit\Framework\TestCase;
diff --git a/src/platform/tests/Bridge/Ollama/ModelCatalogTest.php b/src/platform/src/Bridge/Ollama/Tests/ModelCatalogTest.php
similarity index 98%
rename from src/platform/tests/Bridge/Ollama/ModelCatalogTest.php
rename to src/platform/src/Bridge/Ollama/Tests/ModelCatalogTest.php
index fe2930583..e296eb7ce 100644
--- a/src/platform/tests/Bridge/Ollama/ModelCatalogTest.php
+++ b/src/platform/src/Bridge/Ollama/Tests/ModelCatalogTest.php
@@ -9,7 +9,7 @@
* file that was distributed with this source code.
*/
-namespace Symfony\AI\Platform\Tests\Bridge\Ollama;
+namespace Symfony\AI\Platform\Bridge\Ollama\Tests;
use Symfony\AI\Platform\Bridge\Ollama\ModelCatalog;
use Symfony\AI\Platform\Bridge\Ollama\Ollama;
diff --git a/src/platform/tests/Bridge/Ollama/OllamaApiCatalogTest.php b/src/platform/src/Bridge/Ollama/Tests/OllamaApiCatalogTest.php
similarity index 97%
rename from src/platform/tests/Bridge/Ollama/OllamaApiCatalogTest.php
rename to src/platform/src/Bridge/Ollama/Tests/OllamaApiCatalogTest.php
index 4377f5691..2f1e0911c 100644
--- a/src/platform/tests/Bridge/Ollama/OllamaApiCatalogTest.php
+++ b/src/platform/src/Bridge/Ollama/Tests/OllamaApiCatalogTest.php
@@ -9,7 +9,7 @@
* file that was distributed with this source code.
*/
-namespace Symfony\AI\Platform\Tests\Bridge\Ollama;
+namespace Symfony\AI\Platform\Bridge\Ollama\Tests;
use PHPUnit\Framework\TestCase;
use Symfony\AI\Platform\Bridge\Ollama\Ollama;
diff --git a/src/platform/tests/Bridge/Ollama/OllamaClientTest.php b/src/platform/src/Bridge/Ollama/Tests/OllamaClientTest.php
similarity index 99%
rename from src/platform/tests/Bridge/Ollama/OllamaClientTest.php
rename to src/platform/src/Bridge/Ollama/Tests/OllamaClientTest.php
index 1c039b8d8..8cadaef33 100644
--- a/src/platform/tests/Bridge/Ollama/OllamaClientTest.php
+++ b/src/platform/src/Bridge/Ollama/Tests/OllamaClientTest.php
@@ -9,7 +9,7 @@
* file that was distributed with this source code.
*/
-namespace Symfony\AI\Platform\Tests\Bridge\Ollama;
+namespace Symfony\AI\Platform\Bridge\Ollama\Tests;
use PHPUnit\Framework\TestCase;
use Symfony\AI\Platform\Bridge\Ollama\Ollama;
diff --git a/src/platform/tests/Bridge/Ollama/OllamaResultConverterTest.php b/src/platform/src/Bridge/Ollama/Tests/OllamaResultConverterTest.php
similarity index 99%
rename from src/platform/tests/Bridge/Ollama/OllamaResultConverterTest.php
rename to src/platform/src/Bridge/Ollama/Tests/OllamaResultConverterTest.php
index d4e7a0098..40709416c 100644
--- a/src/platform/tests/Bridge/Ollama/OllamaResultConverterTest.php
+++ b/src/platform/src/Bridge/Ollama/Tests/OllamaResultConverterTest.php
@@ -9,7 +9,7 @@
* file that was distributed with this source code.
*/
-namespace Symfony\AI\Platform\Tests\Bridge\Ollama;
+namespace Symfony\AI\Platform\Bridge\Ollama\Tests;
use PHPUnit\Framework\TestCase;
use Symfony\AI\Platform\Bridge\Ollama\Ollama;
diff --git a/src/platform/tests/Bridge/Ollama/TokenUsageExtractorTest.php b/src/platform/src/Bridge/Ollama/Tests/TokenUsageExtractorTest.php
similarity index 98%
rename from src/platform/tests/Bridge/Ollama/TokenUsageExtractorTest.php
rename to src/platform/src/Bridge/Ollama/Tests/TokenUsageExtractorTest.php
index 4bc966f95..ed07f67ee 100644
--- a/src/platform/tests/Bridge/Ollama/TokenUsageExtractorTest.php
+++ b/src/platform/src/Bridge/Ollama/Tests/TokenUsageExtractorTest.php
@@ -9,7 +9,7 @@
* file that was distributed with this source code.
*/
-namespace Symfony\AI\Platform\Tests\Bridge\Ollama;
+namespace Symfony\AI\Platform\Bridge\Ollama\Tests;
use PHPUnit\Framework\MockObject\MockObject;
use PHPUnit\Framework\TestCase;
diff --git a/src/platform/src/Bridge/Ollama/composer.json b/src/platform/src/Bridge/Ollama/composer.json
new file mode 100644
index 000000000..134b07d42
--- /dev/null
+++ b/src/platform/src/Bridge/Ollama/composer.json
@@ -0,0 +1,61 @@
+{
+ "name": "symfony/ai-ollama-platform",
+ "description": "Ollama platform bridge for Symfony AI",
+ "license": "MIT",
+ "type": "symfony-ai-platform",
+ "keywords": [
+ "ai",
+ "bridge",
+ "local",
+ "ollama",
+ "platform"
+ ],
+ "authors": [
+ {
+ "name": "Christopher Hertel",
+ "email": "mail@christopher-hertel.de"
+ },
+ {
+ "name": "Oskar Stark",
+ "email": "oskarstark@googlemail.com"
+ },
+ {
+ "name": "Symfony Community",
+ "homepage": "https://symfony.com/contributors"
+ }
+ ],
+ "require": {
+ "php": ">=8.2",
+ "symfony/ai-platform": "@dev",
+ "symfony/http-client": "^7.3|^8.0"
+ },
+ "require-dev": {
+ "phpstan/phpstan": "^2.1",
+ "phpstan/phpstan-strict-rules": "^2.0",
+ "phpunit/phpunit": "^11.5.46"
+ },
+ "minimum-stability": "dev",
+ "autoload": {
+ "psr-4": {
+ "Symfony\\AI\\Platform\\Bridge\\Ollama\\": ""
+ }
+ },
+ "autoload-dev": {
+ "psr-4": {
+ "Symfony\\AI\\PHPStan\\": "../../../../../.phpstan/",
+ "Symfony\\AI\\Platform\\Bridge\\Ollama\\Tests\\": "Tests/"
+ }
+ },
+ "config": {
+ "sort-packages": true
+ },
+ "extra": {
+ "branch-alias": {
+ "dev-main": "0.x-dev"
+ },
+ "thanks": {
+ "name": "symfony/ai",
+ "url": "https://github.com/symfony/ai"
+ }
+ }
+}
diff --git a/src/platform/src/Bridge/Ollama/phpstan.dist.neon b/src/platform/src/Bridge/Ollama/phpstan.dist.neon
new file mode 100644
index 000000000..5503dac38
--- /dev/null
+++ b/src/platform/src/Bridge/Ollama/phpstan.dist.neon
@@ -0,0 +1,23 @@
+includes:
+ - ../../../../../.phpstan/extension.neon
+
+parameters:
+ level: 6
+ paths:
+ - .
+ - Tests/
+ excludePaths:
+ - vendor/
+ treatPhpDocTypesAsCertain: false
+ ignoreErrors:
+ -
+ message: "#^Method .*::test.*\\(\\) has no return type specified\\.$#"
+ reportUnmatched: false
+ -
+ identifier: missingType.iterableValue
+ path: Tests/*
+ reportUnmatched: false
+ -
+ identifier: 'symfonyAi.forbidNativeException'
+ path: Tests/*
+ reportUnmatched: false
diff --git a/src/platform/src/Bridge/Ollama/phpunit.xml.dist b/src/platform/src/Bridge/Ollama/phpunit.xml.dist
new file mode 100644
index 000000000..1af6596aa
--- /dev/null
+++ b/src/platform/src/Bridge/Ollama/phpunit.xml.dist
@@ -0,0 +1,32 @@
+
+
+
+
+
+
+
+
+
+ ./Tests/
+
+
+
+
+
+ ./
+
+
+ ./Resources
+ ./Tests
+ ./vendor
+
+
+
diff --git a/src/platform/src/Bridge/OpenAi/README.md b/src/platform/src/Bridge/OpenAi/README.md
new file mode 100644
index 000000000..10333fd86
--- /dev/null
+++ b/src/platform/src/Bridge/OpenAi/README.md
@@ -0,0 +1,19 @@
+OpenAI Platform
+===============
+
+Provides [OpenAI](https://openai.com/) platform integration for Symfony AI Platform.
+
+This bridge includes support for:
+- GPT models (chat completions)
+- Embeddings
+- DALL-E (image generation)
+- Whisper (audio transcription)
+- Text-to-Speech
+
+Resources
+---------
+
+ * [Contributing](https://symfony.com/doc/current/contributing/index.html)
+ * [Report issues](https://github.com/symfony/ai/issues) and
+ [send Pull Requests](https://github.com/symfony/ai/pulls)
+ in the [main Symfony AI repository](https://github.com/symfony/ai)
diff --git a/src/platform/tests/Bridge/OpenAi/Contract/DocumentNormalizerTest.php b/src/platform/src/Bridge/OpenAi/Tests/Contract/DocumentNormalizerTest.php
similarity index 90%
rename from src/platform/tests/Bridge/OpenAi/Contract/DocumentNormalizerTest.php
rename to src/platform/src/Bridge/OpenAi/Tests/Contract/DocumentNormalizerTest.php
index afc5cc4f7..c602bfb6b 100644
--- a/src/platform/tests/Bridge/OpenAi/Contract/DocumentNormalizerTest.php
+++ b/src/platform/src/Bridge/OpenAi/Tests/Contract/DocumentNormalizerTest.php
@@ -9,7 +9,7 @@
* file that was distributed with this source code.
*/
-namespace Symfony\AI\Platform\Tests\Bridge\OpenAi\Contract;
+namespace Symfony\AI\Platform\Bridge\OpenAi\Tests\Contract;
use PHPUnit\Framework\Attributes\DataProvider;
use PHPUnit\Framework\TestCase;
@@ -54,12 +54,12 @@ public function testNormalize(Document $document, array $expected)
public static function normalizeDataProvider(): iterable
{
yield 'document from file' => [
- Document::fromFile(\dirname(__DIR__, 6).'/fixtures/document.pdf'),
+ Document::fromFile(\dirname(__DIR__, 7).'/fixtures/document.pdf'),
[
'type' => 'file',
'file' => [
'filename' => 'document.pdf',
- 'file_data' => 'data:application/pdf;base64,'.base64_encode(file_get_contents(\dirname(__DIR__, 6).'/fixtures/document.pdf')),
+ 'file_data' => 'data:application/pdf;base64,'.base64_encode(file_get_contents(\dirname(__DIR__, 7).'/fixtures/document.pdf')),
],
],
];
diff --git a/src/platform/tests/Bridge/OpenAi/Contract/Gpt/Message/AssistantMessageNormalizerTest.php b/src/platform/src/Bridge/OpenAi/Tests/Contract/Gpt/Message/AssistantMessageNormalizerTest.php
similarity index 97%
rename from src/platform/tests/Bridge/OpenAi/Contract/Gpt/Message/AssistantMessageNormalizerTest.php
rename to src/platform/src/Bridge/OpenAi/Tests/Contract/Gpt/Message/AssistantMessageNormalizerTest.php
index b8c401a81..8c24ae1cc 100644
--- a/src/platform/tests/Bridge/OpenAi/Contract/Gpt/Message/AssistantMessageNormalizerTest.php
+++ b/src/platform/src/Bridge/OpenAi/Tests/Contract/Gpt/Message/AssistantMessageNormalizerTest.php
@@ -9,7 +9,7 @@
* file that was distributed with this source code.
*/
-namespace Symfony\AI\Platform\Tests\Bridge\OpenAi\Contract\Gpt\Message;
+namespace Symfony\AI\Platform\Bridge\OpenAi\Tests\Contract\Gpt\Message;
use PHPUnit\Framework\Attributes\DataProvider;
use PHPUnit\Framework\TestCase;
diff --git a/src/platform/tests/Bridge/OpenAi/Contract/Gpt/Message/Content/DocumentNormalizerTest.php b/src/platform/src/Bridge/OpenAi/Tests/Contract/Gpt/Message/Content/DocumentNormalizerTest.php
similarity index 89%
rename from src/platform/tests/Bridge/OpenAi/Contract/Gpt/Message/Content/DocumentNormalizerTest.php
rename to src/platform/src/Bridge/OpenAi/Tests/Contract/Gpt/Message/Content/DocumentNormalizerTest.php
index 9525ace68..75d8ba702 100644
--- a/src/platform/tests/Bridge/OpenAi/Contract/Gpt/Message/Content/DocumentNormalizerTest.php
+++ b/src/platform/src/Bridge/OpenAi/Tests/Contract/Gpt/Message/Content/DocumentNormalizerTest.php
@@ -9,7 +9,7 @@
* file that was distributed with this source code.
*/
-namespace Symfony\AI\Platform\Tests\Bridge\OpenAi\Contract\Gpt\Message\Content;
+namespace Symfony\AI\Platform\Bridge\OpenAi\Tests\Contract\Gpt\Message\Content;
use PHPUnit\Framework\Attributes\DataProvider;
use PHPUnit\Framework\TestCase;
@@ -26,7 +26,7 @@ class DocumentNormalizerTest extends TestCase
{
public function testNormalize()
{
- $doc = Document::fromFile(\dirname(__DIR__, 9).'/fixtures/document.pdf');
+ $doc = Document::fromFile(\dirname(__DIR__, 10).'/fixtures/document.pdf');
$actual = (new DocumentNormalizer())->normalize($doc, null, [Contract::CONTEXT_MODEL => new Gpt('o3')]);
$this->assertEquals([
@@ -47,7 +47,7 @@ public function testSupportsNormalization(mixed $data, Model $model, bool $expec
public static function supportsNormalizationProvider(): \Generator
{
- $doc = Document::fromFile(\dirname(__DIR__, 9).'/fixtures/document.pdf');
+ $doc = Document::fromFile(\dirname(__DIR__, 10).'/fixtures/document.pdf');
$gpt = new Gpt('o3', [Capability::INPUT_PDF]);
yield 'supported' => [$doc, $gpt, true];
diff --git a/src/platform/tests/Bridge/OpenAi/Contract/Gpt/Message/Content/ImageNormalizerTest.php b/src/platform/src/Bridge/OpenAi/Tests/Contract/Gpt/Message/Content/ImageNormalizerTest.php
similarity index 89%
rename from src/platform/tests/Bridge/OpenAi/Contract/Gpt/Message/Content/ImageNormalizerTest.php
rename to src/platform/src/Bridge/OpenAi/Tests/Contract/Gpt/Message/Content/ImageNormalizerTest.php
index 55f986f2e..49929e007 100644
--- a/src/platform/tests/Bridge/OpenAi/Contract/Gpt/Message/Content/ImageNormalizerTest.php
+++ b/src/platform/src/Bridge/OpenAi/Tests/Contract/Gpt/Message/Content/ImageNormalizerTest.php
@@ -9,7 +9,7 @@
* file that was distributed with this source code.
*/
-namespace Symfony\AI\Platform\Tests\Bridge\OpenAi\Contract\Gpt\Message\Content;
+namespace Symfony\AI\Platform\Bridge\OpenAi\Tests\Contract\Gpt\Message\Content;
use PHPUnit\Framework\Attributes\DataProvider;
use PHPUnit\Framework\TestCase;
@@ -26,7 +26,7 @@ class ImageNormalizerTest extends TestCase
{
public function testNormalize()
{
- $image = Image::fromFile(\dirname(__DIR__, 9).'/fixtures/image.jpg');
+ $image = Image::fromFile(\dirname(__DIR__, 10).'/fixtures/image.jpg');
$actual = (new ImageNormalizer())->normalize($image, null, [Contract::CONTEXT_MODEL => new Gpt('o3')]);
$this->assertEquals([
@@ -46,7 +46,7 @@ public function testSupportsNormalization(mixed $data, Model $model, bool $expec
public static function supportsNormalizationProvider(): \Generator
{
- $image = Image::fromFile(\dirname(__DIR__, 9).'/fixtures/image.jpg');
+ $image = Image::fromFile(\dirname(__DIR__, 10).'/fixtures/image.jpg');
$gpt = new Gpt('o3', [Capability::INPUT_IMAGE]);
yield 'supported' => [$image, $gpt, true];
diff --git a/src/platform/tests/Bridge/OpenAi/Contract/Gpt/Message/Content/ImageUrlNormalizerTest.php b/src/platform/src/Bridge/OpenAi/Tests/Contract/Gpt/Message/Content/ImageUrlNormalizerTest.php
similarity index 96%
rename from src/platform/tests/Bridge/OpenAi/Contract/Gpt/Message/Content/ImageUrlNormalizerTest.php
rename to src/platform/src/Bridge/OpenAi/Tests/Contract/Gpt/Message/Content/ImageUrlNormalizerTest.php
index 60ae8fe94..4079e841b 100644
--- a/src/platform/tests/Bridge/OpenAi/Contract/Gpt/Message/Content/ImageUrlNormalizerTest.php
+++ b/src/platform/src/Bridge/OpenAi/Tests/Contract/Gpt/Message/Content/ImageUrlNormalizerTest.php
@@ -9,7 +9,7 @@
* file that was distributed with this source code.
*/
-namespace Symfony\AI\Platform\Tests\Bridge\OpenAi\Contract\Gpt\Message\Content;
+namespace Symfony\AI\Platform\Bridge\OpenAi\Tests\Contract\Gpt\Message\Content;
use PHPUnit\Framework\Attributes\DataProvider;
use PHPUnit\Framework\TestCase;
diff --git a/src/platform/tests/Bridge/OpenAi/Contract/Gpt/Message/Content/TextNormalizerTest.php b/src/platform/src/Bridge/OpenAi/Tests/Contract/Gpt/Message/Content/TextNormalizerTest.php
similarity index 96%
rename from src/platform/tests/Bridge/OpenAi/Contract/Gpt/Message/Content/TextNormalizerTest.php
rename to src/platform/src/Bridge/OpenAi/Tests/Contract/Gpt/Message/Content/TextNormalizerTest.php
index 2527638b6..5b8bfab63 100644
--- a/src/platform/tests/Bridge/OpenAi/Contract/Gpt/Message/Content/TextNormalizerTest.php
+++ b/src/platform/src/Bridge/OpenAi/Tests/Contract/Gpt/Message/Content/TextNormalizerTest.php
@@ -9,7 +9,7 @@
* file that was distributed with this source code.
*/
-namespace Symfony\AI\Platform\Tests\Bridge\OpenAi\Contract\Gpt\Message\Content;
+namespace Symfony\AI\Platform\Bridge\OpenAi\Tests\Contract\Gpt\Message\Content;
use PHPUnit\Framework\Attributes\DataProvider;
use PHPUnit\Framework\TestCase;
diff --git a/src/platform/tests/Bridge/OpenAi/Contract/Gpt/Message/MessageBagNormalizerTest.php b/src/platform/src/Bridge/OpenAi/Tests/Contract/Gpt/Message/MessageBagNormalizerTest.php
similarity index 98%
rename from src/platform/tests/Bridge/OpenAi/Contract/Gpt/Message/MessageBagNormalizerTest.php
rename to src/platform/src/Bridge/OpenAi/Tests/Contract/Gpt/Message/MessageBagNormalizerTest.php
index 019220c8c..8cf9914f3 100644
--- a/src/platform/tests/Bridge/OpenAi/Contract/Gpt/Message/MessageBagNormalizerTest.php
+++ b/src/platform/src/Bridge/OpenAi/Tests/Contract/Gpt/Message/MessageBagNormalizerTest.php
@@ -9,7 +9,7 @@
* file that was distributed with this source code.
*/
-namespace Symfony\AI\Platform\Tests\Bridge\OpenAi\Contract\Gpt\Message;
+namespace Symfony\AI\Platform\Bridge\OpenAi\Tests\Contract\Gpt\Message;
use PHPUnit\Framework\Attributes\DataProvider;
use PHPUnit\Framework\TestCase;
diff --git a/src/platform/tests/Bridge/OpenAi/Contract/Gpt/Message/ToolCallMessageNormalizerTest.php b/src/platform/src/Bridge/OpenAi/Tests/Contract/Gpt/Message/ToolCallMessageNormalizerTest.php
similarity index 97%
rename from src/platform/tests/Bridge/OpenAi/Contract/Gpt/Message/ToolCallMessageNormalizerTest.php
rename to src/platform/src/Bridge/OpenAi/Tests/Contract/Gpt/Message/ToolCallMessageNormalizerTest.php
index 4bb69a131..d213c4282 100644
--- a/src/platform/tests/Bridge/OpenAi/Contract/Gpt/Message/ToolCallMessageNormalizerTest.php
+++ b/src/platform/src/Bridge/OpenAi/Tests/Contract/Gpt/Message/ToolCallMessageNormalizerTest.php
@@ -9,7 +9,7 @@
* file that was distributed with this source code.
*/
-namespace Symfony\AI\Platform\Tests\Bridge\OpenAi\Contract\Gpt\Message;
+namespace Symfony\AI\Platform\Bridge\OpenAi\Tests\Contract\Gpt\Message;
use PHPUnit\Framework\Attributes\DataProvider;
use PHPUnit\Framework\TestCase;
diff --git a/src/platform/tests/Bridge/OpenAi/Contract/Gpt/ToolCallNormalizerTest.php b/src/platform/src/Bridge/OpenAi/Tests/Contract/Gpt/ToolCallNormalizerTest.php
similarity index 96%
rename from src/platform/tests/Bridge/OpenAi/Contract/Gpt/ToolCallNormalizerTest.php
rename to src/platform/src/Bridge/OpenAi/Tests/Contract/Gpt/ToolCallNormalizerTest.php
index 0b4e7c188..ef2c99365 100644
--- a/src/platform/tests/Bridge/OpenAi/Contract/Gpt/ToolCallNormalizerTest.php
+++ b/src/platform/src/Bridge/OpenAi/Tests/Contract/Gpt/ToolCallNormalizerTest.php
@@ -9,7 +9,7 @@
* file that was distributed with this source code.
*/
-namespace Symfony\AI\Platform\Tests\Bridge\OpenAi\Contract\Gpt;
+namespace Symfony\AI\Platform\Bridge\OpenAi\Tests\Contract\Gpt;
use PHPUnit\Framework\Attributes\DataProvider;
use PHPUnit\Framework\TestCase;
diff --git a/src/platform/tests/Bridge/OpenAi/Contract/Gpt/ToolNormalizerTest.php b/src/platform/src/Bridge/OpenAi/Tests/Contract/Gpt/ToolNormalizerTest.php
similarity index 97%
rename from src/platform/tests/Bridge/OpenAi/Contract/Gpt/ToolNormalizerTest.php
rename to src/platform/src/Bridge/OpenAi/Tests/Contract/Gpt/ToolNormalizerTest.php
index 71b7d2868..e6e330fc0 100644
--- a/src/platform/tests/Bridge/OpenAi/Contract/Gpt/ToolNormalizerTest.php
+++ b/src/platform/src/Bridge/OpenAi/Tests/Contract/Gpt/ToolNormalizerTest.php
@@ -9,7 +9,7 @@
* file that was distributed with this source code.
*/
-namespace Symfony\AI\Platform\Tests\Bridge\OpenAi\Contract\Gpt;
+namespace Symfony\AI\Platform\Bridge\OpenAi\Tests\Contract\Gpt;
use PHPUnit\Framework\Attributes\DataProvider;
use PHPUnit\Framework\TestCase;
diff --git a/src/platform/tests/Bridge/OpenAi/DallE/Base64ImageTest.php b/src/platform/src/Bridge/OpenAi/Tests/DallE/Base64ImageTest.php
similarity index 94%
rename from src/platform/tests/Bridge/OpenAi/DallE/Base64ImageTest.php
rename to src/platform/src/Bridge/OpenAi/Tests/DallE/Base64ImageTest.php
index 79eddb197..0bd63fd16 100644
--- a/src/platform/tests/Bridge/OpenAi/DallE/Base64ImageTest.php
+++ b/src/platform/src/Bridge/OpenAi/Tests/DallE/Base64ImageTest.php
@@ -9,7 +9,7 @@
* file that was distributed with this source code.
*/
-namespace Symfony\AI\Platform\Tests\Bridge\OpenAi\DallE;
+namespace Symfony\AI\Platform\Bridge\OpenAi\Tests\DallE;
use PHPUnit\Framework\TestCase;
use Symfony\AI\Platform\Bridge\OpenAi\DallE\Base64Image;
diff --git a/src/platform/tests/Bridge/OpenAi/DallE/ImageResultTest.php b/src/platform/src/Bridge/OpenAi/Tests/DallE/ImageResultTest.php
similarity index 97%
rename from src/platform/tests/Bridge/OpenAi/DallE/ImageResultTest.php
rename to src/platform/src/Bridge/OpenAi/Tests/DallE/ImageResultTest.php
index cae6017ee..74915d93d 100644
--- a/src/platform/tests/Bridge/OpenAi/DallE/ImageResultTest.php
+++ b/src/platform/src/Bridge/OpenAi/Tests/DallE/ImageResultTest.php
@@ -9,7 +9,7 @@
* file that was distributed with this source code.
*/
-namespace Symfony\AI\Platform\Tests\Bridge\OpenAi\DallE;
+namespace Symfony\AI\Platform\Bridge\OpenAi\Tests\DallE;
use PHPUnit\Framework\TestCase;
use Symfony\AI\Platform\Bridge\OpenAi\DallE\Base64Image;
diff --git a/src/platform/tests/Bridge/OpenAi/DallE/ModelClientTest.php b/src/platform/src/Bridge/OpenAi/Tests/DallE/ModelClientTest.php
similarity index 98%
rename from src/platform/tests/Bridge/OpenAi/DallE/ModelClientTest.php
rename to src/platform/src/Bridge/OpenAi/Tests/DallE/ModelClientTest.php
index cd365d9e1..757445b8e 100644
--- a/src/platform/tests/Bridge/OpenAi/DallE/ModelClientTest.php
+++ b/src/platform/src/Bridge/OpenAi/Tests/DallE/ModelClientTest.php
@@ -9,7 +9,7 @@
* file that was distributed with this source code.
*/
-namespace Symfony\AI\Platform\Tests\Bridge\OpenAi\DallE;
+namespace Symfony\AI\Platform\Bridge\OpenAi\Tests\DallE;
use PHPUnit\Framework\Attributes\TestWith;
use PHPUnit\Framework\TestCase;
diff --git a/src/platform/tests/Bridge/OpenAi/DallE/ResultConverterTest.php b/src/platform/src/Bridge/OpenAi/Tests/DallE/ResultConverterTest.php
similarity index 97%
rename from src/platform/tests/Bridge/OpenAi/DallE/ResultConverterTest.php
rename to src/platform/src/Bridge/OpenAi/Tests/DallE/ResultConverterTest.php
index d96030c46..7c6bac4ed 100644
--- a/src/platform/tests/Bridge/OpenAi/DallE/ResultConverterTest.php
+++ b/src/platform/src/Bridge/OpenAi/Tests/DallE/ResultConverterTest.php
@@ -9,7 +9,7 @@
* file that was distributed with this source code.
*/
-namespace Symfony\AI\Platform\Tests\Bridge\OpenAi\DallE;
+namespace Symfony\AI\Platform\Bridge\OpenAi\Tests\DallE;
use PHPUnit\Framework\TestCase;
use Symfony\AI\Platform\Bridge\OpenAi\DallE\Base64Image;
diff --git a/src/platform/tests/Bridge/OpenAi/DallE/UrlImageTest.php b/src/platform/src/Bridge/OpenAi/Tests/DallE/UrlImageTest.php
similarity index 93%
rename from src/platform/tests/Bridge/OpenAi/DallE/UrlImageTest.php
rename to src/platform/src/Bridge/OpenAi/Tests/DallE/UrlImageTest.php
index 0e97b591d..70f8e4b96 100644
--- a/src/platform/tests/Bridge/OpenAi/DallE/UrlImageTest.php
+++ b/src/platform/src/Bridge/OpenAi/Tests/DallE/UrlImageTest.php
@@ -9,7 +9,7 @@
* file that was distributed with this source code.
*/
-namespace Symfony\AI\Platform\Tests\Bridge\OpenAi\DallE;
+namespace Symfony\AI\Platform\Bridge\OpenAi\Tests\DallE;
use PHPUnit\Framework\TestCase;
use Symfony\AI\Platform\Bridge\OpenAi\DallE\UrlImage;
diff --git a/src/platform/tests/Bridge/OpenAi/DallETest.php b/src/platform/src/Bridge/OpenAi/Tests/DallETest.php
similarity index 94%
rename from src/platform/tests/Bridge/OpenAi/DallETest.php
rename to src/platform/src/Bridge/OpenAi/Tests/DallETest.php
index 01d9738c1..8bd3a7b66 100644
--- a/src/platform/tests/Bridge/OpenAi/DallETest.php
+++ b/src/platform/src/Bridge/OpenAi/Tests/DallETest.php
@@ -9,7 +9,7 @@
* file that was distributed with this source code.
*/
-namespace Symfony\AI\Platform\Tests\Bridge\OpenAi;
+namespace Symfony\AI\Platform\Bridge\OpenAi\Tests;
use PHPUnit\Framework\TestCase;
use Symfony\AI\Platform\Bridge\OpenAi\DallE;
diff --git a/src/platform/tests/Bridge/OpenAi/Embeddings/ModelClientTest.php b/src/platform/src/Bridge/OpenAi/Tests/Embeddings/ModelClientTest.php
similarity index 98%
rename from src/platform/tests/Bridge/OpenAi/Embeddings/ModelClientTest.php
rename to src/platform/src/Bridge/OpenAi/Tests/Embeddings/ModelClientTest.php
index 1f37e77a3..32ba0ad5a 100644
--- a/src/platform/tests/Bridge/OpenAi/Embeddings/ModelClientTest.php
+++ b/src/platform/src/Bridge/OpenAi/Tests/Embeddings/ModelClientTest.php
@@ -9,7 +9,7 @@
* file that was distributed with this source code.
*/
-namespace Symfony\AI\Platform\Tests\Bridge\OpenAi\Embeddings;
+namespace Symfony\AI\Platform\Bridge\OpenAi\Tests\Embeddings;
use PHPUnit\Framework\Attributes\TestWith;
use PHPUnit\Framework\TestCase;
diff --git a/src/platform/tests/Bridge/OpenAi/Embeddings/ResultConverterTest.php b/src/platform/src/Bridge/OpenAi/Tests/Embeddings/ResultConverterTest.php
similarity index 96%
rename from src/platform/tests/Bridge/OpenAi/Embeddings/ResultConverterTest.php
rename to src/platform/src/Bridge/OpenAi/Tests/Embeddings/ResultConverterTest.php
index e7c6689f0..e3c13b851 100644
--- a/src/platform/tests/Bridge/OpenAi/Embeddings/ResultConverterTest.php
+++ b/src/platform/src/Bridge/OpenAi/Tests/Embeddings/ResultConverterTest.php
@@ -9,7 +9,7 @@
* file that was distributed with this source code.
*/
-namespace Symfony\AI\Platform\Tests\Bridge\OpenAi\Embeddings;
+namespace Symfony\AI\Platform\Bridge\OpenAi\Tests\Embeddings;
use PHPUnit\Framework\TestCase;
use Symfony\AI\Platform\Bridge\OpenAi\Embeddings\ResultConverter;
diff --git a/src/platform/tests/Bridge/OpenAi/EmbeddingsTest.php b/src/platform/src/Bridge/OpenAi/Tests/EmbeddingsTest.php
similarity index 96%
rename from src/platform/tests/Bridge/OpenAi/EmbeddingsTest.php
rename to src/platform/src/Bridge/OpenAi/Tests/EmbeddingsTest.php
index 3b72d0c86..90ae7d5fc 100644
--- a/src/platform/tests/Bridge/OpenAi/EmbeddingsTest.php
+++ b/src/platform/src/Bridge/OpenAi/Tests/EmbeddingsTest.php
@@ -9,7 +9,7 @@
* file that was distributed with this source code.
*/
-namespace Symfony\AI\Platform\Tests\Bridge\OpenAi;
+namespace Symfony\AI\Platform\Bridge\OpenAi\Tests;
use PHPUnit\Framework\TestCase;
use Symfony\AI\Platform\Bridge\OpenAi\Embeddings;
diff --git a/src/platform/tests/Bridge/OpenAi/Gpt/ModelClientTest.php b/src/platform/src/Bridge/OpenAi/Tests/Gpt/ModelClientTest.php
similarity index 99%
rename from src/platform/tests/Bridge/OpenAi/Gpt/ModelClientTest.php
rename to src/platform/src/Bridge/OpenAi/Tests/Gpt/ModelClientTest.php
index be7bb756a..0be6d8d3d 100644
--- a/src/platform/tests/Bridge/OpenAi/Gpt/ModelClientTest.php
+++ b/src/platform/src/Bridge/OpenAi/Tests/Gpt/ModelClientTest.php
@@ -9,7 +9,7 @@
* file that was distributed with this source code.
*/
-namespace Symfony\AI\Platform\Tests\Bridge\OpenAi\Gpt;
+namespace Symfony\AI\Platform\Bridge\OpenAi\Tests\Gpt;
use PHPUnit\Framework\Attributes\TestWith;
use PHPUnit\Framework\TestCase;
diff --git a/src/platform/tests/Bridge/OpenAi/Gpt/ResultConverterRateLimitTest.php b/src/platform/src/Bridge/OpenAi/Tests/Gpt/ResultConverterRateLimitTest.php
similarity index 97%
rename from src/platform/tests/Bridge/OpenAi/Gpt/ResultConverterRateLimitTest.php
rename to src/platform/src/Bridge/OpenAi/Tests/Gpt/ResultConverterRateLimitTest.php
index c2537b8fb..807c862dc 100644
--- a/src/platform/tests/Bridge/OpenAi/Gpt/ResultConverterRateLimitTest.php
+++ b/src/platform/src/Bridge/OpenAi/Tests/Gpt/ResultConverterRateLimitTest.php
@@ -9,7 +9,7 @@
* file that was distributed with this source code.
*/
-namespace Symfony\AI\Platform\Tests\Bridge\OpenAi\Gpt;
+namespace Symfony\AI\Platform\Bridge\OpenAi\Tests\Gpt;
use PHPUnit\Framework\TestCase;
use Symfony\AI\Platform\Bridge\OpenAi\Gpt\ResultConverter;
diff --git a/src/platform/tests/Bridge/OpenAi/Gpt/ResultConverterTest.php b/src/platform/src/Bridge/OpenAi/Tests/Gpt/ResultConverterTest.php
similarity index 99%
rename from src/platform/tests/Bridge/OpenAi/Gpt/ResultConverterTest.php
rename to src/platform/src/Bridge/OpenAi/Tests/Gpt/ResultConverterTest.php
index 1138fef56..0ade6d797 100644
--- a/src/platform/tests/Bridge/OpenAi/Gpt/ResultConverterTest.php
+++ b/src/platform/src/Bridge/OpenAi/Tests/Gpt/ResultConverterTest.php
@@ -9,7 +9,7 @@
* file that was distributed with this source code.
*/
-namespace Symfony\AI\Platform\Tests\Bridge\OpenAi\Gpt;
+namespace Symfony\AI\Platform\Bridge\OpenAi\Tests\Gpt;
use PHPUnit\Framework\TestCase;
use Symfony\AI\Platform\Bridge\OpenAi\Gpt\ResultConverter;
diff --git a/src/platform/tests/Bridge/OpenAi/GptTest.php b/src/platform/src/Bridge/OpenAi/Tests/GptTest.php
similarity index 94%
rename from src/platform/tests/Bridge/OpenAi/GptTest.php
rename to src/platform/src/Bridge/OpenAi/Tests/GptTest.php
index 2073cd93d..b70b57c75 100644
--- a/src/platform/tests/Bridge/OpenAi/GptTest.php
+++ b/src/platform/src/Bridge/OpenAi/Tests/GptTest.php
@@ -9,7 +9,7 @@
* file that was distributed with this source code.
*/
-namespace Symfony\AI\Platform\Tests\Bridge\OpenAi;
+namespace Symfony\AI\Platform\Bridge\OpenAi\Tests;
use PHPUnit\Framework\TestCase;
use Symfony\AI\Platform\Bridge\OpenAi\Gpt;
diff --git a/src/platform/tests/Bridge/OpenAi/ModelCatalogTest.php b/src/platform/src/Bridge/OpenAi/Tests/ModelCatalogTest.php
similarity index 99%
rename from src/platform/tests/Bridge/OpenAi/ModelCatalogTest.php
rename to src/platform/src/Bridge/OpenAi/Tests/ModelCatalogTest.php
index ff02cfc02..a6734d994 100644
--- a/src/platform/tests/Bridge/OpenAi/ModelCatalogTest.php
+++ b/src/platform/src/Bridge/OpenAi/Tests/ModelCatalogTest.php
@@ -9,7 +9,7 @@
* file that was distributed with this source code.
*/
-namespace Symfony\AI\Platform\Tests\Bridge\OpenAi;
+namespace Symfony\AI\Platform\Bridge\OpenAi\Tests;
use Symfony\AI\Platform\Bridge\OpenAi\DallE;
use Symfony\AI\Platform\Bridge\OpenAi\Embeddings;
diff --git a/src/platform/tests/Bridge/OpenAi/PlatformFactoryTest.php b/src/platform/src/Bridge/OpenAi/Tests/PlatformFactoryTest.php
similarity index 96%
rename from src/platform/tests/Bridge/OpenAi/PlatformFactoryTest.php
rename to src/platform/src/Bridge/OpenAi/Tests/PlatformFactoryTest.php
index 2c97ffcb9..1e4337144 100644
--- a/src/platform/tests/Bridge/OpenAi/PlatformFactoryTest.php
+++ b/src/platform/src/Bridge/OpenAi/Tests/PlatformFactoryTest.php
@@ -9,7 +9,7 @@
* file that was distributed with this source code.
*/
-namespace Symfony\AI\Platform\Tests\Bridge\OpenAi;
+namespace Symfony\AI\Platform\Bridge\OpenAi\Tests;
use PHPUnit\Framework\TestCase;
use Symfony\AI\Platform\Bridge\OpenAi\PlatformFactory;
diff --git a/src/platform/tests/Bridge/OpenAi/TextToSpeech/ModelClientTest.php b/src/platform/src/Bridge/OpenAi/Tests/TextToSpeech/ModelClientTest.php
similarity index 98%
rename from src/platform/tests/Bridge/OpenAi/TextToSpeech/ModelClientTest.php
rename to src/platform/src/Bridge/OpenAi/Tests/TextToSpeech/ModelClientTest.php
index 018f74d6d..3d4dd7303 100644
--- a/src/platform/tests/Bridge/OpenAi/TextToSpeech/ModelClientTest.php
+++ b/src/platform/src/Bridge/OpenAi/Tests/TextToSpeech/ModelClientTest.php
@@ -9,7 +9,7 @@
* file that was distributed with this source code.
*/
-namespace Symfony\AI\Platform\Tests\Bridge\OpenAi\TextToSpeech;
+namespace Symfony\AI\Platform\Bridge\OpenAi\Tests\TextToSpeech;
use PHPUnit\Framework\TestCase;
use Symfony\AI\Platform\Bridge\OpenAi\TextToSpeech;
diff --git a/src/platform/tests/Bridge/OpenAi/TextToSpeech/ResultConverterTest.php b/src/platform/src/Bridge/OpenAi/Tests/TextToSpeech/ResultConverterTest.php
similarity index 97%
rename from src/platform/tests/Bridge/OpenAi/TextToSpeech/ResultConverterTest.php
rename to src/platform/src/Bridge/OpenAi/Tests/TextToSpeech/ResultConverterTest.php
index 3071c140f..e99b21a67 100644
--- a/src/platform/tests/Bridge/OpenAi/TextToSpeech/ResultConverterTest.php
+++ b/src/platform/src/Bridge/OpenAi/Tests/TextToSpeech/ResultConverterTest.php
@@ -9,7 +9,7 @@
* file that was distributed with this source code.
*/
-namespace Symfony\AI\Platform\Tests\Bridge\OpenAi\TextToSpeech;
+namespace Symfony\AI\Platform\Bridge\OpenAi\Tests\TextToSpeech;
use PHPUnit\Framework\TestCase;
use Symfony\AI\Platform\Bridge\OpenAi\TextToSpeech;
diff --git a/src/platform/tests/Bridge/OpenAi/TokenUsageExtractorTest.php b/src/platform/src/Bridge/OpenAi/Tests/TokenUsageExtractorTest.php
similarity index 100%
rename from src/platform/tests/Bridge/OpenAi/TokenUsageExtractorTest.php
rename to src/platform/src/Bridge/OpenAi/Tests/TokenUsageExtractorTest.php
diff --git a/src/platform/tests/Bridge/OpenAi/Whisper/ModelClientTest.php b/src/platform/src/Bridge/OpenAi/Tests/Whisper/ModelClientTest.php
similarity index 98%
rename from src/platform/tests/Bridge/OpenAi/Whisper/ModelClientTest.php
rename to src/platform/src/Bridge/OpenAi/Tests/Whisper/ModelClientTest.php
index 70065a7e1..a9968f7a2 100644
--- a/src/platform/tests/Bridge/OpenAi/Whisper/ModelClientTest.php
+++ b/src/platform/src/Bridge/OpenAi/Tests/Whisper/ModelClientTest.php
@@ -9,7 +9,7 @@
* file that was distributed with this source code.
*/
-namespace Symfony\AI\Platform\Tests\Bridge\OpenAi\Whisper;
+namespace Symfony\AI\Platform\Bridge\OpenAi\Tests\Whisper;
use PHPUnit\Framework\Attributes\TestWith;
use PHPUnit\Framework\TestCase;
diff --git a/src/platform/tests/Bridge/OpenAi/WhisperTest.php b/src/platform/src/Bridge/OpenAi/Tests/WhisperTest.php
similarity index 95%
rename from src/platform/tests/Bridge/OpenAi/WhisperTest.php
rename to src/platform/src/Bridge/OpenAi/Tests/WhisperTest.php
index 0a8b79f85..07bc1259b 100644
--- a/src/platform/tests/Bridge/OpenAi/WhisperTest.php
+++ b/src/platform/src/Bridge/OpenAi/Tests/WhisperTest.php
@@ -9,7 +9,7 @@
* file that was distributed with this source code.
*/
-namespace Symfony\AI\Platform\Tests\Bridge\OpenAi;
+namespace Symfony\AI\Platform\Bridge\OpenAi\Tests;
use PHPUnit\Framework\TestCase;
use Symfony\AI\Platform\Bridge\OpenAi\Whisper;
diff --git a/src/platform/src/Bridge/OpenAi/composer.json b/src/platform/src/Bridge/OpenAi/composer.json
new file mode 100644
index 000000000..e459693cd
--- /dev/null
+++ b/src/platform/src/Bridge/OpenAi/composer.json
@@ -0,0 +1,66 @@
+{
+ "name": "symfony/ai-open-ai-platform",
+ "description": "OpenAI platform bridge for Symfony AI",
+ "license": "MIT",
+ "type": "symfony-ai-platform",
+ "keywords": [
+ "ai",
+ "bridge",
+ "chatgpt",
+ "dall-e",
+ "embeddings",
+ "gpt",
+ "openai",
+ "platform",
+ "text-to-speech",
+ "whisper"
+ ],
+ "authors": [
+ {
+ "name": "Christopher Hertel",
+ "email": "mail@christopher-hertel.de"
+ },
+ {
+ "name": "Oskar Stark",
+ "email": "oskarstark@googlemail.com"
+ },
+ {
+ "name": "Symfony Community",
+ "homepage": "https://symfony.com/contributors"
+ }
+ ],
+ "require": {
+ "php": ">=8.2",
+ "symfony/ai-platform": "@dev",
+ "symfony/http-client": "^7.3|^8.0"
+ },
+ "require-dev": {
+ "phpstan/phpstan": "^2.1",
+ "phpstan/phpstan-strict-rules": "^2.0",
+ "phpunit/phpunit": "^11.5.46"
+ },
+ "minimum-stability": "dev",
+ "autoload": {
+ "psr-4": {
+ "Symfony\\AI\\Platform\\Bridge\\OpenAi\\": ""
+ }
+ },
+ "autoload-dev": {
+ "psr-4": {
+ "Symfony\\AI\\PHPStan\\": "../../../../../.phpstan/",
+ "Symfony\\AI\\Platform\\Bridge\\OpenAi\\Tests\\": "Tests/"
+ }
+ },
+ "config": {
+ "sort-packages": true
+ },
+ "extra": {
+ "branch-alias": {
+ "dev-main": "0.x-dev"
+ },
+ "thanks": {
+ "name": "symfony/ai",
+ "url": "https://github.com/symfony/ai"
+ }
+ }
+}
diff --git a/src/platform/src/Bridge/OpenAi/phpstan.dist.neon b/src/platform/src/Bridge/OpenAi/phpstan.dist.neon
new file mode 100644
index 000000000..5503dac38
--- /dev/null
+++ b/src/platform/src/Bridge/OpenAi/phpstan.dist.neon
@@ -0,0 +1,23 @@
+includes:
+ - ../../../../../.phpstan/extension.neon
+
+parameters:
+ level: 6
+ paths:
+ - .
+ - Tests/
+ excludePaths:
+ - vendor/
+ treatPhpDocTypesAsCertain: false
+ ignoreErrors:
+ -
+ message: "#^Method .*::test.*\\(\\) has no return type specified\\.$#"
+ reportUnmatched: false
+ -
+ identifier: missingType.iterableValue
+ path: Tests/*
+ reportUnmatched: false
+ -
+ identifier: 'symfonyAi.forbidNativeException'
+ path: Tests/*
+ reportUnmatched: false
diff --git a/src/platform/src/Bridge/OpenAi/phpunit.xml.dist b/src/platform/src/Bridge/OpenAi/phpunit.xml.dist
new file mode 100644
index 000000000..97762ad3e
--- /dev/null
+++ b/src/platform/src/Bridge/OpenAi/phpunit.xml.dist
@@ -0,0 +1,32 @@
+
+
+
+
+
+
+
+
+
+ ./Tests/
+
+
+
+
+
+ ./
+
+
+ ./Resources
+ ./Tests
+ ./vendor
+
+
+
diff --git a/src/platform/src/Bridge/OpenRouter/README.md b/src/platform/src/Bridge/OpenRouter/README.md
new file mode 100644
index 000000000..0277fcc10
--- /dev/null
+++ b/src/platform/src/Bridge/OpenRouter/README.md
@@ -0,0 +1,12 @@
+OpenRouter Platform
+===================
+
+OpenRouter platform bridge for Symfony AI.
+
+Resources
+---------
+
+ * [Contributing](https://symfony.com/doc/current/contributing/index.html)
+ * [Report issues](https://github.com/symfony/ai/issues) and
+ [send Pull Requests](https://github.com/symfony/ai/pulls)
+ in the [main Symfony AI repository](https://github.com/symfony/ai)
diff --git a/src/platform/tests/Bridge/OpenRouter/ModelApiCatalogTest.php b/src/platform/src/Bridge/OpenRouter/Tests/ModelApiCatalogTest.php
similarity index 99%
rename from src/platform/tests/Bridge/OpenRouter/ModelApiCatalogTest.php
rename to src/platform/src/Bridge/OpenRouter/Tests/ModelApiCatalogTest.php
index f37ab15a6..aa0cb21e1 100644
--- a/src/platform/tests/Bridge/OpenRouter/ModelApiCatalogTest.php
+++ b/src/platform/src/Bridge/OpenRouter/Tests/ModelApiCatalogTest.php
@@ -9,7 +9,7 @@
* file that was distributed with this source code.
*/
-namespace Symfony\AI\Platform\Tests\Bridge\OpenRouter;
+namespace Symfony\AI\Platform\Bridge\OpenRouter\Tests;
use PHPUnit\Framework\TestCase;
use Symfony\AI\Platform\Bridge\Generic\CompletionsModel;
diff --git a/src/platform/tests/Bridge/OpenRouter/ModelCatalogTest.php b/src/platform/src/Bridge/OpenRouter/Tests/ModelCatalogTest.php
similarity index 99%
rename from src/platform/tests/Bridge/OpenRouter/ModelCatalogTest.php
rename to src/platform/src/Bridge/OpenRouter/Tests/ModelCatalogTest.php
index 8ff5c4463..798ef6288 100644
--- a/src/platform/tests/Bridge/OpenRouter/ModelCatalogTest.php
+++ b/src/platform/src/Bridge/OpenRouter/Tests/ModelCatalogTest.php
@@ -9,7 +9,7 @@
* file that was distributed with this source code.
*/
-namespace Symfony\AI\Platform\Tests\Bridge\OpenRouter;
+namespace Symfony\AI\Platform\Bridge\OpenRouter\Tests;
use PHPUnit\Framework\Attributes\DataProvider;
use Symfony\AI\Platform\Bridge\Generic\CompletionsModel;
diff --git a/src/platform/tests/Bridge/OpenRouter/PlatformFactoryTest.php b/src/platform/src/Bridge/OpenRouter/Tests/PlatformFactoryTest.php
similarity index 96%
rename from src/platform/tests/Bridge/OpenRouter/PlatformFactoryTest.php
rename to src/platform/src/Bridge/OpenRouter/Tests/PlatformFactoryTest.php
index a392cb0e3..717bdadef 100644
--- a/src/platform/tests/Bridge/OpenRouter/PlatformFactoryTest.php
+++ b/src/platform/src/Bridge/OpenRouter/Tests/PlatformFactoryTest.php
@@ -9,7 +9,7 @@
* file that was distributed with this source code.
*/
-namespace Symfony\AI\Platform\Tests\Bridge\OpenRouter;
+namespace Symfony\AI\Platform\Bridge\OpenRouter\Tests;
use PHPUnit\Framework\TestCase;
use Symfony\AI\Platform\Bridge\OpenRouter\PlatformFactory;
diff --git a/src/platform/src/Bridge/OpenRouter/composer.json b/src/platform/src/Bridge/OpenRouter/composer.json
new file mode 100644
index 000000000..ff3d937be
--- /dev/null
+++ b/src/platform/src/Bridge/OpenRouter/composer.json
@@ -0,0 +1,61 @@
+{
+ "name": "symfony/ai-open-router-platform",
+ "description": "OpenRouter platform bridge for Symfony AI",
+ "license": "MIT",
+ "type": "symfony-ai-platform",
+ "keywords": [
+ "ai",
+ "bridge",
+ "openrouter",
+ "platform"
+ ],
+ "authors": [
+ {
+ "name": "Christopher Hertel",
+ "email": "mail@christopher-hertel.de"
+ },
+ {
+ "name": "Oskar Stark",
+ "email": "oskarstark@googlemail.com"
+ },
+ {
+ "name": "Symfony Community",
+ "homepage": "https://symfony.com/contributors"
+ }
+ ],
+ "require": {
+ "php": ">=8.2",
+ "symfony/ai-generic-platform": "@dev",
+ "symfony/ai-platform": "@dev",
+ "symfony/http-client": "^7.3|^8.0"
+ },
+ "require-dev": {
+ "phpstan/phpstan": "^2.1",
+ "phpstan/phpstan-strict-rules": "^2.0",
+ "phpunit/phpunit": "^11.5.46"
+ },
+ "minimum-stability": "dev",
+ "autoload": {
+ "psr-4": {
+ "Symfony\\AI\\Platform\\Bridge\\OpenRouter\\": ""
+ }
+ },
+ "autoload-dev": {
+ "psr-4": {
+ "Symfony\\AI\\PHPStan\\": "../../../../../.phpstan/",
+ "Symfony\\AI\\Platform\\Bridge\\OpenRouter\\Tests\\": "Tests/"
+ }
+ },
+ "config": {
+ "sort-packages": true
+ },
+ "extra": {
+ "branch-alias": {
+ "dev-main": "0.x-dev"
+ },
+ "thanks": {
+ "name": "symfony/ai",
+ "url": "https://github.com/symfony/ai"
+ }
+ }
+}
diff --git a/src/platform/src/Bridge/OpenRouter/phpstan.dist.neon b/src/platform/src/Bridge/OpenRouter/phpstan.dist.neon
new file mode 100644
index 000000000..5503dac38
--- /dev/null
+++ b/src/platform/src/Bridge/OpenRouter/phpstan.dist.neon
@@ -0,0 +1,23 @@
+includes:
+ - ../../../../../.phpstan/extension.neon
+
+parameters:
+ level: 6
+ paths:
+ - .
+ - Tests/
+ excludePaths:
+ - vendor/
+ treatPhpDocTypesAsCertain: false
+ ignoreErrors:
+ -
+ message: "#^Method .*::test.*\\(\\) has no return type specified\\.$#"
+ reportUnmatched: false
+ -
+ identifier: missingType.iterableValue
+ path: Tests/*
+ reportUnmatched: false
+ -
+ identifier: 'symfonyAi.forbidNativeException'
+ path: Tests/*
+ reportUnmatched: false
diff --git a/src/platform/src/Bridge/OpenRouter/phpunit.xml.dist b/src/platform/src/Bridge/OpenRouter/phpunit.xml.dist
new file mode 100644
index 000000000..6b9ea2e59
--- /dev/null
+++ b/src/platform/src/Bridge/OpenRouter/phpunit.xml.dist
@@ -0,0 +1,32 @@
+
+
+
+
+
+
+
+
+
+ ./Tests/
+
+
+
+
+
+ ./
+
+
+ ./Resources
+ ./Tests
+ ./vendor
+
+
+
diff --git a/src/platform/src/Bridge/Perplexity/README.md b/src/platform/src/Bridge/Perplexity/README.md
new file mode 100644
index 000000000..c007a4754
--- /dev/null
+++ b/src/platform/src/Bridge/Perplexity/README.md
@@ -0,0 +1,12 @@
+Perplexity Platform
+===================
+
+Perplexity platform bridge for Symfony AI.
+
+Resources
+---------
+
+ * [Contributing](https://symfony.com/doc/current/contributing/index.html)
+ * [Report issues](https://github.com/symfony/ai/issues) and
+ [send Pull Requests](https://github.com/symfony/ai/pulls)
+ in the [main Symfony AI repository](https://github.com/symfony/ai)
diff --git a/src/platform/tests/Bridge/Perplexity/Contract/FileUrlNormalizerTest.php b/src/platform/src/Bridge/Perplexity/Tests/Contract/FileUrlNormalizerTest.php
similarity index 87%
rename from src/platform/tests/Bridge/Perplexity/Contract/FileUrlNormalizerTest.php
rename to src/platform/src/Bridge/Perplexity/Tests/Contract/FileUrlNormalizerTest.php
index de8228354..7ddcfe6e5 100644
--- a/src/platform/tests/Bridge/Perplexity/Contract/FileUrlNormalizerTest.php
+++ b/src/platform/src/Bridge/Perplexity/Tests/Contract/FileUrlNormalizerTest.php
@@ -9,7 +9,7 @@
* file that was distributed with this source code.
*/
-namespace Symfony\AI\Platform\Tests\Bridge\Perplexity\Contract;
+namespace Symfony\AI\Platform\Bridge\Perplexity\Tests\Contract;
use PHPUnit\Framework\Attributes\DataProvider;
use PHPUnit\Framework\TestCase;
@@ -24,7 +24,7 @@ public function testSupportsNormalization()
{
$normalizer = new FileUrlNormalizer();
- $this->assertTrue($normalizer->supportsNormalization(new DocumentUrl(\dirname(__DIR__, 6).'/fixtures/not-a-document.pdf'), context: [
+ $this->assertTrue($normalizer->supportsNormalization(new DocumentUrl(\dirname(__DIR__, 7).'/fixtures/not-a-document.pdf'), context: [
Contract::CONTEXT_MODEL => new Perplexity('sonar'),
]));
$this->assertFalse($normalizer->supportsNormalization('not a document'));
@@ -54,11 +54,11 @@ public function testNormalize(DocumentUrl $document, array $expected)
public static function normalizeDataProvider(): iterable
{
yield 'document from file url' => [
- new DocumentUrl(\dirname(__DIR__, 6).'/fixtures/document.pdf'),
+ new DocumentUrl(\dirname(__DIR__, 7).'/fixtures/document.pdf'),
[
'type' => 'file_url',
'file_url' => [
- 'url' => \dirname(__DIR__, 6).'/fixtures/document.pdf',
+ 'url' => \dirname(__DIR__, 7).'/fixtures/document.pdf',
],
],
];
diff --git a/src/platform/tests/Bridge/Perplexity/ModelCatalogTest.php b/src/platform/src/Bridge/Perplexity/Tests/ModelCatalogTest.php
similarity index 97%
rename from src/platform/tests/Bridge/Perplexity/ModelCatalogTest.php
rename to src/platform/src/Bridge/Perplexity/Tests/ModelCatalogTest.php
index ae1180661..c94b60a11 100644
--- a/src/platform/tests/Bridge/Perplexity/ModelCatalogTest.php
+++ b/src/platform/src/Bridge/Perplexity/Tests/ModelCatalogTest.php
@@ -9,7 +9,7 @@
* file that was distributed with this source code.
*/
-namespace Symfony\AI\Platform\Tests\Bridge\Perplexity;
+namespace Symfony\AI\Platform\Bridge\Perplexity\Tests;
use Symfony\AI\Platform\Bridge\Perplexity\ModelCatalog;
use Symfony\AI\Platform\Bridge\Perplexity\Perplexity;
diff --git a/src/platform/tests/Bridge/Perplexity/ModelClientTest.php b/src/platform/src/Bridge/Perplexity/Tests/ModelClientTest.php
similarity index 100%
rename from src/platform/tests/Bridge/Perplexity/ModelClientTest.php
rename to src/platform/src/Bridge/Perplexity/Tests/ModelClientTest.php
diff --git a/src/platform/tests/Bridge/Perplexity/PerplexityTest.php b/src/platform/src/Bridge/Perplexity/Tests/PerplexityTest.php
similarity index 94%
rename from src/platform/tests/Bridge/Perplexity/PerplexityTest.php
rename to src/platform/src/Bridge/Perplexity/Tests/PerplexityTest.php
index 5c9300861..f6f770cd8 100644
--- a/src/platform/tests/Bridge/Perplexity/PerplexityTest.php
+++ b/src/platform/src/Bridge/Perplexity/Tests/PerplexityTest.php
@@ -9,7 +9,7 @@
* file that was distributed with this source code.
*/
-namespace Symfony\AI\Platform\Tests\Bridge\Perplexity;
+namespace Symfony\AI\Platform\Bridge\Perplexity\Tests;
use PHPUnit\Framework\TestCase;
use Symfony\AI\Platform\Bridge\Perplexity\Perplexity;
diff --git a/src/platform/tests/Bridge/Perplexity/PlatformFactoryTest.php b/src/platform/src/Bridge/Perplexity/Tests/PlatformFactoryTest.php
similarity index 96%
rename from src/platform/tests/Bridge/Perplexity/PlatformFactoryTest.php
rename to src/platform/src/Bridge/Perplexity/Tests/PlatformFactoryTest.php
index 0a6b6d07c..0fd484600 100644
--- a/src/platform/tests/Bridge/Perplexity/PlatformFactoryTest.php
+++ b/src/platform/src/Bridge/Perplexity/Tests/PlatformFactoryTest.php
@@ -9,7 +9,7 @@
* file that was distributed with this source code.
*/
-namespace Symfony\AI\Platform\Tests\Bridge\Perplexity;
+namespace Symfony\AI\Platform\Bridge\Perplexity\Tests;
use PHPUnit\Framework\TestCase;
use Symfony\AI\Platform\Bridge\Perplexity\PlatformFactory;
diff --git a/src/platform/tests/Bridge/Perplexity/ResultConverterTest.php b/src/platform/src/Bridge/Perplexity/Tests/ResultConverterTest.php
similarity index 99%
rename from src/platform/tests/Bridge/Perplexity/ResultConverterTest.php
rename to src/platform/src/Bridge/Perplexity/Tests/ResultConverterTest.php
index b659e7b50..3e78084f5 100644
--- a/src/platform/tests/Bridge/Perplexity/ResultConverterTest.php
+++ b/src/platform/src/Bridge/Perplexity/Tests/ResultConverterTest.php
@@ -9,7 +9,7 @@
* file that was distributed with this source code.
*/
-namespace Symfony\AI\Platform\Tests\Bridge\Perplexity;
+namespace Symfony\AI\Platform\Bridge\Perplexity\Tests;
use PHPUnit\Framework\TestCase;
use Symfony\AI\Platform\Bridge\Perplexity\ResultConverter;
diff --git a/src/platform/tests/Bridge/Perplexity/TokenUsageExtractorTest.php b/src/platform/src/Bridge/Perplexity/Tests/TokenUsageExtractorTest.php
similarity index 100%
rename from src/platform/tests/Bridge/Perplexity/TokenUsageExtractorTest.php
rename to src/platform/src/Bridge/Perplexity/Tests/TokenUsageExtractorTest.php
diff --git a/src/platform/src/Bridge/Perplexity/composer.json b/src/platform/src/Bridge/Perplexity/composer.json
new file mode 100644
index 000000000..0261f73dc
--- /dev/null
+++ b/src/platform/src/Bridge/Perplexity/composer.json
@@ -0,0 +1,61 @@
+{
+ "name": "symfony/ai-perplexity-platform",
+ "description": "Perplexity platform bridge for Symfony AI",
+ "license": "MIT",
+ "type": "symfony-ai-platform",
+ "keywords": [
+ "ai",
+ "bridge",
+ "perplexity",
+ "platform",
+ "search"
+ ],
+ "authors": [
+ {
+ "name": "Christopher Hertel",
+ "email": "mail@christopher-hertel.de"
+ },
+ {
+ "name": "Oskar Stark",
+ "email": "oskarstark@googlemail.com"
+ },
+ {
+ "name": "Symfony Community",
+ "homepage": "https://symfony.com/contributors"
+ }
+ ],
+ "require": {
+ "php": ">=8.2",
+ "symfony/ai-platform": "@dev",
+ "symfony/http-client": "^7.3|^8.0"
+ },
+ "require-dev": {
+ "phpstan/phpstan": "^2.1",
+ "phpstan/phpstan-strict-rules": "^2.0",
+ "phpunit/phpunit": "^11.5.46"
+ },
+ "minimum-stability": "dev",
+ "autoload": {
+ "psr-4": {
+ "Symfony\\AI\\Platform\\Bridge\\Perplexity\\": ""
+ }
+ },
+ "autoload-dev": {
+ "psr-4": {
+ "Symfony\\AI\\PHPStan\\": "../../../../../.phpstan/",
+ "Symfony\\AI\\Platform\\Bridge\\Perplexity\\Tests\\": "Tests/"
+ }
+ },
+ "config": {
+ "sort-packages": true
+ },
+ "extra": {
+ "branch-alias": {
+ "dev-main": "0.x-dev"
+ },
+ "thanks": {
+ "name": "symfony/ai",
+ "url": "https://github.com/symfony/ai"
+ }
+ }
+}
diff --git a/src/platform/src/Bridge/Perplexity/phpstan.dist.neon b/src/platform/src/Bridge/Perplexity/phpstan.dist.neon
new file mode 100644
index 000000000..5503dac38
--- /dev/null
+++ b/src/platform/src/Bridge/Perplexity/phpstan.dist.neon
@@ -0,0 +1,23 @@
+includes:
+ - ../../../../../.phpstan/extension.neon
+
+parameters:
+ level: 6
+ paths:
+ - .
+ - Tests/
+ excludePaths:
+ - vendor/
+ treatPhpDocTypesAsCertain: false
+ ignoreErrors:
+ -
+ message: "#^Method .*::test.*\\(\\) has no return type specified\\.$#"
+ reportUnmatched: false
+ -
+ identifier: missingType.iterableValue
+ path: Tests/*
+ reportUnmatched: false
+ -
+ identifier: 'symfonyAi.forbidNativeException'
+ path: Tests/*
+ reportUnmatched: false
diff --git a/src/platform/src/Bridge/Perplexity/phpunit.xml.dist b/src/platform/src/Bridge/Perplexity/phpunit.xml.dist
new file mode 100644
index 000000000..3510cee3d
--- /dev/null
+++ b/src/platform/src/Bridge/Perplexity/phpunit.xml.dist
@@ -0,0 +1,32 @@
+
+
+
+
+
+
+
+
+
+ ./Tests/
+
+
+
+
+
+ ./
+
+
+ ./Resources
+ ./Tests
+ ./vendor
+
+
+
diff --git a/src/platform/src/Bridge/Replicate/README.md b/src/platform/src/Bridge/Replicate/README.md
new file mode 100644
index 000000000..300a1f7a7
--- /dev/null
+++ b/src/platform/src/Bridge/Replicate/README.md
@@ -0,0 +1,12 @@
+Replicate Platform
+==================
+
+Replicate platform bridge for Symfony AI.
+
+Resources
+---------
+
+ * [Contributing](https://symfony.com/doc/current/contributing/index.html)
+ * [Report issues](https://github.com/symfony/ai/issues) and
+ [send Pull Requests](https://github.com/symfony/ai/pulls)
+ in the [main Symfony AI repository](https://github.com/symfony/ai)
diff --git a/src/platform/tests/Bridge/Replicate/ClientTest.php b/src/platform/src/Bridge/Replicate/Tests/ClientTest.php
similarity index 98%
rename from src/platform/tests/Bridge/Replicate/ClientTest.php
rename to src/platform/src/Bridge/Replicate/Tests/ClientTest.php
index 3c0054aaf..97fec5e7b 100644
--- a/src/platform/tests/Bridge/Replicate/ClientTest.php
+++ b/src/platform/src/Bridge/Replicate/Tests/ClientTest.php
@@ -9,7 +9,7 @@
* file that was distributed with this source code.
*/
-namespace Symfony\AI\Platform\Tests\Bridge\Replicate;
+namespace Symfony\AI\Platform\Bridge\Replicate\Tests;
use PHPUnit\Framework\TestCase;
use Symfony\AI\Platform\Bridge\Replicate\Client;
diff --git a/src/platform/tests/Bridge/Replicate/Contract/LlamaMessageBagNormalizerTest.php b/src/platform/src/Bridge/Replicate/Tests/Contract/LlamaMessageBagNormalizerTest.php
similarity index 97%
rename from src/platform/tests/Bridge/Replicate/Contract/LlamaMessageBagNormalizerTest.php
rename to src/platform/src/Bridge/Replicate/Tests/Contract/LlamaMessageBagNormalizerTest.php
index ba0768c4b..d1368fdc6 100644
--- a/src/platform/tests/Bridge/Replicate/Contract/LlamaMessageBagNormalizerTest.php
+++ b/src/platform/src/Bridge/Replicate/Tests/Contract/LlamaMessageBagNormalizerTest.php
@@ -9,7 +9,7 @@
* file that was distributed with this source code.
*/
-namespace Symfony\AI\Platform\Tests\Bridge\Replicate\Contract;
+namespace Symfony\AI\Platform\Bridge\Replicate\Tests\Contract;
use PHPUnit\Framework\TestCase;
use Symfony\AI\Platform\Bridge\Meta\Llama;
diff --git a/src/platform/tests/Bridge/Replicate/LlamaModelClientTest.php b/src/platform/src/Bridge/Replicate/Tests/LlamaModelClientTest.php
similarity index 97%
rename from src/platform/tests/Bridge/Replicate/LlamaModelClientTest.php
rename to src/platform/src/Bridge/Replicate/Tests/LlamaModelClientTest.php
index 04494ebd0..3edf3dc95 100644
--- a/src/platform/tests/Bridge/Replicate/LlamaModelClientTest.php
+++ b/src/platform/src/Bridge/Replicate/Tests/LlamaModelClientTest.php
@@ -9,7 +9,7 @@
* file that was distributed with this source code.
*/
-namespace Symfony\AI\Platform\Tests\Bridge\Replicate;
+namespace Symfony\AI\Platform\Bridge\Replicate\Tests;
use PHPUnit\Framework\TestCase;
use Symfony\AI\Platform\Bridge\Meta\Llama;
diff --git a/src/platform/tests/Bridge/Replicate/LlamaResultConverterTest.php b/src/platform/src/Bridge/Replicate/Tests/LlamaResultConverterTest.php
similarity index 98%
rename from src/platform/tests/Bridge/Replicate/LlamaResultConverterTest.php
rename to src/platform/src/Bridge/Replicate/Tests/LlamaResultConverterTest.php
index ab30e0696..7a6558094 100644
--- a/src/platform/tests/Bridge/Replicate/LlamaResultConverterTest.php
+++ b/src/platform/src/Bridge/Replicate/Tests/LlamaResultConverterTest.php
@@ -9,7 +9,7 @@
* file that was distributed with this source code.
*/
-namespace Symfony\AI\Platform\Tests\Bridge\Replicate;
+namespace Symfony\AI\Platform\Bridge\Replicate\Tests;
use PHPUnit\Framework\TestCase;
use Symfony\AI\Platform\Bridge\Meta\Llama;
diff --git a/src/platform/tests/Bridge/Replicate/ModelCatalogTest.php b/src/platform/src/Bridge/Replicate/Tests/ModelCatalogTest.php
similarity index 98%
rename from src/platform/tests/Bridge/Replicate/ModelCatalogTest.php
rename to src/platform/src/Bridge/Replicate/Tests/ModelCatalogTest.php
index 7c8aea162..0de3d74c4 100644
--- a/src/platform/tests/Bridge/Replicate/ModelCatalogTest.php
+++ b/src/platform/src/Bridge/Replicate/Tests/ModelCatalogTest.php
@@ -9,7 +9,7 @@
* file that was distributed with this source code.
*/
-namespace Symfony\AI\Platform\Tests\Bridge\Replicate;
+namespace Symfony\AI\Platform\Bridge\Replicate\Tests;
use Symfony\AI\Platform\Bridge\Meta\Llama;
use Symfony\AI\Platform\Bridge\Replicate\ModelCatalog;
diff --git a/src/platform/src/Bridge/Replicate/composer.json b/src/platform/src/Bridge/Replicate/composer.json
new file mode 100644
index 000000000..906d35d2e
--- /dev/null
+++ b/src/platform/src/Bridge/Replicate/composer.json
@@ -0,0 +1,61 @@
+{
+ "name": "symfony/ai-replicate-platform",
+ "description": "Replicate platform bridge for Symfony AI",
+ "license": "MIT",
+ "type": "symfony-ai-platform",
+ "keywords": [
+ "ai",
+ "bridge",
+ "platform",
+ "replicate"
+ ],
+ "authors": [
+ {
+ "name": "Christopher Hertel",
+ "email": "mail@christopher-hertel.de"
+ },
+ {
+ "name": "Oskar Stark",
+ "email": "oskarstark@googlemail.com"
+ },
+ {
+ "name": "Symfony Community",
+ "homepage": "https://symfony.com/contributors"
+ }
+ ],
+ "require": {
+ "php": ">=8.2",
+ "symfony/ai-meta-platform": "@dev",
+ "symfony/ai-platform": "@dev",
+ "symfony/http-client": "^7.3|^8.0"
+ },
+ "require-dev": {
+ "phpstan/phpstan": "^2.1",
+ "phpstan/phpstan-strict-rules": "^2.0",
+ "phpunit/phpunit": "^11.5.46"
+ },
+ "minimum-stability": "dev",
+ "autoload": {
+ "psr-4": {
+ "Symfony\\AI\\Platform\\Bridge\\Replicate\\": ""
+ }
+ },
+ "autoload-dev": {
+ "psr-4": {
+ "Symfony\\AI\\PHPStan\\": "../../../../../.phpstan/",
+ "Symfony\\AI\\Platform\\Bridge\\Replicate\\Tests\\": "Tests/"
+ }
+ },
+ "config": {
+ "sort-packages": true
+ },
+ "extra": {
+ "branch-alias": {
+ "dev-main": "0.x-dev"
+ },
+ "thanks": {
+ "name": "symfony/ai",
+ "url": "https://github.com/symfony/ai"
+ }
+ }
+}
diff --git a/src/platform/src/Bridge/Replicate/phpstan.dist.neon b/src/platform/src/Bridge/Replicate/phpstan.dist.neon
new file mode 100644
index 000000000..5503dac38
--- /dev/null
+++ b/src/platform/src/Bridge/Replicate/phpstan.dist.neon
@@ -0,0 +1,23 @@
+includes:
+ - ../../../../../.phpstan/extension.neon
+
+parameters:
+ level: 6
+ paths:
+ - .
+ - Tests/
+ excludePaths:
+ - vendor/
+ treatPhpDocTypesAsCertain: false
+ ignoreErrors:
+ -
+ message: "#^Method .*::test.*\\(\\) has no return type specified\\.$#"
+ reportUnmatched: false
+ -
+ identifier: missingType.iterableValue
+ path: Tests/*
+ reportUnmatched: false
+ -
+ identifier: 'symfonyAi.forbidNativeException'
+ path: Tests/*
+ reportUnmatched: false
diff --git a/src/platform/src/Bridge/Replicate/phpunit.xml.dist b/src/platform/src/Bridge/Replicate/phpunit.xml.dist
new file mode 100644
index 000000000..03caa4173
--- /dev/null
+++ b/src/platform/src/Bridge/Replicate/phpunit.xml.dist
@@ -0,0 +1,32 @@
+
+
+
+
+
+
+
+
+
+ ./Tests/
+
+
+
+
+
+ ./
+
+
+ ./Resources
+ ./Tests
+ ./vendor
+
+
+
diff --git a/src/platform/src/Bridge/Scaleway/README.md b/src/platform/src/Bridge/Scaleway/README.md
new file mode 100644
index 000000000..e99640545
--- /dev/null
+++ b/src/platform/src/Bridge/Scaleway/README.md
@@ -0,0 +1,12 @@
+Scaleway Platform
+=================
+
+Scaleway platform bridge for Symfony AI.
+
+Resources
+---------
+
+ * [Contributing](https://symfony.com/doc/current/contributing/index.html)
+ * [Report issues](https://github.com/symfony/ai/issues) and
+ [send Pull Requests](https://github.com/symfony/ai/pulls)
+ in the [main Symfony AI repository](https://github.com/symfony/ai)
diff --git a/src/platform/tests/Bridge/Scaleway/Embeddings/ModelClientTest.php b/src/platform/src/Bridge/Scaleway/Tests/Embeddings/ModelClientTest.php
similarity index 100%
rename from src/platform/tests/Bridge/Scaleway/Embeddings/ModelClientTest.php
rename to src/platform/src/Bridge/Scaleway/Tests/Embeddings/ModelClientTest.php
diff --git a/src/platform/tests/Bridge/Scaleway/Embeddings/ResultConverterTest.php b/src/platform/src/Bridge/Scaleway/Tests/Embeddings/ResultConverterTest.php
similarity index 100%
rename from src/platform/tests/Bridge/Scaleway/Embeddings/ResultConverterTest.php
rename to src/platform/src/Bridge/Scaleway/Tests/Embeddings/ResultConverterTest.php
diff --git a/src/platform/tests/Bridge/Scaleway/EmbeddingsTest.php b/src/platform/src/Bridge/Scaleway/Tests/EmbeddingsTest.php
similarity index 100%
rename from src/platform/tests/Bridge/Scaleway/EmbeddingsTest.php
rename to src/platform/src/Bridge/Scaleway/Tests/EmbeddingsTest.php
diff --git a/src/platform/tests/Bridge/Scaleway/Llm/ModelClientTest.php b/src/platform/src/Bridge/Scaleway/Tests/Llm/ModelClientTest.php
similarity index 100%
rename from src/platform/tests/Bridge/Scaleway/Llm/ModelClientTest.php
rename to src/platform/src/Bridge/Scaleway/Tests/Llm/ModelClientTest.php
diff --git a/src/platform/tests/Bridge/Scaleway/Llm/ResultConverterTest.php b/src/platform/src/Bridge/Scaleway/Tests/Llm/ResultConverterTest.php
similarity index 100%
rename from src/platform/tests/Bridge/Scaleway/Llm/ResultConverterTest.php
rename to src/platform/src/Bridge/Scaleway/Tests/Llm/ResultConverterTest.php
diff --git a/src/platform/tests/Bridge/Scaleway/ModelCatalogTest.php b/src/platform/src/Bridge/Scaleway/Tests/ModelCatalogTest.php
similarity index 98%
rename from src/platform/tests/Bridge/Scaleway/ModelCatalogTest.php
rename to src/platform/src/Bridge/Scaleway/Tests/ModelCatalogTest.php
index e323d408a..6eec0739f 100644
--- a/src/platform/tests/Bridge/Scaleway/ModelCatalogTest.php
+++ b/src/platform/src/Bridge/Scaleway/Tests/ModelCatalogTest.php
@@ -9,7 +9,7 @@
* file that was distributed with this source code.
*/
-namespace Symfony\AI\Platform\Tests\Bridge\Scaleway;
+namespace Symfony\AI\Platform\Bridge\Scaleway\Tests;
use Symfony\AI\Platform\Bridge\Scaleway\Embeddings;
use Symfony\AI\Platform\Bridge\Scaleway\ModelCatalog;
diff --git a/src/platform/tests/Bridge/Scaleway/PlatformFactoryTest.php b/src/platform/src/Bridge/Scaleway/Tests/PlatformFactoryTest.php
similarity index 100%
rename from src/platform/tests/Bridge/Scaleway/PlatformFactoryTest.php
rename to src/platform/src/Bridge/Scaleway/Tests/PlatformFactoryTest.php
diff --git a/src/platform/src/Bridge/Scaleway/composer.json b/src/platform/src/Bridge/Scaleway/composer.json
new file mode 100644
index 000000000..47a1d1b95
--- /dev/null
+++ b/src/platform/src/Bridge/Scaleway/composer.json
@@ -0,0 +1,60 @@
+{
+ "name": "symfony/ai-scaleway-platform",
+ "description": "Scaleway platform bridge for Symfony AI",
+ "license": "MIT",
+ "type": "symfony-ai-platform",
+ "keywords": [
+ "ai",
+ "bridge",
+ "platform",
+ "scaleway"
+ ],
+ "authors": [
+ {
+ "name": "Christopher Hertel",
+ "email": "mail@christopher-hertel.de"
+ },
+ {
+ "name": "Oskar Stark",
+ "email": "oskarstark@googlemail.com"
+ },
+ {
+ "name": "Symfony Community",
+ "homepage": "https://symfony.com/contributors"
+ }
+ ],
+ "require": {
+ "php": ">=8.2",
+ "symfony/ai-platform": "@dev",
+ "symfony/http-client": "^7.3|^8.0"
+ },
+ "require-dev": {
+ "phpstan/phpstan": "^2.1",
+ "phpstan/phpstan-strict-rules": "^2.0",
+ "phpunit/phpunit": "^11.5.46"
+ },
+ "minimum-stability": "dev",
+ "autoload": {
+ "psr-4": {
+ "Symfony\\AI\\Platform\\Bridge\\Scaleway\\": ""
+ }
+ },
+ "autoload-dev": {
+ "psr-4": {
+ "Symfony\\AI\\PHPStan\\": "../../../../../.phpstan/",
+ "Symfony\\AI\\Platform\\Bridge\\Scaleway\\Tests\\": "Tests/"
+ }
+ },
+ "config": {
+ "sort-packages": true
+ },
+ "extra": {
+ "branch-alias": {
+ "dev-main": "0.x-dev"
+ },
+ "thanks": {
+ "name": "symfony/ai",
+ "url": "https://github.com/symfony/ai"
+ }
+ }
+}
diff --git a/src/platform/src/Bridge/Scaleway/phpstan.dist.neon b/src/platform/src/Bridge/Scaleway/phpstan.dist.neon
new file mode 100644
index 000000000..5503dac38
--- /dev/null
+++ b/src/platform/src/Bridge/Scaleway/phpstan.dist.neon
@@ -0,0 +1,23 @@
+includes:
+ - ../../../../../.phpstan/extension.neon
+
+parameters:
+ level: 6
+ paths:
+ - .
+ - Tests/
+ excludePaths:
+ - vendor/
+ treatPhpDocTypesAsCertain: false
+ ignoreErrors:
+ -
+ message: "#^Method .*::test.*\\(\\) has no return type specified\\.$#"
+ reportUnmatched: false
+ -
+ identifier: missingType.iterableValue
+ path: Tests/*
+ reportUnmatched: false
+ -
+ identifier: 'symfonyAi.forbidNativeException'
+ path: Tests/*
+ reportUnmatched: false
diff --git a/src/platform/src/Bridge/Scaleway/phpunit.xml.dist b/src/platform/src/Bridge/Scaleway/phpunit.xml.dist
new file mode 100644
index 000000000..79d483528
--- /dev/null
+++ b/src/platform/src/Bridge/Scaleway/phpunit.xml.dist
@@ -0,0 +1,32 @@
+
+
+
+
+
+
+
+
+
+ ./Tests/
+
+
+
+
+
+ ./
+
+
+ ./Resources
+ ./Tests
+ ./vendor
+
+
+
diff --git a/src/platform/src/Bridge/TransformersPhp/README.md b/src/platform/src/Bridge/TransformersPhp/README.md
new file mode 100644
index 000000000..2794c1d5d
--- /dev/null
+++ b/src/platform/src/Bridge/TransformersPhp/README.md
@@ -0,0 +1,12 @@
+TransformersPhp Platform
+========================
+
+TransformersPhp platform bridge for Symfony AI.
+
+Resources
+---------
+
+ * [Contributing](https://symfony.com/doc/current/contributing/index.html)
+ * [Report issues](https://github.com/symfony/ai/issues) and
+ [send Pull Requests](https://github.com/symfony/ai/pulls)
+ in the [main Symfony AI repository](https://github.com/symfony/ai)
diff --git a/src/platform/tests/Bridge/TransformersPhp/ModelCatalogTest.php b/src/platform/src/Bridge/TransformersPhp/Tests/ModelCatalogTest.php
similarity index 95%
rename from src/platform/tests/Bridge/TransformersPhp/ModelCatalogTest.php
rename to src/platform/src/Bridge/TransformersPhp/Tests/ModelCatalogTest.php
index 345479666..947c6f361 100644
--- a/src/platform/tests/Bridge/TransformersPhp/ModelCatalogTest.php
+++ b/src/platform/src/Bridge/TransformersPhp/Tests/ModelCatalogTest.php
@@ -9,7 +9,7 @@
* file that was distributed with this source code.
*/
-namespace Symfony\AI\Platform\Tests\Bridge\TransformersPhp;
+namespace Symfony\AI\Platform\Bridge\TransformersPhp\Tests;
use Symfony\AI\Platform\Bridge\TransformersPhp\ModelCatalog;
use Symfony\AI\Platform\Capability;
diff --git a/src/platform/src/Bridge/TransformersPhp/composer.json b/src/platform/src/Bridge/TransformersPhp/composer.json
new file mode 100644
index 000000000..de39d9c73
--- /dev/null
+++ b/src/platform/src/Bridge/TransformersPhp/composer.json
@@ -0,0 +1,65 @@
+{
+ "name": "symfony/ai-transformers-php-platform",
+ "description": "TransformersPhp platform bridge for Symfony AI",
+ "license": "MIT",
+ "type": "symfony-ai-platform",
+ "keywords": [
+ "ai",
+ "bridge",
+ "local",
+ "platform",
+ "transformers"
+ ],
+ "authors": [
+ {
+ "name": "Christopher Hertel",
+ "email": "mail@christopher-hertel.de"
+ },
+ {
+ "name": "Oskar Stark",
+ "email": "oskarstark@googlemail.com"
+ },
+ {
+ "name": "Symfony Community",
+ "homepage": "https://symfony.com/contributors"
+ }
+ ],
+ "require": {
+ "php": ">=8.2",
+ "symfony/ai-platform": "@dev",
+ "codewithkyrian/transformers": "^0.6.2"
+ },
+ "require-dev": {
+ "phpstan/phpstan": "^2.1",
+ "phpstan/phpstan-strict-rules": "^2.0",
+ "phpunit/phpunit": "^11.5.46"
+ },
+ "minimum-stability": "dev",
+ "autoload": {
+ "psr-4": {
+ "Symfony\\AI\\Platform\\Bridge\\TransformersPhp\\": ""
+ }
+ },
+ "autoload-dev": {
+ "psr-4": {
+ "Symfony\\AI\\PHPStan\\": "../../../../../.phpstan/",
+ "Symfony\\AI\\Platform\\Bridge\\TransformersPhp\\Tests\\": "Tests/"
+ }
+ },
+ "config": {
+ "allow-plugins": {
+ "codewithkyrian/platform-package-installer": true,
+ "codewithkyrian/transformers-libsloader": true
+ },
+ "sort-packages": true
+ },
+ "extra": {
+ "branch-alias": {
+ "dev-main": "0.x-dev"
+ },
+ "thanks": {
+ "name": "symfony/ai",
+ "url": "https://github.com/symfony/ai"
+ }
+ }
+}
diff --git a/src/platform/src/Bridge/TransformersPhp/phpstan.dist.neon b/src/platform/src/Bridge/TransformersPhp/phpstan.dist.neon
new file mode 100644
index 000000000..5503dac38
--- /dev/null
+++ b/src/platform/src/Bridge/TransformersPhp/phpstan.dist.neon
@@ -0,0 +1,23 @@
+includes:
+ - ../../../../../.phpstan/extension.neon
+
+parameters:
+ level: 6
+ paths:
+ - .
+ - Tests/
+ excludePaths:
+ - vendor/
+ treatPhpDocTypesAsCertain: false
+ ignoreErrors:
+ -
+ message: "#^Method .*::test.*\\(\\) has no return type specified\\.$#"
+ reportUnmatched: false
+ -
+ identifier: missingType.iterableValue
+ path: Tests/*
+ reportUnmatched: false
+ -
+ identifier: 'symfonyAi.forbidNativeException'
+ path: Tests/*
+ reportUnmatched: false
diff --git a/src/platform/src/Bridge/TransformersPhp/phpunit.xml.dist b/src/platform/src/Bridge/TransformersPhp/phpunit.xml.dist
new file mode 100644
index 000000000..05693d332
--- /dev/null
+++ b/src/platform/src/Bridge/TransformersPhp/phpunit.xml.dist
@@ -0,0 +1,32 @@
+
+
+
+
+
+
+
+
+
+ ./Tests/
+
+
+
+
+
+ ./
+
+
+ ./Resources
+ ./Tests
+ ./vendor
+
+
+
diff --git a/src/platform/src/Bridge/VertexAi/README.md b/src/platform/src/Bridge/VertexAi/README.md
new file mode 100644
index 000000000..66c6f8933
--- /dev/null
+++ b/src/platform/src/Bridge/VertexAi/README.md
@@ -0,0 +1,12 @@
+VertexAi Platform
+=================
+
+Google Vertex AI platform bridge for Symfony AI.
+
+Resources
+---------
+
+ * [Contributing](https://symfony.com/doc/current/contributing/index.html)
+ * [Report issues](https://github.com/symfony/ai/issues) and
+ [send Pull Requests](https://github.com/symfony/ai/pulls)
+ in the [main Symfony AI repository](https://github.com/symfony/ai)
diff --git a/src/platform/tests/Bridge/VertexAi/Contract/AssistantMessageNormalizerTest.php b/src/platform/src/Bridge/VertexAi/Tests/Contract/AssistantMessageNormalizerTest.php
similarity index 97%
rename from src/platform/tests/Bridge/VertexAi/Contract/AssistantMessageNormalizerTest.php
rename to src/platform/src/Bridge/VertexAi/Tests/Contract/AssistantMessageNormalizerTest.php
index 0e356fb2a..5974e3570 100644
--- a/src/platform/tests/Bridge/VertexAi/Contract/AssistantMessageNormalizerTest.php
+++ b/src/platform/src/Bridge/VertexAi/Tests/Contract/AssistantMessageNormalizerTest.php
@@ -9,7 +9,7 @@
* file that was distributed with this source code.
*/
-namespace Symfony\AI\Platform\Tests\Bridge\VertexAi\Contract;
+namespace Symfony\AI\Platform\Bridge\VertexAi\Tests\Contract;
use PHPUnit\Framework\Attributes\DataProvider;
use PHPUnit\Framework\TestCase;
diff --git a/src/platform/tests/Bridge/VertexAi/Contract/MessageBagNormalizerTest.php b/src/platform/src/Bridge/VertexAi/Tests/Contract/MessageBagNormalizerTest.php
similarity index 96%
rename from src/platform/tests/Bridge/VertexAi/Contract/MessageBagNormalizerTest.php
rename to src/platform/src/Bridge/VertexAi/Tests/Contract/MessageBagNormalizerTest.php
index 6292a99b9..c81dae4f7 100644
--- a/src/platform/tests/Bridge/VertexAi/Contract/MessageBagNormalizerTest.php
+++ b/src/platform/src/Bridge/VertexAi/Tests/Contract/MessageBagNormalizerTest.php
@@ -9,7 +9,7 @@
* file that was distributed with this source code.
*/
-namespace Symfony\AI\Platform\Tests\Bridge\VertexAi\Contract;
+namespace Symfony\AI\Platform\Bridge\VertexAi\Tests\Contract;
use PHPUnit\Framework\Attributes\DataProvider;
use PHPUnit\Framework\TestCase;
@@ -92,13 +92,13 @@ public static function provideMessageBagData(): iterable
yield 'text with image' => [
new MessageBag(
- Message::ofUser('Tell me about this instrument', Image::fromFile(\dirname(__DIR__, 6).'/fixtures/image.jpg'))
+ Message::ofUser('Tell me about this instrument', Image::fromFile(\dirname(__DIR__, 7).'/fixtures/image.jpg'))
),
[
'contents' => [
['role' => 'user', 'parts' => [
['text' => 'Tell me about this instrument'],
- ['inlineData' => ['mimeType' => 'image/jpeg', 'data' => base64_encode(file_get_contents(\dirname(__DIR__, 6).'/fixtures/image.jpg'))]],
+ ['inlineData' => ['mimeType' => 'image/jpeg', 'data' => base64_encode(file_get_contents(\dirname(__DIR__, 7).'/fixtures/image.jpg'))]],
]],
],
],
diff --git a/src/platform/tests/Bridge/VertexAi/Contract/ToolCallMessageNormalizerTest.php b/src/platform/src/Bridge/VertexAi/Tests/Contract/ToolCallMessageNormalizerTest.php
similarity index 97%
rename from src/platform/tests/Bridge/VertexAi/Contract/ToolCallMessageNormalizerTest.php
rename to src/platform/src/Bridge/VertexAi/Tests/Contract/ToolCallMessageNormalizerTest.php
index 20ee5ba77..cdf7c6687 100644
--- a/src/platform/tests/Bridge/VertexAi/Contract/ToolCallMessageNormalizerTest.php
+++ b/src/platform/src/Bridge/VertexAi/Tests/Contract/ToolCallMessageNormalizerTest.php
@@ -9,7 +9,7 @@
* file that was distributed with this source code.
*/
-namespace Symfony\AI\Platform\Tests\Bridge\VertexAi\Contract;
+namespace Symfony\AI\Platform\Bridge\VertexAi\Tests\Contract;
use PHPUnit\Framework\Attributes\DataProvider;
use PHPUnit\Framework\TestCase;
diff --git a/src/platform/tests/Bridge/VertexAi/Contract/ToolNormalizerTest.php b/src/platform/src/Bridge/VertexAi/Tests/Contract/ToolNormalizerTest.php
similarity index 98%
rename from src/platform/tests/Bridge/VertexAi/Contract/ToolNormalizerTest.php
rename to src/platform/src/Bridge/VertexAi/Tests/Contract/ToolNormalizerTest.php
index 70e405420..a54bc00bf 100644
--- a/src/platform/tests/Bridge/VertexAi/Contract/ToolNormalizerTest.php
+++ b/src/platform/src/Bridge/VertexAi/Tests/Contract/ToolNormalizerTest.php
@@ -9,7 +9,7 @@
* file that was distributed with this source code.
*/
-namespace Symfony\AI\Platform\Tests\Bridge\VertexAi\Contract;
+namespace Symfony\AI\Platform\Bridge\VertexAi\Tests\Contract;
use PHPUnit\Framework\Attributes\DataProvider;
use PHPUnit\Framework\TestCase;
diff --git a/src/platform/tests/Bridge/VertexAi/Contract/UserMessageNormalizerTest.php b/src/platform/src/Bridge/VertexAi/Tests/Contract/UserMessageNormalizerTest.php
similarity index 88%
rename from src/platform/tests/Bridge/VertexAi/Contract/UserMessageNormalizerTest.php
rename to src/platform/src/Bridge/VertexAi/Tests/Contract/UserMessageNormalizerTest.php
index 4c46f6858..67f4e7515 100644
--- a/src/platform/tests/Bridge/VertexAi/Contract/UserMessageNormalizerTest.php
+++ b/src/platform/src/Bridge/VertexAi/Tests/Contract/UserMessageNormalizerTest.php
@@ -9,7 +9,7 @@
* file that was distributed with this source code.
*/
-namespace Symfony\AI\Platform\Tests\Bridge\VertexAi\Contract;
+namespace Symfony\AI\Platform\Bridge\VertexAi\Tests\Contract;
use PHPUnit\Framework\Attributes\DataProvider;
use PHPUnit\Framework\TestCase;
@@ -52,6 +52,16 @@ public function testNormalizeTextContent()
$this->assertSame([['text' => 'Write a story about a magic backpack.']], $normalized);
}
+ /**
+ * @return iterable
+ */
+ public static function binaryContentProvider(): iterable
+ {
+ yield 'image' => [Image::fromFile(\dirname(__DIR__, 5).'/tests/Fixtures/image.jpg'), 'image/jpeg', '/9j/'];
+ yield 'document' => [Document::fromFile(\dirname(__DIR__, 5).'/tests/Fixtures/document.pdf'), 'application/pdf', 'JVBE'];
+ yield 'audio' => [Audio::fromFile(\dirname(__DIR__, 5).'/tests/Fixtures/audio.mp3'), 'audio/mpeg', 'SUQz'];
+ }
+
#[DataProvider('binaryContentProvider')]
public function testNormalizeBinaryContent(File $content, string $expectedMimeType, string $expectedPrefix)
{
@@ -68,14 +78,4 @@ public function testNormalizeBinaryContent(File $content, string $expectedMimeTy
$this->assertStringStartsWith($expectedPrefix, $normalized[1]['inlineData']['data']);
}
-
- /**
- * @return iterable
- */
- public static function binaryContentProvider(): iterable
- {
- yield 'image' => [Image::fromFile(\dirname(__DIR__, 6).'/fixtures/image.jpg'), 'image/jpeg', '/9j/'];
- yield 'document' => [Document::fromFile(\dirname(__DIR__, 6).'/fixtures/document.pdf'), 'application/pdf', 'JVBE'];
- yield 'audio' => [Audio::fromFile(\dirname(__DIR__, 6).'/fixtures/audio.mp3'), 'audio/mpeg', 'SUQz'];
- }
}
diff --git a/src/platform/tests/Bridge/VertexAi/Embeddings/ModelClientTest.php b/src/platform/src/Bridge/VertexAi/Tests/Embeddings/ModelClientTest.php
similarity index 95%
rename from src/platform/tests/Bridge/VertexAi/Embeddings/ModelClientTest.php
rename to src/platform/src/Bridge/VertexAi/Tests/Embeddings/ModelClientTest.php
index a78e0c67b..6b11786f9 100644
--- a/src/platform/tests/Bridge/VertexAi/Embeddings/ModelClientTest.php
+++ b/src/platform/src/Bridge/VertexAi/Tests/Embeddings/ModelClientTest.php
@@ -9,7 +9,7 @@
* file that was distributed with this source code.
*/
-namespace Symfony\AI\Platform\Tests\Bridge\VertexAi\Embeddings;
+namespace Symfony\AI\Platform\Bridge\VertexAi\Tests\Embeddings;
use PHPUnit\Framework\TestCase;
use Symfony\AI\Platform\Bridge\VertexAi\Embeddings\Model;
diff --git a/src/platform/tests/Bridge/VertexAi/Embeddings/ResultConverterTest.php b/src/platform/src/Bridge/VertexAi/Tests/Embeddings/ResultConverterTest.php
similarity index 95%
rename from src/platform/tests/Bridge/VertexAi/Embeddings/ResultConverterTest.php
rename to src/platform/src/Bridge/VertexAi/Tests/Embeddings/ResultConverterTest.php
index a37c49cd5..5e4dfccb7 100644
--- a/src/platform/tests/Bridge/VertexAi/Embeddings/ResultConverterTest.php
+++ b/src/platform/src/Bridge/VertexAi/Tests/Embeddings/ResultConverterTest.php
@@ -9,7 +9,7 @@
* file that was distributed with this source code.
*/
-namespace Symfony\AI\Platform\Tests\Bridge\VertexAi\Embeddings;
+namespace Symfony\AI\Platform\Bridge\VertexAi\Tests\Embeddings;
use PHPUnit\Framework\TestCase;
use Symfony\AI\Platform\Bridge\VertexAi\Embeddings\ResultConverter;
diff --git a/src/platform/src/Bridge/VertexAi/Tests/Gemini/Fixtures/code_execution_outcome_deadline_exceeded.json b/src/platform/src/Bridge/VertexAi/Tests/Gemini/Fixtures/code_execution_outcome_deadline_exceeded.json
new file mode 100644
index 000000000..9b4a592a0
--- /dev/null
+++ b/src/platform/src/Bridge/VertexAi/Tests/Gemini/Fixtures/code_execution_outcome_deadline_exceeded.json
@@ -0,0 +1,31 @@
+{
+ "candidates": [
+ {
+ "content": {
+ "parts": [
+ {
+ "text": "First text"
+ },
+ {
+ "executableCode": {
+ "language": "PYTHON",
+ "code": "print('Hello, World!')"
+ }
+ },
+ {
+ "codeExecutionResult": {
+ "outcome": "OUTCOME_DEADLINE_EXCEEDED",
+ "output": "An error occurred during code execution."
+ }
+ },
+ {
+ "text": "Last text"
+ }
+ ],
+ "role": "model"
+ },
+ "finishReason": "STOP",
+ "index": 0
+ }
+ ]
+}
diff --git a/src/platform/src/Bridge/VertexAi/Tests/Gemini/Fixtures/code_execution_outcome_failed.json b/src/platform/src/Bridge/VertexAi/Tests/Gemini/Fixtures/code_execution_outcome_failed.json
new file mode 100644
index 000000000..8a1580137
--- /dev/null
+++ b/src/platform/src/Bridge/VertexAi/Tests/Gemini/Fixtures/code_execution_outcome_failed.json
@@ -0,0 +1,31 @@
+{
+ "candidates": [
+ {
+ "content": {
+ "parts": [
+ {
+ "text": "First text"
+ },
+ {
+ "executableCode": {
+ "language": "PYTHON",
+ "code": "print('Hello, World!')"
+ }
+ },
+ {
+ "codeExecutionResult": {
+ "outcome": "OUTCOME_FAILED",
+ "output": "An error occurred during code execution."
+ }
+ },
+ {
+ "text": "Last text"
+ }
+ ],
+ "role": "model"
+ },
+ "finishReason": "STOP",
+ "index": 0
+ }
+ ]
+}
diff --git a/src/platform/src/Bridge/VertexAi/Tests/Gemini/Fixtures/code_execution_outcome_ok.json b/src/platform/src/Bridge/VertexAi/Tests/Gemini/Fixtures/code_execution_outcome_ok.json
new file mode 100644
index 000000000..3738f01b2
--- /dev/null
+++ b/src/platform/src/Bridge/VertexAi/Tests/Gemini/Fixtures/code_execution_outcome_ok.json
@@ -0,0 +1,37 @@
+{
+ "candidates": [
+ {
+ "content": {
+ "parts": [
+ {
+ "text": "First text"
+ },
+ {
+ "executableCode": {
+ "language": "PYTHON",
+ "code": "print('Hello, World!')"
+ }
+ },
+ {
+ "codeExecutionResult": {
+ "outcome": "OUTCOME_OK",
+ "output": "Hello, World!"
+ }
+ },
+ {
+ "text": "Second text\n"
+ },
+ {
+ "text": "Third text\n"
+ },
+ {
+ "text": "Fourth text"
+ }
+ ],
+ "role": "model"
+ },
+ "finishReason": "STOP",
+ "index": 0
+ }
+ ]
+}
diff --git a/src/platform/tests/Bridge/VertexAi/Gemini/ModelClientTest.php b/src/platform/src/Bridge/VertexAi/Tests/Gemini/ModelClientTest.php
similarity index 97%
rename from src/platform/tests/Bridge/VertexAi/Gemini/ModelClientTest.php
rename to src/platform/src/Bridge/VertexAi/Tests/Gemini/ModelClientTest.php
index 8af8f4b54..69bf0662f 100644
--- a/src/platform/tests/Bridge/VertexAi/Gemini/ModelClientTest.php
+++ b/src/platform/src/Bridge/VertexAi/Tests/Gemini/ModelClientTest.php
@@ -9,7 +9,7 @@
* file that was distributed with this source code.
*/
-namespace Symfony\AI\Platform\Tests\Bridge\VertexAi\Gemini;
+namespace Symfony\AI\Platform\Bridge\VertexAi\Tests\Gemini;
use PHPUnit\Framework\TestCase;
use Symfony\AI\Platform\Bridge\VertexAi\Gemini\Model;
diff --git a/src/platform/tests/Bridge/VertexAi/Gemini/ResultConverterTest.php b/src/platform/src/Bridge/VertexAi/Tests/Gemini/ResultConverterTest.php
similarity index 96%
rename from src/platform/tests/Bridge/VertexAi/Gemini/ResultConverterTest.php
rename to src/platform/src/Bridge/VertexAi/Tests/Gemini/ResultConverterTest.php
index d84ad6284..57c7f91b4 100644
--- a/src/platform/tests/Bridge/VertexAi/Gemini/ResultConverterTest.php
+++ b/src/platform/src/Bridge/VertexAi/Tests/Gemini/ResultConverterTest.php
@@ -9,7 +9,7 @@
* file that was distributed with this source code.
*/
-namespace Symfony\AI\Platform\Tests\Bridge\VertexAi\Gemini;
+namespace Symfony\AI\Platform\Bridge\VertexAi\Tests\Gemini;
use PHPUnit\Framework\TestCase;
use Symfony\AI\Platform\Bridge\VertexAi\Gemini\ResultConverter;
@@ -46,7 +46,7 @@ public function testItConvertsAResponseToAVectorResult()
public function testItReturnsAggregatedTextOnSuccess()
{
$response = $this->createStub(ResponseInterface::class);
- $responseContent = file_get_contents(__DIR__.'/fixtures/code_execution_outcome_ok.json');
+ $responseContent = file_get_contents(__DIR__.'/Fixtures/code_execution_outcome_ok.json');
$response
->method('toArray')
@@ -99,7 +99,7 @@ public function testItReturnsToolCallEvenIfMultipleContentPartsAreGiven()
public function testItThrowsExceptionOnFailure()
{
$response = $this->createStub(ResponseInterface::class);
- $responseContent = file_get_contents(__DIR__.'/fixtures/code_execution_outcome_failed.json');
+ $responseContent = file_get_contents(__DIR__.'/Fixtures/code_execution_outcome_failed.json');
$response
->method('toArray')
@@ -114,7 +114,7 @@ public function testItThrowsExceptionOnFailure()
public function testItThrowsExceptionOnTimeout()
{
$response = $this->createStub(ResponseInterface::class);
- $responseContent = file_get_contents(__DIR__.'/fixtures/code_execution_outcome_deadline_exceeded.json');
+ $responseContent = file_get_contents(__DIR__.'/Fixtures/code_execution_outcome_deadline_exceeded.json');
$response
->method('toArray')
diff --git a/src/platform/tests/Bridge/VertexAi/ModelCatalogTest.php b/src/platform/src/Bridge/VertexAi/Tests/ModelCatalogTest.php
similarity index 98%
rename from src/platform/tests/Bridge/VertexAi/ModelCatalogTest.php
rename to src/platform/src/Bridge/VertexAi/Tests/ModelCatalogTest.php
index 92000eed6..3e47036a8 100644
--- a/src/platform/tests/Bridge/VertexAi/ModelCatalogTest.php
+++ b/src/platform/src/Bridge/VertexAi/Tests/ModelCatalogTest.php
@@ -9,7 +9,7 @@
* file that was distributed with this source code.
*/
-namespace Symfony\AI\Platform\Tests\Bridge\VertexAi;
+namespace Symfony\AI\Platform\Bridge\VertexAi\Tests;
use Symfony\AI\Platform\Bridge\VertexAi\Embeddings\Model as EmbeddingsModel;
use Symfony\AI\Platform\Bridge\VertexAi\Gemini\Model as GeminiModel;
diff --git a/src/platform/tests/Bridge/VertexAi/TokenUsageExtractorTest.php b/src/platform/src/Bridge/VertexAi/Tests/TokenUsageExtractorTest.php
similarity index 100%
rename from src/platform/tests/Bridge/VertexAi/TokenUsageExtractorTest.php
rename to src/platform/src/Bridge/VertexAi/Tests/TokenUsageExtractorTest.php
diff --git a/src/platform/src/Bridge/VertexAi/composer.json b/src/platform/src/Bridge/VertexAi/composer.json
new file mode 100644
index 000000000..75d5689ed
--- /dev/null
+++ b/src/platform/src/Bridge/VertexAi/composer.json
@@ -0,0 +1,65 @@
+{
+ "name": "symfony/ai-vertex-ai-platform",
+ "description": "Google Vertex AI platform bridge for Symfony AI",
+ "license": "MIT",
+ "type": "symfony-ai-platform",
+ "keywords": [
+ "ai",
+ "bridge",
+ "google",
+ "platform",
+ "vertexai"
+ ],
+ "authors": [
+ {
+ "name": "Christopher Hertel",
+ "email": "mail@christopher-hertel.de"
+ },
+ {
+ "name": "Oskar Stark",
+ "email": "oskarstark@googlemail.com"
+ },
+ {
+ "name": "Symfony Community",
+ "homepage": "https://symfony.com/contributors"
+ }
+ ],
+ "require": {
+ "google/auth": "^1.47",
+ "php": ">=8.2",
+ "symfony/ai-gemini-platform": "@dev",
+ "symfony/ai-platform": "@dev",
+ "symfony/http-client": "^7.3|^8.0"
+ },
+ "require-dev": {
+ "phpstan/phpstan": "^2.1",
+ "phpstan/phpstan-strict-rules": "^2.0",
+ "phpunit/phpunit": "^11.5.46",
+ "symfony/ai-agent": "@dev"
+ },
+ "minimum-stability": "dev",
+ "autoload": {
+ "psr-4": {
+ "Symfony\\AI\\Platform\\Bridge\\VertexAi\\": ""
+ }
+ },
+ "autoload-dev": {
+ "psr-4": {
+ "Symfony\\AI\\Agent\\Tests\\": "../../../../agent/tests/",
+ "Symfony\\AI\\PHPStan\\": "../../../../../.phpstan/",
+ "Symfony\\AI\\Platform\\Bridge\\VertexAi\\Tests\\": "Tests/"
+ }
+ },
+ "config": {
+ "sort-packages": true
+ },
+ "extra": {
+ "branch-alias": {
+ "dev-main": "0.x-dev"
+ },
+ "thanks": {
+ "name": "symfony/ai",
+ "url": "https://github.com/symfony/ai"
+ }
+ }
+}
diff --git a/src/platform/src/Bridge/VertexAi/phpstan.dist.neon b/src/platform/src/Bridge/VertexAi/phpstan.dist.neon
new file mode 100644
index 000000000..5503dac38
--- /dev/null
+++ b/src/platform/src/Bridge/VertexAi/phpstan.dist.neon
@@ -0,0 +1,23 @@
+includes:
+ - ../../../../../.phpstan/extension.neon
+
+parameters:
+ level: 6
+ paths:
+ - .
+ - Tests/
+ excludePaths:
+ - vendor/
+ treatPhpDocTypesAsCertain: false
+ ignoreErrors:
+ -
+ message: "#^Method .*::test.*\\(\\) has no return type specified\\.$#"
+ reportUnmatched: false
+ -
+ identifier: missingType.iterableValue
+ path: Tests/*
+ reportUnmatched: false
+ -
+ identifier: 'symfonyAi.forbidNativeException'
+ path: Tests/*
+ reportUnmatched: false
diff --git a/src/platform/src/Bridge/VertexAi/phpunit.xml.dist b/src/platform/src/Bridge/VertexAi/phpunit.xml.dist
new file mode 100644
index 000000000..0ba21e7da
--- /dev/null
+++ b/src/platform/src/Bridge/VertexAi/phpunit.xml.dist
@@ -0,0 +1,32 @@
+
+
+
+
+
+
+
+
+
+ ./Tests/
+
+
+
+
+
+ ./
+
+
+ ./Resources
+ ./Tests
+ ./vendor
+
+
+
diff --git a/src/platform/src/Bridge/Voyage/README.md b/src/platform/src/Bridge/Voyage/README.md
new file mode 100644
index 000000000..bb076aa19
--- /dev/null
+++ b/src/platform/src/Bridge/Voyage/README.md
@@ -0,0 +1,12 @@
+Voyage Platform
+===============
+
+Voyage platform bridge for Symfony AI.
+
+Resources
+---------
+
+ * [Contributing](https://symfony.com/doc/current/contributing/index.html)
+ * [Report issues](https://github.com/symfony/ai/issues) and
+ [send Pull Requests](https://github.com/symfony/ai/pulls)
+ in the [main Symfony AI repository](https://github.com/symfony/ai)
diff --git a/src/platform/tests/Bridge/Voyage/Contract/Multimodal/CollectionNormalizerTest.php b/src/platform/src/Bridge/Voyage/Tests/Contract/Multimodal/CollectionNormalizerTest.php
similarity index 98%
rename from src/platform/tests/Bridge/Voyage/Contract/Multimodal/CollectionNormalizerTest.php
rename to src/platform/src/Bridge/Voyage/Tests/Contract/Multimodal/CollectionNormalizerTest.php
index 0a8e057bd..96878362f 100644
--- a/src/platform/tests/Bridge/Voyage/Contract/Multimodal/CollectionNormalizerTest.php
+++ b/src/platform/src/Bridge/Voyage/Tests/Contract/Multimodal/CollectionNormalizerTest.php
@@ -9,7 +9,7 @@
* file that was distributed with this source code.
*/
-namespace Symfony\AI\Platform\Tests\Bridge\Voyage\Contract\Multimodal;
+namespace Symfony\AI\Platform\Bridge\Voyage\Tests\Contract\Multimodal;
use PHPUnit\Framework\Attributes\DataProvider;
use PHPUnit\Framework\TestCase;
diff --git a/src/platform/tests/Bridge/Voyage/Contract/Multimodal/ImageNormalizerTest.php b/src/platform/src/Bridge/Voyage/Tests/Contract/Multimodal/ImageNormalizerTest.php
similarity index 94%
rename from src/platform/tests/Bridge/Voyage/Contract/Multimodal/ImageNormalizerTest.php
rename to src/platform/src/Bridge/Voyage/Tests/Contract/Multimodal/ImageNormalizerTest.php
index 3e9beab49..0a8e67a4b 100644
--- a/src/platform/tests/Bridge/Voyage/Contract/Multimodal/ImageNormalizerTest.php
+++ b/src/platform/src/Bridge/Voyage/Tests/Contract/Multimodal/ImageNormalizerTest.php
@@ -9,7 +9,7 @@
* file that was distributed with this source code.
*/
-namespace Symfony\AI\Platform\Tests\Bridge\Voyage\Contract\Multimodal;
+namespace Symfony\AI\Platform\Bridge\Voyage\Tests\Contract\Multimodal;
use PHPUnit\Framework\Attributes\DataProvider;
use PHPUnit\Framework\TestCase;
@@ -62,6 +62,6 @@ public static function supportsNormalizationDataProvider(): \Generator
private static function getFixtureImage(): Image
{
- return Image::fromFile(\dirname(__DIR__, 7).'/fixtures/image.jpg');
+ return Image::fromFile(\dirname(__DIR__, 8).'/fixtures/image.jpg');
}
}
diff --git a/src/platform/tests/Bridge/Voyage/Contract/Multimodal/ImageUrlNormalizerTest.php b/src/platform/src/Bridge/Voyage/Tests/Contract/Multimodal/ImageUrlNormalizerTest.php
similarity index 97%
rename from src/platform/tests/Bridge/Voyage/Contract/Multimodal/ImageUrlNormalizerTest.php
rename to src/platform/src/Bridge/Voyage/Tests/Contract/Multimodal/ImageUrlNormalizerTest.php
index ff7416a8b..7dfcc78f8 100644
--- a/src/platform/tests/Bridge/Voyage/Contract/Multimodal/ImageUrlNormalizerTest.php
+++ b/src/platform/src/Bridge/Voyage/Tests/Contract/Multimodal/ImageUrlNormalizerTest.php
@@ -9,7 +9,7 @@
* file that was distributed with this source code.
*/
-namespace Symfony\AI\Platform\Tests\Bridge\Voyage\Contract\Multimodal;
+namespace Symfony\AI\Platform\Bridge\Voyage\Tests\Contract\Multimodal;
use PHPUnit\Framework\Attributes\DataProvider;
use PHPUnit\Framework\TestCase;
diff --git a/src/platform/tests/Bridge/Voyage/Contract/Multimodal/MultimodalNormalizerTest.php b/src/platform/src/Bridge/Voyage/Tests/Contract/Multimodal/MultimodalNormalizerTest.php
similarity index 98%
rename from src/platform/tests/Bridge/Voyage/Contract/Multimodal/MultimodalNormalizerTest.php
rename to src/platform/src/Bridge/Voyage/Tests/Contract/Multimodal/MultimodalNormalizerTest.php
index 067d80b6b..bbbaf3c32 100644
--- a/src/platform/tests/Bridge/Voyage/Contract/Multimodal/MultimodalNormalizerTest.php
+++ b/src/platform/src/Bridge/Voyage/Tests/Contract/Multimodal/MultimodalNormalizerTest.php
@@ -9,7 +9,7 @@
* file that was distributed with this source code.
*/
-namespace Symfony\AI\Platform\Tests\Bridge\Voyage\Contract\Multimodal;
+namespace Symfony\AI\Platform\Bridge\Voyage\Tests\Contract\Multimodal;
use PHPUnit\Framework\Attributes\DataProvider;
use PHPUnit\Framework\TestCase;
diff --git a/src/platform/tests/Bridge/Voyage/Contract/Multimodal/TextNormalizerTest.php b/src/platform/src/Bridge/Voyage/Tests/Contract/Multimodal/TextNormalizerTest.php
similarity index 96%
rename from src/platform/tests/Bridge/Voyage/Contract/Multimodal/TextNormalizerTest.php
rename to src/platform/src/Bridge/Voyage/Tests/Contract/Multimodal/TextNormalizerTest.php
index 3efce10f7..aaa16f101 100644
--- a/src/platform/tests/Bridge/Voyage/Contract/Multimodal/TextNormalizerTest.php
+++ b/src/platform/src/Bridge/Voyage/Tests/Contract/Multimodal/TextNormalizerTest.php
@@ -9,7 +9,7 @@
* file that was distributed with this source code.
*/
-namespace Symfony\AI\Platform\Tests\Bridge\Voyage\Contract\Multimodal;
+namespace Symfony\AI\Platform\Bridge\Voyage\Tests\Contract\Multimodal;
use PHPUnit\Framework\Attributes\DataProvider;
use PHPUnit\Framework\TestCase;
diff --git a/src/platform/tests/Bridge/Voyage/Contract/VoyageContractTest.php b/src/platform/src/Bridge/Voyage/Tests/Contract/VoyageContractTest.php
similarity index 98%
rename from src/platform/tests/Bridge/Voyage/Contract/VoyageContractTest.php
rename to src/platform/src/Bridge/Voyage/Tests/Contract/VoyageContractTest.php
index 4575a9a7a..8889893f2 100644
--- a/src/platform/tests/Bridge/Voyage/Contract/VoyageContractTest.php
+++ b/src/platform/src/Bridge/Voyage/Tests/Contract/VoyageContractTest.php
@@ -9,7 +9,7 @@
* file that was distributed with this source code.
*/
-namespace Symfony\AI\Platform\Tests\Bridge\Voyage\Contract;
+namespace Symfony\AI\Platform\Bridge\Voyage\Tests\Contract;
use PHPUnit\Framework\Attributes\DataProvider;
use PHPUnit\Framework\TestCase;
diff --git a/src/platform/tests/Bridge/Voyage/ModelCatalogTest.php b/src/platform/src/Bridge/Voyage/Tests/ModelCatalogTest.php
similarity index 97%
rename from src/platform/tests/Bridge/Voyage/ModelCatalogTest.php
rename to src/platform/src/Bridge/Voyage/Tests/ModelCatalogTest.php
index 171fcd4c6..4d6d7cbdd 100644
--- a/src/platform/tests/Bridge/Voyage/ModelCatalogTest.php
+++ b/src/platform/src/Bridge/Voyage/Tests/ModelCatalogTest.php
@@ -9,7 +9,7 @@
* file that was distributed with this source code.
*/
-namespace Symfony\AI\Platform\Tests\Bridge\Voyage;
+namespace Symfony\AI\Platform\Bridge\Voyage\Tests;
use Symfony\AI\Platform\Bridge\Voyage\ModelCatalog;
use Symfony\AI\Platform\Bridge\Voyage\Voyage;
diff --git a/src/platform/tests/Bridge/Voyage/ModelClientTest.php b/src/platform/src/Bridge/Voyage/Tests/ModelClientTest.php
similarity index 98%
rename from src/platform/tests/Bridge/Voyage/ModelClientTest.php
rename to src/platform/src/Bridge/Voyage/Tests/ModelClientTest.php
index 62b89a0e4..f3c2f3193 100644
--- a/src/platform/tests/Bridge/Voyage/ModelClientTest.php
+++ b/src/platform/src/Bridge/Voyage/Tests/ModelClientTest.php
@@ -9,7 +9,7 @@
* file that was distributed with this source code.
*/
-namespace Symfony\AI\Platform\Tests\Bridge\Voyage;
+namespace Symfony\AI\Platform\Bridge\Voyage\Tests;
use PHPUnit\Framework\Attributes\DataProvider;
use PHPUnit\Framework\TestCase;
diff --git a/src/platform/tests/Bridge/Voyage/ResultConverterTest.php b/src/platform/src/Bridge/Voyage/Tests/ResultConverterTest.php
similarity index 98%
rename from src/platform/tests/Bridge/Voyage/ResultConverterTest.php
rename to src/platform/src/Bridge/Voyage/Tests/ResultConverterTest.php
index 88f9da9ec..772c0050f 100644
--- a/src/platform/tests/Bridge/Voyage/ResultConverterTest.php
+++ b/src/platform/src/Bridge/Voyage/Tests/ResultConverterTest.php
@@ -9,7 +9,7 @@
* file that was distributed with this source code.
*/
-namespace Symfony\AI\Platform\Tests\Bridge\Voyage;
+namespace Symfony\AI\Platform\Bridge\Voyage\Tests;
use PHPUnit\Framework\TestCase;
use Symfony\AI\Platform\Bridge\Voyage\ResultConverter;
diff --git a/src/platform/src/Bridge/Voyage/composer.json b/src/platform/src/Bridge/Voyage/composer.json
new file mode 100644
index 000000000..5203c2b73
--- /dev/null
+++ b/src/platform/src/Bridge/Voyage/composer.json
@@ -0,0 +1,61 @@
+{
+ "name": "symfony/ai-voyage-platform",
+ "description": "Voyage platform bridge for Symfony AI",
+ "license": "MIT",
+ "type": "symfony-ai-platform",
+ "keywords": [
+ "ai",
+ "bridge",
+ "embeddings",
+ "platform",
+ "voyage"
+ ],
+ "authors": [
+ {
+ "name": "Christopher Hertel",
+ "email": "mail@christopher-hertel.de"
+ },
+ {
+ "name": "Oskar Stark",
+ "email": "oskarstark@googlemail.com"
+ },
+ {
+ "name": "Symfony Community",
+ "homepage": "https://symfony.com/contributors"
+ }
+ ],
+ "require": {
+ "php": ">=8.2",
+ "symfony/ai-platform": "@dev",
+ "symfony/http-client": "^7.3|^8.0"
+ },
+ "require-dev": {
+ "phpstan/phpstan": "^2.1",
+ "phpstan/phpstan-strict-rules": "^2.0",
+ "phpunit/phpunit": "^11.5.46"
+ },
+ "minimum-stability": "dev",
+ "autoload": {
+ "psr-4": {
+ "Symfony\\AI\\Platform\\Bridge\\Voyage\\": ""
+ }
+ },
+ "autoload-dev": {
+ "psr-4": {
+ "Symfony\\AI\\PHPStan\\": "../../../../../.phpstan/",
+ "Symfony\\AI\\Platform\\Bridge\\Voyage\\Tests\\": "Tests/"
+ }
+ },
+ "config": {
+ "sort-packages": true
+ },
+ "extra": {
+ "branch-alias": {
+ "dev-main": "0.x-dev"
+ },
+ "thanks": {
+ "name": "symfony/ai",
+ "url": "https://github.com/symfony/ai"
+ }
+ }
+}
diff --git a/src/platform/src/Bridge/Voyage/phpstan.dist.neon b/src/platform/src/Bridge/Voyage/phpstan.dist.neon
new file mode 100644
index 000000000..ebc355d21
--- /dev/null
+++ b/src/platform/src/Bridge/Voyage/phpstan.dist.neon
@@ -0,0 +1,27 @@
+includes:
+ - ../../../../../.phpstan/extension.neon
+
+parameters:
+ level: 6
+ paths:
+ - .
+ - Tests/
+ excludePaths:
+ - vendor/
+ treatPhpDocTypesAsCertain: false
+ ignoreErrors:
+ -
+ message: "#^Method .*::test.*\\(\\) has no return type specified\\.$#"
+ reportUnmatched: false
+ -
+ identifier: missingType.iterableValue
+ path: Tests/*
+ reportUnmatched: false
+ -
+ identifier: missingType.iterableValue
+ path: Contract/*
+ reportUnmatched: false
+ -
+ identifier: 'symfonyAi.forbidNativeException'
+ path: Tests/*
+ reportUnmatched: false
diff --git a/src/platform/src/Bridge/Voyage/phpunit.xml.dist b/src/platform/src/Bridge/Voyage/phpunit.xml.dist
new file mode 100644
index 000000000..565f68770
--- /dev/null
+++ b/src/platform/src/Bridge/Voyage/phpunit.xml.dist
@@ -0,0 +1,32 @@
+
+
+
+
+
+
+
+
+
+ ./Tests/
+
+
+
+
+
+ ./
+
+
+ ./Resources
+ ./Tests
+ ./vendor
+
+
+