refactor: rework LLM Chain into Symfony AI

This commit is contained in:
Christopher Hertel
2025-06-06 23:20:12 +02:00
436 changed files with 24106 additions and 10 deletions

66
.env Normal file
View File

@@ -0,0 +1,66 @@
# You only need to fill in the values when running the examples, see examples/
# For using GPT on OpenAI
OPENAI_API_KEY=
# For using Claude on Anthropic
ANTHROPIC_API_KEY=
# For using Mistral
MISTRAL_API_KEY=
# For using Voyage
VOYAGE_API_KEY=
# For using Replicate
REPLICATE_API_KEY=
# For using Ollama
OLLAMA_HOST_URL=
# For using GPT on Azure
AZURE_OPENAI_BASEURL=
AZURE_OPENAI_KEY=
AZURE_OPENAI_GPT_DEPLOYMENT=
AZURE_OPENAI_GPT_API_VERSION=
AZURE_OPENAI_EMBEDDINGS_DEPLOYMENT=
AZURE_OPENAI_EMBEDDINGS_API_VERSION=
AZURE_OPENAI_WHISPER_DEPLOYMENT=
AZURE_OPENAI_WHISPER_API_VERSION=
# For using Llama on Azure
AZURE_LLAMA_BASEURL=
AZURE_LLAMA_KEY=
# For using Bedrock
AWS_ACCESS_KEY_ID=
AWS_SECRET_ACCESS_KEY=
AWS_DEFAULT_REGION=
# Hugging Face Access Token
HUGGINGFACE_KEY=
# For using OpenRouter
OPENROUTER_KEY=
# For using SerpApi (tool)
SERP_API_KEY=
# For using Tavily (tool)
TAVILY_API_KEY=
# For using Brave (tool)
BRAVE_API_KEY=
# For using MongoDB Atlas (store)
MONGODB_URI=
# For using Pinecone (store)
PINECONE_API_KEY=
PINECONE_HOST=
# Some examples are expensive to run, so we disable them by default
RUN_EXPENSIVE_EXAMPLES=false
# For using Gemini
GOOGLE_API_KEY=

View File

@@ -51,8 +51,7 @@ jobs:
run: |
echo COLUMNS=120 >> $GITHUB_ENV
echo COMPOSER_MIN_STAB='composer config minimum-stability ${{ matrix.minimum-stability || 'stable' }} --ansi' >> $GITHUB_ENV
echo COMPOSER_UP='composer update ${{ matrix.dependency-version == 'lowest' && '--prefer-lowest' || '' }} --no-progress --no-interaction --ansi' >> $GITHUB_ENV
echo COMPOSER_VALIDATE='composer validate --strict' >> $GITHUB_ENV
echo COMPOSER_UP='composer update ${{ matrix.dependency-version == 'lowest' && '--prefer-lowest' || '' }} --no-progress --no-interaction --ansi --ignore-platform-req=ext-mongodb' >> $GITHUB_ENV
echo PHPSTAN='vendor/bin/phpstan' >> $GITHUB_ENV
PACKAGES=$(find src/ -mindepth 2 -type f -name composer.json -not -path "*/vendor/*" -printf '%h\n' | sed 's/^src\///' | grep -Ev "examples" | sort | tr '\n' ' ')
@@ -75,4 +74,4 @@ jobs:
run: |
source .github/workflows/.utils.sh
echo "$PACKAGES" | xargs -n1 | parallel -j +3 "_run_task {} '(cd src/{} && $COMPOSER_MIN_STAB && $COMPOSER_UP && $COMPOSER_VALIDATE && $PHPSTAN)'"
echo "$PACKAGES" | xargs -n1 | parallel -j +3 "_run_task {} '(cd src/{} && $COMPOSER_MIN_STAB && $COMPOSER_UP && $PHPSTAN)'"

View File

@@ -44,7 +44,7 @@ jobs:
run: |
echo COLUMNS=120 >> $GITHUB_ENV
echo COMPOSER_MIN_STAB='composer config minimum-stability ${{ matrix.minimum-stability || 'stable' }} --ansi' >> $GITHUB_ENV
echo COMPOSER_UP='composer update ${{ matrix.dependency-version == 'lowest' && '--prefer-lowest' || '' }} --no-progress --no-interaction --ansi' >> $GITHUB_ENV
echo COMPOSER_UP='composer update ${{ matrix.dependency-version == 'lowest' && '--prefer-lowest' || '' }} --no-progress --no-interaction --ansi --ignore-platform-req=ext-mongodb' >> $GITHUB_ENV
echo PHPUNIT='vendor/bin/phpunit' >> $GITHUB_ENV
[ 'lowest' = '${{ matrix.dependency-version }}' ] && export SYMFONY_DEPRECATIONS_HELPER=weak

8
.gitignore vendored
View File

@@ -1,6 +1,8 @@
.doctor-rst.cache
.env.local
.php-cs-fixer.cache
.phpunit.result.cache
.phpunit.cache
.transformers-cache
/composer.lock
/vendor
composer.lock
vendor

View File

@@ -42,7 +42,7 @@ return (new PhpCsFixer\Config())
->setRiskyAllowed(true)
->setFinder(
(new PhpCsFixer\Finder())
->in(__DIR__.'/src')
->in([__DIR__.'/src', __DIR__.'/examples'])
->append([__FILE__])
->notPath('#/Fixtures/#')
)

845
README.md
View File

