Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
2 changes: 1 addition & 1 deletion examples/bedrock/chat-claude.php
Original file line number Diff line number Diff line change
Expand Up @@ -26,7 +26,7 @@
}

$platform = PlatformFactory::create();
$model = new Claude();
$model = new Claude('claude-3-7-sonnet-20250219');

$agent = new Agent($platform, $model);
$messages = new MessageBag(
Expand Down
2 changes: 1 addition & 1 deletion examples/bedrock/image-claude-binary.php
Original file line number Diff line number Diff line change
Expand Up @@ -27,7 +27,7 @@
}

$platform = PlatformFactory::create();
$model = new Claude();
$model = new Claude('claude-3-7-sonnet-20250219');

$agent = new Agent($platform, $model);
$messages = new MessageBag(
Expand Down
2 changes: 1 addition & 1 deletion examples/bedrock/toolcall-claude.php
Original file line number Diff line number Diff line change
Expand Up @@ -30,7 +30,7 @@
}

$platform = PlatformFactory::create();
$model = new Claude();
$model = new Claude('claude-3-7-sonnet-20250219');

$wikipedia = new Wikipedia(HttpClient::create());
$toolbox = Toolbox::create($wikipedia);
Expand Down
9 changes: 5 additions & 4 deletions src/platform/src/Bridge/Albert/EmbeddingsModelClient.php
Original file line number Diff line number Diff line change
Expand Up @@ -15,8 +15,9 @@
use Symfony\AI\Platform\Exception\InvalidArgumentException;
use Symfony\AI\Platform\Model;
use Symfony\AI\Platform\ModelClientInterface;
use Symfony\AI\Platform\Response\RawHttpResponse;
use Symfony\AI\Platform\Response\RawResponseInterface;
use Symfony\Contracts\HttpClient\HttpClientInterface;
use Symfony\Contracts\HttpClient\ResponseInterface;

