Files
archived-ai/ai.symfony.com/templates/sections/_features.html.twig
Christopher Hertel 0d492e3362 Redesign ai.symfony.com landing page
Overhaul the landing page with a modern, section-based layout:

- Hero slider with 3 rotating slides (Agent, Symfony, MCP) and progress bar
- Component Architecture section with layered SVG diagram
- Features section with 10 tabbed code examples
- Third-party integration bridges logo grid
- Demos section with setup steps and demo cards
- MCP SDK and Symfony Mate sections
- Sticky navbar with glassmorphism effect and Bootstrap tooltips
- Redesigned "Get Involved & Get Support" CTA section
- Full light/dark theme support with CSS variables
- Stimulus controllers for hero slider, feature tabs, and clipboard
- AOS scroll animations
- Subtle gradient backgrounds for secondary sections
2026-03-23 12:25:03 +01:00

300 lines
24 KiB
Twig

<section id="features" class="section-secondary py-5 py-lg-5" data-controller="feature-tabs">
<div class="container">
<h2 class="ff-title fw-bold h3 mb-4 text-center section-heading" data-aos="fade-up">Features</h2>
<div class="d-flex flex-wrap justify-content-center gap-2 mb-4" data-aos="fade-up" data-aos-delay="100">
<button type="button" class="feature-tab active" data-feature-tabs-target="tab" data-action="feature-tabs#switch" data-index="0">Model Inference</button>
<button type="button" class="feature-tab" data-feature-tabs-target="tab" data-action="feature-tabs#switch" data-index="1">Streaming</button>
<button type="button" class="feature-tab" data-feature-tabs-target="tab" data-action="feature-tabs#switch" data-index="2">Speech</button>
<button type="button" class="feature-tab" data-feature-tabs-target="tab" data-action="feature-tabs#switch" data-index="3">Multi-Modal</button>
<button type="button" class="feature-tab" data-feature-tabs-target="tab" data-action="feature-tabs#switch" data-index="4">Structured Output</button>
<button type="button" class="feature-tab" data-feature-tabs-target="tab" data-action="feature-tabs#switch" data-index="5">Agents</button>
<button type="button" class="feature-tab" data-feature-tabs-target="tab" data-action="feature-tabs#switch" data-index="6">Token Usage</button>
<button type="button" class="feature-tab" data-feature-tabs-target="tab" data-action="feature-tabs#switch" data-index="7">Tool Calling</button>
<button type="button" class="feature-tab" data-feature-tabs-target="tab" data-action="feature-tabs#switch" data-index="8">Subagents</button>
<button type="button" class="feature-tab" data-feature-tabs-target="tab" data-action="feature-tabs#switch" data-index="9">RAG</button>
</div>
{# Model Inference #}
<div class="feature-panel active" data-feature-tabs-target="panel">
<div class="row align-items-center g-4">
<div class="col-lg-5" data-aos="fade-right">
<h3 class="ff-title fw-bold h4 mb-3">Model Inference</h3>
<p class="text-muted mb-4">
Send prompts to any AI model and get responses with a single method call.
The Platform abstracts away provider differences — switch between OpenAI, Anthropic, Mistral, or local models without changing your application code.
</p>
<a href="https://github.com/symfony/ai/blob/main/examples/openai/chat.php" class="btn btn-dark px-3 d-inline-flex align-items-center" target="_blank" rel="noopener noreferrer">
{{ ux_icon('simple-icons:github', {width: 18, height: 18, class: 'me-2'}) }}
<span>See example</span>
{{ ux_icon('tabler:arrow-up-right', {width: 18, height: 18, class: 'ms-2'}) }}
</a>
</div>
<div class="col-lg-7" data-aos="fade-left">
<pre class="terminal"><code><span class="variable">$platform</span> = <span class="title class_">PlatformFactory</span>::<span class="title function_ invoke__">create</span>(<span class="variable">$apiKey</span>, <span class="title function_ invoke__">http_client</span>());
<span class="variable">$messages</span> = <span class="keyword">new</span> <span class="title class_">MessageBag</span>(
<span class="title class_">Message</span>::<span class="title function_ invoke__">forSystem</span>(<span class="string">'You are a helpful assistant.'</span>),
<span class="title class_">Message</span>::<span class="title function_ invoke__">ofUser</span>(<span class="string">'What is the Symfony framework?'</span>),
);
<span class="variable">$result</span> = <span class="variable">$platform</span>-&gt;<span class="title function_ invoke__">invoke</span>(<span class="string">'gpt-5-mini'</span>, <span class="variable">$messages</span>);
<span class="keyword">echo</span> <span class="variable">$result</span>-&gt;<span class="title function_ invoke__">asText</span>();</code></pre>
</div>
</div>
</div>
{# Streaming #}
<div class="feature-panel" data-feature-tabs-target="panel">
<div class="row align-items-center g-4">
<div class="col-lg-5">
<h3 class="ff-title fw-bold h4 mb-3">Streaming</h3>
<p class="text-muted mb-4">
Stream responses token by token for real-time output.
Instead of waiting for the full response, display text as it's generated — just like ChatGPT does. Works with any supported model and platform.
</p>
<a href="https://github.com/symfony/ai/blob/main/examples/openai/stream.php" class="btn btn-dark px-3 d-inline-flex align-items-center" target="_blank" rel="noopener noreferrer">
{{ ux_icon('simple-icons:github', {width: 18, height: 18, class: 'me-2'}) }}
<span>See example</span>
{{ ux_icon('tabler:arrow-up-right', {width: 18, height: 18, class: 'ms-2'}) }}
</a>
</div>
<div class="col-lg-7">
<pre class="terminal"><code><span class="variable">$result</span> = <span class="variable">$platform</span>-&gt;<span class="title function_ invoke__">invoke</span>(<span class="string">'gpt-5-mini'</span>, <span class="variable">$messages</span>, [
<span class="string">'stream'</span> =&gt; <span class="keyword">true</span>,
]);
<span class="keyword">foreach</span> (<span class="variable">$result</span>-&gt;<span class="title function_ invoke__">asStream</span>() <span class="keyword">as</span> <span class="variable">$chunk</span>) {
<span class="keyword">echo</span> <span class="variable">$chunk</span>; <span class="comment">// process chunks as they arrive</span>
}</code></pre>
</div>
</div>
</div>
{# Speech #}
<div class="feature-panel" data-feature-tabs-target="panel">
<div class="row align-items-center g-4">
<div class="col-lg-5">
<h3 class="ff-title fw-bold h4 mb-3">Speech</h3>
<p class="text-muted mb-4">
Convert text to natural-sounding speech or transcribe audio recordings to text.
Build voice assistants, podcast transcription tools, or accessibility features with providers like ElevenLabs or OpenAI Whisper — all through the same interface.
</p>
<a href="https://github.com/symfony/ai/blob/main/examples/elevenlabs/text-to-speech.php" class="btn btn-dark px-3 d-inline-flex align-items-center" target="_blank" rel="noopener noreferrer">
{{ ux_icon('simple-icons:github', {width: 18, height: 18, class: 'me-2'}) }}
<span>See example</span>
{{ ux_icon('tabler:arrow-up-right', {width: 18, height: 18, class: 'ms-2'}) }}
</a>
</div>
<div class="col-lg-7">
<pre class="terminal"><code><span class="comment">// Text to Speech</span>
<span class="variable">$result</span> = <span class="variable">$platform</span>-&gt;<span class="title function_ invoke__">invoke</span>(<span class="string">'eleven_multilingual_v2'</span>, <span class="keyword">new</span> <span class="title class_">Text</span>(<span class="string">'Hello!'</span>), [
<span class="string">'voice'</span> =&gt; <span class="string">'pqHfZKP75CvOlQylNhV4'</span>,
]);
<span class="variable">$result</span>-&gt;<span class="title function_ invoke__">asFile</span>(<span class="string">'output.mp3'</span>);
<span class="comment">// Speech to Text</span>
<span class="variable">$result</span> = <span class="variable">$platform</span>-&gt;<span class="title function_ invoke__">invoke</span>(<span class="string">'scribe_v1'</span>, <span class="title class_">Audio</span>::<span class="title function_ invoke__">fromFile</span>(<span class="string">'recording.mp3'</span>));
<span class="keyword">echo</span> <span class="variable">$result</span>-&gt;<span class="title function_ invoke__">asText</span>();</code></pre>
</div>
</div>
</div>
{# Multi-Modal #}
<div class="feature-panel" data-feature-tabs-target="panel">
<div class="row align-items-center g-4">
<div class="col-lg-5">
<h3 class="ff-title fw-bold h4 mb-3">Multi-Modal</h3>
<p class="text-muted mb-4">
Send images, PDFs, and audio alongside text to any supported model.
Build apps that can analyze photos, extract data from documents, or process
voice recordings — all through the same simple API.
</p>
<a href="https://github.com/symfony/ai/blob/main/examples/openai/image-input-binary.php" class="btn btn-dark px-3 d-inline-flex align-items-center" target="_blank" rel="noopener noreferrer">
{{ ux_icon('simple-icons:github', {width: 18, height: 18, class: 'me-2'}) }}
<span>See example</span>
{{ ux_icon('tabler:arrow-up-right', {width: 18, height: 18, class: 'ms-2'}) }}
</a>
</div>
<div class="col-lg-7">
<pre class="terminal"><code><span class="variable">$messages</span> = <span class="keyword">new</span> <span class="title class_">MessageBag</span>(
<span class="title class_">Message</span>::<span class="title function_ invoke__">ofUser</span>(
<span class="string">'Describe this image'</span>,
<span class="title class_">Image</span>::<span class="title function_ invoke__">fromFile</span>(<span class="string">'/path/to/photo.jpg'</span>),
),
);
<span class="variable">$result</span> = <span class="variable">$platform</span>-&gt;<span class="title function_ invoke__">invoke</span>(<span class="string">'gpt-5-mini'</span>, <span class="variable">$messages</span>);
<span class="keyword">echo</span> <span class="variable">$result</span>-&gt;<span class="title function_ invoke__">asText</span>();</code></pre>
</div>
</div>
</div>
{# Structured Output #}
<div class="feature-panel" data-feature-tabs-target="panel">
<div class="row align-items-center g-4">
<div class="col-lg-5">
<h3 class="ff-title fw-bold h4 mb-3">Structured Output</h3>
<p class="text-muted mb-4">
Map AI responses directly to PHP objects with automatic deserialization.
Instead of parsing JSON strings yourself, get type-safe PHP objects back from the model — ready to use in your application logic.
</p>
<a href="https://github.com/symfony/ai/blob/main/examples/openai/structured-output-math.php" class="btn btn-dark px-3 d-inline-flex align-items-center" target="_blank" rel="noopener noreferrer">
{{ ux_icon('simple-icons:github', {width: 18, height: 18, class: 'me-2'}) }}
<span>See example</span>
{{ ux_icon('tabler:arrow-up-right', {width: 18, height: 18, class: 'ms-2'}) }}
</a>
</div>
<div class="col-lg-7">
<pre class="terminal"><code><span class="variable">$messages</span> = <span class="keyword">new</span> <span class="title class_">MessageBag</span>(
<span class="title class_">Message</span>::<span class="title function_ invoke__">forSystem</span>(<span class="string">'You are a helpful math tutor.'</span>),
<span class="title class_">Message</span>::<span class="title function_ invoke__">ofUser</span>(<span class="string">'Solve 8x + 7 = -23'</span>),
);
<span class="variable">$result</span> = <span class="variable">$platform</span>-&gt;<span class="title function_ invoke__">invoke</span>(<span class="string">'gpt-5-mini'</span>, <span class="variable">$messages</span>, [
<span class="string">'response_format'</span> =&gt; <span class="title class_">MathReasoning</span>::<span class="keyword">class</span>,
]);
<span class="variable">$math</span> = <span class="variable">$result</span>-&gt;<span class="title function_ invoke__">asObject</span>(); <span class="comment">// MathReasoning instance</span></code></pre>
</div>
</div>
</div>
{# Agents #}
<div class="feature-panel" data-feature-tabs-target="panel">
<div class="row align-items-center g-4">
<div class="col-lg-5">
<h3 class="ff-title fw-bold h4 mb-3">Agents</h3>
<p class="text-muted mb-4">
Build autonomous agents that reason, plan, and execute multi-step tasks.
An Agent wraps a model with tools and processors, handling the full loop of calling tools, reading results, and deciding what to do next — until the task is complete.
</p>
<a href="https://github.com/symfony/ai/blob/main/examples/openai/agent.php" class="btn btn-dark px-3 d-inline-flex align-items-center" target="_blank" rel="noopener noreferrer">
{{ ux_icon('simple-icons:github', {width: 18, height: 18, class: 'me-2'}) }}
<span>See example</span>
{{ ux_icon('tabler:arrow-up-right', {width: 18, height: 18, class: 'ms-2'}) }}
</a>
</div>
<div class="col-lg-7">
<pre class="terminal"><code><span class="variable">$agent</span> = <span class="keyword">new</span> <span class="title class_">Agent</span>(<span class="variable">$platform</span>, <span class="string">'gpt-5-mini'</span>);
<span class="variable">$messages</span> = <span class="keyword">new</span> <span class="title class_">MessageBag</span>(
<span class="title class_">Message</span>::<span class="title function_ invoke__">forSystem</span>(<span class="string">'You are a helpful assistant.'</span>),
<span class="title class_">Message</span>::<span class="title function_ invoke__">ofUser</span>(<span class="string">'What is the Symfony framework?'</span>),
);
<span class="variable">$result</span> = <span class="variable">$agent</span>-&gt;<span class="title function_ invoke__">call</span>(<span class="variable">$messages</span>);
<span class="keyword">echo</span> <span class="variable">$result</span>-&gt;<span class="title function_ invoke__">getContent</span>();</code></pre>
</div>
</div>
</div>
{# Token Usage #}
<div class="feature-panel" data-feature-tabs-target="panel">
<div class="row align-items-center g-4">
<div class="col-lg-5">
<h3 class="ff-title fw-bold h4 mb-3">Token Usage</h3>
<p class="text-muted mb-4">
Track exactly how many tokens each request consumes — prompt, completion, and total.
Essential for monitoring costs, optimizing prompts, and staying within budget when running AI features in production.
</p>
<a href="https://github.com/symfony/ai/blob/main/examples/openai/token-metadata.php" class="btn btn-dark px-3 d-inline-flex align-items-center" target="_blank" rel="noopener noreferrer">
{{ ux_icon('simple-icons:github', {width: 18, height: 18, class: 'me-2'}) }}
<span>See example</span>
{{ ux_icon('tabler:arrow-up-right', {width: 18, height: 18, class: 'ms-2'}) }}
</a>
</div>
<div class="col-lg-7">
<pre class="terminal"><code><span class="variable">$result</span> = <span class="variable">$agent</span>-&gt;<span class="title function_ invoke__">call</span>(<span class="variable">$messages</span>);
<span class="variable">$usage</span> = <span class="variable">$result</span>-&gt;<span class="title function_ invoke__">getMetadata</span>()-&gt;<span class="title function_ invoke__">get</span>(<span class="string">'token_usage'</span>);
<span class="keyword">echo</span> <span class="variable">$usage</span>-&gt;<span class="title function_ invoke__">getPromptTokens</span>();
<span class="keyword">echo</span> <span class="variable">$usage</span>-&gt;<span class="title function_ invoke__">getCompletionTokens</span>();
<span class="keyword">echo</span> <span class="variable">$usage</span>-&gt;<span class="title function_ invoke__">getTotalTokens</span>();</code></pre>
</div>
</div>
</div>
{# Tool Calling #}
<div class="feature-panel" data-feature-tabs-target="panel">
<div class="row align-items-center g-4">
<div class="col-lg-5">
<h3 class="ff-title fw-bold h4 mb-3">Tool Calling</h3>
<p class="text-muted mb-4">
Let AI models call your PHP functions to fetch data or trigger actions.
Define tools as simple classes — the framework handles schema generation, argument passing, and result formatting automatically.
</p>
<a href="https://github.com/symfony/ai/blob/main/examples/openai/toolcall.php" class="btn btn-dark px-3 d-inline-flex align-items-center" target="_blank" rel="noopener noreferrer">
{{ ux_icon('simple-icons:github', {width: 18, height: 18, class: 'me-2'}) }}
<span>See example</span>
{{ ux_icon('tabler:arrow-up-right', {width: 18, height: 18, class: 'ms-2'}) }}
</a>
</div>
<div class="col-lg-7">
<pre class="terminal"><code><span class="variable">$toolbox</span> = <span class="keyword">new</span> <span class="title class_">Toolbox</span>([<span class="keyword">new</span> <span class="title class_">YoutubeTranscriber</span>(<span class="title function_ invoke__">http_client</span>())]);
<span class="variable">$processor</span> = <span class="keyword">new</span> <span class="title class_">AgentProcessor</span>(<span class="variable">$toolbox</span>);
<span class="variable">$agent</span> = <span class="keyword">new</span> <span class="title class_">Agent</span>(<span class="variable">$platform</span>, <span class="string">'gpt-5-mini'</span>, [<span class="variable">$processor</span>], [<span class="variable">$processor</span>]);
<span class="variable">$result</span> = <span class="variable">$agent</span>-&gt;<span class="title function_ invoke__">call</span>(<span class="variable">$messages</span>);</code></pre>
</div>
</div>
</div>
{# Subagents #}
<div class="feature-panel" data-feature-tabs-target="panel">
<div class="row align-items-center g-4">
<div class="col-lg-5">
<h3 class="ff-title fw-bold h4 mb-3">Subagents</h3>
<p class="text-muted mb-4">
Compose complex workflows by using agents as tools for other agents.
A coordinator agent can delegate specialized tasks — like math, research, or translation — to focused subagents, each with their own model and instructions.
</p>
<a href="https://github.com/symfony/ai/blob/main/examples/openai/agent-as-tool.php" class="btn btn-dark px-3 d-inline-flex align-items-center" target="_blank" rel="noopener noreferrer">
{{ ux_icon('simple-icons:github', {width: 18, height: 18, class: 'me-2'}) }}
<span>See example</span>
{{ ux_icon('tabler:arrow-up-right', {width: 18, height: 18, class: 'ms-2'}) }}
</a>
</div>
<div class="col-lg-7">
<pre class="terminal"><code><span class="variable">$mathAgent</span> = <span class="keyword">new</span> <span class="title class_">Agent</span>(<span class="variable">$platform</span>, <span class="string">'gpt-5.2'</span>, [<span class="variable">$mathPrompt</span>]);
<span class="variable">$subagent</span> = <span class="keyword">new</span> <span class="title class_">Subagent</span>(<span class="variable">$mathAgent</span>);
<span class="variable">$toolbox</span> = <span class="keyword">new</span> <span class="title class_">Toolbox</span>([<span class="variable">$subagent</span>]);
<span class="variable">$processor</span> = <span class="keyword">new</span> <span class="title class_">AgentProcessor</span>(<span class="variable">$toolbox</span>);
<span class="variable">$agent</span> = <span class="keyword">new</span> <span class="title class_">Agent</span>(<span class="variable">$platform</span>, <span class="string">'gpt-5-mini'</span>, [<span class="variable">$processor</span>], [<span class="variable">$processor</span>]);
<span class="variable">$result</span> = <span class="variable">$agent</span>-&gt;<span class="title function_ invoke__">call</span>(<span class="variable">$messages</span>);</code></pre>
</div>
</div>
</div>
{# RAG #}
<div class="feature-panel" data-feature-tabs-target="panel">
<div class="row align-items-center g-4">
<div class="col-lg-5">
<h3 class="ff-title fw-bold h4 mb-3">RAG</h3>
<p class="text-muted mb-4">
Index documents into vector stores and retrieve relevant context automatically.
Let your AI answer questions about your own data — manuals, blog posts, knowledge bases — by finding the most relevant passages before generating a response.
</p>
<a href="https://github.com/symfony/ai/blob/main/examples/rag/in-memory.php" class="btn btn-dark px-3 d-inline-flex align-items-center" target="_blank" rel="noopener noreferrer">
{{ ux_icon('simple-icons:github', {width: 18, height: 18, class: 'me-2'}) }}
<span>See example</span>
{{ ux_icon('tabler:arrow-up-right', {width: 18, height: 18, class: 'ms-2'}) }}
</a>
</div>
<div class="col-lg-7">
<pre class="terminal"><code><span class="variable">$vectorizer</span> = <span class="keyword">new</span> <span class="title class_">Vectorizer</span>(<span class="variable">$platform</span>, <span class="string">'text-embedding-3-small'</span>);
<span class="variable">$processor</span> = <span class="keyword">new</span> <span class="title class_">DocumentProcessor</span>(<span class="variable">$vectorizer</span>, <span class="variable">$store</span>);
<span class="variable">$indexer</span> = <span class="keyword">new</span> <span class="title class_">SourceIndexer</span>(<span class="variable">$loader</span>, <span class="variable">$processor</span>);
<span class="variable">$indexer</span>-&gt;<span class="title function_ invoke__">index</span>([<span class="string">'/path/to/docs'</span>]);
<span class="variable">$retriever</span> = <span class="keyword">new</span> <span class="title class_">Retriever</span>(<span class="variable">$vectorizer</span>, <span class="variable">$store</span>);
<span class="variable">$docs</span> = <span class="variable">$retriever</span>-&gt;<span class="title function_ invoke__">retrieve</span>(<span class="string">'How do I create a command?'</span>);</code></pre>
</div>
</div>
</div>
</div>
</section>