@@ -8,6 +8,843 @@
Symfony AI is a set of packages that integrate AI capabilities into PHP applications.
## Requirements
* PHP 8.2 or higher
## Installation
The recommended way to install Symfony AI components is through [Composer](http://getcomposer.org/):
```bash
composer require symfony/ai-agent
composer require symfony/ai-platform
composer require symfony/ai-store
```
When using Symfony Framework, check out the integration bundle symfony/ai-bundle.
## Examples
See [the examples folder](examples) to run example implementations using this library.
Depending on the example you need to export different environment variables
for API keys or deployment configurations or create a `.env.local` based on `.env` file.
To run all examples, use `make run-examples` or `php example` - to run a subgroup like all HuggingFace related examples
use `php example huggingface`.
For a more sophisticated demo, see the [Symfony Demo Application](https://github.com/php-llm/symfony-demo).
## Basic Concepts & Usage
### Models & Platforms
Symfony AI categorizes two main types of models: **Language Models** and **Embeddings Models**. On top of that, there are
other models, like text-to-speech, image generation, or classification models that are also supported.
Language Models, like GPT, Claude, and Llama, as essential centerpiece of LLM applications
and Embeddings Models as supporting models to provide vector representations of a text.
Those models are provided by different **platforms**, like OpenAI, Azure, Google, Replicate, and others.
#### Example Instantiation
```php
use Symfony\AI\Platform\Bridge\OpenAI\Embeddings;
use Symfony\AI\Platform\Bridge\OpenAI\GPT;
use Symfony\AI\Platform\Bridge\OpenAI\PlatformFactory;
// Platform: OpenAI
$platform = PlatformFactory::create($_ENV['OPENAI_API_KEY']);
// Language Model: GPT (OpenAI)
$model = new GPT(GPT::GPT_4O_MINI);
// Embeddings Model: Embeddings (OpenAI)
$embeddings = new Embeddings();
```
#### Supported Models & Platforms
* Language Models
* [OpenAI's GPT](https://platform.openai.com/docs/models/overview) with [OpenAI](https://platform.openai.com/docs/overview) and [Azure](https://learn.microsoft.com/azure/ai-services/openai/concepts/models) as Platform
* [Anthropic's Claude](https://www.anthropic.com/claude) with [Anthropic](https://www.anthropic.com/) and [AWS](https://aws.amazon.com/bedrock/) as Platform
* [Meta's Llama](https://www.llama.com/) with [Azure](https://learn.microsoft.com/azure/machine-learning/how-to-deploy-models-llama), [Ollama](https://ollama.com/), [Replicate](https://replicate.com/) and [AWS](https://aws.amazon.com/bedrock/) as Platform
* [Google's Gemini](https://gemini.google.com/) with [Google](https://ai.google.dev/) and [OpenRouter](https://www.openrouter.com/) as Platform
* [DeepSeek's R1](https://www.deepseek.com/) with [OpenRouter](https://www.openrouter.com/) as Platform
* [Amazon's Nova](https://nova.amazon.com) with [AWS](https://aws.amazon.com/bedrock/) as Platform
* [Mistral's Mistral](https://www.mistral.ai/) with [Mistral](https://www.mistral.ai/) as Platform
* Embeddings Models
* [OpenAI's Text Embeddings](https://platform.openai.com/docs/guides/embeddings/embedding-models) with [OpenAI](https://platform.openai.com/docs/overview) and [Azure](https://learn.microsoft.com/azure/ai-services/openai/concepts/models) as Platform
* [Voyage's Embeddings](https://docs.voyageai.com/docs/embeddings) with [Voyage](https://www.voyageai.com/) as Platform
* [Mistral Embed](https://www.mistral.ai/) with [Mistral](https://www.mistral.ai/) as Platform
* Other Models
* [OpenAI's Dall·E](https://platform.openai.com/docs/guides/image-generation) with [OpenAI](https://platform.openai.com/docs/overview) as Platform
* [OpenAI's Whisper](https://platform.openai.com/docs/guides/speech-to-text) with [OpenAI](https://platform.openai.com/docs/overview) and [Azure](https://learn.microsoft.com/azure/ai-services/openai/concepts/models) as Platform
* All models provided by [HuggingFace](https://huggingface.co/) can be listed with `make huggingface-models`
And more filtered with `php examples/huggingface/_model-listing.php --provider=hf-inference --task=object-detection`
See [issue #28](https://github.com/php-llm/llm-chain/issues/28) for planned support of other models and platforms.
### Agent & Messages
The core feature of the Symfony AI is to interact with language models via messages. This interaction is done by sending
a **MessageBag** to an **Agent**, which takes care of LLM invocation and response handling.
Messages can be of different types, most importantly `UserMessage`, `SystemMessage`, or `AssistantMessage`, and can also
have different content types, like `Text`, `Image` or `Audio`.
#### Example Agent call with messages
```php
use Symfony\AI\Agent\Agent;
use Symfony\AI\Platform\Message\Message;
use Symfony\AI\Platform\Message\MessageBag;
// Platform & LLM instantiation
$agent = new Agent($platform, $model);
$messages = new MessageBag(
Message::forSystem('You are a helpful chatbot answering questions about LLM agent.'),
Message::ofUser('Hello, how are you?'),
);
$response = $agent->call($messages);
echo $response->getContent(); // "I'm fine, thank you. How can I help you today?"
```
The `MessageInterface` and `Content` interface help to customize this process if needed, e.g. additional state handling.
#### Options
The second parameter of the `call` method is an array of options, which can be used to configure the behavior of the
agent, like `stream`, `output_structure`, or `response_format`. This behavior is a combination of features provided by
the underlying model and platform, or additional features provided by processors registered to the agent.
Options designed for additional features provided by Symfony AI can be found in this documentation. For model- and
platform-specific options, please refer to the respective documentation.
```php
// agent and MessageBag instantiation
$response = $agent->call($messages, [
'temperature' => 0.5, // example option controlling the randomness of the response, e.g. GPT and Claude
'n' => 3, // example option controlling the number of responses generated, e.g. GPT
]);
```
#### Code Examples
1. [Anthropic's Claude](examples/anthropic/chat.php)
1. [OpenAI's GPT with Azure](examples/azure/chat-gpt.php)
1. [OpenAI's GPT](examples/openai/chat.php)
1. [OpenAI's o1](examples/openai/chat-o1.php)
1. [Meta's Llama with Azure](examples/azure/chat-llama.php)
1. [Meta's Llama with Ollama](examples/ollama/chat-llama.php)
1. [Meta's Llama with Replicate](examples/replicate/chat-llama.php)
1. [Google's Gemini with Google](examples/google/chat.php)
1. [Google's Gemini with OpenRouter](examples/openrouter/chat-gemini.php)
1. [Mistral's Mistral with Mistral](examples/mistral/chat-mistral.php)
### Tools
To integrate LLMs with your application, Symfony AI supports [tool calling](https://platform.openai.com/docs/guides/function-calling) out of the box.
Tools are services that can be called by the LLM to provide additional features or process data.
Tool calling can be enabled by registering the processors in the agent:
```php
use Symfony\AI\Agent\Agent;
use Symfony\AI\Agent\Toolbox\AgentProcessor;
use Symfony\AI\Agent\Toolbox\Toolbox;
// Platform & LLM instantiation
$yourTool = new YourTool();
$toolbox = Toolbox::create($yourTool);
$toolProcessor = new AgentProcessor($toolbox);
$agent = new Agent($platform, $model, inputProcessor: [$toolProcessor], outputProcessor: [$toolProcessor]);
```
Custom tools can basically be any class, but must configure by the `#[AsTool]` attribute.
```php
use Symfony\AI\Toolbox\Attribute\AsTool;
#[AsTool('company_name', 'Provides the name of your company')]
final class CompanyName
{
public function __invoke(): string
{
return 'ACME Corp.'
}
}
```
#### Tool Return Value
In the end, the tool's response needs to be a string, but Symfony AI converts arrays and objects, that implement the
`JsonSerializable` interface, to JSON strings for you. So you can return arrays or objects directly from your tool.
#### Tool Methods
You can configure the method to be called by the LLM with the `#[AsTool]` attribute and have multiple tools per class:
```php
use Symfony\AI\Toolbox\Attribute\AsTool;
#[AsTool(
name: 'weather_current',
description: 'get current weather for a location',
method: 'current',
)]
#[AsTool(
name: 'weather_forecast',
description: 'get weather forecast for a location',
method: 'forecast',
)]
final readonly class OpenMeteo
{
public function current(float $latitude, float $longitude): array
{
// ...
}
public function forecast(float $latitude, float $longitude): array
{
// ...
}
}
```
#### Tool Parameters
Symfony AI generates a JSON Schema representation for all tools in the `Toolbox` based on the `#[AsTool]` attribute and
method arguments and param comments in the doc block. Additionally, JSON Schema support validation rules, which are
partially support by LLMs like GPT.
To leverage this, configure the `#[With]` attribute on the method arguments of your tool:
```php
use Symfony\AI\Agent\Toolbox\Attribute\AsTool;
use Symfony\AI\Platform\Contract\JsonSchema\Attribute\With;
#[AsTool('my_tool', 'Example tool with parameters requirements.')]
final class MyTool
{
/**
* @param string $name The name of an object
* @param int $number The number of an object
*/
public function __invoke(
#[With(pattern: '/([a-z0-1]){5}/')]
string $name,
#[With(minimum: 0, maximum: 10)]
int $number,
): string {
// ...
}
}
```
See attribute class [With](src/agent/JsonSchema/Attribute/With.php) for all available options.
> [!NOTE]
> Please be aware, that this is only converted in a JSON Schema for the LLM to respect, but not validated by Symfony AI.
#### Third-Party Tools
In some cases you might want to use third-party tools, which are not part of your application. Adding the `#[AsTool]`
attribute to the class is not possible in those cases, but you can explicitly register the tool in the `MemoryFactory`:
```php
use Symfony\AI\Agent\Toolbox\Toolbox;
use Symfony\AI\Agent\Toolbox\ToolFactory\MemoryToolFactory;
use Symfony\Component\Clock\Clock;
$metadataFactory = (new MemoryToolFactory())
->addTool(Clock::class, 'clock', 'Get the current date and time', 'now');
$toolbox = new Toolbox($metadataFactory, [new Clock()]);
```
> [!NOTE]
> Please be aware that not all return types are supported by the toolbox, so a decorator might still be needed.
This can be combined with the `ChainFactory` which enables you to use explicitly registered tools and `#[AsTool]` tagged
tools in the same chain - which even enables you to overwrite the pre-existing configuration of a tool:
```php
use Symfony\AI\Agent\Toolbox\Toolbox;
use Symfony\AI\Agent\Toolbox\ToolFactory\ChainFactory;
use Symfony\AI\Agent\Toolbox\ToolFactory\MemoryToolFactory;
use Symfony\AI\Agent\Toolbox\ToolFactory\ReflectionToolFactory;
$reflectionFactory = new ReflectionToolFactory(); // Register tools with #[AsTool] attribute
$metadataFactory = (new MemoryToolFactory()) // Register or overwrite tools explicitly
->addTool(...);
$toolbox = new Toolbox(new AgentFactory($metadataFactory, $reflectionFactory), [...]);
```
> [!NOTE]
> The order of the factories in the `ChainFactory` matters, as the first factory has the highest priority.
#### Agent uses Agent 🤯
Similar to third-party tools, an agent can also use an different agent as a tool. This can be useful to encapsulate
complex logic or to reuse an agent in multiple places or hide sub-agents from the LLM.
```php
use Symfony\AI\Agent\Toolbox\ToolFactory\MemoryToolFactory;
use Symfony\AI\Agent\Toolbox\Toolbox;
use Symfony\AI\Agent\Toolbox\Tool\Agent;
// agent was initialized before
$agentTool = new Agent($agent);
$metadataFactory = (new MemoryToolFactory())
->addTool($agentTool, 'research_agent', 'Meaningful description for sub-agent');
$toolbox = new Toolbox($metadataFactory, [$agentTool]);
```
#### Fault Tolerance
To gracefully handle errors that occur during tool calling, e.g. wrong tool names or runtime errors, you can use the
`FaultTolerantToolbox` as a decorator for the `Toolbox`. It will catch the exceptions and return readable error messages
to the LLM.
```php
use Symfony\AI\Agent\Agent;
use Symfony\AI\Agent\Toolbox\AgentProcessor;
use Symfony\AI\Agent\Toolbox\FaultTolerantToolbox;
// Platform, LLM & Toolbox instantiation
$toolbox = new FaultTolerantToolbox($innerToolbox);
$toolProcessor = new AgentProcessor($toolbox);
$agent = new Agent($platform, $model, inputProcessor: [$toolProcessor], outputProcessor: [$toolProcessor]);
```
#### Tool Filtering
To limit the tools provided to the LLM in a specific agent call to a subset of the configured tools, you can use the
`tools` option with a list of tool names:
```php
$this->agent->call($messages, ['tools' => ['tavily_search']]);
```
#### Tool Result Interception
To react to the result of a tool, you can implement an EventListener or EventSubscriber, that listens to the
`ToolCallsExecuted` event. This event is dispatched after the `Toolbox` executed all current tool calls and enables
you to skip the next LLM call by setting a response yourself:
```php
$eventDispatcher->addListener(ToolCallsExecuted::class, function (ToolCallsExecuted $event): void {
foreach ($event->toolCallResults as $toolCallResult) {
if (str_starts_with($toolCallResult->toolCall->name, 'weather_')) {
$event->response = new StructuredResponse($toolCallResult->result);
}
}
});
```
#### Keeping Tool Messages
Sometimes you might wish to keep the tool messages (`AssistantMessage` containing the `toolCalls` and `ToolCallMessage` containing the response) in the context.
Enable the `keepToolMessages` flag of the toolbox' `AgentProcessor` to ensure those messages will be added to your `MessageBag`.
```php
use Symfony\AI\Agent\Toolbox\AgentProcessor;
use Symfony\AI\Agent\Toolbox\Toolbox;
// Platform & LLM instantiation
$messages = new MessageBag(
Message::forSystem(<<<PROMPT
Please answer all user questions only using the similary_search tool. Do not add information and if you cannot
find an answer, say so.
PROMPT),
Message::ofUser('...') // The user's question.
);
$yourTool = new YourTool();
$toolbox = Toolbox::create($yourTool);
$toolProcessor = new AgentProcessor($toolbox, keepToolMessages: true);
$agent = new Agent($platform, $model, inputProcessor: [$toolProcessor], outputProcessor: [$toolProcessor]);
$response = $agent->call($messages);
// $messages will now include the tool messages
```
#### Code Examples (with built-in tools)
1. [Brave Tool](examples/toolbox/brave.php)
1. [Clock Tool](examples/toolbox/clock.php)
1. [Crawler Tool](examples/toolbox/brave.php)
1. [SerpAPI Tool](examples/toolbox/serpapi.php)
1. [Tavily Tool](examples/toolbox/tavily.php)
1. [Weather Tool with Event Listener](examples/toolbox/weather-event.php)
1. [Wikipedia Tool](examples/anthropic/toolcall.php)
1. [YouTube Transcriber Tool](examples/openai/toolcall.php)
### Document Embedding, Vector Stores & Similarity Search (RAG)
Symfony AI supports document embedding and similarity search using vector stores like ChromaDB, Azure AI Search, MongoDB
Atlas Search, or Pinecone.
For populating a vector store, Symfony AI provides the service `Embedder`, which requires an instance of an
`EmbeddingsModel` and one of `StoreInterface`, and works with a collection of `Document` objects as input:
```php
use Symfony\AI\Platform\Bridge\OpenAI\Embeddings;
use Symfony\AI\Platform\Bridge\OpenAI\PlatformFactory;
use Symfony\AI\Store\Bridge\Pinecone\Store;
use Symfony\AI\Store\Embedder;
use Probots\Pinecone\Pinecone;
$embedder = new Embedder(
PlatformFactory::create($_ENV['OPENAI_API_KEY']),
new Embeddings(),
new Store(Pinecone::client($_ENV['PINECONE_API_KEY'], $_ENV['PINECONE_HOST']),
);
$embedder->embed($documents);
```
The collection of `Document` instances is usually created by text input of your domain entities:
```php
use Symfony\AI\Store\Document\Metadata;
use Symfony\AI\Store\Document\TextDocument;
foreach ($entities as $entity) {
$documents[] = new TextDocument(
id: $entity->getId(), // UUID instance
content: $entity->toString(), // Text representation of relevant data for embedding
metadata: new Metadata($entity->toArray()), // Array representation of an entity to be stored additionally
);
}
```
> [!NOTE]
> Not all data needs to be stored in the vector store, but you could also hydrate the original data entry based
> on the ID or metadata after retrieval from the store.*
In the end the agent is used in combination with a retrieval tool on top of the vector store, e.g. the built-in
`SimilaritySearch` tool provided by the library:
```php
use Symfony\AI\Agent\Agent;
use Symfony\AI\Agent\Toolbox\AgentProcessor;
use Symfony\AI\Agent\Toolbox\Tool\SimilaritySearch;
use Symfony\AI\Agent\Toolbox\Toolbox;
use Symfony\AI\Platform\Message\Message;
use Symfony\AI\Platform\Message\MessageBag;
// Initialize Platform & Models
$similaritySearch = new SimilaritySearch($model, $store);
$toolbox = Toolbox::create($similaritySearch);
$processor = new Agent($toolbox);
$agent = new Agent($platform, $model, [$processor], [$processor]);
$messages = new MessageBag(
Message::forSystem(<<<PROMPT
Please answer all user questions only using the similary_search tool. Do not add information and if you cannot
find an answer, say so.
PROMPT),
Message::ofUser('...') // The user's question.
);
$response = $agent->call($messages);
```
#### Code Examples
1. [MongoDB Store](examples/store/mongodb-similarity-search.php)
1. [Pinecone Store](examples/store/pinecone-similarity-search.php)
#### Supported Stores
* [ChromaDB](https://trychroma.com) (requires `codewithkyrian/chromadb-php` as additional dependency)
* [Azure AI Search](https://azure.microsoft.com/en-us/products/ai-services/ai-search)
* [MongoDB Atlas Search](https://mongodb.com/products/platform/atlas-vector-search) (requires `mongodb/mongodb` as additional dependency)
* [Pinecone](https://pinecone.io) (requires `probots-io/pinecone-php` as additional dependency)
See [issue #28](https://github.com/php-llm/llm-chain/issues/28) for planned support of other models and platforms.
## Advanced Usage & Features
### Structured Output
A typical use-case of LLMs is to classify and extract data from unstructured sources, which is supported by some models
by features like **Structured Output** or providing a **Response Format**.
#### PHP Classes as Output
Symfony AI supports that use-case by abstracting the hustle of defining and providing schemas to the LLM and converting
the response back to PHP objects.
To achieve this, a specific agent processor needs to be registered:
```php
use Symfony\AI\Agent\Agent;
use Symfony\AI\Agent\StructuredOutput\AgentProcessor;
use Symfony\AI\Agent\StructuredOutput\ResponseFormatFactory;
use Symfony\AI\Platform\Message\Message;
use Symfony\AI\Platform\Message\MessageBag;
use Symfony\AI\Fixtures\StructuredOutput\MathReasoning;
use Symfony\Component\Serializer\Encoder\JsonEncoder;
use Symfony\Component\Serializer\Normalizer\ObjectNormalizer;
use Symfony\Component\Serializer\Serializer;
// Initialize Platform and LLM
$serializer = new Serializer([new ObjectNormalizer()], [new JsonEncoder()]);
$processor = new AgentProcessor(new ResponseFormatFactory(), $serializer);
$agent = new Agent($platform, $model, [$processor], [$processor]);
$messages = new MessageBag(
Message::forSystem('You are a helpful math tutor. Guide the user through the solution step by step.'),
Message::ofUser('how can I solve 8x + 7 = -23'),
);
$response = $agent->call($messages, ['output_structure' => MathReasoning::class]);
dump($response->getContent()); // returns an instance of `MathReasoning` class
```
#### Array Structures as Output
Also PHP array structures as `response_format` are supported, which also requires the agent processor mentioned above:
```php
use Symfony\AI\Platform\Message\Message;
use Symfony\AI\Platform\Message\MessageBag;
// Initialize Platform, LLM and agent with processors and Clock tool
$messages = new MessageBag(Message::ofUser('What date and time is it?'));
$response = $agent->call($messages, ['response_format' => [
'type' => 'json_schema',
'json_schema' => [
'name' => 'clock',
'strict' => true,
'schema' => [
'type' => 'object',
'properties' => [
'date' => ['type' => 'string', 'description' => 'The current date in the format YYYY-MM-DD.'],
'time' => ['type' => 'string', 'description' => 'The current time in the format HH:MM:SS.'],
],
'required' => ['date', 'time'],
'additionalProperties' => false,
],
],
]]);
dump($response->getContent()); // returns an array
```
#### Code Examples
1. [Structured Output with PHP class)](examples/openai/structured-output-math.php)
1. [Structured Output with array](examples/openai/structured-output-clock.php)
### Response Streaming
Since LLMs usually generate a response word by word, most of them also support streaming the response using Server Side
Events. Symfony AI supports that by abstracting the conversion and returning a Generator as content of the response.
```php
use Symfony\AI\Agent\Agent;
use Symfony\AI\Message\Message;
use Symfony\AI\Message\MessageBag;
// Initialize Platform and LLM
$agent = new Agent($model);
$messages = new MessageBag(
Message::forSystem('You are a thoughtful philosopher.'),
Message::ofUser('What is the purpose of an ant?'),
);
$response = $agent->call($messages, [
'stream' => true, // enable streaming of response text
]);
foreach ($response->getContent() as $word) {
echo $word;
}
```
In a terminal application this generator can be used directly, but with a web app an additional layer like [Mercure](https://mercure.rocks)
needs to be used.
#### Code Examples
1. [Streaming Claude](examples/anthropic/stream.php)
1. [Streaming GPT](examples/openai/stream.php)
1. [Streaming Mistral](examples/mistral/stream.php)
### Image Processing
Some LLMs also support images as input, which Symfony AI supports as `Content` type within the `UserMessage`:
```php
use Symfony\AI\Platform\Message\Content\Image;
use Symfony\AI\Platform\Message\Message;
use Symfony\AI\Platform\Message\MessageBag;
// Initialize Platform, LLM & agent
$messages = new MessageBag(
Message::forSystem('You are an image analyzer bot that helps identify the content of images.'),
Message::ofUser(
'Describe the image as a comedian would do it.',
Image::fromFile(dirname(__DIR__).'/tests/fixtures/image.jpg'), // Path to an image file
Image::fromDataUrl('data:image/png;base64,...'), // Data URL of an image
new ImageUrl('https://foo.com/bar.png'), // URL to an image
),
);
$response = $agent->call($messages);
```
#### Code Examples
1. [Binary Image Input with GPT](examples/openai/image-input-binary.php)
1. [Image URL Input with GPT](examples/openai/image-input-url.php)
### Audio Processing
Similar to images, some LLMs also support audio as input, which is just another `Content` type within the `UserMessage`:
```php
use Symfony\AI\Platform\Message\Content\Audio;
use Symfony\AI\Platform\Message\Message;
use Symfony\AI\Platform\Message\MessageBag;
// Initialize Platform, LLM & agent
$messages = new MessageBag(
Message::ofUser(
'What is this recording about?',
Audio::fromFile(dirname(__DIR__).'/tests/fixtures/audio.mp3'), // Path to an audio file
),
);
$response = $agent->call($messages);
```
#### Code Examples
1. [Audio Input with GPT](examples/openai/audio-input.php)
### Embeddings
Creating embeddings of word, sentences, or paragraphs is a typical use case around the interaction with LLMs, and
therefore Symfony AI implements a `EmbeddingsModel` interface with various models, see above.
The standalone usage results in an `Vector` instance:
```php
use Symfony\AI\Platform\Bridge\OpenAI\Embeddings;
// Initialize Platform
$embeddings = new Embeddings($platform, Embeddings::TEXT_3_SMALL);
$vectors = $platform->request($embeddings, $textInput)->getContent();
dump($vectors[0]->getData()); // Array of float values
```
#### Code Examples
1. [OpenAI's Emebddings](examples/openai/embeddings.php)
1. [Voyage's Embeddings](examples/voyage/embeddings.php)
1. [Mistral's Embed](examples/mistral/embeddings.php)
### Parallel Platform Calls
Platform supports multiple model calls in parallel, which can be useful to speed up the processing:
```php
// Initialize Platform & Model
foreach ($inputs as $input) {
$responses[] = $platform->request($model, $input);
}
foreach ($responses as $response) {
echo $response->getContent().PHP_EOL;
}
```
> [!NOTE]
> This requires cURL and the `ext-curl` extension to be installed.
#### Code Examples
1. [Parallel GPT Calls](examples/parallel-chat-gpt.php)
1. [Parallel Embeddings Calls](examples/parallel-embeddings.php)
> [!NOTE]
> Please be aware that some embedding models also support batch processing out of the box.
### Input & Output Processing
The behavior of the agent is extendable with services that implement `InputProcessor` and/or `OutputProcessor`
interface. They are provided while instantiating the agent instance:
```php
use Symfony\AI\Agent\Agent;
// Initialize Platform, LLM and processors
$agent = new Agent($platform, $model, $inputProcessors, $outputProcessors);
```
#### InputProcessor
`InputProcessor` instances are called in the agent before handing over the `MessageBag` and the `$options` array to the LLM and are
able to mutate both on top of the `Input` instance provided.
```php
use Symfony\AI\Agent\Input;
use Symfony\AI\Agent\InputProcessorInterface;
use Symfony\AI\Platform\Message\AssistantMessage;
final class MyProcessor implements InputProcessorInterface
{
public function processInput(Input $input): void
{
// mutate options
$options = $input->getOptions();
$options['foo'] = 'bar';
$input->setOptions($options);
// mutate MessageBag
$input->messages->append(new AssistantMessage(sprintf('Please answer using the locale %s', $this->locale)));
}
}
```
#### OutputProcessor
`OutputProcessor` instances are called after the LLM provided a response and can - on top of options and messages -
mutate or replace the given response:
```php
use Symfony\AI\Agent\Output;
use Symfony\AI\Agent\OutputProcessorInterface;
final class MyProcessor implements OutputProcessorInterface
{
public function processOutput(Output $out): void
{
// mutate response
if (str_contains($output->response->getContent, self::STOP_WORD)) {
$output->reponse = new TextReponse('Sorry, we were unable to find relevant information.')
}
}
}
```
#### Agent Awareness
Both, `Input` and `Output` instances, provide access to the LLM used by the agent, but the agent itself is only
provided, in case the processor implemented the `AgentAwareInterface` interface, which can be combined with using the
`AgentAwareTrait`:
```php
use Symfony\AI\Agent\AgentAwareInterface;
use Symfony\AI\Agent\AgentAwareTrait;
use Symfony\AI\Agent\Output;
use Symfony\AI\Agent\OutputProcessorInterface;
final class MyProcessor implements OutputProcessorInterface, AgentAwareInterface
{
use AgentAwareTrait;
public function processOutput(Output $out): void
{
// additional agent interaction
$response = $this->agent->call(...);
}
}
```
## HuggingFace
Symfony AI comes out of the box with an integration for [HuggingFace](https://huggingface.co/) which is a platform for
hosting and sharing all kinds of models, including LLMs, embeddings, image generation, and classification models.
You can just instantiate the Platform with the corresponding HuggingFace bridge and use it with the `task` option:
```php
use Symfony\AI\Bridge\HuggingFace\Model;
use Symfony\AI\Platform\Bridge\HuggingFace\PlatformFactory;
use Symfony\AI\Platform\Bridge\HuggingFace\Task;
use Symfony\AI\Platform\Message\Content\Image;
$platform = PlatformFactory::create($apiKey);
$model = new Model('facebook/detr-resnet-50');
$image = Image::fromFile(dirname(__DIR__, 2).'/tests/fixtures/image.jpg');
$response = $platform->request($model, $image, [
'task' => Task::OBJECT_DETECTION, // defining a task is mandatory for internal request & response handling
]);
dump($response->getContent());
```
#### Code Examples
1. [Audio Classification](examples/huggingface/audio-classification.php)
1. [Automatic Speech Recognition](examples/huggingface/automatic-speech-recognition.php)
1. [Chat Completion](examples/huggingface/chat-completion.php)
1. [Feature Extraction (Embeddings)](examples/huggingface/feature-extraction.php)
1. [Fill Mask](examples/huggingface/fill-mask.php)
1. [Image Classification](examples/huggingface/image-classification.php)
1. [Image Segmentation.php](examples/huggingface/image-segmentation.php)
1. [Image-to-Text](examples/huggingface/image-to-text.php)
1. [Object Detection](examples/huggingface/object-detection.php)
1. [Question Answering](examples/huggingface/question-answering.php)
1. [Sentence Similarity](examples/huggingface/sentence-similarity.php)
1. [Summarization](examples/huggingface/summarization.php)
1. [Table Question Answering](examples/huggingface/table-question-answering.php)
1. [Text Classification](examples/huggingface/text-classification.php)
1. [Text Generation](examples/huggingface/text-generation.php)
1. [Text-to-Image](examples/huggingface/text-to-image.php)
1. [Token Classification](examples/huggingface/token-classification.php)
1. [Translation](examples/huggingface/translation.php)
1. [Zero-shot Classification](examples/huggingface/zero-shot-classification.php)
## TransformerPHP
With installing the library `codewithkyrian/transformers` it is possible to run [ONNX](https://onnx.ai/) models locally
without the need of an extra tool like Ollama or a cloud service. This requires [FFI](https://www.php.net/manual/en/book.ffi.php)
and comes with an extra setup, see [TransformersPHP's Getting Starter](https://transformers.codewithkyrian.com/getting-started).
The usage with Symfony AI is similar to the HuggingFace integration, and also requires the `task` option to be set:
```php
use Codewithkyrian\Transformers\Pipelines\Task;
use Symfony\AI\Bridge\TransformersPHP\Model;
use Symfony\AI\Platform\Bridge\TransformersPHP\PlatformFactory;
$platform = PlatformFactory::create();
$model = new Model('Xenova/LaMini-Flan-T5-783M');
$response = $platform->request($model, 'How many continents are there in the world?', [
'task' => Task::Text2TextGeneration,
]);
echo $response->getContent().PHP_EOL;
```
#### Code Examples
1. [Text Generation with TransformersPHP](examples/transformers/text-generation.php)
## Sponsor
Help Symfony by [sponsoring][2] its development!
@@ -18,3 +855,11 @@ Thank you for considering contributing to Symfony AI! You can find the [contribu
[1]: https://symfony.com/backers
[2]: https://symfony.com/sponsor
## Fixture Licenses
For testing multi-modal features, the repository contains binary media content, with the following owners and licenses:
* `tests/Fixture/image.jpg`: Chris F., Creative Commons, see [pexels.com](https://www.pexels.com/photo/blauer-und-gruner-elefant-mit-licht-1680755/)
* `tests/Fixture/audio.mp3`: davidbain, Creative Commons, see [freesound.org](https://freesound.org/people/davidbain/sounds/136777/)
* `tests/Fixture/document.pdf`: Chem8240ja, Public Domain, see [Wikipedia](https://en.m.wikipedia.org/wiki/File:Re_example.pdf)

View File

@@ -1,13 +1,45 @@
{
"name": "symfony/ai",
"description": "Symfony AI Monorepo",
"license": "MIT",
"keywords": [
"dev"
],
"minimum-stability": "dev",
"prefer-stable": true,
"require-dev": {
"php": ">=8.1",
"php": ">=8.2",
"async-aws/bedrock-runtime": "^0.1.0",
"codewithkyrian/transformers": "^0.5.3",
"php-cs-fixer/shim": "^3.75",
"probots-io/pinecone-php": "^1.0",
"symfony/ai-agent": "@dev",
"symfony/ai-platform": "@dev",
"symfony/ai-store": "@dev",
"symfony/console": "^6.4|^7.0",
"symfony/css-selector": "^6.4|^7.0",
"symfony/dom-crawler": "^6.4|^7.0",
"symfony/dotenv": "^6.4|^7.0",
"symfony/event-dispatcher": "^6.4|^7.0",
"symfony/filesystem": "^6.4|^7.0",
"symfony/finder": "^6.4|^7.0",
"php-cs-fixer/shim": "^3.75"
"symfony/process": "^6.4|^7.0",
"symfony/var-dumper": "^6.4|^7.0"
},
"repositories": [
{ "type": "path", "url": "src/agent" },
{ "type": "path", "url": "src/platform" },
{ "type": "path", "url": "src/store" }
],
"autoload-dev": {
"psr-4": {
"Symfony\\AI\\Fixtures\\": "fixtures/"
}
},
"config": {
"sort-packages": true,
"allow-plugins": {
"codewithkyrian/transformers-libsloader": true
}
}
}

110
example Executable file
View File

@@ -0,0 +1,110 @@
#!/usr/bin/env php
<?php
use Symfony\Component\Console\Command\Command;
use Symfony\Component\Console\Helper\Table;
use Symfony\Component\Console\Input\InputArgument;
use Symfony\Component\Console\Input\InputInterface;
use Symfony\Component\Console\Output\OutputInterface;
use Symfony\Component\Console\SingleCommandApplication;
use Symfony\Component\Console\Style\SymfonyStyle;
use Symfony\Component\Finder\Finder;
use Symfony\Component\Finder\SplFileInfo;
use Symfony\Component\Process\Process;
require_once __DIR__.'/vendor/autoload.php';
$app = (new SingleCommandApplication('Symfony AI Example Runner'))
->setDescription('Runs all Symfony AI examples in folder examples/')
->addArgument('subdirectory', InputArgument::OPTIONAL, 'Subdirectory to run examples from, e.g. "anthropic" or "huggingface".')
->setCode(function (InputInterface $input, OutputInterface $output) {
$io = new SymfonyStyle($input, $output);
$io->title('Symfony AI Examples');
$directory = __DIR__.'/examples';
if ($subdirectory = $input->getArgument('subdirectory')) {
$directory .= '/'.$subdirectory;
if (!is_dir($directory)) {
$io->error(sprintf('Subdirectory "%s" does not exist.', $subdirectory));
return Command::FAILURE;
}
}
$examples = (new Finder())
->in($directory)
->name('*.php')
->sortByName()
->files();
/** @var array{example: SplFileInfo, process: Process} $exampleRuns */
$exampleRuns = [];
foreach ($examples as $example) {
$exampleRuns[] = [
'example' => $example,
'process' => $process = new Process(['php', $example->getRealPath()]),
];
$process->start();
}
$section = $output->section();
$renderTable = function () use ($exampleRuns, $section) {
$section->clear();
$table = new Table($section);
$table->setHeaders(['Example', 'State', 'Output']);
foreach ($exampleRuns as $run) {
/** @var SplFileInfo $example */
/** @var Process $process */
['example' => $example, 'process' => $process] = $run;
$output = str_replace(PHP_EOL, ' ', $process->getOutput());
$output = strlen($output) <= 100 ? $output : substr($output, 0, 100).'...';
$emptyOutput = 0 === strlen(trim($output));
$state = 'Running';
if ($process->isTerminated()) {
$success = $process->isSuccessful() && !$emptyOutput;
$state = $success ? '<info>Finished</info>'
: (1 === $run['process']->getExitCode() || $emptyOutput ? '<error>Failed</error>' : '<comment>Skipped</comment>');
}
$table->addRow([$example->getRelativePathname(), $state, $output]);
}
$table->render();
};
$examplesRunning = fn () => array_reduce($exampleRuns, fn ($running, $example) => $running || $example['process']->isRunning(), false);
while ($examplesRunning()) {
$renderTable();
sleep(1);
}
$renderTable();
$io->newLine();
$successCount = array_reduce($exampleRuns, function ($count, $example) {
if ($example['process']->isSuccessful() && strlen(trim($example['process']->getOutput())) > 0) {
return $count + 1;
}
return $count;
}, 0);
$totalCount = count($exampleRuns);
if ($successCount < $totalCount) {
$io->warning(sprintf('%d out of %d examples ran successfully.', $successCount, $totalCount));
} else {
$io->success(sprintf('All %d examples ran successfully!', $totalCount));
}
foreach ($exampleRuns as $run) {
if (!$run['process']->isSuccessful()) {
$io->section('Error in ' . $run['example']->getRelativePathname());
$io->text($run['process']->getOutput());
$io->text($run['process']->getErrorOutput());
}
}
return Command::SUCCESS;
})
->run();

View File

@@ -0,0 +1,37 @@
<?php
/*
* This file is part of the Symfony package.
*
* (c) Fabien Potencier <fabien@symfony.com>
*
* For the full copyright and license information, please view the LICENSE
* file that was distributed with this source code.
*/
use Symfony\AI\Agent\Agent;
use Symfony\AI\Platform\Bridge\Anthropic\Claude;
use Symfony\AI\Platform\Bridge\Anthropic\PlatformFactory;
use Symfony\AI\Platform\Message\Message;
use Symfony\AI\Platform\Message\MessageBag;
use Symfony\Component\Dotenv\Dotenv;
require_once dirname(__DIR__, 2).'/vendor/autoload.php';
(new Dotenv())->loadEnv(dirname(__DIR__, 2).'/.env');
if (empty($_ENV['ANTHROPIC_API_KEY'])) {
echo 'Please set the ANTHROPIC_API_KEY environment variable.'.\PHP_EOL;
exit(1);
}
$platform = PlatformFactory::create($_ENV['ANTHROPIC_API_KEY']);
$model = new Claude(Claude::SONNET_37);
$agent = new Agent($platform, $model);
$messages = new MessageBag(
Message::forSystem('You are a pirate and you write funny.'),
Message::ofUser('What is the Symfony framework?'),
);
$response = $agent->call($messages);
echo $response->getContent().\PHP_EOL;

View File

@@ -0,0 +1,41 @@
<?php
/*
* This file is part of the Symfony package.
*
* (c) Fabien Potencier <fabien@symfony.com>
*
* For the full copyright and license information, please view the LICENSE
* file that was distributed with this source code.
*/
use Symfony\AI\Agent\Agent;
use Symfony\AI\Platform\Bridge\Anthropic\Claude;
use Symfony\AI\Platform\Bridge\Anthropic\PlatformFactory;
use Symfony\AI\Platform\Message\Content\Image;
use Symfony\AI\Platform\Message\Message;
use Symfony\AI\Platform\Message\MessageBag;
use Symfony\Component\Dotenv\Dotenv;
require_once dirname(__DIR__, 2).'/vendor/autoload.php';
(new Dotenv())->loadEnv(dirname(__DIR__, 2).'/.env');
if (empty($_ENV['ANTHROPIC_API_KEY'])) {
echo 'Please set the ANTHROPIC_API_KEY environment variable.'.\PHP_EOL;
exit(1);
}
$platform = PlatformFactory::create($_ENV['ANTHROPIC_API_KEY']);
$model = new Claude(Claude::SONNET_37);
$agent = new Agent($platform, $model);
$messages = new MessageBag(
Message::forSystem('You are an image analyzer bot that helps identify the content of images.'),
Message::ofUser(
Image::fromFile(dirname(__DIR__, 2).'/fixtures/image.jpg'),
'Describe this image.',
),
);
$response = $agent->call($messages);
echo $response->getContent().\PHP_EOL;

View File

@@ -0,0 +1,41 @@
<?php
/*
* This file is part of the Symfony package.
*
* (c) Fabien Potencier <fabien@symfony.com>
*
* For the full copyright and license information, please view the LICENSE
* file that was distributed with this source code.
*/
use Symfony\AI\Agent\Agent;
use Symfony\AI\Platform\Bridge\Anthropic\Claude;
use Symfony\AI\Platform\Bridge\Anthropic\PlatformFactory;
use Symfony\AI\Platform\Message\Content\ImageUrl;
use Symfony\AI\Platform\Message\Message;
use Symfony\AI\Platform\Message\MessageBag;
use Symfony\Component\Dotenv\Dotenv;
require_once dirname(__DIR__, 2).'/vendor/autoload.php';
(new Dotenv())->loadEnv(dirname(__DIR__, 2).'/.env');
if (empty($_ENV['ANTHROPIC_API_KEY'])) {
echo 'Please set the ANTHROPIC_API_KEY environment variable.'.\PHP_EOL;
exit(1);
}
$platform = PlatformFactory::create($_ENV['ANTHROPIC_API_KEY']);
$model = new Claude(Claude::SONNET_37);
$agent = new Agent($platform, $model);
$messages = new MessageBag(
Message::forSystem('You are an image analyzer bot that helps identify the content of images.'),
Message::ofUser(
new ImageUrl('https://upload.wikimedia.org/wikipedia/commons/a/a7/Camponotus_flavomarginatus_ant.jpg'),
'Describe this image.',
),
);
$response = $agent->call($messages);
echo $response->getContent().\PHP_EOL;

View File

@@ -0,0 +1,40 @@
<?php
/*
* This file is part of the Symfony package.
*
* (c) Fabien Potencier <fabien@symfony.com>
*
* For the full copyright and license information, please view the LICENSE
* file that was distributed with this source code.
*/
use Symfony\AI\Agent\Agent;
use Symfony\AI\Platform\Bridge\Anthropic\Claude;
use Symfony\AI\Platform\Bridge\Anthropic\PlatformFactory;
use Symfony\AI\Platform\Message\Content\Document;
use Symfony\AI\Platform\Message\Message;
use Symfony\AI\Platform\Message\MessageBag;
use Symfony\Component\Dotenv\Dotenv;
require_once dirname(__DIR__, 2).'/vendor/autoload.php';
(new Dotenv())->loadEnv(dirname(__DIR__, 2).'/.env');
if (empty($_ENV['ANTHROPIC_API_KEY'])) {
echo 'Please set the ANTHROPIC_API_KEY environment variable.'.\PHP_EOL;
exit(1);
}
$platform = PlatformFactory::create($_ENV['ANTHROPIC_API_KEY']);
$model = new Claude(Claude::SONNET_37);
$agent = new Agent($platform, $model);
$messages = new MessageBag(
Message::ofUser(
Document::fromFile(dirname(__DIR__, 2).'/fixtures/document.pdf'),
'What is this document about?',
),
);
$response = $agent->call($messages);
echo $response->getContent().\PHP_EOL;

View File

@@ -0,0 +1,40 @@
<?php
/*
* This file is part of the Symfony package.
*
* (c) Fabien Potencier <fabien@symfony.com>
*
* For the full copyright and license information, please view the LICENSE
* file that was distributed with this source code.
*/
use Symfony\AI\Agent\Agent;
use Symfony\AI\Platform\Bridge\Anthropic\Claude;
use Symfony\AI\Platform\Bridge\Anthropic\PlatformFactory;
use Symfony\AI\Platform\Message\Content\DocumentUrl;
use Symfony\AI\Platform\Message\Message;
use Symfony\AI\Platform\Message\MessageBag;
use Symfony\Component\Dotenv\Dotenv;
require_once dirname(__DIR__, 2).'/vendor/autoload.php';
(new Dotenv())->loadEnv(dirname(__DIR__, 2).'/.env');
if (empty($_ENV['ANTHROPIC_API_KEY'])) {
echo 'Please set the ANTHROPIC_API_KEY environment variable.'.\PHP_EOL;
exit(1);
}
$platform = PlatformFactory::create($_ENV['ANTHROPIC_API_KEY']);
$model = new Claude(Claude::SONNET_37);
$agent = new Agent($platform, $model);
$messages = new MessageBag(
Message::ofUser(
new DocumentUrl('https://upload.wikimedia.org/wikipedia/commons/2/20/Re_example.pdf'),
'What is this document about?',
),
);
$response = $agent->call($messages);
echo $response->getContent().\PHP_EOL;

View File

@@ -0,0 +1,42 @@
<?php
/*
* This file is part of the Symfony package.
*
* (c) Fabien Potencier <fabien@symfony.com>
*
* For the full copyright and license information, please view the LICENSE
* file that was distributed with this source code.
*/
use Symfony\AI\Agent\Agent;
use Symfony\AI\Platform\Bridge\Anthropic\Claude;
use Symfony\AI\Platform\Bridge\Anthropic\PlatformFactory;
use Symfony\AI\Platform\Message\Message;
use Symfony\AI\Platform\Message\MessageBag;
use Symfony\Component\Dotenv\Dotenv;
require_once dirname(__DIR__, 2).'/vendor/autoload.php';
(new Dotenv())->loadEnv(dirname(__DIR__, 2).'/.env');
if (empty($_ENV['ANTHROPIC_API_KEY'])) {
echo 'Please set the ANTHROPIC_API_KEY environment variable.'.\PHP_EOL;
exit(1);
}
$platform = PlatformFactory::create($_ENV['ANTHROPIC_API_KEY']);
$model = new Claude();
$agent = new Agent($platform, $model);
$messages = new MessageBag(
Message::forSystem('You are a thoughtful philosopher.'),
Message::ofUser('What is the purpose of an ant?'),
);
$response = $agent->call($messages, [
'stream' => true, // enable streaming of response text
]);
foreach ($response->getContent() as $word) {
echo $word;
}
echo \PHP_EOL;

View File

@@ -0,0 +1,42 @@
<?php
/*
* This file is part of the Symfony package.
*
* (c) Fabien Potencier <fabien@symfony.com>
*
* For the full copyright and license information, please view the LICENSE
* file that was distributed with this source code.
*/
use Symfony\AI\Agent\Agent;
use Symfony\AI\Agent\Toolbox\AgentProcessor;
use Symfony\AI\Agent\Toolbox\Tool\Wikipedia;
use Symfony\AI\Agent\Toolbox\Toolbox;
use Symfony\AI\Platform\Bridge\Anthropic\Claude;
use Symfony\AI\Platform\Bridge\Anthropic\PlatformFactory;
use Symfony\AI\Platform\Message\Message;
use Symfony\AI\Platform\Message\MessageBag;
use Symfony\Component\Dotenv\Dotenv;
use Symfony\Component\HttpClient\HttpClient;
require_once dirname(__DIR__, 2).'/vendor/autoload.php';
(new Dotenv())->loadEnv(dirname(__DIR__, 2).'/.env');
if (empty($_ENV['ANTHROPIC_API_KEY'])) {
echo 'Please set the ANTHROPIC_API_KEY environment variable.'.\PHP_EOL;
exit(1);
}
$platform = PlatformFactory::create($_ENV['ANTHROPIC_API_KEY']);
$model = new Claude();
$wikipedia = new Wikipedia(HttpClient::create());
$toolbox = Toolbox::create($wikipedia);
$processor = new AgentProcessor($toolbox);
$agent = new Agent($platform, $model, [$processor], [$processor]);
$messages = new MessageBag(Message::ofUser('Who is the current chancellor of Germany?'));
$response = $agent->call($messages);
echo $response->getContent().\PHP_EOL;

View File

@@ -0,0 +1,37 @@
<?php
/*
* This file is part of the Symfony package.
*
* (c) Fabien Potencier <fabien@symfony.com>
*
* For the full copyright and license information, please view the LICENSE
* file that was distributed with this source code.
*/
use Symfony\AI\Platform\Bridge\Azure\OpenAI\PlatformFactory;
use Symfony\AI\Platform\Bridge\OpenAI\Whisper;
use Symfony\AI\Platform\Message\Content\Audio;
use Symfony\Component\Dotenv\Dotenv;
require_once dirname(__DIR__, 2).'/vendor/autoload.php';
(new Dotenv())->loadEnv(dirname(__DIR__, 2).'/.env');
if (empty($_ENV['AZURE_OPENAI_BASEURL']) || empty($_ENV['AZURE_OPENAI_WHISPER_DEPLOYMENT']) || empty($_ENV['AZURE_OPENAI_WHISPER_API_VERSION']) || empty($_ENV['AZURE_OPENAI_KEY'])
) {
echo 'Please set the AZURE_OPENAI_BASEURL, AZURE_OPENAI_WHISPER_DEPLOYMENT, AZURE_OPENAI_WHISPER_API_VERSION, and AZURE_OPENAI_KEY environment variables.'.\PHP_EOL;
exit(1);
}
$platform = PlatformFactory::create(
$_ENV['AZURE_OPENAI_BASEURL'],
$_ENV['AZURE_OPENAI_WHISPER_DEPLOYMENT'],
$_ENV['AZURE_OPENAI_WHISPER_API_VERSION'],
$_ENV['AZURE_OPENAI_KEY'],
);
$model = new Whisper();
$file = Audio::fromFile(dirname(__DIR__, 2).'/fixtures/audio.mp3');
$response = $platform->request($model, $file);
echo $response->getContent().\PHP_EOL;

View File

@@ -0,0 +1,43 @@
<?php
/*
* This file is part of the Symfony package.
*
* (c) Fabien Potencier <fabien@symfony.com>
*
* For the full copyright and license information, please view the LICENSE
* file that was distributed with this source code.
*/
use Symfony\AI\Agent\Agent;
use Symfony\AI\Platform\Bridge\Azure\OpenAI\PlatformFactory;
use Symfony\AI\Platform\Bridge\OpenAI\GPT;
use Symfony\AI\Platform\Message\Message;
use Symfony\AI\Platform\Message\MessageBag;
use Symfony\Component\Dotenv\Dotenv;
require_once dirname(__DIR__, 2).'/vendor/autoload.php';
(new Dotenv())->loadEnv(dirname(__DIR__, 2).'/.env');
if (empty($_ENV['AZURE_OPENAI_BASEURL']) || empty($_ENV['AZURE_OPENAI_GPT_DEPLOYMENT']) || empty($_ENV['AZURE_OPENAI_GPT_API_VERSION']) || empty($_ENV['AZURE_OPENAI_KEY'])
) {
echo 'Please set the AZURE_OPENAI_BASEURL, AZURE_OPENAI_GPT_DEPLOYMENT, AZURE_OPENAI_GPT_API_VERSION, and AZURE_OPENAI_KEY environment variables.'.\PHP_EOL;
exit(1);
}
$platform = PlatformFactory::create(
$_ENV['AZURE_OPENAI_BASEURL'],
$_ENV['AZURE_OPENAI_GPT_DEPLOYMENT'],
$_ENV['AZURE_OPENAI_GPT_API_VERSION'],
$_ENV['AZURE_OPENAI_KEY'],
);
$model = new GPT(GPT::GPT_4O_MINI);
$agent = new Agent($platform, $model);
$messages = new MessageBag(
Message::forSystem('You are a pirate and you write funny.'),
Message::ofUser('What is the Symfony framework?'),
);
$response = $agent->call($messages);
echo $response->getContent().\PHP_EOL;

View File

@@ -0,0 +1,40 @@
<?php
/*
* This file is part of the Symfony package.
*
* (c) Fabien Potencier <fabien@symfony.com>
*
* For the full copyright and license information, please view the LICENSE
* file that was distributed with this source code.
*/
use Symfony\AI\Agent\Agent;
use Symfony\AI\Platform\Bridge\Azure\Meta\PlatformFactory;
use Symfony\AI\Platform\Bridge\Meta\Llama;
use Symfony\AI\Platform\Message\Message;
use Symfony\AI\Platform\Message\MessageBag;
use Symfony\Component\Dotenv\Dotenv;
require_once dirname(__DIR__, 2).'/vendor/autoload.php';
(new Dotenv())->loadEnv(dirname(__DIR__, 2).'/.env');
if (empty($_ENV['AZURE_LLAMA_BASEURL']) || empty($_ENV['AZURE_LLAMA_KEY'])) {
echo 'Please set the AZURE_LLAMA_BASEURL and AZURE_LLAMA_KEY environment variable.'.\PHP_EOL;
exit(1);
}
$platform = PlatformFactory::create($_ENV['AZURE_LLAMA_BASEURL'], $_ENV['AZURE_LLAMA_KEY']);
$model = new Llama(Llama::V3_3_70B_INSTRUCT);
$agent = new Agent($platform, $model);
$messages = new MessageBag(Message::ofUser('I am going to Paris, what should I see?'));
$response = $agent->call($messages, [
'max_tokens' => 2048,
'temperature' => 0.8,
'top_p' => 0.1,
'presence_penalty' => 0,
'frequency_penalty' => 0,
]);
echo $response->getContent().\PHP_EOL;

View File

@@ -0,0 +1,42 @@
<?php
/*
* This file is part of the Symfony package.
*
* (c) Fabien Potencier <fabien@symfony.com>
*
* For the full copyright and license information, please view the LICENSE
* file that was distributed with this source code.
*/
use Symfony\AI\Platform\Bridge\Azure\OpenAI\PlatformFactory;
use Symfony\AI\Platform\Bridge\OpenAI\Embeddings;
use Symfony\AI\Platform\Response\VectorResponse;
use Symfony\Component\Dotenv\Dotenv;
require_once dirname(__DIR__, 2).'/vendor/autoload.php';
(new Dotenv())->loadEnv(dirname(__DIR__, 2).'/.env');
if (empty($_ENV['AZURE_OPENAI_BASEURL']) || empty($_ENV['AZURE_OPENAI_EMBEDDINGS_DEPLOYMENT']) || empty($_ENV['AZURE_OPENAI_EMBEDDINGS_API_VERSION']) || empty($_ENV['AZURE_OPENAI_KEY'])
) {
echo 'Please set the AZURE_OPENAI_BASEURL, AZURE_OPENAI_EMBEDDINGS_DEPLOYMENT, AZURE_OPENAI_EMBEDDINGS_API_VERSION, and AZURE_OPENAI_KEY environment variables.'.\PHP_EOL;
exit(1);
}
$platform = PlatformFactory::create(
$_ENV['AZURE_OPENAI_BASEURL'],
$_ENV['AZURE_OPENAI_EMBEDDINGS_DEPLOYMENT'],
$_ENV['AZURE_OPENAI_EMBEDDINGS_API_VERSION'],
$_ENV['AZURE_OPENAI_KEY'],
);
$embeddings = new Embeddings();
$response = $platform->request($embeddings, <<<TEXT
Once upon a time, there was a country called Japan. It was a beautiful country with a lot of mountains and rivers.
The people of Japan were very kind and hardworking. They loved their country very much and took care of it. The
country was very peaceful and prosperous. The people lived happily ever after.
TEXT);
assert($response instanceof VectorResponse);
echo 'Dimensions: '.$response->getContent()[0]->getDimensions().\PHP_EOL;

View File

@@ -0,0 +1,38 @@
<?php
/*
* This file is part of the Symfony package.
*
* (c) Fabien Potencier <fabien@symfony.com>
*
* For the full copyright and license information, please view the LICENSE
* file that was distributed with this source code.
*/
use Symfony\AI\Agent\Agent;
use Symfony\AI\Platform\Bridge\Anthropic\Claude;
use Symfony\AI\Platform\Bridge\Bedrock\PlatformFactory;
use Symfony\AI\Platform\Message\Message;
use Symfony\AI\Platform\Message\MessageBag;
use Symfony\Component\Dotenv\Dotenv;
require_once dirname(__DIR__, 2).'/vendor/autoload.php';
(new Dotenv())->loadEnv(dirname(__DIR__, 2).'/.env');
if (empty($_ENV['AWS_ACCESS_KEY_ID']) || empty($_ENV['AWS_SECRET_ACCESS_KEY']) || empty($_ENV['AWS_DEFAULT_REGION'])
) {
echo 'Please set the AWS_ACCESS_KEY_ID, AWS_SECRET_ACCESS_KEY and AWS_DEFAULT_REGION environment variables.'.\PHP_EOL;
exit(1);
}
$platform = PlatformFactory::create();
$model = new Claude();
$agent = new Agent($platform, $model);
$messages = new MessageBag(
Message::forSystem('You answer questions in short and concise manner.'),
Message::ofUser('What is the Symfony framework?'),
);
$response = $agent->call($messages);
echo $response->getContent().\PHP_EOL;

View File

@@ -0,0 +1,38 @@
<?php
/*
* This file is part of the Symfony package.
*
* (c) Fabien Potencier <fabien@symfony.com>
*
* For the full copyright and license information, please view the LICENSE
* file that was distributed with this source code.
*/
use Symfony\AI\Agent\Agent;
use Symfony\AI\Platform\Bridge\Bedrock\PlatformFactory;
use Symfony\AI\Platform\Bridge\Meta\Llama;
use Symfony\AI\Platform\Message\Message;
use Symfony\AI\Platform\Message\MessageBag;
use Symfony\Component\Dotenv\Dotenv;
require_once dirname(__DIR__, 2).'/vendor/autoload.php';
(new Dotenv())->loadEnv(dirname(__DIR__, 2).'/.env');
if (empty($_ENV['AWS_ACCESS_KEY_ID']) || empty($_ENV['AWS_SECRET_ACCESS_KEY']) || empty($_ENV['AWS_DEFAULT_REGION'])
) {
echo 'Please set the AWS_ACCESS_KEY_ID, AWS_SECRET_ACCESS_KEY and AWS_DEFAULT_REGION environment variables.'.\PHP_EOL;
exit(1);
}
$platform = PlatformFactory::create();
$model = new Llama(Llama::V3_2_3B_INSTRUCT);
$agent = new Agent($platform, $model);
$messages = new MessageBag(
Message::forSystem('You are a pirate and you write funny.'),
Message::ofUser('What is the Symfony framework?'),
);
$response = $agent->call($messages);
echo $response->getContent().\PHP_EOL;

View File

@@ -0,0 +1,38 @@
<?php
/*
* This file is part of the Symfony package.
*
* (c) Fabien Potencier <fabien@symfony.com>
*
* For the full copyright and license information, please view the LICENSE
* file that was distributed with this source code.
*/
use Symfony\AI\Agent\Agent;
use Symfony\AI\Platform\Bridge\Bedrock\Nova\Nova;
use Symfony\AI\Platform\Bridge\Bedrock\PlatformFactory;
use Symfony\AI\Platform\Message\Message;
use Symfony\AI\Platform\Message\MessageBag;
use Symfony\Component\Dotenv\Dotenv;
require_once dirname(__DIR__, 2).'/vendor/autoload.php';
(new Dotenv())->loadEnv(dirname(__DIR__, 2).'/.env');
if (empty($_ENV['AWS_ACCESS_KEY_ID']) || empty($_ENV['AWS_SECRET_ACCESS_KEY']) || empty($_ENV['AWS_DEFAULT_REGION'])
) {
echo 'Please set the AWS_ACCESS_KEY_ID, AWS_SECRET_ACCESS_KEY and AWS_DEFAULT_REGION environment variables.'.\PHP_EOL;
exit(1);
}
$platform = PlatformFactory::create();
$model = new Nova(Nova::PRO);
$agent = new Agent($platform, $model);
$messages = new MessageBag(
Message::forSystem('You are a pirate and you write funny.'),
Message::ofUser('What is the Symfony framework?'),
);
$response = $agent->call($messages);
echo $response->getContent().\PHP_EOL;

View File

@@ -0,0 +1,42 @@
<?php
/*
* This file is part of the Symfony package.
*
* (c) Fabien Potencier <fabien@symfony.com>
*
* For the full copyright and license information, please view the LICENSE
* file that was distributed with this source code.
*/
use Symfony\AI\Agent\Agent;
use Symfony\AI\Platform\Bridge\Anthropic\Claude;
use Symfony\AI\Platform\Bridge\Bedrock\PlatformFactory;
use Symfony\AI\Platform\Message\Content\Image;
use Symfony\AI\Platform\Message\Message;
use Symfony\AI\Platform\Message\MessageBag;
use Symfony\Component\Dotenv\Dotenv;
require_once dirname(__DIR__, 2).'/vendor/autoload.php';
(new Dotenv())->loadEnv(dirname(__DIR__, 2).'/.env');
if (empty($_ENV['AWS_ACCESS_KEY_ID']) || empty($_ENV['AWS_SECRET_ACCESS_KEY']) || empty($_ENV['AWS_DEFAULT_REGION'])
) {
echo 'Please set the AWS_ACCESS_KEY_ID, AWS_SECRET_ACCESS_KEY and AWS_DEFAULT_REGION environment variables.'.\PHP_EOL;
exit(1);
}
$platform = PlatformFactory::create();
$model = new Claude();
$agent = new Agent($platform, $model);
$messages = new MessageBag(
Message::forSystem('You are an image analyzer bot that helps identify the content of images.'),
Message::ofUser(
'Describe the image as a comedian would do it.',
Image::fromFile(dirname(__DIR__, 2).'/fixtures/image.jpg'),
),
);
$response = $agent->call($messages);
echo $response->getContent().\PHP_EOL;

View File

@@ -0,0 +1,42 @@
<?php
/*
* This file is part of the Symfony package.
*
* (c) Fabien Potencier <fabien@symfony.com>
*
* For the full copyright and license information, please view the LICENSE
* file that was distributed with this source code.
*/
use Symfony\AI\Agent\Agent;
use Symfony\AI\Platform\Bridge\Bedrock\Nova\Nova;
use Symfony\AI\Platform\Bridge\Bedrock\PlatformFactory;
use Symfony\AI\Platform\Message\Content\Image;
use Symfony\AI\Platform\Message\Message;
use Symfony\AI\Platform\Message\MessageBag;
use Symfony\Component\Dotenv\Dotenv;
require_once dirname(__DIR__, 2).'/vendor/autoload.php';
(new Dotenv())->loadEnv(dirname(__DIR__, 2).'/.env');
if (empty($_ENV['AWS_ACCESS_KEY_ID']) || empty($_ENV['AWS_SECRET_ACCESS_KEY']) || empty($_ENV['AWS_DEFAULT_REGION'])
) {
echo 'Please set the AWS_ACCESS_KEY_ID, AWS_SECRET_ACCESS_KEY and AWS_DEFAULT_REGION environment variables.'.\PHP_EOL;
exit(1);
}
$platform = PlatformFactory::create();
$model = new Nova(Nova::PRO);
$agent = new Agent($platform, $model);
$messages = new MessageBag(
Message::forSystem('You are an image analyzer bot that helps identify the content of images.'),
Message::ofUser(
'Describe the image as a comedian would do it.',
Image::fromFile(dirname(__DIR__, 2).'/fixtures/image.jpg'),
),
);
$response = $agent->call($messages);
echo $response->getContent().\PHP_EOL;

View File

@@ -0,0 +1,43 @@
<?php
/*
* This file is part of the Symfony package.
*
* (c) Fabien Potencier <fabien@symfony.com>
*
* For the full copyright and license information, please view the LICENSE
* file that was distributed with this source code.
*/
use Symfony\AI\Agent\Agent;
use Symfony\AI\Agent\Toolbox\AgentProcessor;
use Symfony\AI\Agent\Toolbox\Tool\Wikipedia;
use Symfony\AI\Agent\Toolbox\Toolbox;
use Symfony\AI\Platform\Bridge\Anthropic\Claude;
use Symfony\AI\Platform\Bridge\Bedrock\PlatformFactory;
use Symfony\AI\Platform\Message\Message;
use Symfony\AI\Platform\Message\MessageBag;
use Symfony\Component\Dotenv\Dotenv;
use Symfony\Component\HttpClient\HttpClient;
require_once dirname(__DIR__, 2).'/vendor/autoload.php';
(new Dotenv())->loadEnv(dirname(__DIR__, 2).'/.env');
if (empty($_ENV['AWS_ACCESS_KEY_ID']) || empty($_ENV['AWS_SECRET_ACCESS_KEY']) || empty($_ENV['AWS_DEFAULT_REGION'])
) {
echo 'Please set the AWS_ACCESS_KEY_ID, AWS_SECRET_ACCESS_KEY and AWS_DEFAULT_REGION environment variables.'.\PHP_EOL;
exit(1);
}
$platform = PlatformFactory::create();
$model = new Claude();
$wikipedia = new Wikipedia(HttpClient::create());
$toolbox = Toolbox::create($wikipedia);
$processor = new AgentProcessor($toolbox);
$agent = new Agent($platform, $model, [$processor], [$processor]);
$messages = new MessageBag(Message::ofUser('Who is the current chancellor of Germany?'));
$response = $agent->call($messages);
echo $response->getContent().\PHP_EOL;

View File

@@ -0,0 +1,45 @@
<?php
/*
* This file is part of the Symfony package.
*
* (c) Fabien Potencier <fabien@symfony.com>
*
* For the full copyright and license information, please view the LICENSE
* file that was distributed with this source code.
*/
use Symfony\AI\Agent\Agent;
use Symfony\AI\Agent\Toolbox\AgentProcessor;
use Symfony\AI\Agent\Toolbox\Tool\Wikipedia;
use Symfony\AI\Agent\Toolbox\Toolbox;
use Symfony\AI\Platform\Bridge\Bedrock\Nova\Nova;
use Symfony\AI\Platform\Bridge\Bedrock\PlatformFactory;
use Symfony\AI\Platform\Message\Message;
use Symfony\AI\Platform\Message\MessageBag;
use Symfony\Component\Dotenv\Dotenv;
use Symfony\Component\HttpClient\HttpClient;
require_once dirname(__DIR__, 2).'/vendor/autoload.php';
(new Dotenv())->loadEnv(dirname(__DIR__, 2).'/.env');
if (empty($_ENV['AWS_ACCESS_KEY_ID']) || empty($_ENV['AWS_SECRET_ACCESS_KEY']) || empty($_ENV['AWS_DEFAULT_REGION'])
) {
echo 'Please set the AWS_ACCESS_KEY_ID, AWS_SECRET_ACCESS_KEY and AWS_DEFAULT_REGION environment variables.'.\PHP_EOL;
exit(1);
}
$platform = PlatformFactory::create();
$model = new Nova();
$wikipedia = new Wikipedia(HttpClient::create());
$toolbox = Toolbox::create($wikipedia);
$processor = new AgentProcessor($toolbox);
$agent = new Agent($platform, $model, [$processor], [$processor]);
$messages = new MessageBag(
Message::ofUser('Who is the current chancellor of Germany? Use Wikipedia to find the answer.')
);
$response = $agent->call($messages);
echo $response->getContent().\PHP_EOL;

View File

@@ -0,0 +1,37 @@
<?php
/*
* This file is part of the Symfony package.
*
* (c) Fabien Potencier <fabien@symfony.com>
*
* For the full copyright and license information, please view the LICENSE
* file that was distributed with this source code.
*/
use Symfony\AI\Agent\Agent;
use Symfony\AI\Agent\InputProcessor\SystemPromptInputProcessor;
use Symfony\AI\Platform\Bridge\OpenAI\GPT;
use Symfony\AI\Platform\Bridge\OpenAI\PlatformFactory;
use Symfony\AI\Platform\Message\Message;
use Symfony\AI\Platform\Message\MessageBag;
use Symfony\Component\Dotenv\Dotenv;
require_once dirname(__DIR__).'/vendor/autoload.php';
(new Dotenv())->loadEnv(dirname(__DIR__).'/.env');
if (empty($_ENV['OPENAI_API_KEY'])) {
echo 'Please set the OPENAI_API_KEY environment variable.'.\PHP_EOL;
exit(1);
}
$platform = PlatformFactory::create($_ENV['OPENAI_API_KEY']);
$model = new GPT(GPT::GPT_4O_MINI);
$processor = new SystemPromptInputProcessor('You are Yoda and write like he speaks. But short.');
$agent = new Agent($platform, $model, [$processor]);
$messages = new MessageBag(Message::ofUser('What is the meaning of life?'));
$response = $agent->call($messages);
echo $response->getContent().\PHP_EOL;

37
examples/google/chat.php Normal file
View File

@@ -0,0 +1,37 @@
<?php
/*
* This file is part of the Symfony package.
*
* (c) Fabien Potencier <fabien@symfony.com>
*
* For the full copyright and license information, please view the LICENSE
* file that was distributed with this source code.
*/
use Symfony\AI\Agent\Agent;
use Symfony\AI\Platform\Bridge\Google\Gemini;
use Symfony\AI\Platform\Bridge\Google\PlatformFactory;
use Symfony\AI\Platform\Message\Message;
use Symfony\AI\Platform\Message\MessageBag;
use Symfony\Component\Dotenv\Dotenv;
require_once dirname(__DIR__, 2).'/vendor/autoload.php';
(new Dotenv())->loadEnv(dirname(__DIR__, 2).'/.env');
if (empty($_ENV['GOOGLE_API_KEY'])) {
echo 'Please set the GOOGLE_API_KEY environment variable.'.\PHP_EOL;
exit(1);
}
$platform = PlatformFactory::create($_ENV['GOOGLE_API_KEY']);
$model = new Gemini(Gemini::GEMINI_2_FLASH);
$agent = new Agent($platform, $model);
$messages = new MessageBag(
Message::forSystem('You are a pirate and you write funny.'),
Message::ofUser('What is the Symfony framework?'),
);
$response = $agent->call($messages);
echo $response->getContent().\PHP_EOL;

View File

@@ -0,0 +1,41 @@
<?php
/*
* This file is part of the Symfony package.
*
* (c) Fabien Potencier <fabien@symfony.com>
*
* For the full copyright and license information, please view the LICENSE
* file that was distributed with this source code.
*/
use Symfony\AI\Agent\Agent;
use Symfony\AI\Platform\Bridge\Google\Gemini;
use Symfony\AI\Platform\Bridge\Google\PlatformFactory;
use Symfony\AI\Platform\Message\Content\Image;
use Symfony\AI\Platform\Message\Message;
use Symfony\AI\Platform\Message\MessageBag;
use Symfony\Component\Dotenv\Dotenv;
require_once dirname(__DIR__, 2).'/vendor/autoload.php';
(new Dotenv())->loadEnv(dirname(__DIR__, 2).'/.env');
if (empty($_ENV['GOOGLE_API_KEY'])) {
echo 'Please set the GOOGLE_API_KEY environment variable.'.\PHP_EOL;
exit(1);
}
$platform = PlatformFactory::create($_ENV['GOOGLE_API_KEY']);
$model = new Gemini(Gemini::GEMINI_1_5_FLASH);
$agent = new Agent($platform, $model);
$messages = new MessageBag(
Message::forSystem('You are an image analyzer bot that helps identify the content of images.'),
Message::ofUser(
'Describe the image as a comedian would do it.',
Image::fromFile(dirname(__DIR__, 2).'/fixtures/image.jpg'),
),
);
$response = $agent->call($messages);
echo $response->getContent().\PHP_EOL;

View File

@@ -0,0 +1,42 @@
<?php
/*
* This file is part of the Symfony package.
*
* (c) Fabien Potencier <fabien@symfony.com>
*
* For the full copyright and license information, please view the LICENSE
* file that was distributed with this source code.
*/
use Symfony\AI\Agent\Agent;
use Symfony\AI\Platform\Bridge\Google\Gemini;
use Symfony\AI\Platform\Bridge\Google\PlatformFactory;
use Symfony\AI\Platform\Message\Message;
use Symfony\AI\Platform\Message\MessageBag;
use Symfony\Component\Dotenv\Dotenv;
require_once dirname(__DIR__, 2).'/vendor/autoload.php';
(new Dotenv())->loadEnv(dirname(__DIR__, 2).'/.env');
if (empty($_ENV['GOOGLE_API_KEY'])) {
echo 'Please set the GOOGLE_API_KEY environment variable.'.\PHP_EOL;
exit(1);
}
$platform = PlatformFactory::create($_ENV['GOOGLE_API_KEY']);
$model = new Gemini(Gemini::GEMINI_2_FLASH);
$agent = new Agent($platform, $model);
$messages = new MessageBag(
Message::forSystem('You are a funny clown that entertains people.'),
Message::ofUser('What is the purpose of an ant?'),
);
$response = $agent->call($messages, [
'stream' => true, // enable streaming of response text
]);
foreach ($response->getContent() as $word) {
echo $word;
}
echo \PHP_EOL;

View File

@@ -0,0 +1,48 @@
<?php
/*
* This file is part of the Symfony package.
*
* (c) Fabien Potencier <fabien@symfony.com>
*
* For the full copyright and license information, please view the LICENSE
* file that was distributed with this source code.
*/
use Symfony\AI\Platform\Bridge\HuggingFace\ApiClient;
use Symfony\AI\Platform\Model;
use Symfony\Component\Console\Command\Command;
use Symfony\Component\Console\Input\InputInterface;
use Symfony\Component\Console\Input\InputOption;
use Symfony\Component\Console\Output\OutputInterface;
use Symfony\Component\Console\SingleCommandApplication;
use Symfony\Component\Console\Style\SymfonyStyle;
require_once dirname(__DIR__, 2).'/vendor/autoload.php';
$app = (new SingleCommandApplication('HuggingFace Model Listing'))
->setDescription('Lists all available models on HuggingFace')
->addOption('provider', 'p', InputOption::VALUE_REQUIRED, 'Name of the inference provider to filter models by')
->addOption('task', 't', InputOption::VALUE_REQUIRED, 'Name of the task to filter models by')
->setCode(function (InputInterface $input, OutputInterface $output) {
$io = new SymfonyStyle($input, $output);
$io->title('HuggingFace Model Listing');
$provider = $input->getOption('provider');
$task = $input->getOption('task');
$models = (new ApiClient())->models($provider, $task);
if (0 === count($models)) {
$io->error('No models found for the given provider and task.');
return Command::FAILURE;
}
$io->listing(
array_map(fn (Model $model) => $model->getName(), $models)
);
return Command::SUCCESS;
})
->run();

View File

@@ -0,0 +1,34 @@
<?php
/*
* This file is part of the Symfony package.
*
* (c) Fabien Potencier <fabien@symfony.com>
*
* For the full copyright and license information, please view the LICENSE
* file that was distributed with this source code.
*/
use Symfony\AI\Platform\Bridge\HuggingFace\PlatformFactory;
use Symfony\AI\Platform\Bridge\HuggingFace\Task;
use Symfony\AI\Platform\Message\Content\Audio;
use Symfony\AI\Platform\Model;
use Symfony\Component\Dotenv\Dotenv;
require_once dirname(__DIR__, 2).'/vendor/autoload.php';
(new Dotenv())->loadEnv(dirname(__DIR__, 2).'/.env');
if (empty($_ENV['HUGGINGFACE_KEY'])) {
echo 'Please set the HUGGINGFACE_KEY environment variable.'.\PHP_EOL;
exit(1);
}
$platform = PlatformFactory::create($_ENV['HUGGINGFACE_KEY']);
$model = new Model('MIT/ast-finetuned-audioset-10-10-0.4593');
$audio = Audio::fromFile(dirname(__DIR__, 2).'/fixtures/audio.mp3');
$response = $platform->request($model, $audio, [
'task' => Task::AUDIO_CLASSIFICATION,
]);
dump($response->getContent());

View File

@@ -0,0 +1,34 @@
<?php
/*
* This file is part of the Symfony package.
*
* (c) Fabien Potencier <fabien@symfony.com>
*
* For the full copyright and license information, please view the LICENSE
* file that was distributed with this source code.
*/
use Symfony\AI\Platform\Bridge\HuggingFace\PlatformFactory;
use Symfony\AI\Platform\Bridge\HuggingFace\Task;
use Symfony\AI\Platform\Message\Content\Audio;
use Symfony\AI\Platform\Model;
use Symfony\Component\Dotenv\Dotenv;
require_once dirname(__DIR__, 2).'/vendor/autoload.php';
(new Dotenv())->loadEnv(dirname(__DIR__, 2).'/.env');
if (empty($_ENV['HUGGINGFACE_KEY'])) {
echo 'Please set the HUGGINGFACE_KEY environment variable.'.\PHP_EOL;
exit(1);
}
$platform = PlatformFactory::create($_ENV['HUGGINGFACE_KEY']);
$model = new Model('openai/whisper-large-v3');
$audio = Audio::fromFile(dirname(__DIR__, 2).'/fixtures/audio.mp3');
$response = $platform->request($model, $audio, [
'task' => Task::AUTOMATIC_SPEECH_RECOGNITION,
]);
echo $response->getContent().\PHP_EOL;

View File

@@ -0,0 +1,35 @@
<?php
/*
* This file is part of the Symfony package.
*
* (c) Fabien Potencier <fabien@symfony.com>
*
* For the full copyright and license information, please view the LICENSE
* file that was distributed with this source code.
*/
use Symfony\AI\Platform\Bridge\HuggingFace\PlatformFactory;
use Symfony\AI\Platform\Bridge\HuggingFace\Task;
use Symfony\AI\Platform\Message\Message;
use Symfony\AI\Platform\Message\MessageBag;
use Symfony\AI\Platform\Model;
use Symfony\Component\Dotenv\Dotenv;
require_once dirname(__DIR__, 2).'/vendor/autoload.php';
(new Dotenv())->loadEnv(dirname(__DIR__, 2).'/.env');
if (empty($_ENV['HUGGINGFACE_KEY'])) {
echo 'Please set the HUGGINGFACE_KEY environment variable.'.\PHP_EOL;
exit(1);
}
$platform = PlatformFactory::create($_ENV['HUGGINGFACE_KEY']);
$model = new Model('HuggingFaceH4/zephyr-7b-beta');
$messages = new MessageBag(Message::ofUser('Hello, how are you doing today?'));
$response = $platform->request($model, $messages, [
'task' => Task::CHAT_COMPLETION,
]);
echo $response->getContent().\PHP_EOL;

View File

@@ -0,0 +1,35 @@
<?php
/*
* This file is part of the Symfony package.
*
* (c) Fabien Potencier <fabien@symfony.com>
*
* For the full copyright and license information, please view the LICENSE
* file that was distributed with this source code.
*/
use Symfony\AI\Platform\Bridge\HuggingFace\PlatformFactory;
use Symfony\AI\Platform\Bridge\HuggingFace\Task;
use Symfony\AI\Platform\Model;
use Symfony\AI\Platform\Response\VectorResponse;
use Symfony\Component\Dotenv\Dotenv;
require_once dirname(__DIR__, 2).'/vendor/autoload.php';
(new Dotenv())->loadEnv(dirname(__DIR__, 2).'/.env');
if (empty($_ENV['HUGGINGFACE_KEY'])) {
echo 'Please set the HUGGINGFACE_KEY environment variable.'.\PHP_EOL;
exit(1);
}
$platform = PlatformFactory::create($_ENV['HUGGINGFACE_KEY']);
$model = new Model('thenlper/gte-large');
$response = $platform->request($model, 'Today is a sunny day and I will get some ice cream.', [
'task' => Task::FEATURE_EXTRACTION,
]);
assert($response instanceof VectorResponse);
echo 'Dimensions: '.$response->getContent()[0]->getDimensions().\PHP_EOL;

View File

@@ -0,0 +1,32 @@
<?php
/*
* This file is part of the Symfony package.
*
* (c) Fabien Potencier <fabien@symfony.com>
*
* For the full copyright and license information, please view the LICENSE
* file that was distributed with this source code.
*/
use Symfony\AI\Platform\Bridge\HuggingFace\PlatformFactory;
use Symfony\AI\Platform\Bridge\HuggingFace\Task;
use Symfony\AI\Platform\Model;
use Symfony\Component\Dotenv\Dotenv;
require_once dirname(__DIR__, 2).'/vendor/autoload.php';
(new Dotenv())->loadEnv(dirname(__DIR__, 2).'/.env');
if (empty($_ENV['HUGGINGFACE_KEY'])) {
echo 'Please set the HUGGINGFACE_KEY environment variable.'.\PHP_EOL;
exit(1);
}
$platform = PlatformFactory::create($_ENV['HUGGINGFACE_KEY']);
$model = new Model('FacebookAI/xlm-roberta-base');
$response = $platform->request($model, 'Hello I\'m a <mask> model.', [
'task' => Task::FILL_MASK,
]);
dump($response->getContent());

View File

@@ -0,0 +1,34 @@
<?php
/*
* This file is part of the Symfony package.
*
* (c) Fabien Potencier <fabien@symfony.com>
*
* For the full copyright and license information, please view the LICENSE
* file that was distributed with this source code.
*/
use Symfony\AI\Platform\Bridge\HuggingFace\PlatformFactory;
use Symfony\AI\Platform\Bridge\HuggingFace\Task;
use Symfony\AI\Platform\Message\Content\Image;
use Symfony\AI\Platform\Model;
use Symfony\Component\Dotenv\Dotenv;
require_once dirname(__DIR__, 2).'/vendor/autoload.php';
(new Dotenv())->loadEnv(dirname(__DIR__, 2).'/.env');
if (empty($_ENV['HUGGINGFACE_KEY'])) {
echo 'Please set the HUGGINGFACE_KEY environment variable.'.\PHP_EOL;
exit(1);
}
$platform = PlatformFactory::create($_ENV['HUGGINGFACE_KEY']);
$model = new Model('google/vit-base-patch16-224');
$image = Image::fromFile(dirname(__DIR__, 2).'/fixtures/image.jpg');
$response = $platform->request($model, $image, [
'task' => Task::IMAGE_CLASSIFICATION,
]);
dump($response->getContent());

View File

@@ -0,0 +1,34 @@
<?php
/*
* This file is part of the Symfony package.
*
* (c) Fabien Potencier <fabien@symfony.com>
*
* For the full copyright and license information, please view the LICENSE
* file that was distributed with this source code.
*/
use Symfony\AI\Platform\Bridge\HuggingFace\PlatformFactory;
use Symfony\AI\Platform\Bridge\HuggingFace\Task;
use Symfony\AI\Platform\Message\Content\Image;
use Symfony\AI\Platform\Model;
use Symfony\Component\Dotenv\Dotenv;
require_once dirname(__DIR__, 2).'/vendor/autoload.php';
(new Dotenv())->loadEnv(dirname(__DIR__, 2).'/.env');
if (empty($_ENV['HUGGINGFACE_KEY'])) {
echo 'Please set the HUGGINGFACE_KEY environment variable.'.\PHP_EOL;
exit(1);
}
$platform = PlatformFactory::create($_ENV['HUGGINGFACE_KEY']);
$model = new Model('nvidia/segformer-b0-finetuned-ade-512-512');
$image = Image::fromFile(dirname(__DIR__, 2).'/fixtures/image.jpg');
$response = $platform->request($model, $image, [
'task' => Task::IMAGE_SEGMENTATION,
]);
dump($response->getContent());

View File

@@ -0,0 +1,34 @@
<?php
/*
* This file is part of the Symfony package.
*
* (c) Fabien Potencier <fabien@symfony.com>
*
* For the full copyright and license information, please view the LICENSE
* file that was distributed with this source code.
*/
use Symfony\AI\Platform\Bridge\HuggingFace\PlatformFactory;
use Symfony\AI\Platform\Bridge\HuggingFace\Task;
use Symfony\AI\Platform\Message\Content\Image;
use Symfony\AI\Platform\Model;
use Symfony\Component\Dotenv\Dotenv;
require_once dirname(__DIR__, 2).'/vendor/autoload.php';
(new Dotenv())->loadEnv(dirname(__DIR__, 2).'/.env');
if (empty($_ENV['HUGGINGFACE_KEY'])) {
echo 'Please set the HUGGINGFACE_KEY environment variable.'.\PHP_EOL;
exit(1);
}
$platform = PlatformFactory::create($_ENV['HUGGINGFACE_KEY']);
$model = new Model('Salesforce/blip-image-captioning-base');
$image = Image::fromFile(dirname(__DIR__, 2).'/fixtures/image.jpg');
$response = $platform->request($model, $image, [
'task' => Task::IMAGE_TO_TEXT,
]);
echo $response->getContent().\PHP_EOL;

View File

@@ -0,0 +1,34 @@
<?php
/*
* This file is part of the Symfony package.
*
* (c) Fabien Potencier <fabien@symfony.com>
*
* For the full copyright and license information, please view the LICENSE
* file that was distributed with this source code.
*/
use Symfony\AI\Platform\Bridge\HuggingFace\PlatformFactory;
use Symfony\AI\Platform\Bridge\HuggingFace\Task;
use Symfony\AI\Platform\Message\Content\Image;
use Symfony\AI\Platform\Model;
use Symfony\Component\Dotenv\Dotenv;
require_once dirname(__DIR__, 2).'/vendor/autoload.php';
(new Dotenv())->loadEnv(dirname(__DIR__, 2).'/.env');
if (empty($_ENV['HUGGINGFACE_KEY'])) {
echo 'Please set the HUGGINGFACE_KEY environment variable.'.\PHP_EOL;
exit(1);
}
$platform = PlatformFactory::create($_ENV['HUGGINGFACE_KEY']);
$model = new Model('facebook/detr-resnet-50');
$image = Image::fromFile(dirname(__DIR__, 2).'/fixtures/image.jpg');
$response = $platform->request($model, $image, [
'task' => Task::OBJECT_DETECTION,
]);
dump($response->getContent());

View File

@@ -0,0 +1,37 @@
<?php
/*
* This file is part of the Symfony package.
*
* (c) Fabien Potencier <fabien@symfony.com>
*
* For the full copyright and license information, please view the LICENSE
* file that was distributed with this source code.
*/
use Symfony\AI\Platform\Bridge\HuggingFace\PlatformFactory;
use Symfony\AI\Platform\Bridge\HuggingFace\Task;
use Symfony\AI\Platform\Model;
use Symfony\Component\Dotenv\Dotenv;
require_once dirname(__DIR__, 2).'/vendor/autoload.php';
(new Dotenv())->loadEnv(dirname(__DIR__, 2).'/.env');
if (empty($_ENV['HUGGINGFACE_KEY'])) {
echo 'Please set the HUGGINGFACE_KEY environment variable.'.\PHP_EOL;
exit(1);
}
$platform = PlatformFactory::create($_ENV['HUGGINGFACE_KEY']);
$model = new Model('deepset/roberta-base-squad2');
$input = [
'question' => 'What is the capital of France?',
'context' => 'Paris is the capital and most populous city of France, with an estimated population of 2,175,601 residents as of 2018, in an area of more than 105 square kilometres.',
];
$response = $platform->request($model, $input, [
'task' => Task::QUESTION_ANSWERING,
]);
dump($response->getContent());

View File

@@ -0,0 +1,41 @@
<?php
/*
* This file is part of the Symfony package.
*
* (c) Fabien Potencier <fabien@symfony.com>
*
* For the full copyright and license information, please view the LICENSE
* file that was distributed with this source code.
*/
use Symfony\AI\Platform\Bridge\HuggingFace\PlatformFactory;
use Symfony\AI\Platform\Bridge\HuggingFace\Task;
use Symfony\AI\Platform\Model;
use Symfony\Component\Dotenv\Dotenv;
require_once dirname(__DIR__, 2).'/vendor/autoload.php';
(new Dotenv())->loadEnv(dirname(__DIR__, 2).'/.env');
if (empty($_ENV['HUGGINGFACE_KEY'])) {
echo 'Please set the HUGGINGFACE_KEY environment variable.'.\PHP_EOL;
exit(1);
}
$platform = PlatformFactory::create($_ENV['HUGGINGFACE_KEY']);
$model = new Model('sentence-transformers/all-MiniLM-L6-v2');
$input = [
'source_sentence' => 'That is a happy dog',
'sentences' => [
'That is a happy canine',
'That is a happy cat',
'Today is a sunny day',
],
];
$response = $platform->request($model, $input, [
'task' => Task::SENTENCE_SIMILARITY,
]);
dump($response->getContent());

View File

@@ -0,0 +1,42 @@
<?php
/*
* This file is part of the Symfony package.
*
* (c) Fabien Potencier <fabien@symfony.com>
*
* For the full copyright and license information, please view the LICENSE
* file that was distributed with this source code.
*/
use Symfony\AI\Platform\Bridge\HuggingFace\PlatformFactory;
use Symfony\AI\Platform\Bridge\HuggingFace\Task;
use Symfony\AI\Platform\Model;
use Symfony\Component\Dotenv\Dotenv;
require_once dirname(__DIR__, 2).'/vendor/autoload.php';
(new Dotenv())->loadEnv(dirname(__DIR__, 2).'/.env');
if (empty($_ENV['HUGGINGFACE_KEY'])) {
echo 'Please set the HUGGINGFACE_KEY environment variable.'.\PHP_EOL;
exit(1);
}
$platform = PlatformFactory::create($_ENV['HUGGINGFACE_KEY']);
$model = new Model('facebook/bart-large-cnn');
$longText = <<<TEXT
The tower is 324 metres (1,063 ft) tall, about the same height as an 81-storey building, and the tallest structure
in Paris. Its base is square, measuring 125 metres (410 ft) on each side. During its construction, the Eiffel Tower
surpassed the Washington Monument to become the tallest man-made structure in the world, a title it held for 41
years until the Chrysler Building in New York City was finished in 1930. It was the first structure to reach a
height of 300 metres. Due to the addition of a broadcasting aerial at the top of the tower in 1957, it is now taller
than the Chrysler Building by 5.2 metres (17 ft). Excluding transmitters, the Eiffel Tower is the second tallest
free-standing structure in France after the Millau Viaduct.
TEXT;
$response = $platform->request($model, $longText, [
'task' => Task::SUMMARIZATION,
]);
echo $response->getContent().\PHP_EOL;

View File

@@ -0,0 +1,40 @@
<?php
/*
* This file is part of the Symfony package.
*
* (c) Fabien Potencier <fabien@symfony.com>
*
* For the full copyright and license information, please view the LICENSE
* file that was distributed with this source code.
*/
use Symfony\AI\Platform\Bridge\HuggingFace\PlatformFactory;
use Symfony\AI\Platform\Bridge\HuggingFace\Task;
use Symfony\AI\Platform\Model;
use Symfony\Component\Dotenv\Dotenv;
require_once dirname(__DIR__, 2).'/vendor/autoload.php';
(new Dotenv())->loadEnv(dirname(__DIR__, 2).'/.env');
if (empty($_ENV['HUGGINGFACE_KEY'])) {
echo 'Please set the HUGGINGFACE_KEY environment variable.'.\PHP_EOL;
exit(1);
}
$platform = PlatformFactory::create($_ENV['HUGGINGFACE_KEY']);
$model = new Model('microsoft/tapex-base');
$input = [
'query' => 'select year where city = beijing',
'table' => [
'year' => [1896, 1900, 1904, 2004, 2008, 2012],
'city' => ['athens', 'paris', 'st. louis', 'athens', 'beijing', 'london'],
],
];
$response = $platform->request($model, $input, [
'task' => Task::TABLE_QUESTION_ANSWERING,
]);
dump($response->getContent());

View File

@@ -0,0 +1,32 @@
<?php
/*
* This file is part of the Symfony package.
*
* (c) Fabien Potencier <fabien@symfony.com>
*
* For the full copyright and license information, please view the LICENSE
* file that was distributed with this source code.
*/
use Symfony\AI\Platform\Bridge\HuggingFace\PlatformFactory;
use Symfony\AI\Platform\Bridge\HuggingFace\Task;
use Symfony\AI\Platform\Model;
use Symfony\Component\Dotenv\Dotenv;
require_once dirname(__DIR__, 2).'/vendor/autoload.php';
(new Dotenv())->loadEnv(dirname(__DIR__, 2).'/.env');
if (empty($_ENV['HUGGINGFACE_KEY'])) {
echo 'Please set the HUGGINGFACE_KEY environment variable.'.\PHP_EOL;
exit(1);
}
$platform = PlatformFactory::create($_ENV['HUGGINGFACE_KEY']);
$model = new Model('ProsusAI/finbert');
$response = $platform->request($model, 'I like you. I love you.', [
'task' => Task::TEXT_CLASSIFICATION,
]);
dump($response->getContent());

View File

@@ -0,0 +1,32 @@
<?php
/*
* This file is part of the Symfony package.
*
* (c) Fabien Potencier <fabien@symfony.com>
*
* For the full copyright and license information, please view the LICENSE
* file that was distributed with this source code.
*/
use Symfony\AI\Platform\Bridge\HuggingFace\PlatformFactory;
use Symfony\AI\Platform\Bridge\HuggingFace\Task;
use Symfony\AI\Platform\Model;
use Symfony\Component\Dotenv\Dotenv;
require_once dirname(__DIR__, 2).'/vendor/autoload.php';
(new Dotenv())->loadEnv(dirname(__DIR__, 2).'/.env');
if (empty($_ENV['HUGGINGFACE_KEY'])) {
echo 'Please set the HUGGINGFACE_KEY environment variable.'.\PHP_EOL;
exit(1);
}
$platform = PlatformFactory::create($_ENV['HUGGINGFACE_KEY']);
$model = new Model('gpt2');
$response = $platform->request($model, 'The quick brown fox jumps over the lazy', [
'task' => Task::TEXT_GENERATION,
]);
echo $response->getContent().\PHP_EOL;

View File

@@ -0,0 +1,35 @@
<?php
/*
* This file is part of the Symfony package.
*
* (c) Fabien Potencier <fabien@symfony.com>
*
* For the full copyright and license information, please view the LICENSE
* file that was distributed with this source code.
*/
use Symfony\AI\Platform\Bridge\HuggingFace\PlatformFactory;
use Symfony\AI\Platform\Bridge\HuggingFace\Task;
use Symfony\AI\Platform\Model;
use Symfony\AI\Platform\Response\BinaryResponse;
use Symfony\Component\Dotenv\Dotenv;
require_once dirname(__DIR__, 2).'/vendor/autoload.php';
(new Dotenv())->loadEnv(dirname(__DIR__, 2).'/.env');
if (empty($_ENV['HUGGINGFACE_KEY'])) {
echo 'Please set the HUGGINGFACE_KEY environment variable.'.\PHP_EOL;
exit(1);
}
$platform = PlatformFactory::create($_ENV['HUGGINGFACE_KEY']);
$model = new Model('black-forest-labs/FLUX.1-dev');
$response = $platform->request($model, 'Astronaut riding a horse', [
'task' => Task::TEXT_TO_IMAGE,
]);
assert($response instanceof BinaryResponse);
echo $response->toBase64().\PHP_EOL;

View File

@@ -0,0 +1,32 @@
<?php
/*
* This file is part of the Symfony package.
*
* (c) Fabien Potencier <fabien@symfony.com>
*
* For the full copyright and license information, please view the LICENSE
* file that was distributed with this source code.
*/
use Symfony\AI\Platform\Bridge\HuggingFace\PlatformFactory;
use Symfony\AI\Platform\Bridge\HuggingFace\Task;
use Symfony\AI\Platform\Model;
use Symfony\Component\Dotenv\Dotenv;
require_once dirname(__DIR__, 2).'/vendor/autoload.php';
(new Dotenv())->loadEnv(dirname(__DIR__, 2).'/.env');
if (empty($_ENV['HUGGINGFACE_KEY'])) {
echo 'Please set the HUGGINGFACE_KEY environment variable.'.\PHP_EOL;
exit(1);
}
$platform = PlatformFactory::create($_ENV['HUGGINGFACE_KEY']);
$model = new Model('dbmdz/bert-large-cased-finetuned-conll03-english');
$response = $platform->request($model, 'John Smith works at Microsoft in London.', [
'task' => Task::TOKEN_CLASSIFICATION,
]);
dump($response->getContent());

View File

@@ -0,0 +1,34 @@
<?php
/*
* This file is part of the Symfony package.
*
* (c) Fabien Potencier <fabien@symfony.com>
*
* For the full copyright and license information, please view the LICENSE
* file that was distributed with this source code.
*/
use Symfony\AI\Platform\Bridge\HuggingFace\PlatformFactory;
use Symfony\AI\Platform\Bridge\HuggingFace\Task;
use Symfony\AI\Platform\Model;
use Symfony\Component\Dotenv\Dotenv;
require_once dirname(__DIR__, 2).'/vendor/autoload.php';
(new Dotenv())->loadEnv(dirname(__DIR__, 2).'/.env');
if (empty($_ENV['HUGGINGFACE_KEY'])) {
echo 'Please set the HUGGINGFACE_KEY environment variable.'.\PHP_EOL;
exit(1);
}
$platform = PlatformFactory::create($_ENV['HUGGINGFACE_KEY']);
$model = new Model('facebook/mbart-large-50-many-to-many-mmt');
$response = $platform->request($model, 'Меня зовут Вольфганг и я живу в Берлине', [
'task' => Task::TRANSLATION,
'src_lang' => 'ru',
'tgt_lang' => 'en',
]);
echo $response->getContent().\PHP_EOL;

View File

@@ -0,0 +1,34 @@
<?php
/*
* This file is part of the Symfony package.
*
* (c) Fabien Potencier <fabien@symfony.com>
*
* For the full copyright and license information, please view the LICENSE
* file that was distributed with this source code.
*/
use Symfony\AI\Platform\Bridge\HuggingFace\PlatformFactory;
use Symfony\AI\Platform\Bridge\HuggingFace\Task;
use Symfony\AI\Platform\Model;
use Symfony\Component\Dotenv\Dotenv;
require_once dirname(__DIR__, 2).'/vendor/autoload.php';
(new Dotenv())->loadEnv(dirname(__DIR__, 2).'/.env');
if (empty($_ENV['HUGGINGFACE_KEY'])) {
echo 'Please set the HUGGINGFACE_KEY environment variable.'.\PHP_EOL;
exit(1);
}
$platform = PlatformFactory::create($_ENV['HUGGINGFACE_KEY']);
$model = new Model('facebook/bart-large-mnli');
$text = 'Hi, I recently bought a device from your company but it is not working as advertised and I would like to get reimbursed!';
$response = $platform->request($model, $text, [
'task' => Task::ZERO_SHOT_CLASSIFICATION,
'candidate_labels' => ['refund', 'legal', 'faq'],
]);
dump($response->getContent());

36
examples/mistral/chat.php Normal file
View File

@@ -0,0 +1,36 @@
<?php
/*
* This file is part of the Symfony package.
*
* (c) Fabien Potencier <fabien@symfony.com>
*
* For the full copyright and license information, please view the LICENSE
* file that was distributed with this source code.
*/
use Symfony\AI\Agent\Agent;
use Symfony\AI\Platform\Bridge\Mistral\Mistral;
use Symfony\AI\Platform\Bridge\Mistral\PlatformFactory;
use Symfony\AI\Platform\Message\Message;
use Symfony\AI\Platform\Message\MessageBag;
use Symfony\Component\Dotenv\Dotenv;
require_once dirname(__DIR__, 2).'/vendor/autoload.php';
(new Dotenv())->loadEnv(dirname(__DIR__, 2).'/.env');
if (empty($_ENV['MISTRAL_API_KEY'])) {
echo 'Please set the REPLICATE_API_KEY environment variable.'.\PHP_EOL;
exit(1);
}
$platform = PlatformFactory::create($_ENV['MISTRAL_API_KEY']);
$model = new Mistral();
$agent = new Agent($platform, $model);
$messages = new MessageBag(Message::ofUser('What is the best French cheese?'));
$response = $agent->call($messages, [
'temperature' => 0.7,
]);
echo $response->getContent().\PHP_EOL;

View File

@@ -0,0 +1,37 @@
<?php
/*
* This file is part of the Symfony package.
*
* (c) Fabien Potencier <fabien@symfony.com>
*
* For the full copyright and license information, please view the LICENSE
* file that was distributed with this source code.
*/
use Symfony\AI\Platform\Bridge\Mistral\Embeddings;
use Symfony\AI\Platform\Bridge\Mistral\PlatformFactory;
use Symfony\AI\Platform\Response\VectorResponse;
use Symfony\Component\Dotenv\Dotenv;
require_once dirname(__DIR__, 2).'/vendor/autoload.php';
(new Dotenv())->loadEnv(dirname(__DIR__, 2).'/.env');
if (empty($_ENV['MISTRAL_API_KEY'])) {
echo 'Please set the MISTRAL_API_KEY environment variable.'.\PHP_EOL;
exit(1);
}
$platform = PlatformFactory::create($_ENV['MISTRAL_API_KEY']);
$model = new Embeddings();
$response = $platform->request($model, <<<TEXT
In the middle of the 20th century, food scientists began to understand the importance of vitamins and minerals in
human health. They discovered that certain nutrients were essential for growth, development, and overall well-being.
This led to the fortification of foods with vitamins and minerals, such as adding vitamin D to milk and iodine to
salt. The goal was to prevent deficiencies and promote better health in the population.
TEXT);
assert($response instanceof VectorResponse);
echo 'Dimensions: '.$response->getContent()[0]->getDimensions().\PHP_EOL;

View File

@@ -0,0 +1,41 @@
<?php
/*
* This file is part of the Symfony package.
*
* (c) Fabien Potencier <fabien@symfony.com>
*
* For the full copyright and license information, please view the LICENSE
* file that was distributed with this source code.
*/
use Symfony\AI\Agent\Agent;
use Symfony\AI\Platform\Bridge\Mistral\Mistral;
use Symfony\AI\Platform\Bridge\Mistral\PlatformFactory;
use Symfony\AI\Platform\Message\Content\Image;
use Symfony\AI\Platform\Message\Message;
use Symfony\AI\Platform\Message\MessageBag;
use Symfony\Component\Dotenv\Dotenv;
require_once dirname(__DIR__, 2).'/vendor/autoload.php';
(new Dotenv())->loadEnv(dirname(__DIR__, 2).'/.env');
if (empty($_ENV['OPENAI_API_KEY'])) {
echo 'Please set the OPENAI_API_KEY environment variable.'.\PHP_EOL;
exit(1);
}
$platform = PlatformFactory::create($_ENV['MISTRAL_API_KEY']);
$model = new Mistral(Mistral::MISTRAL_SMALL);
$agent = new Agent($platform, $model);
$messages = new MessageBag(
Message::forSystem('You are an image analyzer bot that helps identify the content of images.'),
Message::ofUser(
'Describe the image as a comedian would do it.',
Image::fromFile(dirname(__DIR__, 2).'/fixtures/image.jpg'),
),
);
$response = $agent->call($messages);
echo $response->getContent().\PHP_EOL;

View File

@@ -0,0 +1,39 @@
<?php
/*
* This file is part of the Symfony package.
*
* (c) Fabien Potencier <fabien@symfony.com>
*
* For the full copyright and license information, please view the LICENSE
* file that was distributed with this source code.
*/
use Symfony\AI\Agent\Agent;
use Symfony\AI\Platform\Bridge\Mistral\Mistral;
use Symfony\AI\Platform\Bridge\Mistral\PlatformFactory;
use Symfony\AI\Platform\Message\Message;
use Symfony\AI\Platform\Message\MessageBag;
use Symfony\Component\Dotenv\Dotenv;
require_once dirname(__DIR__, 2).'/vendor/autoload.php';
(new Dotenv())->loadEnv(dirname(__DIR__, 2).'/.env');
if (empty($_ENV['MISTRAL_API_KEY'])) {
echo 'Please set the REPLICATE_API_KEY environment variable.'.\PHP_EOL;
exit(1);
}
$platform = PlatformFactory::create($_ENV['MISTRAL_API_KEY']);
$model = new Mistral();
$agent = new Agent($platform, $model);
$messages = new MessageBag(Message::ofUser('What is the eighth prime number?'));
$response = $agent->call($messages, [
'stream' => true,
]);
foreach ($response->getContent() as $word) {
echo $word;
}
echo \PHP_EOL;

View File

@@ -0,0 +1,45 @@
<?php
/*
* This file is part of the Symfony package.
*
* (c) Fabien Potencier <fabien@symfony.com>
*
* For the full copyright and license information, please view the LICENSE
* file that was distributed with this source code.
*/
use Symfony\AI\Agent\Agent;
use Symfony\AI\Agent\StructuredOutput\AgentProcessor;
use Symfony\AI\Agent\StructuredOutput\ResponseFormatFactory;
use Symfony\AI\Fixtures\StructuredOutput\MathReasoning;
use Symfony\AI\Platform\Bridge\Mistral\Mistral;
use Symfony\AI\Platform\Bridge\Mistral\PlatformFactory;
use Symfony\AI\Platform\Message\Message;
use Symfony\AI\Platform\Message\MessageBag;
use Symfony\Component\Dotenv\Dotenv;
use Symfony\Component\Serializer\Encoder\JsonEncoder;
use Symfony\Component\Serializer\Normalizer\ObjectNormalizer;
use Symfony\Component\Serializer\Serializer;
require_once dirname(__DIR__, 2).'/vendor/autoload.php';
(new Dotenv())->loadEnv(dirname(__DIR__, 2).'/.env');
if (empty($_ENV['MISTRAL_API_KEY'])) {
echo 'Please set the MISTRAL_API_KEY environment variable.'.\PHP_EOL;
exit(1);
}
$platform = PlatformFactory::create($_ENV['MISTRAL_API_KEY']);
$model = new Mistral(Mistral::MISTRAL_SMALL);
$serializer = new Serializer([new ObjectNormalizer()], [new JsonEncoder()]);
$processor = new AgentProcessor(new ResponseFormatFactory(), $serializer);
$agent = new Agent($platform, $model, [$processor], [$processor]);
$messages = new MessageBag(
Message::forSystem('You are a helpful math tutor. Guide the user through the solution step by step.'),
Message::ofUser('how can I solve 8x + 7 = -23'),
);
$response = $agent->call($messages, ['output_structure' => MathReasoning::class]);
dump($response->getContent());

View File

@@ -0,0 +1,47 @@
<?php
/*
* This file is part of the Symfony package.
*
* (c) Fabien Potencier <fabien@symfony.com>
*
* For the full copyright and license information, please view the LICENSE
* file that was distributed with this source code.
*/
use Symfony\AI\Agent\Agent;
use Symfony\AI\Agent\Toolbox\AgentProcessor;
use Symfony\AI\Agent\Toolbox\Tool\YouTubeTranscriber;
use Symfony\AI\Agent\Toolbox\Toolbox;
use Symfony\AI\Platform\Bridge\Mistral\Mistral;
use Symfony\AI\Platform\Bridge\Mistral\PlatformFactory;
use Symfony\AI\Platform\Message\Message;
use Symfony\AI\Platform\Message\MessageBag;
use Symfony\Component\Dotenv\Dotenv;
use Symfony\Component\HttpClient\HttpClient;
require_once dirname(__DIR__, 2).'/vendor/autoload.php';
(new Dotenv())->loadEnv(dirname(__DIR__, 2).'/.env');
if (empty($_ENV['MISTRAL_API_KEY'])) {
echo 'Please set the REPLICATE_API_KEY environment variable.'.\PHP_EOL;
exit(1);
}
$platform = PlatformFactory::create($_ENV['MISTRAL_API_KEY']);
$model = new Mistral();
$transcriber = new YouTubeTranscriber(HttpClient::create());
$toolbox = Toolbox::create($transcriber);
$processor = new AgentProcessor($toolbox);
$agent = new Agent($platform, $model, [$processor], [$processor]);
$messages = new MessageBag(Message::ofUser('Please summarize this video for me: https://www.youtube.com/watch?v=6uXW-ulpj0s'));
$response = $agent->call($messages, [
'stream' => true,
]);
foreach ($response->getContent() as $word) {
echo $word;
}
echo \PHP_EOL;

View File

@@ -0,0 +1,40 @@
<?php
/*
* This file is part of the Symfony package.
*
* (c) Fabien Potencier <fabien@symfony.com>
*
* For the full copyright and license information, please view the LICENSE
* file that was distributed with this source code.
*/
use Symfony\AI\Agent\Agent;
use Symfony\AI\Agent\Toolbox\AgentProcessor;
use Symfony\AI\Agent\Toolbox\Tool\Clock;
use Symfony\AI\Agent\Toolbox\Toolbox;
use Symfony\AI\Platform\Bridge\Mistral\Mistral;
use Symfony\AI\Platform\Bridge\Mistral\PlatformFactory;
use Symfony\AI\Platform\Message\Message;
use Symfony\AI\Platform\Message\MessageBag;
use Symfony\Component\Dotenv\Dotenv;
require_once dirname(__DIR__, 2).'/vendor/autoload.php';
(new Dotenv())->loadEnv(dirname(__DIR__, 2).'/.env');
if (empty($_ENV['MISTRAL_API_KEY'])) {
echo 'Please set the REPLICATE_API_KEY environment variable.'.\PHP_EOL;
exit(1);
}
$platform = PlatformFactory::create($_ENV['MISTRAL_API_KEY']);
$model = new Mistral();
$toolbox = Toolbox::create(new Clock());
$processor = new AgentProcessor($toolbox);
$agent = new Agent($platform, $model, [$processor], [$processor]);
$messages = new MessageBag(Message::ofUser('What time is it?'));
$response = $agent->call($messages);
echo $response->getContent().\PHP_EOL;

View File

@@ -0,0 +1,37 @@
<?php
/*
* This file is part of the Symfony package.
*
* (c) Fabien Potencier <fabien@symfony.com>
*
* For the full copyright and license information, please view the LICENSE
* file that was distributed with this source code.
*/
use Symfony\AI\Agent\Agent;
use Symfony\AI\Platform\Bridge\Meta\Llama;
use Symfony\AI\Platform\Bridge\Ollama\PlatformFactory;
use Symfony\AI\Platform\Message\Message;
use Symfony\AI\Platform\Message\MessageBag;
use Symfony\Component\Dotenv\Dotenv;
require_once dirname(__DIR__, 2).'/vendor/autoload.php';
(new Dotenv())->loadEnv(dirname(__DIR__, 2).'/.env');
if (empty($_ENV['OLLAMA_HOST_URL'])) {
echo 'Please set the OLLAMA_HOST_URL environment variable.'.\PHP_EOL;
exit(1);
}
$platform = PlatformFactory::create($_ENV['OLLAMA_HOST_URL']);
$model = new Llama('llama3.2');
$agent = new Agent($platform, $model);
$messages = new MessageBag(
Message::forSystem('You are a helpful assistant.'),
Message::ofUser('Tina has one brother and one sister. How many sisters do Tina\'s siblings have?'),
);
$response = $agent->call($messages);
echo $response->getContent().\PHP_EOL;

View File

@@ -0,0 +1,40 @@
<?php
/*
* This file is part of the Symfony package.
*
* (c) Fabien Potencier <fabien@symfony.com>
*
* For the full copyright and license information, please view the LICENSE
* file that was distributed with this source code.
*/
use Symfony\AI\Agent\Agent;
use Symfony\AI\Platform\Bridge\OpenAI\GPT;
use Symfony\AI\Platform\Bridge\OpenAI\PlatformFactory;
use Symfony\AI\Platform\Message\Content\Audio;
use Symfony\AI\Platform\Message\Message;
use Symfony\AI\Platform\Message\MessageBag;
use Symfony\Component\Dotenv\Dotenv;
require_once dirname(__DIR__, 2).'/vendor/autoload.php';
(new Dotenv())->loadEnv(dirname(__DIR__, 2).'/.env');
if (empty($_ENV['OPENAI_API_KEY'])) {
echo 'Please set the OPENAI_API_KEY environment variable.'.\PHP_EOL;
exit(1);
}
$platform = PlatformFactory::create($_ENV['OPENAI_API_KEY']);
$model = new GPT(GPT::GPT_4O_AUDIO);
$agent = new Agent($platform, $model);
$messages = new MessageBag(
Message::ofUser(
'What is this recording about?',
Audio::fromFile(dirname(__DIR__, 2).'/fixtures/audio.mp3'),
),
);
$response = $agent->call($messages);
echo $response->getContent().\PHP_EOL;

View File

@@ -0,0 +1,31 @@
<?php
/*
* This file is part of the Symfony package.
*
* (c) Fabien Potencier <fabien@symfony.com>
*
* For the full copyright and license information, please view the LICENSE
* file that was distributed with this source code.
*/
use Symfony\AI\Platform\Bridge\OpenAI\PlatformFactory;
use Symfony\AI\Platform\Bridge\OpenAI\Whisper;
use Symfony\AI\Platform\Message\Content\Audio;
use Symfony\Component\Dotenv\Dotenv;
require_once dirname(__DIR__, 2).'/vendor/autoload.php';
(new Dotenv())->loadEnv(dirname(__DIR__, 2).'/.env');
if (empty($_ENV['OPENAI_API_KEY'])) {
echo 'Please set the OPENAI_API_KEY environment variable.'.\PHP_EOL;
exit(1);
}
$platform = PlatformFactory::create($_ENV['OPENAI_API_KEY']);
$model = new Whisper();
$file = Audio::fromFile(dirname(__DIR__, 2).'/fixtures/audio.mp3');
$response = $platform->request($model, $file);
echo $response->getContent().\PHP_EOL;

View File

@@ -0,0 +1,46 @@
<?php
/*
* This file is part of the Symfony package.
*
* (c) Fabien Potencier <fabien@symfony.com>
*
* For the full copyright and license information, please view the LICENSE
* file that was distributed with this source code.
*/
use Symfony\AI\Agent\Agent;
use Symfony\AI\Platform\Bridge\OpenAI\GPT;
use Symfony\AI\Platform\Bridge\OpenAI\PlatformFactory;
use Symfony\AI\Platform\Message\Message;
use Symfony\AI\Platform\Message\MessageBag;
use Symfony\Component\Dotenv\Dotenv;
require_once dirname(__DIR__, 2).'/vendor/autoload.php';
(new Dotenv())->loadEnv(dirname(__DIR__, 2).'/.env');
if (empty($_ENV['OPENAI_API_KEY'])) {
echo 'Please set the OPENAI_API_KEY environment variable.'.\PHP_EOL;
exit(1);
}
if (empty($_ENV['RUN_EXPENSIVE_EXAMPLES']) || false === filter_var($_ENV['RUN_EXPENSIVE_EXAMPLES'], \FILTER_VALIDATE_BOOLEAN)) {
echo 'This example is marked as expensive and will not run unless RUN_EXPENSIVE_EXAMPLES is set to true.'.\PHP_EOL;
exit(134);
}
$platform = PlatformFactory::create($_ENV['OPENAI_API_KEY']);
$model = new GPT(GPT::O1_PREVIEW);
$prompt = <<<PROMPT
I want to build a Symfony app in PHP 8.2 that takes user questions and looks them
up in a database where they are mapped to answers. If there is close match, it
retrieves the matched answer. If there isn't, it asks the user to provide an answer
and stores the question/answer pair in the database. Make a plan for the directory
structure you'll need, then return each file in full. Only supply your reasoning
at the beginning and end, not throughout the code.
PROMPT;
$response = (new Agent($platform, $model))->call(new MessageBag(Message::ofUser($prompt)));
echo $response->getContent().\PHP_EOL;

41
examples/openai/chat.php Normal file
View File

@@ -0,0 +1,41 @@
<?php
/*
* This file is part of the Symfony package.
*
* (c) Fabien Potencier <fabien@symfony.com>
*
* For the full copyright and license information, please view the LICENSE
* file that was distributed with this source code.
*/
use Symfony\AI\Agent\Agent;
use Symfony\AI\Platform\Bridge\OpenAI\GPT;
use Symfony\AI\Platform\Bridge\OpenAI\PlatformFactory;
use Symfony\AI\Platform\Message\Message;
use Symfony\AI\Platform\Message\MessageBag;
use Symfony\Component\Dotenv\Dotenv;
require_once dirname(__DIR__, 2).'/vendor/autoload.php';
(new Dotenv())->loadEnv(dirname(__DIR__, 2).'/.env');
if (empty($_ENV['OPENAI_API_KEY'])) {
echo 'Please set the OPENAI_API_KEY environment variable.'.\PHP_EOL;
exit(1);
}
$platform = PlatformFactory::create($_ENV['OPENAI_API_KEY']);
$model = new GPT(GPT::GPT_4O_MINI, [
'temperature' => 0.5, // default options for the model
]);
$agent = new Agent($platform, $model);
$messages = new MessageBag(
Message::forSystem('You are a pirate and you write funny.'),
Message::ofUser('What is the Symfony framework?'),
);
$response = $agent->call($messages, [
'max_tokens' => 500, // specific options just for this call
]);
echo $response->getContent().\PHP_EOL;

View File

@@ -0,0 +1,36 @@
<?php
/*
* This file is part of the Symfony package.
*
* (c) Fabien Potencier <fabien@symfony.com>
*
* For the full copyright and license information, please view the LICENSE
* file that was distributed with this source code.
*/
use Symfony\AI\Platform\Bridge\OpenAI\Embeddings;
use Symfony\AI\Platform\Bridge\OpenAI\PlatformFactory;
use Symfony\AI\Platform\Response\VectorResponse;
use Symfony\Component\Dotenv\Dotenv;
require_once dirname(__DIR__, 2).'/vendor/autoload.php';
(new Dotenv())->loadEnv(dirname(__DIR__, 2).'/.env');
if (empty($_ENV['OPENAI_API_KEY'])) {
echo 'Please set the OPENAI_API_KEY environment variable.'.\PHP_EOL;
exit(1);
}
$platform = PlatformFactory::create($_ENV['OPENAI_API_KEY']);
$embeddings = new Embeddings();
$response = $platform->request($embeddings, <<<TEXT
Once upon a time, there was a country called Japan. It was a beautiful country with a lot of mountains and rivers.
The people of Japan were very kind and hardworking. They loved their country very much and took care of it. The
country was very peaceful and prosperous. The people lived happily ever after.
TEXT);
assert($response instanceof VectorResponse);
echo 'Dimensions: '.$response->getContent()[0]->getDimensions().\PHP_EOL;

View File

@@ -0,0 +1,41 @@
<?php
/*
* This file is part of the Symfony package.
*
* (c) Fabien Potencier <fabien@symfony.com>
*
* For the full copyright and license information, please view the LICENSE
* file that was distributed with this source code.
*/
use Symfony\AI\Agent\Agent;
use Symfony\AI\Platform\Bridge\OpenAI\GPT;
use Symfony\AI\Platform\Bridge\OpenAI\PlatformFactory;
use Symfony\AI\Platform\Message\Content\Image;
use Symfony\AI\Platform\Message\Message;
use Symfony\AI\Platform\Message\MessageBag;
use Symfony\Component\Dotenv\Dotenv;
require_once dirname(__DIR__, 2).'/vendor/autoload.php';
(new Dotenv())->loadEnv(dirname(__DIR__, 2).'/.env');
if (empty($_ENV['OPENAI_API_KEY'])) {
echo 'Please set the OPENAI_API_KEY environment variable.'.\PHP_EOL;
exit(1);
}
$platform = PlatformFactory::create($_ENV['OPENAI_API_KEY']);
$model = new GPT(GPT::GPT_4O_MINI);
$agent = new Agent($platform, $model);
$messages = new MessageBag(
Message::forSystem('You are an image analyzer bot that helps identify the content of images.'),
Message::ofUser(
'Describe the image as a comedian would do it.',
Image::fromFile(dirname(__DIR__, 2).'/fixtures/image.jpg'),
),
);
$response = $agent->call($messages);
echo $response->getContent().\PHP_EOL;

View File

@@ -0,0 +1,41 @@
<?php
/*
* This file is part of the Symfony package.
*
* (c) Fabien Potencier <fabien@symfony.com>
*
* For the full copyright and license information, please view the LICENSE
* file that was distributed with this source code.
*/
use Symfony\AI\Agent\Agent;
use Symfony\AI\Platform\Bridge\OpenAI\GPT;
use Symfony\AI\Platform\Bridge\OpenAI\PlatformFactory;
use Symfony\AI\Platform\Message\Content\ImageUrl;
use Symfony\AI\Platform\Message\Message;
use Symfony\AI\Platform\Message\MessageBag;
use Symfony\Component\Dotenv\Dotenv;
require_once dirname(__DIR__, 2).'/vendor/autoload.php';
(new Dotenv())->loadEnv(dirname(__DIR__, 2).'/.env');
if (empty($_ENV['OPENAI_API_KEY'])) {
echo 'Please set the OPENAI_API_KEY environment variable.'.\PHP_EOL;
exit(1);
}
$platform = PlatformFactory::create($_ENV['OPENAI_API_KEY']);
$model = new GPT(GPT::GPT_4O_MINI);
$agent = new Agent($platform, $model);
$messages = new MessageBag(
Message::forSystem('You are an image analyzer bot that helps identify the content of images.'),
Message::ofUser(
'Describe the image as a comedian would do it.',
new ImageUrl('https://upload.wikimedia.org/wikipedia/commons/thumb/3/31/Webysther_20160423_-_Elephpant.svg/350px-Webysther_20160423_-_Elephpant.svg.png'),
),
);
$response = $agent->call($messages);
echo $response->getContent().\PHP_EOL;

View File

@@ -0,0 +1,37 @@
<?php
/*
* This file is part of the Symfony package.
*
* (c) Fabien Potencier <fabien@symfony.com>
*
* For the full copyright and license information, please view the LICENSE
* file that was distributed with this source code.
*/
use Symfony\AI\Platform\Bridge\OpenAI\DallE;
use Symfony\AI\Platform\Bridge\OpenAI\PlatformFactory;
use Symfony\Component\Dotenv\Dotenv;
require_once dirname(__DIR__, 2).'/vendor/autoload.php';
(new Dotenv())->loadEnv(dirname(__DIR__, 2).'/.env');
if (empty($_ENV['OPENAI_API_KEY'])) {
echo 'Please set the OPENAI_API_KEY environment variable.'.\PHP_EOL;
exit(1);
}
$platform = PlatformFactory::create($_ENV['OPENAI_API_KEY']);
$response = $platform->request(
model: new DallE(), // Utilize Dall-E 2 version in default
input: 'A cartoon-style elephant with a long trunk and large ears.',
options: [
'response_format' => 'url', // Generate response as URL
'n' => 2, // Generate multiple images for example
],
);
foreach ($response->getContent() as $index => $image) {
echo 'Image '.$index.': '.$image->url.\PHP_EOL;
}

View File

@@ -0,0 +1,41 @@
<?php
/*
* This file is part of the Symfony package.
*
* (c) Fabien Potencier <fabien@symfony.com>
*
* For the full copyright and license information, please view the LICENSE
* file that was distributed with this source code.
*/
use Symfony\AI\Platform\Bridge\OpenAI\DallE;
use Symfony\AI\Platform\Bridge\OpenAI\DallE\ImageResponse;
use Symfony\AI\Platform\Bridge\OpenAI\PlatformFactory;
use Symfony\Component\Dotenv\Dotenv;
require_once dirname(__DIR__, 2).'/vendor/autoload.php';
(new Dotenv())->loadEnv(dirname(__DIR__, 2).'/.env');
if (empty($_ENV['OPENAI_API_KEY'])) {
echo 'Please set the OPENAI_API_KEY environment variable.'.\PHP_EOL;
exit(1);
}
$platform = PlatformFactory::create($_ENV['OPENAI_API_KEY']);
$response = $platform->request(
model: new DallE(name: DallE::DALL_E_3),
input: 'A cartoon-style elephant with a long trunk and large ears.',
options: [
'response_format' => 'url', // Generate response as URL
],
);
assert($response instanceof ImageResponse);
echo 'Revised Prompt: '.$response->revisedPrompt.\PHP_EOL.\PHP_EOL;
foreach ($response->getContent() as $index => $image) {
echo 'Image '.$index.': '.$image->url.\PHP_EOL;
}

View File

@@ -0,0 +1,42 @@
<?php
/*
* This file is part of the Symfony package.
*
* (c) Fabien Potencier <fabien@symfony.com>
*
* For the full copyright and license information, please view the LICENSE
* file that was distributed with this source code.
*/
use Symfony\AI\Agent\Agent;
use Symfony\AI\Platform\Bridge\OpenAI\GPT;
use Symfony\AI\Platform\Bridge\OpenAI\PlatformFactory;
use Symfony\AI\Platform\Message\Message;
use Symfony\AI\Platform\Message\MessageBag;
use Symfony\Component\Dotenv\Dotenv;
require_once dirname(__DIR__, 2).'/vendor/autoload.php';
(new Dotenv())->loadEnv(dirname(__DIR__, 2).'/.env');
if (empty($_ENV['OPENAI_API_KEY'])) {
echo 'Please set the OPENAI_API_KEY environment variable.'.\PHP_EOL;
exit(1);
}
$platform = PlatformFactory::create($_ENV['OPENAI_API_KEY']);
$model = new GPT(GPT::GPT_4O_MINI);
$agent = new Agent($platform, $model);
$messages = new MessageBag(
Message::forSystem('You are a thoughtful philosopher.'),
Message::ofUser('What is the purpose of an ant?'),
);
$response = $agent->call($messages, [
'stream' => true, // enable streaming of response text
]);
foreach ($response->getContent() as $word) {
echo $word;
}
echo \PHP_EOL;

View File

@@ -0,0 +1,59 @@
<?php
/*
* This file is part of the Symfony package.
*
* (c) Fabien Potencier <fabien@symfony.com>
*
* For the full copyright and license information, please view the LICENSE
* file that was distributed with this source code.
*/
use Symfony\AI\Agent\Agent;
use Symfony\AI\Agent\StructuredOutput\AgentProcessor as StructuredOutputProcessor;
use Symfony\AI\Agent\Toolbox\AgentProcessor as ToolProcessor;
use Symfony\AI\Agent\Toolbox\Tool\Clock;
use Symfony\AI\Agent\Toolbox\Toolbox;
use Symfony\AI\Platform\Bridge\OpenAI\GPT;
use Symfony\AI\Platform\Bridge\OpenAI\PlatformFactory;
use Symfony\AI\Platform\Message\Message;
use Symfony\AI\Platform\Message\MessageBag;
use Symfony\Component\Clock\Clock as SymfonyClock;
use Symfony\Component\Dotenv\Dotenv;
require_once dirname(__DIR__, 2).'/vendor/autoload.php';
(new Dotenv())->loadEnv(dirname(__DIR__, 2).'/.env');
if (empty($_ENV['OPENAI_API_KEY'])) {
echo 'Please set the OPENAI_API_KEY environment variable.'.\PHP_EOL;
exit(1);
}
$platform = PlatformFactory::create($_ENV['OPENAI_API_KEY']);
$model = new GPT(GPT::GPT_4O_MINI);
$clock = new Clock(new SymfonyClock());
$toolbox = Toolbox::create($clock);
$toolProcessor = new ToolProcessor($toolbox);
$structuredOutputProcessor = new StructuredOutputProcessor();
$agent = new Agent($platform, $model, [$toolProcessor, $structuredOutputProcessor], [$toolProcessor, $structuredOutputProcessor]);
$messages = new MessageBag(Message::ofUser('What date and time is it?'));
$response = $agent->call($messages, ['response_format' => [
'type' => 'json_schema',
'json_schema' => [
'name' => 'clock',
'strict' => true,
'schema' => [
'type' => 'object',
'properties' => [
'date' => ['type' => 'string', 'description' => 'The current date in the format YYYY-MM-DD.'],
'time' => ['type' => 'string', 'description' => 'The current time in the format HH:MM:SS.'],
],
'required' => ['date', 'time'],
'additionalProperties' => false,
],
],
]]);
dump($response->getContent());

View File

@@ -0,0 +1,40 @@
<?php
/*
* This file is part of the Symfony package.
*
* (c) Fabien Potencier <fabien@symfony.com>
*
* For the full copyright and license information, please view the LICENSE
* file that was distributed with this source code.
*/
use Symfony\AI\Agent\Agent;
use Symfony\AI\Agent\StructuredOutput\AgentProcessor;
use Symfony\AI\Fixtures\StructuredOutput\MathReasoning;
use Symfony\AI\Platform\Bridge\OpenAI\GPT;
use Symfony\AI\Platform\Bridge\OpenAI\PlatformFactory;
use Symfony\AI\Platform\Message\Message;
use Symfony\AI\Platform\Message\MessageBag;
use Symfony\Component\Dotenv\Dotenv;
require_once dirname(__DIR__, 2).'/vendor/autoload.php';
(new Dotenv())->loadEnv(dirname(__DIR__, 2).'/.env');
if (empty($_ENV['OPENAI_API_KEY'])) {
echo 'Please set the OPENAI_API_KEY environment variable.'.\PHP_EOL;
exit(1);
}
$platform = PlatformFactory::create($_ENV['OPENAI_API_KEY']);
$model = new GPT(GPT::GPT_4O_MINI);
$processor = new AgentProcessor();
$agent = new Agent($platform, $model, [$processor], [$processor]);
$messages = new MessageBag(
Message::forSystem('You are a helpful math tutor. Guide the user through the solution step by step.'),
Message::ofUser('how can I solve 8x + 7 = -23'),
);
$response = $agent->call($messages, ['output_structure' => MathReasoning::class]);
dump($response->getContent());

View File

@@ -0,0 +1,47 @@
<?php
/*
* This file is part of the Symfony package.
*
* (c) Fabien Potencier <fabien@symfony.com>
*
* For the full copyright and license information, please view the LICENSE
* file that was distributed with this source code.
*/
use Symfony\AI\Agent\Agent;
use Symfony\AI\Platform\Bridge\OpenAI\GPT;
use Symfony\AI\Platform\Bridge\OpenAI\PlatformFactory;
use Symfony\AI\Platform\Bridge\OpenAI\TokenOutputProcessor;
use Symfony\AI\Platform\Message\Message;
use Symfony\AI\Platform\Message\MessageBag;
use Symfony\Component\Dotenv\Dotenv;
require_once dirname(__DIR__, 2).'/vendor/autoload.php';
(new Dotenv())->loadEnv(dirname(__DIR__, 2).'/.env');
if (empty($_ENV['OPENAI_API_KEY'])) {
echo 'Please set the OPENAI_API_KEY environment variable.'.\PHP_EOL;
exit(1);
}
$platform = PlatformFactory::create($_ENV['OPENAI_API_KEY']);
$model = new GPT(GPT::GPT_4O_MINI, [
'temperature' => 0.5, // default options for the model
]);
$agent = new Agent($platform, $model, outputProcessors: [new TokenOutputProcessor()]);
$messages = new MessageBag(
Message::forSystem('You are a pirate and you write funny.'),
Message::ofUser('What is the Symfony framework?'),
);
$response = $agent->call($messages, [
'max_tokens' => 500, // specific options just for this call
]);
$metadata = $response->getMetadata();
echo 'Utilized Tokens: '.$metadata['total_tokens'].\PHP_EOL;
echo '-- Prompt Tokens: '.$metadata['prompt_tokens'].\PHP_EOL;
echo '-- Completion Tokens: '.$metadata['completion_tokens'].\PHP_EOL;
echo 'Remaining Tokens: '.$metadata['remaining_tokens'].\PHP_EOL;

View File

@@ -0,0 +1,51 @@
<?php
/*
* This file is part of the Symfony package.
*
* (c) Fabien Potencier <fabien@symfony.com>
*
* For the full copyright and license information, please view the LICENSE
* file that was distributed with this source code.
*/
use Symfony\AI\Agent\Agent;
use Symfony\AI\Agent\Toolbox\AgentProcessor;
use Symfony\AI\Agent\Toolbox\Tool\Wikipedia;
use Symfony\AI\Agent\Toolbox\Toolbox;
use Symfony\AI\Platform\Bridge\OpenAI\GPT;
use Symfony\AI\Platform\Bridge\OpenAI\PlatformFactory;
use Symfony\AI\Platform\Message\Message;
use Symfony\AI\Platform\Message\MessageBag;
use Symfony\Component\Dotenv\Dotenv;
use Symfony\Component\HttpClient\HttpClient;
require_once dirname(__DIR__, 2).'/vendor/autoload.php';
(new Dotenv())->loadEnv(dirname(__DIR__, 2).'/.env');
if (empty($_ENV['OPENAI_API_KEY'])) {
echo 'Please set the OPENAI_API_KEY environment variable.'.\PHP_EOL;
exit(1);
}
$platform = PlatformFactory::create($_ENV['OPENAI_API_KEY']);
$model = new GPT(GPT::GPT_4O_MINI);
$wikipedia = new Wikipedia(HttpClient::create());
$toolbox = Toolbox::create($wikipedia);
$processor = new AgentProcessor($toolbox);
$agent = new Agent($platform, $model, [$processor], [$processor]);
$messages = new MessageBag(Message::ofUser(<<<TXT
First, define unicorn in 30 words.
Then lookup at Wikipedia what the irish history looks like in 2 sentences.
Please tell me before you call tools.
TXT));
$response = $agent->call($messages, [
'stream' => true, // enable streaming of response text
]);
foreach ($response->getContent() as $word) {
echo $word;
}
echo \PHP_EOL;

View File

@@ -0,0 +1,42 @@
<?php
/*
* This file is part of the Symfony package.
*
* (c) Fabien Potencier <fabien@symfony.com>
*
* For the full copyright and license information, please view the LICENSE
* file that was distributed with this source code.
*/
use Symfony\AI\Agent\Agent;
use Symfony\AI\Agent\Toolbox\AgentProcessor;
use Symfony\AI\Agent\Toolbox\Tool\YouTubeTranscriber;
use Symfony\AI\Agent\Toolbox\Toolbox;
use Symfony\AI\Platform\Bridge\OpenAI\GPT;
use Symfony\AI\Platform\Bridge\OpenAI\PlatformFactory;
use Symfony\AI\Platform\Message\Message;
use Symfony\AI\Platform\Message\MessageBag;
use Symfony\Component\Dotenv\Dotenv;
use Symfony\Component\HttpClient\HttpClient;
require_once dirname(__DIR__, 2).'/vendor/autoload.php';
(new Dotenv())->loadEnv(dirname(__DIR__, 2).'/.env');
if (empty($_ENV['OPENAI_API_KEY'])) {
echo 'Please set the OPENAI_API_KEY environment variable.'.\PHP_EOL;
exit(1);
}
$platform = PlatformFactory::create($_ENV['OPENAI_API_KEY']);
$model = new GPT(GPT::GPT_4O_MINI);
$transcriber = new YouTubeTranscriber(HttpClient::create());
$toolbox = Toolbox::create($transcriber);
$processor = new AgentProcessor($toolbox);
$agent = new Agent($platform, $model, [$processor], [$processor]);
$messages = new MessageBag(Message::ofUser('Please summarize this video for me: https://www.youtube.com/watch?v=6uXW-ulpj0s'));
$response = $agent->call($messages);
echo $response->getContent().\PHP_EOL;

View File

@@ -0,0 +1,39 @@
<?php
/*
* This file is part of the Symfony package.
*
* (c) Fabien Potencier <fabien@symfony.com>
*
* For the full copyright and license information, please view the LICENSE
* file that was distributed with this source code.
*/
use Symfony\AI\Agent\Agent;
use Symfony\AI\Platform\Bridge\OpenRouter\PlatformFactory;
use Symfony\AI\Platform\Message\Message;
use Symfony\AI\Platform\Message\MessageBag;
use Symfony\AI\Platform\Model;
use Symfony\Component\Dotenv\Dotenv;
require_once dirname(__DIR__, 2).'/vendor/autoload.php';
(new Dotenv())->loadEnv(dirname(__DIR__, 2).'/.env');
if (empty($_ENV['OPENROUTER_KEY'])) {
echo 'Please set the OPENROUTER_KEY environment variable.'.\PHP_EOL;
exit(1);
}
$platform = PlatformFactory::create($_ENV['OPENROUTER_KEY']);
// In case free is running into 429 rate limit errors, you can use the paid model:
// $model = new Model('google/gemini-2.0-flash-lite-001');
$model = new Model('google/gemini-2.0-flash-exp:free');
$agent = new Agent($platform, $model);
$messages = new MessageBag(
Message::forSystem('You are a helpful assistant.'),
Message::ofUser('Tina has one brother and one sister. How many sisters do Tina\'s siblings have?'),
);
$response = $agent->call($messages);
echo $response->getContent().\PHP_EOL;

View File

@@ -0,0 +1,47 @@
<?php
declare(strict_types=1);
/*
* This file is part of the Symfony package.
*
* (c) Fabien Potencier <fabien@symfony.com>
*
* For the full copyright and license information, please view the LICENSE
* file that was distributed with this source code.
*/
use Symfony\AI\Platform\Bridge\OpenAI\GPT;
use Symfony\AI\Platform\Bridge\OpenAI\PlatformFactory;
use Symfony\AI\Platform\Message\Message;
use Symfony\AI\Platform\Message\MessageBag;
use Symfony\Component\Dotenv\Dotenv;
require_once dirname(__DIR__).'/vendor/autoload.php';
(new Dotenv())->loadEnv(dirname(__DIR__).'/.env');
if (empty($_ENV['OPENAI_API_KEY'])) {
echo 'Please set the OPENAI_API_KEY environment variable.'.\PHP_EOL;
exit(1);
}
$platform = PlatformFactory::create($_ENV['OPENAI_API_KEY']);
$model = new GPT(GPT::GPT_4O_MINI, [
'temperature' => 0.5, // default options for the model
]);
$messages = new MessageBag(
Message::forSystem('You will be given a letter and you answer with only the next letter of the alphabet.'),
);
echo 'Initiating parallel calls to GPT on platform ...'.\PHP_EOL;
$responses = [];
foreach (range('A', 'D') as $letter) {
echo ' - Request for the letter '.$letter.' initiated.'.\PHP_EOL;
$responses[] = $platform->request($model, $messages->with(Message::ofUser($letter)));
}
echo 'Waiting for the responses ...'.\PHP_EOL;
foreach ($responses as $response) {
echo 'Next Letter: '.$response->getContent().\PHP_EOL;
}

View File

@@ -0,0 +1,43 @@
<?php
declare(strict_types=1);
/*
* This file is part of the Symfony package.
*
* (c) Fabien Potencier <fabien@symfony.com>
*
* For the full copyright and license information, please view the LICENSE
* file that was distributed with this source code.
*/
use Symfony\AI\Platform\Bridge\OpenAI\Embeddings;
use Symfony\AI\Platform\Bridge\OpenAI\PlatformFactory;
use Symfony\AI\Platform\Response\VectorResponse;
use Symfony\Component\Dotenv\Dotenv;
require_once dirname(__DIR__).'/vendor/autoload.php';
(new Dotenv())->loadEnv(dirname(__DIR__).'/.env');
if (empty($_ENV['OPENAI_API_KEY'])) {
echo 'Please set the OPENAI_API_KEY environment variable.'.\PHP_EOL;
exit(1);
}
$platform = PlatformFactory::create($_ENV['OPENAI_API_KEY']);
$ada = new Embeddings(Embeddings::TEXT_ADA_002);
$small = new Embeddings(Embeddings::TEXT_3_SMALL);
$large = new Embeddings(Embeddings::TEXT_3_LARGE);
echo 'Initiating parallel embeddings calls to platform ...'.\PHP_EOL;
$responses = [];
foreach (['ADA' => $ada, 'Small' => $small, 'Large' => $large] as $name => $model) {
echo ' - Request for model '.$name.' initiated.'.\PHP_EOL;
$responses[] = $platform->request($model, 'Hello, world!');
}
echo 'Waiting for the responses ...'.\PHP_EOL;
foreach ($responses as $response) {
assert($response instanceof VectorResponse);
echo 'Dimensions: '.$response->getContent()[0]->getDimensions().\PHP_EOL;
}

View File

@@ -0,0 +1,37 @@
<?php
/*
* This file is part of the Symfony package.
*
* (c) Fabien Potencier <fabien@symfony.com>
*
* For the full copyright and license information, please view the LICENSE
* file that was distributed with this source code.
*/
use Symfony\AI\Agent\Agent;
use Symfony\AI\Platform\Bridge\Meta\Llama;
use Symfony\AI\Platform\Bridge\Replicate\PlatformFactory;
use Symfony\AI\Platform\Message\Message;
use Symfony\AI\Platform\Message\MessageBag;
use Symfony\Component\Dotenv\Dotenv;
require_once dirname(__DIR__, 2).'/vendor/autoload.php';
(new Dotenv())->loadEnv(dirname(__DIR__, 2).'/.env');
if (empty($_ENV['REPLICATE_API_KEY'])) {
echo 'Please set the REPLICATE_API_KEY environment variable.'.\PHP_EOL;
exit(1);
}
$platform = PlatformFactory::create($_ENV['REPLICATE_API_KEY']);
$model = new Llama();
$agent = new Agent($platform, $model);
$messages = new MessageBag(
Message::forSystem('You are a helpful assistant.'),
Message::ofUser('Tina has one brother and one sister. How many sisters do Tina\'s siblings have?'),
);
$response = $agent->call($messages);
echo $response->getContent().\PHP_EOL;

View File

@@ -0,0 +1,83 @@
<?php
/*
* This file is part of the Symfony package.
*
* (c) Fabien Potencier <fabien@symfony.com>
*
* For the full copyright and license information, please view the LICENSE
* file that was distributed with this source code.
*/
use MongoDB\Client as MongoDBClient;
use Symfony\AI\Agent\Agent;
use Symfony\AI\Agent\Toolbox\AgentProcessor;
use Symfony\AI\Agent\Toolbox\Tool\SimilaritySearch;
use Symfony\AI\Agent\Toolbox\Toolbox;
use Symfony\AI\Platform\Bridge\OpenAI\Embeddings;
use Symfony\AI\Platform\Bridge\OpenAI\GPT;
use Symfony\AI\Platform\Bridge\OpenAI\PlatformFactory;
use Symfony\AI\Platform\Message\Message;
use Symfony\AI\Platform\Message\MessageBag;
use Symfony\AI\Store\Bridge\MongoDB\Store;
use Symfony\AI\Store\Document\Metadata;
use Symfony\AI\Store\Document\TextDocument;
use Symfony\AI\Store\Embedder;
use Symfony\Component\Dotenv\Dotenv;
use Symfony\Component\Uid\Uuid;
require_once dirname(__DIR__, 2).'/vendor/autoload.php';
(new Dotenv())->loadEnv(dirname(__DIR__, 2).'/.env');
if (empty($_ENV['OPENAI_API_KEY']) || empty($_ENV['MONGODB_URI'])) {
echo 'Please set OPENAI_API_KEY and MONGODB_URI environment variables.'.\PHP_EOL;
exit(1);
}
// initialize the store
$store = new Store(
client: new MongoDBClient($_ENV['MONGODB_URI']),
databaseName: 'my-database',
collectionName: 'my-collection',
indexName: 'my-index',
vectorFieldName: 'vector',
);
// our data
$movies = [
['title' => 'Inception', 'description' => 'A skilled thief is given a chance at redemption if he can successfully perform inception, the act of planting an idea in someone\'s subconscious.', 'director' => 'Christopher Nolan'],
['title' => 'The Matrix', 'description' => 'A hacker discovers the world he lives in is a simulated reality and joins a rebellion to overthrow its controllers.', 'director' => 'The Wachowskis'],
['title' => 'The Godfather', 'description' => 'The aging patriarch of an organized crime dynasty transfers control of his empire to his reluctant son.', 'director' => 'Francis Ford Coppola'],
];
// create embeddings and documents
foreach ($movies as $movie) {
$documents[] = new TextDocument(
id: Uuid::v4(),
content: 'Title: '.$movie['title'].\PHP_EOL.'Director: '.$movie['director'].\PHP_EOL.'Description: '.$movie['description'],
metadata: new Metadata($movie),
);
}
// create embeddings for documents
$platform = PlatformFactory::create($_ENV['OPENAI_API_KEY']);
$embedder = new Embedder($platform, $embeddings = new Embeddings(), $store);
$embedder->embed($documents);
// initialize the index
$store->initialize();
$model = new GPT(GPT::GPT_4O_MINI);
$similaritySearch = new SimilaritySearch($platform, $embeddings, $store);
$toolbox = Toolbox::create($similaritySearch);
$processor = new AgentProcessor($toolbox);
$agent = new Agent($platform, $model, [$processor], [$processor]);
$messages = new MessageBag(
Message::forSystem('Please answer all user questions only using SimilaritySearch function.'),
Message::ofUser('Which movie fits the theme of the mafia?')
);
$response = $agent->call($messages);
echo $response->getContent().\PHP_EOL;

View File

@@ -0,0 +1,74 @@
<?php
/*
* This file is part of the Symfony package.
*
* (c) Fabien Potencier <fabien@symfony.com>
*
* For the full copyright and license information, please view the LICENSE
* file that was distributed with this source code.
*/
use Probots\Pinecone\Pinecone;
use Symfony\AI\Agent\Agent;
use Symfony\AI\Agent\Toolbox\AgentProcessor;
use Symfony\AI\Agent\Toolbox\Tool\SimilaritySearch;
use Symfony\AI\Agent\Toolbox\Toolbox;
use Symfony\AI\Platform\Bridge\OpenAI\Embeddings;
use Symfony\AI\Platform\Bridge\OpenAI\GPT;
use Symfony\AI\Platform\Bridge\OpenAI\PlatformFactory;
use Symfony\AI\Platform\Message\Message;
use Symfony\AI\Platform\Message\MessageBag;
use Symfony\AI\Store\Bridge\Pinecone\Store;
use Symfony\AI\Store\Document\Metadata;
use Symfony\AI\Store\Document\TextDocument;
use Symfony\AI\Store\Embedder;
use Symfony\Component\Dotenv\Dotenv;
use Symfony\Component\Uid\Uuid;
require_once dirname(__DIR__, 2).'/vendor/autoload.php';
(new Dotenv())->loadEnv(dirname(__DIR__, 2).'/.env');
if (empty($_ENV['OPENAI_API_KEY']) || empty($_ENV['PINECONE_API_KEY']) || empty($_ENV['PINECONE_HOST'])) {
echo 'Please set OPENAI_API_KEY, PINECONE_API_KEY and PINECONE_HOST environment variables.'.\PHP_EOL;
exit(1);
}
// initialize the store
$store = new Store(Pinecone::client($_ENV['PINECONE_API_KEY'], $_ENV['PINECONE_HOST']));
// our data
$movies = [
['title' => 'Inception', 'description' => 'A skilled thief is given a chance at redemption if he can successfully perform inception, the act of planting an idea in someone\'s subconscious.', 'director' => 'Christopher Nolan'],
['title' => 'The Matrix', 'description' => 'A hacker discovers the world he lives in is a simulated reality and joins a rebellion to overthrow its controllers.', 'director' => 'The Wachowskis'],
['title' => 'The Godfather', 'description' => 'The aging patriarch of an organized crime dynasty transfers control of his empire to his reluctant son.', 'director' => 'Francis Ford Coppola'],
];
// create embeddings and documents
foreach ($movies as $movie) {
$documents[] = new TextDocument(
id: Uuid::v4(),
content: 'Title: '.$movie['title'].\PHP_EOL.'Director: '.$movie['director'].\PHP_EOL.'Description: '.$movie['description'],
metadata: new Metadata($movie),
);
}
// create embeddings for documents
$platform = PlatformFactory::create($_ENV['OPENAI_API_KEY']);
$embedder = new Embedder($platform, $embeddings = new Embeddings(), $store);
$embedder->embed($documents);
$model = new GPT(GPT::GPT_4O_MINI);
$similaritySearch = new SimilaritySearch($platform, $embeddings, $store);
$toolbox = Toolbox::create($similaritySearch);
$processor = new AgentProcessor($toolbox);
$agent = new Agent($platform, $model, [$processor], [$processor]);
$messages = new MessageBag(
Message::forSystem('Please answer all user questions only using SimilaritySearch function.'),
Message::ofUser('Which movie fits the theme of the mafia?')
);
$response = $agent->call($messages);
echo $response->getContent().\PHP_EOL;

View File

@@ -0,0 +1,44 @@
<?php
/*
* This file is part of the Symfony package.
*
* (c) Fabien Potencier <fabien@symfony.com>
*
* For the full copyright and license information, please view the LICENSE
* file that was distributed with this source code.
*/
use Symfony\AI\Agent\Agent;
use Symfony\AI\Agent\Toolbox\AgentProcessor;
use Symfony\AI\Agent\Toolbox\Tool\Brave;
use Symfony\AI\Agent\Toolbox\Tool\Crawler;
use Symfony\AI\Agent\Toolbox\Toolbox;
use Symfony\AI\Platform\Bridge\OpenAI\GPT;
use Symfony\AI\Platform\Bridge\OpenAI\PlatformFactory;
use Symfony\AI\Platform\Message\Message;
use Symfony\AI\Platform\Message\MessageBag;
use Symfony\Component\Dotenv\Dotenv;
use Symfony\Component\HttpClient\HttpClient;
require_once dirname(__DIR__, 2).'/vendor/autoload.php';
(new Dotenv())->loadEnv(dirname(__DIR__, 2).'/.env');
if (empty($_ENV['OPENAI_API_KEY']) || empty($_ENV['BRAVE_API_KEY'])) {
echo 'Please set the OPENAI_API_KEY and BRAVE_API_KEY environment variable.'.\PHP_EOL;
exit(1);
}
$platform = PlatformFactory::create($_ENV['OPENAI_API_KEY']);
$model = new GPT(GPT::GPT_4O_MINI);
$httpClient = HttpClient::create();
$brave = new Brave($httpClient, $_ENV['BRAVE_API_KEY']);
$crawler = new Crawler($httpClient);
$toolbox = Toolbox::create($brave, $crawler);
$processor = new AgentProcessor($toolbox);
$agent = new Agent($platform, $model, [$processor], [$processor]);
$messages = new MessageBag(Message::ofUser('What was the latest game result of Dallas Cowboys?'));
$response = $agent->call($messages);
echo $response->getContent().\PHP_EOL;

View File

@@ -0,0 +1,43 @@
<?php
/*
* This file is part of the Symfony package.
*
* (c) Fabien Potencier <fabien@symfony.com>
*
* For the full copyright and license information, please view the LICENSE
* file that was distributed with this source code.
*/
use Symfony\AI\Agent\Agent;
use Symfony\AI\Agent\Toolbox\AgentProcessor;
use Symfony\AI\Agent\Toolbox\Toolbox;
use Symfony\AI\Agent\Toolbox\ToolFactory\MemoryToolFactory;
use Symfony\AI\Platform\Bridge\OpenAI\GPT;
use Symfony\AI\Platform\Bridge\OpenAI\PlatformFactory;
use Symfony\AI\Platform\Message\Message;
use Symfony\AI\Platform\Message\MessageBag;
use Symfony\Component\Clock\Clock;
use Symfony\Component\Dotenv\Dotenv;
require_once dirname(__DIR__, 2).'/vendor/autoload.php';
(new Dotenv())->loadEnv(dirname(__DIR__, 2).'/.env');
if (empty($_ENV['OPENAI_API_KEY'])) {
echo 'Please set the OPENAI_API_KEY environment variable.'.\PHP_EOL;
exit(1);
}
$platform = PlatformFactory::create($_ENV['OPENAI_API_KEY']);
$model = new GPT(GPT::GPT_4O_MINI);
$metadataFactory = (new MemoryToolFactory())
->addTool(Clock::class, 'clock', 'Get the current date and time', 'now');
$toolbox = new Toolbox($metadataFactory, [new Clock()]);
$processor = new AgentProcessor($toolbox);
$agent = new Agent($platform, $model, [$processor], [$processor]);
$messages = new MessageBag(Message::ofUser('What date and time is it?'));
$response = $agent->call($messages);
echo $response->getContent().\PHP_EOL;

View File

@@ -0,0 +1,41 @@
<?php
/*
* This file is part of the Symfony package.
*
* (c) Fabien Potencier <fabien@symfony.com>
*
* For the full copyright and license information, please view the LICENSE
* file that was distributed with this source code.
*/
use Symfony\AI\Agent\Agent;
use Symfony\AI\Agent\Toolbox\AgentProcessor;
use Symfony\AI\Agent\Toolbox\Tool\SerpApi;
use Symfony\AI\Agent\Toolbox\Toolbox;
use Symfony\AI\Platform\Bridge\OpenAI\GPT;
use Symfony\AI\Platform\Bridge\OpenAI\PlatformFactory;
use Symfony\AI\Platform\Message\Message;
use Symfony\AI\Platform\Message\MessageBag;
use Symfony\Component\Dotenv\Dotenv;
use Symfony\Component\HttpClient\HttpClient;
require_once dirname(__DIR__, 2).'/vendor/autoload.php';
(new Dotenv())->loadEnv(dirname(__DIR__, 2).'/.env');
if (empty($_ENV['OPENAI_API_KEY']) || empty($_ENV['SERP_API_KEY'])) {
echo 'Please set the OPENAI_API_KEY and SERP_API_KEY environment variable.'.\PHP_EOL;
exit(1);
}
$platform = PlatformFactory::create($_ENV['OPENAI_API_KEY']);
$model = new GPT(GPT::GPT_4O_MINI);
$serpApi = new SerpApi(HttpClient::create(), $_ENV['SERP_API_KEY']);
$toolbox = Toolbox::create($serpApi);
$processor = new AgentProcessor($toolbox);
$agent = new Agent($platform, $model, [$processor], [$processor]);
$messages = new MessageBag(Message::ofUser('Who is the current chancellor of Germany?'));
$response = $agent->call($messages);
echo $response->getContent().\PHP_EOL;

View File

@@ -0,0 +1,41 @@
<?php
/*
* This file is part of the Symfony package.
*
* (c) Fabien Potencier <fabien@symfony.com>
*
* For the full copyright and license information, please view the LICENSE
* file that was distributed with this source code.
*/
use Symfony\AI\Agent\Agent;
use Symfony\AI\Agent\Toolbox\AgentProcessor;
use Symfony\AI\Agent\Toolbox\Tool\Tavily;
use Symfony\AI\Agent\Toolbox\Toolbox;
use Symfony\AI\Platform\Bridge\OpenAI\GPT;
use Symfony\AI\Platform\Bridge\OpenAI\PlatformFactory;
use Symfony\AI\Platform\Message\Message;
use Symfony\AI\Platform\Message\MessageBag;
use Symfony\Component\Dotenv\Dotenv;
use Symfony\Component\HttpClient\HttpClient;
require_once dirname(__DIR__, 2).'/vendor/autoload.php';
(new Dotenv())->loadEnv(dirname(__DIR__, 2).'/.env');
if (empty($_ENV['OPENAI_API_KEY']) || empty($_ENV['TAVILY_API_KEY'])) {
echo 'Please set the OPENAI_API_KEY and TAVILY_API_KEY environment variable.'.\PHP_EOL;
exit(1);
}
$platform = PlatformFactory::create($_ENV['OPENAI_API_KEY']);
$model = new GPT(GPT::GPT_4O_MINI);
$tavily = new Tavily(HttpClient::create(), $_ENV['TAVILY_API_KEY']);
$toolbox = Toolbox::create($tavily);
$processor = new AgentProcessor($toolbox);
$agent = new Agent($platform, $model, [$processor], [$processor]);
$messages = new MessageBag(Message::ofUser('What was the latest game result of Dallas Cowboys?'));
$response = $agent->call($messages);
echo $response->getContent().\PHP_EOL;

View File

@@ -0,0 +1,55 @@
<?php
/*
* This file is part of the Symfony package.
*
* (c) Fabien Potencier <fabien@symfony.com>
*
* For the full copyright and license information, please view the LICENSE
* file that was distributed with this source code.
*/
use Symfony\AI\Agent\Agent;
use Symfony\AI\Agent\Toolbox\AgentProcessor;
use Symfony\AI\Agent\Toolbox\Event\ToolCallsExecuted;
use Symfony\AI\Agent\Toolbox\Tool\OpenMeteo;
use Symfony\AI\Agent\Toolbox\Toolbox;
use Symfony\AI\Platform\Bridge\OpenAI\GPT;
use Symfony\AI\Platform\Bridge\OpenAI\PlatformFactory;
use Symfony\AI\Platform\Message\Message;
use Symfony\AI\Platform\Message\MessageBag;
use Symfony\AI\Platform\Response\ObjectResponse;
use Symfony\Component\Dotenv\Dotenv;
use Symfony\Component\EventDispatcher\EventDispatcher;
use Symfony\Component\HttpClient\HttpClient;
require_once dirname(__DIR__, 2).'/vendor/autoload.php';
(new Dotenv())->loadEnv(dirname(__DIR__, 2).'/.env');
if (empty($_ENV['OPENAI_API_KEY'])) {
echo 'Please set the OPENAI_API_KEY environment variable.'.\PHP_EOL;
exit(1);
}
$platform = PlatformFactory::create($_ENV['OPENAI_API_KEY']);
$model = new GPT(GPT::GPT_4O_MINI);
$openMeteo = new OpenMeteo(HttpClient::create());
$toolbox = Toolbox::create($openMeteo);
$eventDispatcher = new EventDispatcher();
$processor = new AgentProcessor($toolbox, eventDispatcher: $eventDispatcher);
$agent = new Agent($platform, $model, [$processor], [$processor]);
// Add tool call result listener to enforce chain exits direct with structured response for weather tools
$eventDispatcher->addListener(ToolCallsExecuted::class, function (ToolCallsExecuted $event): void {
foreach ($event->toolCallResults as $toolCallResult) {
if (str_starts_with($toolCallResult->toolCall->name, 'weather_')) {
$event->response = new ObjectResponse($toolCallResult->result);
}
}
});
$messages = new MessageBag(Message::ofUser('How is the weather currently in Berlin?'));
$response = $agent->call($messages);
dump($response->getContent());

View File

@@ -0,0 +1,35 @@
<?php
/*
* This file is part of the Symfony package.
*
* (c) Fabien Potencier <fabien@symfony.com>
*
* For the full copyright and license information, please view the LICENSE
* file that was distributed with this source code.
*/
use Codewithkyrian\Transformers\Pipelines\Task;
use Symfony\AI\Platform\Bridge\TransformersPHP\PlatformFactory;
use Symfony\AI\Platform\Model;
require_once dirname(__DIR__, 2).'/vendor/autoload.php';
if (!extension_loaded('ffi') || '1' !== ini_get('ffi.enable')) {
echo 'FFI extension is not loaded or enabled. Please enable it in your php.ini file.'.\PHP_EOL;
echo 'See https://github.com/CodeWithKyrian/transformers-php for setup instructions.'.\PHP_EOL;
exit(1);
}
if (!is_dir(dirname(__DIR__, 2).'/.transformers-cache/Xenova/LaMini-Flan-T5-783M')) {
echo 'Model "Xenova/LaMini-Flan-T5-783M" not found. Downloading it will be part of the first run. This may take a while...'.\PHP_EOL;
}
$platform = PlatformFactory::create();
$model = new Model('Xenova/LaMini-Flan-T5-783M');
$response = $platform->request($model, 'How many continents are there in the world?', [
'task' => Task::Text2TextGeneration,
]);
echo $response->getContent().\PHP_EOL;

View File

@@ -0,0 +1,36 @@
<?php
/*
* This file is part of the Symfony package.
*
* (c) Fabien Potencier <fabien@symfony.com>
*
* For the full copyright and license information, please view the LICENSE
* file that was distributed with this source code.
*/
use Symfony\AI\Platform\Bridge\Voyage\PlatformFactory;
use Symfony\AI\Platform\Bridge\Voyage\Voyage;
use Symfony\AI\Platform\Response\VectorResponse;
use Symfony\Component\Dotenv\Dotenv;
require_once dirname(__DIR__, 2).'/vendor/autoload.php';
(new Dotenv())->loadEnv(dirname(__DIR__, 2).'/.env');
if (empty($_ENV['VOYAGE_API_KEY'])) {
echo 'Please set the VOYAGE_API_KEY environment variable.'.\PHP_EOL;
exit(1);
}
$platform = PlatformFactory::create($_ENV['VOYAGE_API_KEY']);
$embeddings = new Voyage();
$response = $platform->request($embeddings, <<<TEXT
Once upon a time, there was a country called Japan. It was a beautiful country with a lot of mountains and rivers.
The people of Japan were very kind and hardworking. They loved their country very much and took care of it. The
country was very peaceful and prosperous. The people lived happily ever after.
TEXT);
assert($response instanceof VectorResponse);
echo 'Dimensions: '.$response->getContent()[0]->getDimensions().\PHP_EOL;

View File

@@ -0,0 +1,8 @@
<?php
namespace Symfony\AI\Fixtures;
final class SomeStructure
{
public string $some;
}

View File

@@ -0,0 +1,15 @@
<?php
namespace Symfony\AI\Fixtures\StructuredOutput;
final class MathReasoning
{
/**
* @param Step[] $steps
*/
public function __construct(
public array $steps,
public string $finalAnswer,
) {
}
}

View File

@@ -0,0 +1,12 @@
<?php
namespace Symfony\AI\Fixtures\StructuredOutput;
final class Step
{
public function __construct(
public string $explanation,
public string $output,
) {
}
}

View File

@@ -0,0 +1,15 @@
<?php
namespace Symfony\AI\Fixtures\StructuredOutput;
final class User
{
public int $id;
/**
* @var string The name of the user in lowercase
*/
public string $name;
public \DateTimeInterface $createdAt;
public bool $isActive;
public ?int $age = null;
}

View File

@@ -0,0 +1,18 @@
<?php
namespace Symfony\AI\Fixtures\StructuredOutput;
final class UserWithConstructor
{
/**
* @param string $name The name of the user in lowercase
*/
public function __construct(
public int $id,
public string $name,
public \DateTimeInterface $createdAt,
public bool $isActive,
public ?int $age = null,
) {
}
}

View File

@@ -0,0 +1,18 @@
<?php
namespace Symfony\AI\Fixtures\Tool;
use Symfony\AI\Agent\Toolbox\Attribute\AsTool;
#[AsTool('tool_no_params', 'A tool without parameters')]
final class ToolArray
{
/**
* @param string[] $urls
* @param list<int> $ids
*/
public function __invoke(array $urls, array $ids): string
{
return 'Hello world!';
}
}

View File

@@ -0,0 +1,14 @@
<?php
namespace Symfony\AI\Fixtures\Tool;
use Symfony\AI\Agent\Toolbox\Attribute\AsTool;
#[AsTool('tool_exception', description: 'This tool is broken', method: 'bar')]
final class ToolException
{
public function bar(): string
{
throw new \Exception('Tool error.');
}
}

View File

@@ -0,0 +1,14 @@
<?php
namespace Symfony\AI\Fixtures\Tool;
use Symfony\AI\Agent\Toolbox\Attribute\AsTool;
#[AsTool('tool_misconfigured', description: 'This tool is misconfigured, see method', method: 'foo')]
final class ToolMisconfigured
{
public function bar(): string
{
return 'Wrong Config Attribute';
}
}

View File

@@ -0,0 +1,27 @@
<?php
namespace Symfony\AI\Fixtures\Tool;
use Symfony\AI\Agent\Toolbox\Attribute\AsTool;
#[AsTool('tool_hello_world', 'Function to say hello', method: 'hello')]
#[AsTool('tool_required_params', 'Function to say a number', method: 'bar')]
final class ToolMultiple
{
/**
* @param string $world The world to say hello to
*/
public function hello(string $world): string
{
return \sprintf('Hello "%s".', $world);
}
/**
* @param string $text The text given to the tool
* @param int $number A number given to the tool
*/
public function bar(string $text, int $number): string
{
return \sprintf('%s says "%d".', $text, $number);
}
}

View File

@@ -0,0 +1,15 @@
<?php
namespace Symfony\AI\Fixtures\Tool;
final class ToolNoAttribute1
{
/**
* @param string $name the name of the person
* @param int $years the age of the person
*/
public function __invoke(string $name, int $years): string
{
return \sprintf('Happy Birthday, %s! You are %d years old.', $name, $years);
}
}

View File

@@ -0,0 +1,23 @@
<?php
namespace Symfony\AI\Fixtures\Tool;
final class ToolNoAttribute2
{
/**
* @param int $id the ID of the product
* @param int $amount the number of products
*/
public function buy(int $id, int $amount): string
{
return \sprintf('You bought %d of product %d.', $amount, $id);
}
/**
* @param string $orderId the ID of the order
*/
public function cancel(string $orderId): string
{
return \sprintf('You canceled order %s.', $orderId);
}
}

View File

@@ -0,0 +1,14 @@
<?php
namespace Symfony\AI\Fixtures\Tool;
use Symfony\AI\Agent\Toolbox\Attribute\AsTool;
#[AsTool('tool_no_params', 'A tool without parameters')]
final class ToolNoParams
{
public function __invoke(): string
{
return 'Hello world!';
}
}

View File

@@ -0,0 +1,18 @@
<?php
namespace Symfony\AI\Fixtures\Tool;
use Symfony\AI\Agent\Toolbox\Attribute\AsTool;
#[AsTool('tool_optional_param', 'A tool with one optional parameter', method: 'bar')]
final class ToolOptionalParam
{
/**
* @param string $text The text given to the tool
* @param int $number A number given to the tool
*/
public function bar(string $text, int $number = 3): string
{
return \sprintf('%s says "%d".', $text, $number);
}
}

View File

@@ -0,0 +1,18 @@
<?php
namespace Symfony\AI\Fixtures\Tool;
use Symfony\AI\Agent\Toolbox\Attribute\AsTool;
#[AsTool('tool_required_params', 'A tool with required parameters', method: 'bar')]
final class ToolRequiredParams
{
/**
* @param string $text The text given to the tool
* @param int $number A number given to the tool
*/
public function bar(string $text, int $number): string
{
return \sprintf('%s says "%d".', $text, $number);
}
}

Some files were not shown because too many files have changed in this diff Show More