/**
* @author Oskar Stark <oskarstark@googlemail.com>
Expand All @@ -37,11 +38,11 @@ public function supports(Model $model): bool
return $model instanceof Embeddings;
}

public function request(Model $model, array|string $payload, array $options = []): ResponseInterface
public function request(Model $model, array|string $payload, array $options = []): RawResponseInterface
{
return $this->httpClient->request('POST', \sprintf('%s/embeddings', $this->baseUrl), [
return new RawHttpResponse($this->httpClient->request('POST', \sprintf('%s/embeddings', $this->baseUrl), [
'auth_bearer' => $this->apiKey,
'json' => \is_array($payload) ? array_merge($payload, $options) : $payload,
]);
]));
}
}
9 changes: 5 additions & 4 deletions src/platform/src/Bridge/Albert/GPTModelClient.php
Original file line number Diff line number Diff line change
Expand Up @@ -15,9 +15,10 @@
use Symfony\AI\Platform\Exception\InvalidArgumentException;
use Symfony\AI\Platform\Model;
use Symfony\AI\Platform\ModelClientInterface;
use Symfony\AI\Platform\Response\RawHttpResponse;
use Symfony\AI\Platform\Response\RawResponseInterface;
use Symfony\Component\HttpClient\EventSourceHttpClient;
use Symfony\Contracts\HttpClient\HttpClientInterface;
use Symfony\Contracts\HttpClient\ResponseInterface;

/**
* @author Oskar Stark <oskarstark@googlemail.com>
Expand All @@ -42,11 +43,11 @@ public function supports(Model $model): bool
return $model instanceof GPT;
}

public function request(Model $model, array|string $payload, array $options = []): ResponseInterface
public function request(Model $model, array|string $payload, array $options = []): RawResponseInterface
{
return $this->httpClient->request('POST', \sprintf('%s/chat/completions', $this->baseUrl), [
return new RawHttpResponse($this->httpClient->request('POST', \sprintf('%s/chat/completions', $this->baseUrl), [
'auth_bearer' => $this->apiKey,
'json' => \is_array($payload) ? array_merge($payload, $options) : $payload,
]);
]));
}
}
8 changes: 4 additions & 4 deletions src/platform/src/Bridge/Anthropic/ModelClient.php
Original file line number Diff line number Diff line change
Expand Up @@ -13,9 +13,9 @@

use Symfony\AI\Platform\Model;
use Symfony\AI\Platform\ModelClientInterface;
use Symfony\AI\Platform\Response\RawHttpResponse;
use Symfony\Component\HttpClient\EventSourceHttpClient;
use Symfony\Contracts\HttpClient\HttpClientInterface;
use Symfony\Contracts\HttpClient\ResponseInterface;

/**
* @author Christopher Hertel <mail@christopher-hertel.de>
Expand All @@ -37,18 +37,18 @@ public function supports(Model $model): bool
return $model instanceof Claude;
}

public function request(Model $model, array|string $payload, array $options = []): ResponseInterface
public function request(Model $model, array|string $payload, array $options = []): RawHttpResponse
{
if (isset($options['tools'])) {
$options['tool_choice'] = ['type' => 'auto'];
}

return $this->httpClient->request('POST', 'https://api.anthropic.com/v1/messages', [
return new RawHttpResponse($this->httpClient->request('POST', 'https://api.anthropic.com/v1/messages', [
'headers' => [
'x-api-key' => $this->apiKey,
'anthropic-version' => $this->version,
],
'json' => array_merge($options, $payload),
]);
]));
}
}
14 changes: 8 additions & 6 deletions src/platform/src/Bridge/Anthropic/ResponseConverter.php
Original file line number Diff line number Diff line change
Expand Up @@ -13,7 +13,9 @@

use Symfony\AI\Platform\Exception\RuntimeException;
use Symfony\AI\Platform\Model;
use Symfony\AI\Platform\Response\ResponseInterface as LlmResponse;
use Symfony\AI\Platform\Response\RawHttpResponse;
use Symfony\AI\Platform\Response\RawResponseInterface;
use Symfony\AI\Platform\Response\ResponseInterface;
use Symfony\AI\Platform\Response\StreamResponse;
use Symfony\AI\Platform\Response\TextResponse;
use Symfony\AI\Platform\Response\ToolCall;
Expand All @@ -22,7 +24,7 @@
use Symfony\Component\HttpClient\Chunk\ServerSentEvent;
use Symfony\Component\HttpClient\EventSourceHttpClient;
use Symfony\Component\HttpClient\Exception\JsonException;
use Symfony\Contracts\HttpClient\ResponseInterface;
use Symfony\Contracts\HttpClient\ResponseInterface as HttpResponse;

/**
* @author Christopher Hertel <mail@christopher-hertel.de>
Expand All @@ -34,13 +36,13 @@ public function supports(Model $model): bool
return $model instanceof Claude;
}

public function convert(ResponseInterface $response, array $options = []): LlmResponse
public function convert(RawHttpResponse|RawResponseInterface $response, array $options = []): ResponseInterface
{
if ($options['stream'] ?? false) {
return new StreamResponse($this->convertStream($response));
return new StreamResponse($this->convertStream($response->getRawObject()));
}

$data = $response->toArray();
$data = $response->getRawData();

if (!isset($data['content']) || [] === $data['content']) {
throw new RuntimeException('Response does not contain any content');
Expand All @@ -64,7 +66,7 @@ public function convert(ResponseInterface $response, array $options = []): LlmRe
return new TextResponse($data['content'][0]['text']);
}

private function convertStream(ResponseInterface $response): \Generator
private function convertStream(HttpResponse $response): \Generator
{
foreach ((new EventSourceHttpClient())->stream($response) as $chunk) {
if (!$chunk instanceof ServerSentEvent || '[DONE]' === $chunk->getData()) {
Expand Down
8 changes: 4 additions & 4 deletions src/platform/src/Bridge/Azure/Meta/LlamaModelClient.php
Original file line number Diff line number Diff line change
Expand Up @@ -14,8 +14,8 @@
use Symfony\AI\Platform\Bridge\Meta\Llama;
use Symfony\AI\Platform\Model;
use Symfony\AI\Platform\ModelClientInterface;
use Symfony\AI\Platform\Response\RawHttpResponse;
use Symfony\Contracts\HttpClient\HttpClientInterface;
use Symfony\Contracts\HttpClient\ResponseInterface;

/**
* @author Christopher Hertel <mail@christopher-hertel.de>
Expand All @@ -34,16 +34,16 @@ public function supports(Model $model): bool
return $model instanceof Llama;
}

public function request(Model $model, array|string $payload, array $options = []): ResponseInterface
public function request(Model $model, array|string $payload, array $options = []): RawHttpResponse
{
$url = \sprintf('https://%s/chat/completions', $this->baseUrl);

return $this->httpClient->request('POST', $url, [
return new RawHttpResponse($this->httpClient->request('POST', $url, [
'headers' => [
'Content-Type' => 'application/json',
'Authorization' => $this->apiKey,
],
'json' => array_merge($options, $payload),
]);
]));
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -14,10 +14,9 @@
use Symfony\AI\Platform\Bridge\Meta\Llama;
use Symfony\AI\Platform\Exception\RuntimeException;
use Symfony\AI\Platform\Model;
use Symfony\AI\Platform\Response\ResponseInterface as LlmResponse;
use Symfony\AI\Platform\Response\RawResponseInterface;
use Symfony\AI\Platform\Response\TextResponse;
use Symfony\AI\Platform\ResponseConverterInterface;
use Symfony\Contracts\HttpClient\ResponseInterface;

/**
* @author Christopher Hertel <mail@christopher-hertel.de>
Expand All @@ -29,9 +28,9 @@ public function supports(Model $model): bool
return $model instanceof Llama;
}

public function convert(ResponseInterface $response, array $options = []): LlmResponse
public function convert(RawResponseInterface $response, array $options = []): TextResponse
{
$data = $response->toArray();
$data = $response->getRawData();

if (!isset($data['choices'][0]['message']['content'])) {
throw new RuntimeException('Response does not contain output');
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -15,9 +15,9 @@
use Symfony\AI\Platform\Exception\InvalidArgumentException;
use Symfony\AI\Platform\Model;
use Symfony\AI\Platform\ModelClientInterface;
use Symfony\AI\Platform\Response\RawHttpResponse;
use Symfony\Component\HttpClient\EventSourceHttpClient;
use Symfony\Contracts\HttpClient\HttpClientInterface;
use Symfony\Contracts\HttpClient\ResponseInterface;

/**
* @author Christopher Hertel <mail@christopher-hertel.de>
Expand Down Expand Up @@ -46,11 +46,11 @@ public function supports(Model $model): bool
return $model instanceof Embeddings;
}

public function request(Model $model, array|string $payload, array $options = []): ResponseInterface
public function request(Model $model, array|string $payload, array $options = []): RawHttpResponse
{
$url = \sprintf('https://%s/openai/deployments/%s/embeddings', $this->baseUrl, $this->deployment);

return $this->httpClient->request('POST', $url, [
return new RawHttpResponse($this->httpClient->request('POST', $url, [
'headers' => [
'api-key' => $this->apiKey,
],
Expand All @@ -59,6 +59,6 @@ public function request(Model $model, array|string $payload, array $options = []
'model' => $model->getName(),
'input' => $payload,
]),
]);
]));
}
}
8 changes: 4 additions & 4 deletions src/platform/src/Bridge/Azure/OpenAI/GPTModelClient.php
Original file line number Diff line number Diff line change
Expand Up @@ -15,9 +15,9 @@
use Symfony\AI\Platform\Exception\InvalidArgumentException;
use Symfony\AI\Platform\Model;
use Symfony\AI\Platform\ModelClientInterface;
use Symfony\AI\Platform\Response\RawHttpResponse;
use Symfony\Component\HttpClient\EventSourceHttpClient;
use Symfony\Contracts\HttpClient\HttpClientInterface;
use Symfony\Contracts\HttpClient\ResponseInterface;

/**
* @author Christopher Hertel <mail@christopher-hertel.de>
Expand Down Expand Up @@ -46,16 +46,16 @@ public function supports(Model $model): bool
return $model instanceof GPT;
}

public function request(Model $model, object|array|string $payload, array $options = []): ResponseInterface
public function request(Model $model, object|array|string $payload, array $options = []): RawHttpResponse
{
$url = \sprintf('https://%s/openai/deployments/%s/chat/completions', $this->baseUrl, $this->deployment);

return $this->httpClient->request('POST', $url, [
return new RawHttpResponse($this->httpClient->request('POST', $url, [
'headers' => [
'api-key' => $this->apiKey,
],
'query' => ['api-version' => $this->apiVersion],
'json' => array_merge($options, $payload),
]);
]));
}
}
8 changes: 4 additions & 4 deletions src/platform/src/Bridge/Azure/OpenAI/WhisperModelClient.php
Original file line number Diff line number Diff line change
Expand Up @@ -16,9 +16,9 @@
use Symfony\AI\Platform\Exception\InvalidArgumentException;
use Symfony\AI\Platform\Model;
use Symfony\AI\Platform\ModelClientInterface;
use Symfony\AI\Platform\Response\RawHttpResponse;
use Symfony\Component\HttpClient\EventSourceHttpClient;
use Symfony\Contracts\HttpClient\HttpClientInterface;
use Symfony\Contracts\HttpClient\ResponseInterface;

/**
* @author Christopher Hertel <mail@christopher-hertel.de>
Expand Down Expand Up @@ -47,21 +47,21 @@ public function supports(Model $model): bool
return $model instanceof Whisper;
}

public function request(Model $model, array|string $payload, array $options = []): ResponseInterface
public function request(Model $model, array|string $payload, array $options = []): RawHttpResponse
{
$task = $options['task'] ?? Task::TRANSCRIPTION;
$endpoint = Task::TRANSCRIPTION === $task ? 'transcriptions' : 'translations';
$url = \sprintf('https://%s/openai/deployments/%s/audio/%s', $this->baseUrl, $this->deployment, $endpoint);

unset($options['task']);

return $this->httpClient->request('POST', $url, [
return new RawHttpResponse($this->httpClient->request('POST', $url, [
'headers' => [
'api-key' => $this->apiKey,
'Content-Type' => 'multipart/form-data',
],
'query' => ['api-version' => $this->apiVersion],
'body' => array_merge($options, $payload),
]);
]));
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -15,17 +15,18 @@
use AsyncAws\BedrockRuntime\Input\InvokeModelRequest;
use AsyncAws\BedrockRuntime\Result\InvokeModelResponse;
use Symfony\AI\Platform\Bridge\Anthropic\Claude;
use Symfony\AI\Platform\Bridge\Bedrock\BedrockModelClient;
use Symfony\AI\Platform\Bridge\Bedrock\RawBedrockResponse;
use Symfony\AI\Platform\Exception\RuntimeException;
use Symfony\AI\Platform\Model;
use Symfony\AI\Platform\ModelClientInterface;
use Symfony\AI\Platform\Response\TextResponse;
use Symfony\AI\Platform\Response\ToolCall;
use Symfony\AI\Platform\Response\ToolCallResponse;

/**
* @author Björn Altmann
*/
final readonly class ClaudeHandler implements BedrockModelClient
final readonly class ClaudeModelClient implements ModelClientInterface
{
public function __construct(
private BedrockRuntimeClient $bedrockRuntimeClient,
Expand All @@ -38,7 +39,7 @@ public function supports(Model $model): bool
return $model instanceof Claude;
}

public function request(Model $model, array|string $payload, array $options = []): InvokeModelResponse
public function request(Model $model, array|string $payload, array $options = []): RawBedrockResponse
{
unset($payload['model']);

Expand All @@ -56,7 +57,7 @@ public function request(Model $model, array|string $payload, array $options = []
'body' => json_encode(array_merge($options, $payload), \JSON_THROW_ON_ERROR),
];

return $this->bedrockRuntimeClient->invokeModel(new InvokeModelRequest($request));
return new RawBedrockResponse($this->bedrockRuntimeClient->invokeModel(new InvokeModelRequest($request)));
}

public function convert(InvokeModelResponse $bedrockResponse): ToolCallResponse|TextResponse
Expand Down
Loading