diff --git a/src/platform/src/Bridge/OpenAi/Gpt/ResultConverter.php b/src/platform/src/Bridge/OpenAi/Gpt/ResultConverter.php index d571489f9..8b502204f 100644 --- a/src/platform/src/Bridge/OpenAi/Gpt/ResultConverter.php +++ b/src/platform/src/Bridge/OpenAi/Gpt/ResultConverter.php @@ -13,6 +13,7 @@ use Symfony\AI\Platform\Bridge\OpenAi\Gpt; use Symfony\AI\Platform\Exception\AuthenticationException; +use Symfony\AI\Platform\Exception\BadRequestException; use Symfony\AI\Platform\Exception\ContentFilterException; use Symfony\AI\Platform\Exception\RateLimitExceededException; use Symfony\AI\Platform\Exception\RuntimeException; @@ -50,6 +51,11 @@ public function convert(RawResultInterface|RawHttpResult $result, array $options throw new AuthenticationException($errorMessage); } + if (400 === $response->getStatusCode()) { + $errorMessage = json_decode($response->getContent(false), true)['error']['message'] ?? 'Bad Request'; + throw new BadRequestException($errorMessage); + } + if (429 === $response->getStatusCode()) { $headers = $response->getHeaders(false); $resetTime = null; diff --git a/src/platform/src/Exception/BadRequestException.php b/src/platform/src/Exception/BadRequestException.php new file mode 100644 index 000000000..f2aa1bd9a --- /dev/null +++ b/src/platform/src/Exception/BadRequestException.php @@ -0,0 +1,19 @@ + + * + * For the full copyright and license information, please view the LICENSE + * file that was distributed with this source code. + */ + +namespace Symfony\AI\Platform\Exception; + +/** + * @author Oscar Esteve + */ +class BadRequestException extends RuntimeException +{ +} diff --git a/src/platform/tests/Bridge/OpenAi/Gpt/ResultConverterTest.php b/src/platform/tests/Bridge/OpenAi/Gpt/ResultConverterTest.php index dfec86332..185c47e1e 100644 --- a/src/platform/tests/Bridge/OpenAi/Gpt/ResultConverterTest.php +++ b/src/platform/tests/Bridge/OpenAi/Gpt/ResultConverterTest.php @@ -14,6 +14,7 @@ use PHPUnit\Framework\TestCase; use Symfony\AI\Platform\Bridge\OpenAi\Gpt\ResultConverter; use Symfony\AI\Platform\Exception\AuthenticationException; +use Symfony\AI\Platform\Exception\BadRequestException; use Symfony\AI\Platform\Exception\ContentFilterException; use Symfony\AI\Platform\Exception\RuntimeException; use Symfony\AI\Platform\Result\ChoiceResult; @@ -196,4 +197,33 @@ public function testThrowsExceptionForUnsupportedFinishReason() $converter->convert(new RawHttpResult($httpResponse)); } + + public function testThrowsBadRequestExceptionOnBadRequestResponse() + { + $converter = new ResultConverter(); + $httpResponse = self::createMock(ResponseInterface::class); + $httpResponse->method('getStatusCode')->willReturn(400); + $httpResponse->method('getContent')->willReturn(json_encode([ + 'error' => [ + 'message' => 'Bad Request: invalid parameters', + ], + ])); + + $this->expectException(BadRequestException::class); + $this->expectExceptionMessage('Bad Request: invalid parameters'); + + $converter->convert(new RawHttpResult($httpResponse)); + } + + public function testThrowsBadRequestExceptionOnBadRequestResponseWithNoResponseBody() + { + $converter = new ResultConverter(); + $httpResponse = self::createMock(ResponseInterface::class); + $httpResponse->method('getStatusCode')->willReturn(400); + + $this->expectException(BadRequestException::class); + $this->expectExceptionMessage('Bad Request'); + + $converter->convert(new RawHttpResult($httpResponse)); + } }