diff --git a/README.md b/README.md index 695d4f3ca..730ce2079 100644 --- a/README.md +++ b/README.md @@ -13,6 +13,7 @@ See full documentation on [https://async-aws.com](https://async-aws.com). | [async-aws/core](https://github.com/async-aws/core) | [![Latest Stable Version](https://poser.pugx.org/async-aws/core/v/stable)](https://packagist.org/packages/async-aws/core) [![Total Downloads](https://poser.pugx.org/async-aws/core/downloads)](https://packagist.org/packages/async-aws/core) | [![](https://github.com/async-aws/core/workflows/BC%20Check/badge.svg?branch=master)](https://github.com/async-aws/core/actions) | [![](https://async-aws-pr.github.io/commits-since-release-counter/core.svg)](https://github.com/async-aws/core/releases) | | [async-aws/app-sync](https://github.com/async-aws/app-sync) | [![Latest Stable Version](https://poser.pugx.org/async-aws/app-sync/v/stable)](https://packagist.org/packages/async-aws/app-sync) [![Total Downloads](https://poser.pugx.org/async-aws/app-sync/downloads)](https://packagist.org/packages/async-aws/app-sync) | [![](https://github.com/async-aws/app-sync/workflows/BC%20Check/badge.svg?branch=master)](https://github.com/async-aws/app-sync/actions) | [![](https://async-aws-pr.github.io/commits-since-release-counter/app-sync.svg)](https://github.com/async-aws/app-sync/releases) | | [async-aws/athena](https://github.com/async-aws/athena) | [![Latest Stable Version](https://poser.pugx.org/async-aws/athena/v/stable)](https://packagist.org/packages/async-aws/athena) [![Total Downloads](https://poser.pugx.org/async-aws/athena/downloads)](https://packagist.org/packages/async-aws/athena) | [![](https://github.com/async-aws/athena/workflows/BC%20Check/badge.svg?branch=master)](https://github.com/async-aws/athena/actions) | [![](https://async-aws-pr.github.io/commits-since-release-counter/athena.svg)](https://github.com/async-aws/athena/releases) | +| [async-aws/bedrock-runtime](https://github.com/async-aws/bedrock-runtime) | [![Latest Stable Version](https://poser.pugx.org/async-aws/bedrock-runtime/v/stable)](https://packagist.org/packages/async-aws/bedrock-runtime) [![Total Downloads](https://poser.pugx.org/async-aws/bedrock-runtime/downloads)](https://packagist.org/packages/async-aws/bedrock-runtime) | [![](https://github.com/async-aws/bedrock-runtime/workflows/BC%20Check/badge.svg?branch=master)](https://github.com/async-aws/bedrock-runtime/actions) | [![](https://async-aws-pr.github.io/commits-since-release-counter/bedrock-runtime.svg)](https://github.com/async-aws/bedrock-runtime/releases) | | [async-aws/cloud-formation](https://github.com/async-aws/cloud-formation) | [![Latest Stable Version](https://poser.pugx.org/async-aws/cloud-formation/v/stable)](https://packagist.org/packages/async-aws/cloud-formation) [![Total Downloads](https://poser.pugx.org/async-aws/cloud-formation/downloads)](https://packagist.org/packages/async-aws/cloud-formation) | [![](https://github.com/async-aws/cloud-formation/workflows/BC%20Check/badge.svg?branch=master)](https://github.com/async-aws/cloud-formation/actions) | [![](https://async-aws-pr.github.io/commits-since-release-counter/cloud-formation.svg)](https://github.com/async-aws/cloud-formation/releases) | | [async-aws/cloud-front](https://github.com/async-aws/cloud-front) | [![Latest Stable Version](https://poser.pugx.org/async-aws/cloud-front/v/stable)](https://packagist.org/packages/async-aws/cloud-front) [![Total Downloads](https://poser.pugx.org/async-aws/cloud-front/downloads)](https://packagist.org/packages/async-aws/cloud-front) | [![](https://github.com/async-aws/cloud-front/workflows/BC%20Check/badge.svg?branch=master)](https://github.com/async-aws/cloud-front/actions) | [![](https://async-aws-pr.github.io/commits-since-release-counter/cloud-front.svg)](https://github.com/async-aws/cloud-front/releases) | | [async-aws/cloud-watch](https://github.com/async-aws/cloud-watch) | [![Latest Stable Version](https://poser.pugx.org/async-aws/cloud-watch/v/stable)](https://packagist.org/packages/async-aws/cloud-watch) [![Total Downloads](https://poser.pugx.org/async-aws/cloud-watch/downloads)](https://packagist.org/packages/async-aws/cloud-watch) | [![](https://github.com/async-aws/cloud-watch/workflows/BC%20Check/badge.svg?branch=master)](https://github.com/async-aws/cloud-watch/actions) | [![](https://async-aws-pr.github.io/commits-since-release-counter/cloud-watch.svg)](https://github.com/async-aws/cloud-watch/releases) | @@ -46,7 +47,7 @@ See full documentation on [https://async-aws.com](https://async-aws.com). | [async-aws/sqs](https://github.com/async-aws/sqs) | [![Latest Stable Version](https://poser.pugx.org/async-aws/sqs/v/stable)](https://packagist.org/packages/async-aws/sqs) [![Total Downloads](https://poser.pugx.org/async-aws/sqs/downloads)](https://packagist.org/packages/async-aws/sqs) | [![](https://github.com/async-aws/sqs/workflows/BC%20Check/badge.svg?branch=master)](https://github.com/async-aws/sqs/actions) | [![](https://async-aws-pr.github.io/commits-since-release-counter/sqs.svg)](https://github.com/async-aws/sqs/releases) | | [async-aws/ssm](https://github.com/async-aws/ssm) | [![Latest Stable Version](https://poser.pugx.org/async-aws/ssm/v/stable)](https://packagist.org/packages/async-aws/ssm) [![Total Downloads](https://poser.pugx.org/async-aws/ssm/downloads)](https://packagist.org/packages/async-aws/ssm) | [![](https://github.com/async-aws/ssm/workflows/BC%20Check/badge.svg?branch=master)](https://github.com/async-aws/ssm/actions) | [![](https://async-aws-pr.github.io/commits-since-release-counter/ssm.svg)](https://github.com/async-aws/ssm/releases) | | [async-aws/sso](https://github.com/async-aws/sso) | [![Latest Stable Version](https://poser.pugx.org/async-aws/sso/v/stable)](https://packagist.org/packages/async-aws/sso) [![Total Downloads](https://poser.pugx.org/async-aws/sso/downloads)](https://packagist.org/packages/async-aws/sso) | [![](https://github.com/async-aws/sso/workflows/BC%20Check/badge.svg?branch=master)](https://github.com/async-aws/sso/actions) | [![](https://async-aws-pr.github.io/commits-since-release-counter/sso.svg)](https://github.com/async-aws/sso/releases) | -| [async-aws/sso-oidc](https://github.com/async-aws/sso-oidc) | [![Latest Stable Version](https://poser.pugx.org/async-aws/sso-oidc/v/stable)](https://packagist.org/packages/async-aws/sso-oidc) [![Total Downloads](https://poser.pugx.org/async-aws/sso-oidc/downloads)](https://packagist.org/packages/async-aws/sso-oidc) | [![](https://github.com/async-aws/sso-oidc/workflows/BC%20Check/badge.svg?branch=master)](https://github.com/async-aws/sso-oidc/actions) | [![](https://async-aws-pr.github.io/commits-since-release-counter/sso-oidc.svg)](https://github.com/async-aws/sso-oidc/releases) | +| [async-aws/sso-oidc](https://github.com/async-aws/sso-oidc) | [![Latest Stable Version](https://poser.pugx.org/async-aws/sso-oidc/v/stable)](https://packagist.org/packages/async-aws/sso-oidc) [![Total Downloads](https://poser.pugx.org/async-aws/sso-oidc/downloads)](https://packagist.org/packages/async-aws/sso-oidc) | [![](https://github.com/async-aws/sso-oidc/workflows/BC%20Check/badge.svg?branch=master)](https://github.com/async-aws/sso-oidc/actions) | [![](https://async-aws-pr.github.io/commits-since-release-counter/sso-oidc.svg)](https://github.com/async-aws/sso-oidc/releases) | | [async-aws/step-functions](https://github.com/async-aws/step-functions) | [![Latest Stable Version](https://poser.pugx.org/async-aws/step-functions/v/stable)](https://packagist.org/packages/async-aws/step-functions) [![Total Downloads](https://poser.pugx.org/async-aws/step-functions/downloads)](https://packagist.org/packages/async-aws/step-functions) | [![](https://github.com/async-aws/step-functions/workflows/BC%20Check/badge.svg?branch=master)](https://github.com/async-aws/step-functions/actions) | [![](https://async-aws-pr.github.io/commits-since-release-counter/step-functions.svg)](https://github.com/async-aws/step-functions/releases) | | [async-aws/timestream-query](https://github.com/async-aws/timestream-query) | [![Latest Stable Version](https://poser.pugx.org/async-aws/timestream-query/v/stable)](https://packagist.org/packages/async-aws/timestream-query) [![Total Downloads](https://poser.pugx.org/async-aws/timestream-query/downloads)](https://packagist.org/packages/async-aws/timestream-query) | [![](https://github.com/async-aws/timestream-query/workflows/BC%20Check/badge.svg?branch=master)](https://github.com/async-aws/timestream-query/actions) | [![](https://async-aws-pr.github.io/commits-since-release-counter/timestream-query.svg)](https://github.com/async-aws/timestream-query/releases) | | [async-aws/timestream-write](https://github.com/async-aws/timestream-write) | [![Latest Stable Version](https://poser.pugx.org/async-aws/timestream-write/v/stable)](https://packagist.org/packages/async-aws/timestream-write) [![Total Downloads](https://poser.pugx.org/async-aws/timestream-write/downloads)](https://packagist.org/packages/async-aws/timestream-write) | [![](https://github.com/async-aws/timestream-write/workflows/BC%20Check/badge.svg?branch=master)](https://github.com/async-aws/timestream-write/actions) | [![](https://async-aws-pr.github.io/commits-since-release-counter/timestream-write.svg)](https://github.com/async-aws/timestream-write/releases) | diff --git a/composer.json b/composer.json index 2ba32faee..8eba03ecf 100644 --- a/composer.json +++ b/composer.json @@ -49,6 +49,7 @@ "psr-4": { "AsyncAws\\AppSync\\": "src/Service/AppSync/src", "AsyncAws\\Athena\\": "src/Service/Athena/src", + "AsyncAws\\BedrockRuntime\\": "src/Service/BedrockRuntime/src", "AsyncAws\\CloudFormation\\": "src/Service/CloudFormation/src", "AsyncAws\\CloudFront\\": "src/Service/CloudFront/src", "AsyncAws\\CloudWatchLogs\\": "src/Service/CloudWatchLogs/src", @@ -102,6 +103,7 @@ "psr-4": { "AsyncAws\\AppSync\\Tests\\": "src/Service/AppSync/tests", "AsyncAws\\Athena\\Tests\\": "src/Service/Athena/tests", + "AsyncAws\\BedrockRuntime\\Tests\\": "src/Service/BedrockRuntime/tests", "AsyncAws\\CloudFormation\\Tests\\": "src/Service/CloudFormation/tests", "AsyncAws\\CloudFront\\Tests\\": "src/Service/CloudFront/tests", "AsyncAws\\CloudWatchLogs\\Tests\\": "src/Service/CloudWatchLogs/tests", diff --git a/couscous.yml b/couscous.yml index ca8a75ebf..3346ef5ed 100644 --- a/couscous.yml +++ b/couscous.yml @@ -37,6 +37,9 @@ menu: athena: text: Athena url: /clients/athena.html + bedrock-runtime: + text: Bedrock Runtime + url: /clients/bedrock-runtime.html cf: text: Cloud Formation url: /clients/cf.html diff --git a/docs/clients/bedrock-runtime.md b/docs/clients/bedrock-runtime.md new file mode 100644 index 000000000..f690ca3fc --- /dev/null +++ b/docs/clients/bedrock-runtime.md @@ -0,0 +1,43 @@ +--- +layout: client +category: clients +name: BedrockRuntime +package: async-aws/bedrock-runtime +--- + +## Usage + +### InvokeModel + +```php +use AsyncAws\BedrockRuntime\BedrockRuntimeClient; +use AsyncAws\BedrockRuntime\Input\InvokeModelRequest; + +$bedrockRuntime = new BedrockRuntimeClient(); + +$body = [ + 'anthropic_version' => 'bedrock-2023-05-31', + 'max_tokens' => 4096, + 'messages' => [ + [ + 'role' => 'user', + 'content' => [ + ['type' => 'text', 'text' => 'Write me a love poem.'] + ] + ] + ], + 'temperature' => 1 +]; + +$result = $bedrockRuntime->invokeModel(new InvokeModelRequest([ + 'modelId' => 'us.anthropic.claude-3-7-sonnet-20250219-v1:0', + 'contentType' => 'application/json', + 'body' => json_encode($body, JSON_THROW_ON_ERROR) +])); + +$response = json_decode($result->getBody(), true, 512, JSON_THROW_ON_ERROR); + +echo $response['content'][0]['text']; + +``` +more information [InvokeModel](https://docs.aws.amazon.com/bedrock/latest/APIReference/API_runtime_InvokeModel.html) diff --git a/docs/clients/index.md b/docs/clients/index.md index 8900799c4..e333d03b8 100644 --- a/docs/clients/index.md +++ b/docs/clients/index.md @@ -139,6 +139,7 @@ for more information. |---------------------------------------------|-----------------------------------------------------------------------------------------------------------| | [AppSync](./app-sync.md) | [async-aws/app-sync](https://packagist.org/packages/async-aws/app-sync) | | [Athena](./athena.md) | [async-aws/athena](https://packagist.org/packages/async-aws/athena) | +| [BedrockRuntime](./bedrock-runtime.md) | [async-aws/bedrock-runtime](https://packagist.org/packages/async-aws/bedrock-runtime) | | [CloudFormation](./cf.md) | [async-aws/cloud-formation](https://packagist.org/packages/async-aws/cloud-formation) | | [CloudFront](./cloud-front.md) | [async-aws/cloud-front](https://packagist.org/packages/async-aws/cloud-front) | | [CloudWatch](./cloud-watch.md) | [async-aws/cloud-watch](https://packagist.org/packages/async-aws/cloud-watch) | diff --git a/manifest.json b/manifest.json index a70b50556..e346c4a17 100644 --- a/manifest.json +++ b/manifest.json @@ -64,6 +64,16 @@ ] } }, + "BedrockRuntime": { + "source": "https://raw.githubusercontent.com/aws/aws-sdk-php/${LATEST}/src/data/bedrock-runtime/2023-09-30/api-2.json", + "documentation": "https://raw.githubusercontent.com/aws/aws-sdk-php/${LATEST}/src/data/bedrock-runtime/2023-09-30/docs-2.json", + "pagination": "https://raw.githubusercontent.com/aws/aws-sdk-php/${LATEST}/src/data/bedrock-runtime/2023-09-30/paginators-1.json", + "example": "https://raw.githubusercontent.com/aws/aws-sdk-php/${LATEST}/src/data/bedrock-runtime/2023-09-30/examples-1.json", + "api-reference": "https://docs.aws.amazon.com/bedrock/latest/APIReference", + "methods": [ + "InvokeModel" + ] + }, "CloudFormation": { "source": "https://raw.githubusercontent.com/aws/aws-sdk-php/${LATEST}/src/data/cloudformation/2010-05-15/api-2.json", "documentation": "https://raw.githubusercontent.com/aws/aws-sdk-php/${LATEST}/src/data/cloudformation/2010-05-15/docs-2.json", diff --git a/src/Core/CHANGELOG.md b/src/Core/CHANGELOG.md index cb8483cc8..55ad04a88 100644 --- a/src/Core/CHANGELOG.md +++ b/src/Core/CHANGELOG.md @@ -5,6 +5,7 @@ ### Added - AWS api-change: Added `us-isof-east-1` and `us-isof-south-1` regions +- Support for BedrockRuntime ## 1.24.1 diff --git a/src/Core/src/AwsClientFactory.php b/src/Core/src/AwsClientFactory.php index 31dd577f7..b56c5fcd4 100644 --- a/src/Core/src/AwsClientFactory.php +++ b/src/Core/src/AwsClientFactory.php @@ -6,6 +6,7 @@ use AsyncAws\AppSync\AppSyncClient; use AsyncAws\Athena\AthenaClient; +use AsyncAws\BedrockRuntime\BedrockRuntimeClient; use AsyncAws\CloudFormation\CloudFormationClient; use AsyncAws\CloudFront\CloudFrontClient; use AsyncAws\CloudWatch\CloudWatchClient; @@ -118,6 +119,19 @@ public function appSync(): AppSyncClient return $this->serviceCache[__METHOD__]; } + public function bedrockRuntime(): BedrockRuntimeClient + { + if (!class_exists(BedrockRuntimeClient::class)) { + throw MissingDependency::create('async-aws/bedrock-runtime', 'BedrockRuntime'); + } + + if (!isset($this->serviceCache[__METHOD__])) { + $this->serviceCache[__METHOD__] = new BedrockRuntimeClient($this->configuration, $this->credentialProvider, $this->httpClient, $this->logger); + } + + return $this->serviceCache[__METHOD__]; + } + public function cloudFormation(): CloudFormationClient { if (!class_exists(CloudFormationClient::class)) { diff --git a/src/Integration/Symfony/Bundle/CHANGELOG.md b/src/Integration/Symfony/Bundle/CHANGELOG.md index 2790ecf46..17b13c91d 100644 --- a/src/Integration/Symfony/Bundle/CHANGELOG.md +++ b/src/Integration/Symfony/Bundle/CHANGELOG.md @@ -2,6 +2,10 @@ ## NOT RELEASED +### Added + +- Support for BedrockRuntime + ## 1.13.0 ### Added diff --git a/src/Integration/Symfony/Bundle/composer.json b/src/Integration/Symfony/Bundle/composer.json index b621af302..3d82b6f07 100644 --- a/src/Integration/Symfony/Bundle/composer.json +++ b/src/Integration/Symfony/Bundle/composer.json @@ -39,7 +39,7 @@ }, "extra": { "branch-alias": { - "dev-master": "1.13-dev" + "dev-master": "1.14-dev" } } } diff --git a/src/Integration/Symfony/Bundle/src/DependencyInjection/AwsPackagesProvider.php b/src/Integration/Symfony/Bundle/src/DependencyInjection/AwsPackagesProvider.php index 85852cb2d..86693ad10 100644 --- a/src/Integration/Symfony/Bundle/src/DependencyInjection/AwsPackagesProvider.php +++ b/src/Integration/Symfony/Bundle/src/DependencyInjection/AwsPackagesProvider.php @@ -22,6 +22,10 @@ public static function getAllServices(): array 'class' => \AsyncAws\Athena\AthenaClient::class, 'package' => 'async-aws/athena', ], + 'bedrock_runtime' => [ + 'class' => \AsyncAws\BedrockRuntime\BedrockRuntimeClient::class, + 'package' => 'async-aws/bedrock-runtime', + ], 'cloud_formation' => [ 'class' => \AsyncAws\CloudFormation\CloudFormationClient::class, 'package' => 'async-aws/cloud-formation', diff --git a/src/Service/BedrockRuntime/.gitattributes b/src/Service/BedrockRuntime/.gitattributes new file mode 100644 index 000000000..410d4a1a6 --- /dev/null +++ b/src/Service/BedrockRuntime/.gitattributes @@ -0,0 +1,5 @@ +/.github export-ignore +/tests export-ignore +/.gitignore export-ignore +/Makefile export-ignore +/phpunit.xml.dist export-ignore diff --git a/src/Service/BedrockRuntime/.github/FUNDING.yml b/src/Service/BedrockRuntime/.github/FUNDING.yml new file mode 100644 index 000000000..ef7eb6190 --- /dev/null +++ b/src/Service/BedrockRuntime/.github/FUNDING.yml @@ -0,0 +1,3 @@ +# These are supported funding model platforms + +github: [nyholm, jderusse] diff --git a/src/Service/BedrockRuntime/.github/workflows/.editorconfig b/src/Service/BedrockRuntime/.github/workflows/.editorconfig new file mode 100644 index 000000000..7bd3346f2 --- /dev/null +++ b/src/Service/BedrockRuntime/.github/workflows/.editorconfig @@ -0,0 +1,2 @@ +[*.yml] +indent_size = 2 diff --git a/src/Service/BedrockRuntime/.github/workflows/checks.yml b/src/Service/BedrockRuntime/.github/workflows/checks.yml new file mode 100644 index 000000000..b9c47e84b --- /dev/null +++ b/src/Service/BedrockRuntime/.github/workflows/checks.yml @@ -0,0 +1,38 @@ +name: BC Check + +on: + push: + branches: + - master + +jobs: + roave-bc-check: + name: Roave BC Check + runs-on: ubuntu-latest + + steps: + - name: Checkout code + uses: actions/checkout@v4 + with: + fetch-depth: 0 + + - name: Modify composer.json + run: | + sed -i -re 's/"require": \{/"minimum-stability": "dev","prefer-stable": true,"require": \{/' composer.json + cat composer.json + + git config --local user.email "github@async-aws.com" + git config --local user.name "AsyncAws Bot" + git commit -am "Allow unstable dependencies" + + - name: Install PHP with extensions + uses: shivammathur/setup-php@v2 + with: + php-version: 8.3 + tools: composer:v2 + + - name: Install roave/backward-compatibility-check + run: composer require --dev roave/backward-compatibility-check + + - name: Roave BC Check + run: vendor/bin/roave-backward-compatibility-check diff --git a/src/Service/BedrockRuntime/.github/workflows/ci.yml b/src/Service/BedrockRuntime/.github/workflows/ci.yml new file mode 100644 index 000000000..0778da59d --- /dev/null +++ b/src/Service/BedrockRuntime/.github/workflows/ci.yml @@ -0,0 +1,38 @@ +name: Tests + +on: + push: + branches: + - master + +jobs: + + build: + name: Build + runs-on: ubuntu-latest + strategy: + max-parallel: 10 + matrix: + php: ['7.2', '7.3', '7.4', '8.0', '8.1', '8.2', '8.3', '8.4', '8.5'] + + steps: + - name: Set up PHP + uses: shivammathur/setup-php@v2 + with: + php-version: ${{ matrix.php }} + coverage: none + + - name: Checkout code + uses: actions/checkout@v4 + + - name: Initialize tests + run: make initialize + + - name: Download dependencies + run: | + composer config minimum-stability dev + composer req symfony/phpunit-bridge --no-update + composer update --no-interaction --prefer-dist --optimize-autoloader --prefer-stable + + - name: Run tests + run: ./vendor/bin/simple-phpunit diff --git a/src/Service/BedrockRuntime/.gitignore b/src/Service/BedrockRuntime/.gitignore new file mode 100644 index 000000000..4ef8091e0 --- /dev/null +++ b/src/Service/BedrockRuntime/.gitignore @@ -0,0 +1,3 @@ +/vendor/ +*.cache +composer.lock diff --git a/src/Service/BedrockRuntime/CHANGELOG.md b/src/Service/BedrockRuntime/CHANGELOG.md new file mode 100644 index 000000000..a64e84b42 --- /dev/null +++ b/src/Service/BedrockRuntime/CHANGELOG.md @@ -0,0 +1,7 @@ +# Change Log + +## NOT RELEASED + +## 1.0.0 + +First version diff --git a/src/Service/BedrockRuntime/LICENSE b/src/Service/BedrockRuntime/LICENSE new file mode 100644 index 000000000..c924ee5c6 --- /dev/null +++ b/src/Service/BedrockRuntime/LICENSE @@ -0,0 +1,21 @@ +The MIT License (MIT) + +Copyright (c) 2022 Jérémy Derussé, Tobias Nyholm + +Permission is hereby granted, free of charge, to any person obtaining a copy +of this software and associated documentation files (the "Software"), to deal +in the Software without restriction, including without limitation the rights +to use, copy, modify, merge, publish, distribute, sublicense, and/or sell +copies of the Software, and to permit persons to whom the Software is +furnished to do so, subject to the following conditions: + +The above copyright notice and this permission notice shall be included in +all copies or substantial portions of the Software. + +THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR +IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, +FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE +AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER +LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, +OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN +THE SOFTWARE. diff --git a/src/Service/BedrockRuntime/Makefile b/src/Service/BedrockRuntime/Makefile new file mode 100644 index 000000000..850dffccd --- /dev/null +++ b/src/Service/BedrockRuntime/Makefile @@ -0,0 +1,12 @@ +.EXPORT_ALL_VARIABLES: + +initialize: start-docker +start-docker: + echo "Noop" + +test: initialize + ./vendor/bin/simple-phpunit + +clean: stop-docker +stop-docker: + echo "Noop" diff --git a/src/Service/BedrockRuntime/README.md b/src/Service/BedrockRuntime/README.md new file mode 100644 index 000000000..0b63213e8 --- /dev/null +++ b/src/Service/BedrockRuntime/README.md @@ -0,0 +1,20 @@ +# AsyncAws BedrockRuntime Client + +![](https://github.com/async-aws/bedrock-runtime/workflows/Tests/badge.svg?branch=master) +![](https://github.com/async-aws/bedrock-runtime/workflows/BC%20Check/badge.svg?branch=master) + +An API client for BedrockRuntime. + +## Install + +```cli +composer require async-aws/bedrock-runtime +``` + +## Documentation + +See https://async-aws.com/clients/bedrock-runtime.html for documentation. + +## Contribute + +Contributions are welcome and appreciated. Please read https://async-aws.com/contribute/ diff --git a/src/Service/BedrockRuntime/composer.json b/src/Service/BedrockRuntime/composer.json new file mode 100644 index 000000000..93ab0a6fc --- /dev/null +++ b/src/Service/BedrockRuntime/composer.json @@ -0,0 +1,32 @@ +{ + "name": "async-aws/bedrock-runtime", + "description": "BedrockRuntime client, part of the AWS SDK provided by AsyncAws.", + "license": "MIT", + "type": "library", + "keywords": [ + "aws", + "amazon", + "sdk", + "async-aws", + "bedrock-runtime" + ], + "require": { + "php": "^7.2.5 || ^8.0", + "async-aws/core": "^1.9" + }, + "autoload": { + "psr-4": { + "AsyncAws\\BedrockRuntime\\": "src" + } + }, + "autoload-dev": { + "psr-4": { + "AsyncAws\\BedrockRuntime\\Tests\\": "tests/" + } + }, + "extra": { + "branch-alias": { + "dev-master": "1.0-dev" + } + } +} diff --git a/src/Service/BedrockRuntime/phpunit.xml.dist b/src/Service/BedrockRuntime/phpunit.xml.dist new file mode 100644 index 000000000..9894ce353 --- /dev/null +++ b/src/Service/BedrockRuntime/phpunit.xml.dist @@ -0,0 +1,23 @@ + + + + + ./src + + + + + + + + ./tests/ + + + diff --git a/src/Service/BedrockRuntime/src/BedrockRuntimeClient.php b/src/Service/BedrockRuntime/src/BedrockRuntimeClient.php new file mode 100644 index 000000000..ad61d58cc --- /dev/null +++ b/src/Service/BedrockRuntime/src/BedrockRuntimeClient.php @@ -0,0 +1,111 @@ +getResponse($input->request(), new RequestContext(['operation' => 'InvokeModel', 'region' => $input->getRegion(), 'exceptionMapping' => [ + 'AccessDeniedException' => AccessDeniedException::class, + 'ResourceNotFoundException' => ResourceNotFoundException::class, + 'ThrottlingException' => ThrottlingException::class, + 'ModelTimeoutException' => ModelTimeoutException::class, + 'InternalServerException' => InternalServerException::class, + 'ServiceUnavailableException' => ServiceUnavailableException::class, + 'ValidationException' => ValidationException::class, + 'ModelNotReadyException' => ModelNotReadyException::class, + 'ServiceQuotaExceededException' => ServiceQuotaExceededException::class, + 'ModelErrorException' => ModelErrorException::class, + ]])); + + return new InvokeModelResponse($response); + } + + protected function getAwsErrorFactory(): AwsErrorFactoryInterface + { + return new JsonRestAwsErrorFactory(); + } + + protected function getEndpointMetadata(?string $region): array + { + if (null === $region) { + $region = Configuration::DEFAULT_REGION; + } + + return [ + 'endpoint' => "https://bedrock-runtime.$region.amazonaws.com", + 'signRegion' => $region, + 'signService' => 'bedrock', + 'signVersions' => ['v4'], + ]; + } +} diff --git a/src/Service/BedrockRuntime/src/Enum/PerformanceConfigLatency.php b/src/Service/BedrockRuntime/src/Enum/PerformanceConfigLatency.php new file mode 100644 index 000000000..23ef02bf4 --- /dev/null +++ b/src/Service/BedrockRuntime/src/Enum/PerformanceConfigLatency.php @@ -0,0 +1,17 @@ + true, + self::STANDARD => true, + ][$value]); + } +} diff --git a/src/Service/BedrockRuntime/src/Enum/Trace.php b/src/Service/BedrockRuntime/src/Enum/Trace.php new file mode 100644 index 000000000..efcb5d089 --- /dev/null +++ b/src/Service/BedrockRuntime/src/Enum/Trace.php @@ -0,0 +1,17 @@ + true, + self::ENABLED => true, + ][$value]); + } +} diff --git a/src/Service/BedrockRuntime/src/Exception/AccessDeniedException.php b/src/Service/BedrockRuntime/src/Exception/AccessDeniedException.php new file mode 100644 index 000000000..555e64395 --- /dev/null +++ b/src/Service/BedrockRuntime/src/Exception/AccessDeniedException.php @@ -0,0 +1,15 @@ +originalStatusCode; + } + + public function getResourceName(): ?string + { + return $this->resourceName; + } + + protected function populateResult(ResponseInterface $response): void + { + $data = $response->toArray(false); + + $this->originalStatusCode = isset($data['originalStatusCode']) ? (int) $data['originalStatusCode'] : null; + $this->resourceName = isset($data['resourceName']) ? (string) $data['resourceName'] : null; + } +} diff --git a/src/Service/BedrockRuntime/src/Exception/ModelNotReadyException.php b/src/Service/BedrockRuntime/src/Exception/ModelNotReadyException.php new file mode 100644 index 000000000..ef6e11547 --- /dev/null +++ b/src/Service/BedrockRuntime/src/Exception/ModelNotReadyException.php @@ -0,0 +1,16 @@ +body = $input['body'] ?? null; + $this->contentType = $input['contentType'] ?? null; + $this->accept = $input['accept'] ?? null; + $this->modelId = $input['modelId'] ?? null; + $this->trace = $input['trace'] ?? null; + $this->guardrailIdentifier = $input['guardrailIdentifier'] ?? null; + $this->guardrailVersion = $input['guardrailVersion'] ?? null; + $this->performanceConfigLatency = $input['performanceConfigLatency'] ?? null; + parent::__construct($input); + } + + /** + * @param array{ + * body?: null|string, + * contentType?: null|string, + * accept?: null|string, + * modelId?: string, + * trace?: null|Trace::*, + * guardrailIdentifier?: null|string, + * guardrailVersion?: null|string, + * performanceConfigLatency?: null|PerformanceConfigLatency::*, + * '@region'?: string|null, + * }|InvokeModelRequest $input + */ + public static function create($input): self + { + return $input instanceof self ? $input : new self($input); + } + + public function getAccept(): ?string + { + return $this->accept; + } + + public function getBody(): ?string + { + return $this->body; + } + + public function getContentType(): ?string + { + return $this->contentType; + } + + public function getGuardrailIdentifier(): ?string + { + return $this->guardrailIdentifier; + } + + public function getGuardrailVersion(): ?string + { + return $this->guardrailVersion; + } + + public function getModelId(): ?string + { + return $this->modelId; + } + + /** + * @return PerformanceConfigLatency::*|null + */ + public function getPerformanceConfigLatency(): ?string + { + return $this->performanceConfigLatency; + } + + /** + * @return Trace::*|null + */ + public function getTrace(): ?string + { + return $this->trace; + } + + /** + * @internal + */ + public function request(): Request + { + // Prepare headers + $headers = [ + 'Content-Type' => 'application/json', + 'Accept' => 'application/json', + ]; + if (null !== $this->contentType) { + $headers['Content-Type'] = $this->contentType; + } + if (null !== $this->accept) { + $headers['Accept'] = $this->accept; + } + if (null !== $this->trace) { + if (!Trace::exists($this->trace)) { + throw new InvalidArgument(\sprintf('Invalid parameter "trace" for "%s". The value "%s" is not a valid "Trace".', __CLASS__, $this->trace)); + } + $headers['X-Amzn-Bedrock-Trace'] = $this->trace; + } + if (null !== $this->guardrailIdentifier) { + $headers['X-Amzn-Bedrock-GuardrailIdentifier'] = $this->guardrailIdentifier; + } + if (null !== $this->guardrailVersion) { + $headers['X-Amzn-Bedrock-GuardrailVersion'] = $this->guardrailVersion; + } + if (null !== $this->performanceConfigLatency) { + if (!PerformanceConfigLatency::exists($this->performanceConfigLatency)) { + throw new InvalidArgument(\sprintf('Invalid parameter "performanceConfigLatency" for "%s". The value "%s" is not a valid "PerformanceConfigLatency".', __CLASS__, $this->performanceConfigLatency)); + } + $headers['X-Amzn-Bedrock-PerformanceConfig-Latency'] = $this->performanceConfigLatency; + } + + // Prepare query + $query = []; + + // Prepare URI + $uri = []; + if (null === $v = $this->modelId) { + throw new InvalidArgument(\sprintf('Missing parameter "modelId" for "%s". The value cannot be null.', __CLASS__)); + } + $uri['modelId'] = $v; + $uriString = '/model/' . rawurlencode($uri['modelId']) . '/invoke'; + + // Prepare Body + $body = $this->body ?? ''; + + // Return the Request + return new Request('POST', $uriString, $query, $headers, StreamFactory::create($body)); + } + + public function setAccept(?string $value): self + { + $this->accept = $value; + + return $this; + } + + public function setBody(?string $value): self + { + $this->body = $value; + + return $this; + } + + public function setContentType(?string $value): self + { + $this->contentType = $value; + + return $this; + } + + public function setGuardrailIdentifier(?string $value): self + { + $this->guardrailIdentifier = $value; + + return $this; + } + + public function setGuardrailVersion(?string $value): self + { + $this->guardrailVersion = $value; + + return $this; + } + + public function setModelId(?string $value): self + { + $this->modelId = $value; + + return $this; + } + + /** + * @param PerformanceConfigLatency::*|null $value + */ + public function setPerformanceConfigLatency(?string $value): self + { + $this->performanceConfigLatency = $value; + + return $this; + } + + /** + * @param Trace::*|null $value + */ + public function setTrace(?string $value): self + { + $this->trace = $value; + + return $this; + } +} diff --git a/src/Service/BedrockRuntime/src/Result/InvokeModelResponse.php b/src/Service/BedrockRuntime/src/Result/InvokeModelResponse.php new file mode 100644 index 000000000..f63c11e92 --- /dev/null +++ b/src/Service/BedrockRuntime/src/Result/InvokeModelResponse.php @@ -0,0 +1,68 @@ +initialize(); + + return $this->body; + } + + public function getContentType(): string + { + $this->initialize(); + + return $this->contentType; + } + + /** + * @return PerformanceConfigLatency::*|null + */ + public function getPerformanceConfigLatency(): ?string + { + $this->initialize(); + + return $this->performanceConfigLatency; + } + + protected function populateResult(Response $response): void + { + $headers = $response->getHeaders(); + + $this->contentType = $headers['content-type'][0]; + $this->performanceConfigLatency = $headers['x-amzn-bedrock-performanceconfig-latency'][0] ?? null; + + $this->body = $response->getContent(); + } +} diff --git a/src/Service/BedrockRuntime/tests/.gitignore b/src/Service/BedrockRuntime/tests/.gitignore new file mode 100644 index 000000000..e69de29bb diff --git a/src/Service/BedrockRuntime/tests/Integration/BedrockRuntimeClientTest.php b/src/Service/BedrockRuntime/tests/Integration/BedrockRuntimeClientTest.php new file mode 100644 index 000000000..1588372f0 --- /dev/null +++ b/src/Service/BedrockRuntime/tests/Integration/BedrockRuntimeClientTest.php @@ -0,0 +1,43 @@ +getClient(); + + $input = new InvokeModelRequest([ + 'body' => 'change me', + 'contentType' => 'change me', + 'accept' => 'change me', + 'modelId' => 'change me', + 'trace' => 'change me', + 'guardrailIdentifier' => 'change me', + 'guardrailVersion' => 'change me', + 'performanceConfigLatency' => 'change me', + ]); + $result = $client->invokeModel($input); + + $result->resolve(); + + // self::assertTODO(expected, $result->getBody()); + self::assertSame('changeIt', $result->getContentType()); + self::assertSame('changeIt', $result->getPerformanceConfigLatency()); + } + + private function getClient(): BedrockRuntimeClient + { + self::markTestSkipped('There is no docker image available for BedrockRuntime.'); + + return new BedrockRuntimeClient([ + 'endpoint' => 'http://localhost', + ], new NullProvider()); + } +} diff --git a/src/Service/BedrockRuntime/tests/Unit/BedrockRuntimeClientTest.php b/src/Service/BedrockRuntime/tests/Unit/BedrockRuntimeClientTest.php new file mode 100644 index 000000000..546765a7c --- /dev/null +++ b/src/Service/BedrockRuntime/tests/Unit/BedrockRuntimeClientTest.php @@ -0,0 +1,26 @@ + 'change me', + ]); + $result = $client->invokeModel($input); + + self::assertInstanceOf(InvokeModelResponse::class, $result); + self::assertFalse($result->info()['resolved']); + } +} diff --git a/src/Service/BedrockRuntime/tests/Unit/Input/InvokeModelRequestTest.php b/src/Service/BedrockRuntime/tests/Unit/Input/InvokeModelRequestTest.php new file mode 100644 index 000000000..5f9b3762e --- /dev/null +++ b/src/Service/BedrockRuntime/tests/Unit/Input/InvokeModelRequestTest.php @@ -0,0 +1,38 @@ + '{"anthropic_version":"bedrock-2023-05-31","max_tokens":4096,"messages":[{"role":"user","content":[{"type":"text","text":"Write me a love poem."}]}],"temperature":1}', + 'contentType' => 'application/json', + 'accept' => 'application/json', + 'modelId' => 'us.anthropic.claude-3-7-sonnet-20250219-v1:0', + 'trace' => 'DISABLED', + 'guardrailIdentifier' => 'arn:aws:bedrock:eu-west-1:965624758642:guardrail/azertyuiopqs', + 'guardrailVersion' => 'DRAFT', + 'performanceConfigLatency' => 'standard', + ]); + + // see https://docs.aws.amazon.com/bedrock/latest/APIReference/API_runtime_InvokeModel.html + $expected = ' + POST /model/us.anthropic.claude-3-7-sonnet-20250219-v1%3A0/invoke HTTP/1.0 + Content-Type: application/json + Accept: application/json + X-Amzn-Bedrock-GuardrailIdentifier: arn:aws:bedrock:eu-west-1:965624758642:guardrail/azertyuiopqs + X-Amzn-Bedrock-GuardrailVersion: DRAFT + X-Amzn-Bedrock-PerformanceConfig-Latency: standard + X-Amzn-Bedrock-Trace: DISABLED + + {"anthropic_version":"bedrock-2023-05-31","max_tokens":4096,"messages":[{"role":"user","content":[{"type":"text","text":"Write me a love poem."}]}],"temperature":1} + '; + + self::assertRequestEqualsHttpRequest($expected, $input->request()); + } +} diff --git a/src/Service/BedrockRuntime/tests/Unit/Result/InvokeModelResponseTest.php b/src/Service/BedrockRuntime/tests/Unit/Result/InvokeModelResponseTest.php new file mode 100644 index 000000000..ff84e8b8e --- /dev/null +++ b/src/Service/BedrockRuntime/tests/Unit/Result/InvokeModelResponseTest.php @@ -0,0 +1,29 @@ + 'application/json', 'X-Amzn-Bedrock-PerformanceConfig-Latency' => 'standard'] + ); + + $client = new MockHttpClient($response); + $result = new InvokeModelResponse(new Response($client->request('POST', 'http://localhost'), $client, new NullLogger())); + + self::assertSame('{"id":"msg_bdrk_01SK3CsA23VBbZig4HqemAoo","type":"message","role":"assistant","model":"claude-3-7-sonnet-20250219","content":[{"type":"text","text":"# Whispers of the Heart\n\nIn the quiet moments between breaths,\nI find my thoughts wandering to you,\nLike stars that navigate sailors home,\nYour smile guides me through.\n\nThe universe conspired in silent ways,\nTo weave our paths into one,\nNow each sunrise holds new promise,\nA dance we\'ve just begun.\n\nYour laughter echoes in my dreams,\nA melody I\'ve known all along,\nMy heart recognizes yours completely,\nLike remembering a forgotten song.\n\nI love you not just for who you are,\nBut for who I become when we\'re together,\nA better version, a truer self,\nA love to cherish forever."}],"stop_reason":"end_turn","stop_sequence":null,"usage":{"input_tokens":13,"cache_creation_input_tokens":0,"cache_read_input_tokens":0,"output_tokens":153}}', $result->getBody()); + self::assertSame('application/json', $result->getContentType()); + self::assertSame('standard', $result->getPerformanceConfigLatency()); + } +}