diff --git a/examples/anthropic/structured-output-clock.php b/examples/anthropic/structured-output-clock.php new file mode 100644 index 000000000..af1b9e131 --- /dev/null +++ b/examples/anthropic/structured-output-clock.php @@ -0,0 +1,53 @@ + + * + * 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\Anthropic\PlatformFactory; +use Symfony\AI\Platform\Message\Message; +use Symfony\AI\Platform\Message\MessageBag; +use Symfony\AI\Platform\StructuredOutput\PlatformSubscriber; +use Symfony\Component\Clock\Clock as SymfonyClock; +use Symfony\Component\EventDispatcher\EventDispatcher; + +require_once dirname(__DIR__).'/bootstrap.php'; + +$dispatcher = new EventDispatcher(); +$dispatcher->addSubscriber(new PlatformSubscriber()); + +$platform = PlatformFactory::create(env('ANTHROPIC_API_KEY'), http_client(), eventDispatcher: $dispatcher); + +$clock = new Clock(new SymfonyClock()); +$toolbox = new Toolbox([$clock], logger: logger()); +$toolProcessor = new AgentProcessor($toolbox); +$agent = new Agent($platform, 'claude-sonnet-4-5-20250929', [$toolProcessor], [$toolProcessor]); + +$messages = new MessageBag(Message::ofUser('What date and time is it?')); +$result = $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($result->getContent()); diff --git a/examples/anthropic/structured-output-math.php b/examples/anthropic/structured-output-math.php new file mode 100644 index 000000000..66f56fbba --- /dev/null +++ b/examples/anthropic/structured-output-math.php @@ -0,0 +1,32 @@ + + * + * For the full copyright and license information, please view the LICENSE + * file that was distributed with this source code. + */ + +use Symfony\AI\Fixtures\StructuredOutput\MathReasoning; +use Symfony\AI\Platform\Bridge\Anthropic\PlatformFactory; +use Symfony\AI\Platform\Message\Message; +use Symfony\AI\Platform\Message\MessageBag; +use Symfony\AI\Platform\StructuredOutput\PlatformSubscriber; +use Symfony\Component\EventDispatcher\EventDispatcher; + +require_once dirname(__DIR__).'/bootstrap.php'; + +$dispatcher = new EventDispatcher(); +$dispatcher->addSubscriber(new PlatformSubscriber()); + +$platform = PlatformFactory::create(env('ANTHROPIC_API_KEY'), http_client(), eventDispatcher: $dispatcher); +$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'), +); + +$result = $platform->invoke('claude-sonnet-4-5-20250929', $messages, ['response_format' => MathReasoning::class]); + +dump($result->asObject()); diff --git a/src/platform/src/Bridge/Anthropic/ModelClient.php b/src/platform/src/Bridge/Anthropic/ModelClient.php index ff4572fba..39b3d9d09 100644 --- a/src/platform/src/Bridge/Anthropic/ModelClient.php +++ b/src/platform/src/Bridge/Anthropic/ModelClient.php @@ -47,6 +47,15 @@ public function request(Model $model, array|string $payload, array $options = [] $options['tool_choice'] = ['type' => 'auto']; } + if (isset($options['response_format'])) { + $options['beta_features'][] = 'structured-outputs-2025-11-13'; + $options['output_format'] = [ + 'type' => 'json_schema', + 'schema' => $options['response_format']['json_schema']['schema'] ?? [], + ]; + unset($options['response_format']); + } + if (isset($options['beta_features']) && \is_array($options['beta_features']) && \count($options['beta_features']) > 0) { $headers['anthropic-beta'] = implode(',', $options['beta_features']); unset($options['beta_features']);