diff --git a/README.md b/README.md index ec8172d98..581f650f2 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) | [![BC Check](https://github.com/async-aws/core/actions/workflows/checks.yml/badge.svg?branch=master)](https://github.com/async-aws/core/actions/workflows/checks.yml) | [![](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) | [![BC Check](https://github.com/async-aws/app-sync/actions/workflows/checks.yml/badge.svg?branch=master)](https://github.com/async-aws/app-sync/actions/workflows/checks.yml) | [![](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) | [![BC Check](https://github.com/async-aws/athena/actions/workflows/checks.yml/badge.svg?branch=master)](https://github.com/async-aws/athena/actions/workflows/checks.yml) | [![](https://async-aws-pr.github.io/commits-since-release-counter/athena.svg)](https://github.com/async-aws/athena/releases) | +| [async-aws/bedrock-agent](https://github.com/async-aws/bedrock-agent) | [![Latest Stable Version](https://poser.pugx.org/async-aws/bedrock-agent/v/stable)](https://packagist.org/packages/async-aws/bedrock-agent) [![Total Downloads](https://poser.pugx.org/async-aws/bedrock-agent/downloads)](https://packagist.org/packages/async-aws/bedrock-agent) | [![BC Check](https://github.com/async-aws/bedrock-agent/actions/workflows/checks.yml/badge.svg?branch=master)](https://github.com/async-aws/bedrock-agent/actions/workflows/checks.yml) | [![](https://async-aws-pr.github.io/commits-since-release-counter/bedrock-agent.svg)](https://github.com/async-aws/bedrock-agent/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) | [![BC Check](https://github.com/async-aws/bedrock-runtime/actions/workflows/checks.yml/badge.svg?branch=master)](https://github.com/async-aws/bedrock-runtime/actions/workflows/checks.yml) | [![](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) | [![BC Check](https://github.com/async-aws/cloud-formation/actions/workflows/checks.yml/badge.svg?branch=master)](https://github.com/async-aws/cloud-formation/actions/workflows/checks.yml) | [![](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) | [![BC Check](https://github.com/async-aws/cloud-front/actions/workflows/checks.yml/badge.svg?branch=master)](https://github.com/async-aws/cloud-front/actions/workflows/checks.yml) | [![](https://async-aws-pr.github.io/commits-since-release-counter/cloud-front.svg)](https://github.com/async-aws/cloud-front/releases) | diff --git a/composer.json b/composer.json index 5b4ba6ea7..43a70a670 100644 --- a/composer.json +++ b/composer.json @@ -52,6 +52,7 @@ "psr-4": { "AsyncAws\\AppSync\\": "src/Service/AppSync/src", "AsyncAws\\Athena\\": "src/Service/Athena/src", + "AsyncAws\\BedrockAgent\\": "src/Service/BedrockAgent/src", "AsyncAws\\BedrockRuntime\\": "src/Service/BedrockRuntime/src", "AsyncAws\\CloudFormation\\": "src/Service/CloudFormation/src", "AsyncAws\\CloudFront\\": "src/Service/CloudFront/src", @@ -106,6 +107,7 @@ "psr-4": { "AsyncAws\\AppSync\\Tests\\": "src/Service/AppSync/tests", "AsyncAws\\Athena\\Tests\\": "src/Service/Athena/tests", + "AsyncAws\\BedrockAgent\\Tests\\": "src/Service/BedrockAgent/tests", "AsyncAws\\BedrockRuntime\\Tests\\": "src/Service/BedrockRuntime/tests", "AsyncAws\\CloudFormation\\Tests\\": "src/Service/CloudFormation/tests", "AsyncAws\\CloudFront\\Tests\\": "src/Service/CloudFront/tests", diff --git a/couscous.yml b/couscous.yml index 3346ef5ed..dfbd9654d 100644 --- a/couscous.yml +++ b/couscous.yml @@ -37,6 +37,9 @@ menu: athena: text: Athena url: /clients/athena.html + bedrock-agent: + text: Bedrock Agent + url: /clients/bedrock-agent.html bedrock-runtime: text: Bedrock Runtime url: /clients/bedrock-runtime.html diff --git a/docs/clients/bedrock-agent.md b/docs/clients/bedrock-agent.md new file mode 100644 index 000000000..b913a8bf0 --- /dev/null +++ b/docs/clients/bedrock-agent.md @@ -0,0 +1,142 @@ +--- +layout: client +category: clients +name: BedrockAgent +package: async-aws/bedrock-agent +--- + +## Usage + +### Delete knowledge base documents + +```php +use AsyncAws\BedrockAgent\BedrockAgentClient; +use AsyncAws\BedrockAgent\Enum\ContentDataSourceType; +use AsyncAws\BedrockAgent\Input\DeleteKnowledgeBaseDocumentsRequest; +use AsyncAws\BedrockAgent\ValueObject\DocumentIdentifier; +use AsyncAws\BedrockAgent\ValueObject\S3Location; + +$bedrockAgent = new BedrockAgentClient(); + +$request = new DeleteKnowledgeBaseDocumentsRequest([ + 'knowledgeBaseId' => 'kb-1234567890abcdef', + 'dataSourceId' => 'ds-abcdef1234567890', + 'clientToken' => 'token-1234', + 'documentIdentifiers' => [new DocumentIdentifier([ + 'dataSourceType' => ContentDataSourceType::S3, + 's3' => new S3Location([ + 'uri' => 's3://my-bucket/documents/', + ]), + ])], +]); + +$result = $bedrockAgent->deleteKnowledgeBaseDocuments($request); + +foreach ($result->getDocumentDetails() as $documentDetail) { + echo $documentDetail->getStatus() . PHP_EOL; +} + +``` +See [`DeleteKnowledgeBaseDocuments`](https://docs.aws.amazon.com/bedrock/latest/APIReference/API_agent_DeleteKnowledgeBaseDocuments.html) for more information. + +### Get knowledge base documents + +```php +use AsyncAws\BedrockAgent\BedrockAgentClient; +use AsyncAws\BedrockAgent\Enum\ContentDataSourceType; +use AsyncAws\BedrockAgent\Input\GetKnowledgeBaseDocumentsRequest; +use AsyncAws\BedrockAgent\ValueObject\DocumentIdentifier; +use AsyncAws\BedrockAgent\ValueObject\S3Location; + +$bedrockAgent = new BedrockAgentClient(); + +$request = new GetKnowledgeBaseDocumentsRequest([ + 'knowledgeBaseId' => 'kb-1234567890abcdef', + 'dataSourceId' => 'ds-abcdef1234567890', + 'documentIdentifiers' => [new DocumentIdentifier([ + 'dataSourceType' => ContentDataSourceType::S3, + 's3' => new S3Location([ + 'uri' => 's3://my-bucket/documents/', + ]), + ])], +]); + +$result = $bedrockAgent->getKnowledgeBaseDocuments($request); + +foreach ($result->getDocumentDetails() as $documentDetail) { + echo $documentDetail->getIdentifier()->getS3()->getUri() . PHP_EOL; +} + +``` +See [`GetKnowledgeBaseDocuments`](https://docs.aws.amazon.com/bedrock/latest/APIReference/API_agent_GetKnowledgeBaseDocuments.html) for more information. + +### Ingest knowledge base documents + +```php +use AsyncAws\BedrockAgent\Enum\ContentDataSourceType; +use AsyncAws\BedrockAgent\Enum\MetadataSourceType; +use AsyncAws\BedrockAgent\Input\IngestKnowledgeBaseDocumentsRequest; +use AsyncAws\BedrockAgent\ValueObject\CustomS3Location; +use AsyncAws\BedrockAgent\ValueObject\DocumentContent; +use AsyncAws\BedrockAgent\ValueObject\DocumentMetadata; +use AsyncAws\BedrockAgent\ValueObject\KnowledgeBaseDocument; +use AsyncAws\BedrockAgent\ValueObject\S3Content; +use AsyncAws\BedrockAgent\ValueObject\S3Location; + +$bedrockAgent = new BedrockAgentClient(); + +$request = new IngestKnowledgeBaseDocumentsRequest([ + 'knowledgeBaseId' => 'kb-1234567890abcdef', + 'dataSourceId' => 'ds-abcdef1234567890', + 'clientToken' => 'token-1234', + 'documents' => [new KnowledgeBaseDocument([ + 'metadata' => new DocumentMetadata([ + 'type' => MetadataSourceType::S3_LOCATION, + 's3Location' => new CustomS3Location([ + 'uri' => 's3://my-bucket/documents/', + 'bucketOwnerAccountId' => 'account-1234', + ]), + ]), + 'content' => new DocumentContent([ + 'dataSourceType' => ContentDataSourceType::S3, + 's3' => new S3Content([ + 's3Location' => new S3Location([ + 'uri' => 's3://my-bucket/documents/', + ]), + ]), + ]), + ])], +]); + +$result = $bedrockAgent->ingestKnowledgeBaseDocuments($request); + +foreach ($result->getDocumentDetails() as $documentDetail) { + echo $documentDetail->getStatus() . PHP_EOL; + echo $documentDetail->getIdentifier()->getS3()->getUri() . PHP_EOL; +} + +``` +See [`IngestKnowledgeBaseDocuments`](https://docs.aws.amazon.com/bedrock/latest/APIReference/API_agent_IngestKnowledgeBaseDocuments.html) for more information. + +### List knowledge base documents + +```php +use AsyncAws\BedrockAgent\BedrockAgentClient; +use AsyncAws\BedrockAgent\Input\ListKnowledgeBaseDocumentsRequest; + +$bedrockAgent = new BedrockAgentClient(); + +$request = new ListKnowledgeBaseDocumentsRequest([ + 'knowledgeBaseId' => 'kb-1234567890abcdef', + 'dataSourceId' => 'ds-abcdef1234567890', + 'maxResults' => 50, +]); + +$result = $bedrockAgent->listKnowledgeBaseDocuments($request); + +foreach ($result->getDocumentDetails() as $documentDetail) { + echo $documentDetail->getIdentifier()->getS3()->getUri() . PHP_EOL; +} + +``` +See [`ListKnowledgeBaseDocuments`](https://docs.aws.amazon.com/bedrock/latest/APIReference/API_agent_ListKnowledgeBaseDocuments.html) for more information. diff --git a/docs/clients/index.md b/docs/clients/index.md index e333d03b8..26f5c50bc 100644 --- a/docs/clients/index.md +++ b/docs/clients/index.md @@ -139,7 +139,8 @@ 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) | +| [BedrockAgent](./bedrock-agent.md) | [async-aws/bedrock-agent](https://packagist.org/packages/async-aws/bedrock-agent) | +| [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 3f45e52a9..cde169ae3 100644 --- a/manifest.json +++ b/manifest.json @@ -64,6 +64,20 @@ ] } }, + "BedrockAgent": { + "source": "https://raw.githubusercontent.com/aws/aws-sdk-php/${LATEST}/src/data/bedrock-agent/2023-06-05/api-2.json", + "documentation": "https://raw.githubusercontent.com/aws/aws-sdk-php/${LATEST}/src/data/bedrock-agent/2023-06-05/docs-2.json", + "pagination": "https://raw.githubusercontent.com/aws/aws-sdk-php/${LATEST}/src/data/bedrock-agent/2023-06-05/paginators-1.json", + "waiter": "https://raw.githubusercontent.com/aws/aws-sdk-php/${LATEST}/src/data/bedrock-agent/2023-06-05/waiters-2.json", + "example": "https://raw.githubusercontent.com/aws/aws-sdk-php/${LATEST}/src/data/bedrock-agent/2023-06-05/examples-1.json", + "api-reference": "https://docs.aws.amazon.com/bedrock/latest/APIReference", + "methods": [ + "DeleteKnowledgeBaseDocuments", + "GetKnowledgeBaseDocuments", + "IngestKnowledgeBaseDocuments", + "ListKnowledgeBaseDocuments" + ] + }, "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", diff --git a/src/Core/CHANGELOG.md b/src/Core/CHANGELOG.md index eb7e2cc26..9700cbf00 100644 --- a/src/Core/CHANGELOG.md +++ b/src/Core/CHANGELOG.md @@ -6,6 +6,7 @@ - AWS api-change: Added `us-isob-west-1` region - Added `DescribeLogGroups` method +- Support for BedrockAgent ### Dependency bumped diff --git a/src/Core/src/AwsClientFactory.php b/src/Core/src/AwsClientFactory.php index b56c5fcd4..d9fc75bba 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\BedrockAgent\BedrockAgentClient; use AsyncAws\BedrockRuntime\BedrockRuntimeClient; use AsyncAws\CloudFormation\CloudFormationClient; use AsyncAws\CloudFront\CloudFrontClient; @@ -119,6 +120,19 @@ public function appSync(): AppSyncClient return $this->serviceCache[__METHOD__]; } + public function bedrockAgent(): BedrockAgentClient + { + if (!class_exists(BedrockAgentClient::class)) { + throw MissingDependency::create('async-aws/bedrock-agent', 'BedrockAgent'); + } + + if (!isset($this->serviceCache[__METHOD__])) { + $this->serviceCache[__METHOD__] = new BedrockAgentClient($this->configuration, $this->credentialProvider, $this->httpClient, $this->logger); + } + + return $this->serviceCache[__METHOD__]; + } + public function bedrockRuntime(): BedrockRuntimeClient { if (!class_exists(BedrockRuntimeClient::class)) { diff --git a/src/Integration/Symfony/Bundle/CHANGELOG.md b/src/Integration/Symfony/Bundle/CHANGELOG.md index 128853558..102270a42 100644 --- a/src/Integration/Symfony/Bundle/CHANGELOG.md +++ b/src/Integration/Symfony/Bundle/CHANGELOG.md @@ -2,6 +2,10 @@ ## NOT RELEASED +### Added + +- Support for BedrockAgent + ### Dependency bumped - Drop support for PHP versions lower than 8.2 diff --git a/src/Integration/Symfony/Bundle/src/DependencyInjection/AwsPackagesProvider.php b/src/Integration/Symfony/Bundle/src/DependencyInjection/AwsPackagesProvider.php index 86693ad10..8a477c7bc 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_agent' => [ + 'class' => \AsyncAws\BedrockAgent\BedrockAgentClient::class, + 'package' => 'async-aws/bedrock-agent', + ], 'bedrock_runtime' => [ 'class' => \AsyncAws\BedrockRuntime\BedrockRuntimeClient::class, 'package' => 'async-aws/bedrock-runtime', diff --git a/src/Service/BedrockAgent/.gitattributes b/src/Service/BedrockAgent/.gitattributes new file mode 100644 index 000000000..410d4a1a6 --- /dev/null +++ b/src/Service/BedrockAgent/.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/BedrockAgent/.github/FUNDING.yml b/src/Service/BedrockAgent/.github/FUNDING.yml new file mode 100644 index 000000000..ef7eb6190 --- /dev/null +++ b/src/Service/BedrockAgent/.github/FUNDING.yml @@ -0,0 +1,3 @@ +# These are supported funding model platforms + +github: [nyholm, jderusse] diff --git a/src/Service/BedrockAgent/.github/workflows/.editorconfig b/src/Service/BedrockAgent/.github/workflows/.editorconfig new file mode 100644 index 000000000..7bd3346f2 --- /dev/null +++ b/src/Service/BedrockAgent/.github/workflows/.editorconfig @@ -0,0 +1,2 @@ +[*.yml] +indent_size = 2 diff --git a/src/Service/BedrockAgent/.github/workflows/checks.yml b/src/Service/BedrockAgent/.github/workflows/checks.yml new file mode 100644 index 000000000..974722885 --- /dev/null +++ b/src/Service/BedrockAgent/.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@v5 + 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/BedrockAgent/.github/workflows/ci.yml b/src/Service/BedrockAgent/.github/workflows/ci.yml new file mode 100644 index 000000000..fd44f8c70 --- /dev/null +++ b/src/Service/BedrockAgent/.github/workflows/ci.yml @@ -0,0 +1,37 @@ +name: Tests + +on: + push: + branches: + - master + +jobs: + + build: + name: Build + runs-on: ubuntu-latest + strategy: + max-parallel: 10 + matrix: + php: ['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@v5 + + - name: Initialize tests + run: make initialize + + - name: Download dependencies + run: | + composer config minimum-stability dev + composer update --no-interaction --prefer-dist --optimize-autoloader --prefer-stable + + - name: Run tests + run: ./vendor/bin/phpunit diff --git a/src/Service/BedrockAgent/.gitignore b/src/Service/BedrockAgent/.gitignore new file mode 100644 index 000000000..4ef8091e0 --- /dev/null +++ b/src/Service/BedrockAgent/.gitignore @@ -0,0 +1,3 @@ +/vendor/ +*.cache +composer.lock diff --git a/src/Service/BedrockAgent/CHANGELOG.md b/src/Service/BedrockAgent/CHANGELOG.md new file mode 100644 index 000000000..a64e84b42 --- /dev/null +++ b/src/Service/BedrockAgent/CHANGELOG.md @@ -0,0 +1,7 @@ +# Change Log + +## NOT RELEASED + +## 1.0.0 + +First version diff --git a/src/Service/BedrockAgent/LICENSE b/src/Service/BedrockAgent/LICENSE new file mode 100644 index 000000000..c924ee5c6 --- /dev/null +++ b/src/Service/BedrockAgent/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/BedrockAgent/Makefile b/src/Service/BedrockAgent/Makefile new file mode 100644 index 000000000..771133a06 --- /dev/null +++ b/src/Service/BedrockAgent/Makefile @@ -0,0 +1,12 @@ +.EXPORT_ALL_VARIABLES: + +initialize: start-docker +start-docker: + echo "Noop" + +test: initialize + ./vendor/bin/phpunit + +clean: stop-docker +stop-docker: + echo "Noop" diff --git a/src/Service/BedrockAgent/README.md b/src/Service/BedrockAgent/README.md new file mode 100644 index 000000000..9b32651f3 --- /dev/null +++ b/src/Service/BedrockAgent/README.md @@ -0,0 +1,20 @@ +# AsyncAws BedrockAgent Client + +![CI](https://github.com/async-aws/bedrock-agent/actions/workflows/ci.yml/badge.svg?branch=master) +![BC Check](https://github.com/async-aws/bedrock-agent/actions/workflows/checks.yml/badge.svg?branch=master) + +An API client for BedrockAgent. + +## Install + +```cli +composer require async-aws/bedrock-agent +``` + +## Documentation + +See https://async-aws.com/clients/bedrock-agent.html for documentation. + +## Contribute + +Contributions are welcome and appreciated. Please read https://async-aws.com/contribute/ diff --git a/src/Service/BedrockAgent/composer.json b/src/Service/BedrockAgent/composer.json new file mode 100644 index 000000000..3a6fa6d22 --- /dev/null +++ b/src/Service/BedrockAgent/composer.json @@ -0,0 +1,39 @@ +{ + "name": "async-aws/bedrock-agent", + "description": "BedrockAgent client, part of the AWS SDK provided by AsyncAws.", + "license": "MIT", + "type": "library", + "keywords": [ + "aws", + "amazon", + "sdk", + "async-aws", + "bedrock-agent" + ], + "require": { + "php": "^8.2", + "ext-json": "*", + "async-aws/core": "^1.9", + "symfony/polyfill-uuid": "^1.13.1" + }, + "require-dev": { + "phpunit/phpunit": "^11.5.42", + "symfony/error-handler": "^7.3.2 || ^8.0", + "symfony/phpunit-bridge": "^7.3.2 || ^8.0" + }, + "autoload": { + "psr-4": { + "AsyncAws\\BedrockAgent\\": "src" + } + }, + "autoload-dev": { + "psr-4": { + "AsyncAws\\BedrockAgent\\Tests\\": "tests/" + } + }, + "extra": { + "branch-alias": { + "dev-master": "1.0-dev" + } + } +} diff --git a/src/Service/BedrockAgent/phpunit.xml.dist b/src/Service/BedrockAgent/phpunit.xml.dist new file mode 100644 index 000000000..20f6abf4c --- /dev/null +++ b/src/Service/BedrockAgent/phpunit.xml.dist @@ -0,0 +1,31 @@ + + + + + ./src + + + trigger_deprecation + + + + + + + + ./tests/ + + + + + + diff --git a/src/Service/BedrockAgent/src/BedrockAgentClient.php b/src/Service/BedrockAgent/src/BedrockAgentClient.php new file mode 100644 index 000000000..1633b3ca8 --- /dev/null +++ b/src/Service/BedrockAgent/src/BedrockAgentClient.php @@ -0,0 +1,203 @@ +, + * '@region'?: string|null, + * }|DeleteKnowledgeBaseDocumentsRequest $input + * + * @throws AccessDeniedException + * @throws InternalServerException + * @throws ResourceNotFoundException + * @throws ServiceQuotaExceededException + * @throws ThrottlingException + * @throws ValidationException + */ + public function deleteKnowledgeBaseDocuments($input): DeleteKnowledgeBaseDocumentsResponse + { + $input = DeleteKnowledgeBaseDocumentsRequest::create($input); + $response = $this->getResponse($input->request(), new RequestContext(['operation' => 'DeleteKnowledgeBaseDocuments', 'region' => $input->getRegion(), 'exceptionMapping' => [ + 'AccessDeniedException' => AccessDeniedException::class, + 'InternalServerException' => InternalServerException::class, + 'ResourceNotFoundException' => ResourceNotFoundException::class, + 'ServiceQuotaExceededException' => ServiceQuotaExceededException::class, + 'ThrottlingException' => ThrottlingException::class, + 'ValidationException' => ValidationException::class, + ]])); + + return new DeleteKnowledgeBaseDocumentsResponse($response); + } + + /** + * Retrieves specific documents from a data source that is connected to a knowledge base. For more information, see + * Ingest changes directly into a knowledge base [^1] in the Amazon Bedrock User Guide. + * + * [^1]: https://docs.aws.amazon.com/bedrock/latest/userguide/kb-direct-ingestion.html + * + * @see https://docs.aws.amazon.com/bedrock/latest/APIReference/API_GetKnowledgeBaseDocuments.html + * @see https://docs.aws.amazon.com/aws-sdk-php/v3/api/api-bedrock-agent-2023-06-05.html#getknowledgebasedocuments + * + * @param array{ + * knowledgeBaseId: string, + * dataSourceId: string, + * documentIdentifiers: array, + * '@region'?: string|null, + * }|GetKnowledgeBaseDocumentsRequest $input + * + * @throws AccessDeniedException + * @throws InternalServerException + * @throws ResourceNotFoundException + * @throws ServiceQuotaExceededException + * @throws ThrottlingException + * @throws ValidationException + */ + public function getKnowledgeBaseDocuments($input): GetKnowledgeBaseDocumentsResponse + { + $input = GetKnowledgeBaseDocumentsRequest::create($input); + $response = $this->getResponse($input->request(), new RequestContext(['operation' => 'GetKnowledgeBaseDocuments', 'region' => $input->getRegion(), 'exceptionMapping' => [ + 'AccessDeniedException' => AccessDeniedException::class, + 'InternalServerException' => InternalServerException::class, + 'ResourceNotFoundException' => ResourceNotFoundException::class, + 'ServiceQuotaExceededException' => ServiceQuotaExceededException::class, + 'ThrottlingException' => ThrottlingException::class, + 'ValidationException' => ValidationException::class, + ]])); + + return new GetKnowledgeBaseDocumentsResponse($response); + } + + /** + * Ingests documents directly into the knowledge base that is connected to the data source. The `dataSourceType` + * specified in the content for each document must match the type of the data source that you specify in the header. For + * more information, see Ingest changes directly into a knowledge base [^1] in the Amazon Bedrock User Guide. + * + * [^1]: https://docs.aws.amazon.com/bedrock/latest/userguide/kb-direct-ingestion.html + * + * @see https://docs.aws.amazon.com/bedrock/latest/APIReference/API_IngestKnowledgeBaseDocuments.html + * @see https://docs.aws.amazon.com/aws-sdk-php/v3/api/api-bedrock-agent-2023-06-05.html#ingestknowledgebasedocuments + * + * @param array{ + * knowledgeBaseId: string, + * dataSourceId: string, + * clientToken?: string|null, + * documents: array, + * '@region'?: string|null, + * }|IngestKnowledgeBaseDocumentsRequest $input + * + * @throws AccessDeniedException + * @throws InternalServerException + * @throws ResourceNotFoundException + * @throws ServiceQuotaExceededException + * @throws ThrottlingException + * @throws ValidationException + */ + public function ingestKnowledgeBaseDocuments($input): IngestKnowledgeBaseDocumentsResponse + { + $input = IngestKnowledgeBaseDocumentsRequest::create($input); + $response = $this->getResponse($input->request(), new RequestContext(['operation' => 'IngestKnowledgeBaseDocuments', 'region' => $input->getRegion(), 'exceptionMapping' => [ + 'AccessDeniedException' => AccessDeniedException::class, + 'InternalServerException' => InternalServerException::class, + 'ResourceNotFoundException' => ResourceNotFoundException::class, + 'ServiceQuotaExceededException' => ServiceQuotaExceededException::class, + 'ThrottlingException' => ThrottlingException::class, + 'ValidationException' => ValidationException::class, + ]])); + + return new IngestKnowledgeBaseDocumentsResponse($response); + } + + /** + * Retrieves all the documents contained in a data source that is connected to a knowledge base. For more information, + * see Ingest changes directly into a knowledge base [^1] in the Amazon Bedrock User Guide. + * + * [^1]: https://docs.aws.amazon.com/bedrock/latest/userguide/kb-direct-ingestion.html + * + * @see https://docs.aws.amazon.com/bedrock/latest/APIReference/API_ListKnowledgeBaseDocuments.html + * @see https://docs.aws.amazon.com/aws-sdk-php/v3/api/api-bedrock-agent-2023-06-05.html#listknowledgebasedocuments + * + * @param array{ + * knowledgeBaseId: string, + * dataSourceId: string, + * maxResults?: int|null, + * nextToken?: string|null, + * '@region'?: string|null, + * }|ListKnowledgeBaseDocumentsRequest $input + * + * @throws AccessDeniedException + * @throws InternalServerException + * @throws ResourceNotFoundException + * @throws ServiceQuotaExceededException + * @throws ThrottlingException + * @throws ValidationException + */ + public function listKnowledgeBaseDocuments($input): ListKnowledgeBaseDocumentsResponse + { + $input = ListKnowledgeBaseDocumentsRequest::create($input); + $response = $this->getResponse($input->request(), new RequestContext(['operation' => 'ListKnowledgeBaseDocuments', 'region' => $input->getRegion(), 'exceptionMapping' => [ + 'AccessDeniedException' => AccessDeniedException::class, + 'InternalServerException' => InternalServerException::class, + 'ResourceNotFoundException' => ResourceNotFoundException::class, + 'ServiceQuotaExceededException' => ServiceQuotaExceededException::class, + 'ThrottlingException' => ThrottlingException::class, + 'ValidationException' => ValidationException::class, + ]])); + + return new ListKnowledgeBaseDocumentsResponse($response, $this, $input); + } + + protected function getAwsErrorFactory(): AwsErrorFactoryInterface + { + return new JsonRestAwsErrorFactory(); + } + + protected function getEndpointMetadata(?string $region): array + { + if (null === $region) { + $region = Configuration::DEFAULT_REGION; + } + + return [ + 'endpoint' => "https://bedrock-agent.$region.amazonaws.com", + 'signRegion' => $region, + 'signService' => 'bedrock', + 'signVersions' => ['v4'], + ]; + } +} diff --git a/src/Service/BedrockAgent/src/Enum/ContentDataSourceType.php b/src/Service/BedrockAgent/src/Enum/ContentDataSourceType.php new file mode 100644 index 000000000..e7726a918 --- /dev/null +++ b/src/Service/BedrockAgent/src/Enum/ContentDataSourceType.php @@ -0,0 +1,17 @@ + true, + self::S3 => true, + ][$value]); + } +} diff --git a/src/Service/BedrockAgent/src/Enum/CustomSourceType.php b/src/Service/BedrockAgent/src/Enum/CustomSourceType.php new file mode 100644 index 000000000..b04affe64 --- /dev/null +++ b/src/Service/BedrockAgent/src/Enum/CustomSourceType.php @@ -0,0 +1,17 @@ + true, + self::S3_LOCATION => true, + ][$value]); + } +} diff --git a/src/Service/BedrockAgent/src/Enum/DocumentStatus.php b/src/Service/BedrockAgent/src/Enum/DocumentStatus.php new file mode 100644 index 000000000..4f2470283 --- /dev/null +++ b/src/Service/BedrockAgent/src/Enum/DocumentStatus.php @@ -0,0 +1,37 @@ + true, + self::DELETING => true, + self::FAILED => true, + self::IGNORED => true, + self::INDEXED => true, + self::IN_PROGRESS => true, + self::METADATA_PARTIALLY_INDEXED => true, + self::METADATA_UPDATE_FAILED => true, + self::NOT_FOUND => true, + self::PARTIALLY_INDEXED => true, + self::PENDING => true, + self::STARTING => true, + ][$value]); + } +} diff --git a/src/Service/BedrockAgent/src/Enum/InlineContentType.php b/src/Service/BedrockAgent/src/Enum/InlineContentType.php new file mode 100644 index 000000000..bba1c3700 --- /dev/null +++ b/src/Service/BedrockAgent/src/Enum/InlineContentType.php @@ -0,0 +1,17 @@ + true, + self::TEXT => true, + ][$value]); + } +} diff --git a/src/Service/BedrockAgent/src/Enum/MetadataSourceType.php b/src/Service/BedrockAgent/src/Enum/MetadataSourceType.php new file mode 100644 index 000000000..ad270f41b --- /dev/null +++ b/src/Service/BedrockAgent/src/Enum/MetadataSourceType.php @@ -0,0 +1,17 @@ + true, + self::S3_LOCATION => true, + ][$value]); + } +} diff --git a/src/Service/BedrockAgent/src/Enum/MetadataValueType.php b/src/Service/BedrockAgent/src/Enum/MetadataValueType.php new file mode 100644 index 000000000..845acf296 --- /dev/null +++ b/src/Service/BedrockAgent/src/Enum/MetadataValueType.php @@ -0,0 +1,21 @@ + true, + self::NUMBER => true, + self::STRING => true, + self::STRING_LIST => true, + ][$value]); + } +} diff --git a/src/Service/BedrockAgent/src/Exception/AccessDeniedException.php b/src/Service/BedrockAgent/src/Exception/AccessDeniedException.php new file mode 100644 index 000000000..b77c5b6a4 --- /dev/null +++ b/src/Service/BedrockAgent/src/Exception/AccessDeniedException.php @@ -0,0 +1,12 @@ +fieldList; + } + + protected function populateResult(ResponseInterface $response): void + { + $data = $response->toArray(false); + + $this->fieldList = empty($data['fieldList']) ? [] : $this->populateResultValidationExceptionFieldList($data['fieldList']); + } + + private function populateResultValidationExceptionField(array $json): ValidationExceptionField + { + return new ValidationExceptionField([ + 'name' => (string) $json['name'], + 'message' => (string) $json['message'], + ]); + } + + /** + * @return ValidationExceptionField[] + */ + private function populateResultValidationExceptionFieldList(array $json): array + { + $items = []; + foreach ($json as $item) { + $items[] = $this->populateResultValidationExceptionField($item); + } + + return $items; + } +} diff --git a/src/Service/BedrockAgent/src/Input/DeleteKnowledgeBaseDocumentsRequest.php b/src/Service/BedrockAgent/src/Input/DeleteKnowledgeBaseDocumentsRequest.php new file mode 100644 index 000000000..919309d26 --- /dev/null +++ b/src/Service/BedrockAgent/src/Input/DeleteKnowledgeBaseDocumentsRequest.php @@ -0,0 +1,192 @@ +, + * '@region'?: string|null, + * } $input + */ + public function __construct(array $input = []) + { + $this->knowledgeBaseId = $input['knowledgeBaseId'] ?? null; + $this->dataSourceId = $input['dataSourceId'] ?? null; + $this->clientToken = $input['clientToken'] ?? null; + $this->documentIdentifiers = isset($input['documentIdentifiers']) ? array_map([DocumentIdentifier::class, 'create'], $input['documentIdentifiers']) : null; + parent::__construct($input); + } + + /** + * @param array{ + * knowledgeBaseId?: string, + * dataSourceId?: string, + * clientToken?: string|null, + * documentIdentifiers?: array, + * '@region'?: string|null, + * }|DeleteKnowledgeBaseDocumentsRequest $input + */ + public static function create($input): self + { + return $input instanceof self ? $input : new self($input); + } + + public function getClientToken(): ?string + { + return $this->clientToken; + } + + public function getDataSourceId(): ?string + { + return $this->dataSourceId; + } + + /** + * @return DocumentIdentifier[] + */ + public function getDocumentIdentifiers(): array + { + return $this->documentIdentifiers ?? []; + } + + public function getKnowledgeBaseId(): ?string + { + return $this->knowledgeBaseId; + } + + /** + * @internal + */ + public function request(): Request + { + // Prepare headers + $headers = [ + 'Content-Type' => 'application/json', + 'Accept' => 'application/json', + ]; + + // Prepare query + $query = []; + + // Prepare URI + $uri = []; + if (null === $v = $this->knowledgeBaseId) { + throw new InvalidArgument(\sprintf('Missing parameter "knowledgeBaseId" for "%s". The value cannot be null.', __CLASS__)); + } + $uri['knowledgeBaseId'] = $v; + if (null === $v = $this->dataSourceId) { + throw new InvalidArgument(\sprintf('Missing parameter "dataSourceId" for "%s". The value cannot be null.', __CLASS__)); + } + $uri['dataSourceId'] = $v; + $uriString = '/knowledgebases/' . rawurlencode($uri['knowledgeBaseId']) . '/datasources/' . rawurlencode($uri['dataSourceId']) . '/documents/deleteDocuments'; + + // Prepare Body + $bodyPayload = $this->requestBody(); + $body = empty($bodyPayload) ? '{}' : json_encode($bodyPayload, 4194304); + + // Return the Request + return new Request('POST', $uriString, $query, $headers, StreamFactory::create($body)); + } + + public function setClientToken(?string $value): self + { + $this->clientToken = $value; + + return $this; + } + + public function setDataSourceId(?string $value): self + { + $this->dataSourceId = $value; + + return $this; + } + + /** + * @param DocumentIdentifier[] $value + */ + public function setDocumentIdentifiers(array $value): self + { + $this->documentIdentifiers = $value; + + return $this; + } + + public function setKnowledgeBaseId(?string $value): self + { + $this->knowledgeBaseId = $value; + + return $this; + } + + private function requestBody(): array + { + $payload = []; + + if (null === $v = $this->clientToken) { + $v = uuid_create(\UUID_TYPE_RANDOM); + } + $payload['clientToken'] = $v; + if (null === $v = $this->documentIdentifiers) { + throw new InvalidArgument(\sprintf('Missing parameter "documentIdentifiers" for "%s". The value cannot be null.', __CLASS__)); + } + + $index = -1; + $payload['documentIdentifiers'] = []; + foreach ($v as $listValue) { + ++$index; + $payload['documentIdentifiers'][$index] = $listValue->requestBody(); + } + + return $payload; + } +} diff --git a/src/Service/BedrockAgent/src/Input/GetKnowledgeBaseDocumentsRequest.php b/src/Service/BedrockAgent/src/Input/GetKnowledgeBaseDocumentsRequest.php new file mode 100644 index 000000000..a1cf203ab --- /dev/null +++ b/src/Service/BedrockAgent/src/Input/GetKnowledgeBaseDocumentsRequest.php @@ -0,0 +1,162 @@ +, + * '@region'?: string|null, + * } $input + */ + public function __construct(array $input = []) + { + $this->knowledgeBaseId = $input['knowledgeBaseId'] ?? null; + $this->dataSourceId = $input['dataSourceId'] ?? null; + $this->documentIdentifiers = isset($input['documentIdentifiers']) ? array_map([DocumentIdentifier::class, 'create'], $input['documentIdentifiers']) : null; + parent::__construct($input); + } + + /** + * @param array{ + * knowledgeBaseId?: string, + * dataSourceId?: string, + * documentIdentifiers?: array, + * '@region'?: string|null, + * }|GetKnowledgeBaseDocumentsRequest $input + */ + public static function create($input): self + { + return $input instanceof self ? $input : new self($input); + } + + public function getDataSourceId(): ?string + { + return $this->dataSourceId; + } + + /** + * @return DocumentIdentifier[] + */ + public function getDocumentIdentifiers(): array + { + return $this->documentIdentifiers ?? []; + } + + public function getKnowledgeBaseId(): ?string + { + return $this->knowledgeBaseId; + } + + /** + * @internal + */ + public function request(): Request + { + // Prepare headers + $headers = [ + 'Content-Type' => 'application/json', + 'Accept' => 'application/json', + ]; + + // Prepare query + $query = []; + + // Prepare URI + $uri = []; + if (null === $v = $this->knowledgeBaseId) { + throw new InvalidArgument(\sprintf('Missing parameter "knowledgeBaseId" for "%s". The value cannot be null.', __CLASS__)); + } + $uri['knowledgeBaseId'] = $v; + if (null === $v = $this->dataSourceId) { + throw new InvalidArgument(\sprintf('Missing parameter "dataSourceId" for "%s". The value cannot be null.', __CLASS__)); + } + $uri['dataSourceId'] = $v; + $uriString = '/knowledgebases/' . rawurlencode($uri['knowledgeBaseId']) . '/datasources/' . rawurlencode($uri['dataSourceId']) . '/documents/getDocuments'; + + // Prepare Body + $bodyPayload = $this->requestBody(); + $body = empty($bodyPayload) ? '{}' : json_encode($bodyPayload, 4194304); + + // Return the Request + return new Request('POST', $uriString, $query, $headers, StreamFactory::create($body)); + } + + public function setDataSourceId(?string $value): self + { + $this->dataSourceId = $value; + + return $this; + } + + /** + * @param DocumentIdentifier[] $value + */ + public function setDocumentIdentifiers(array $value): self + { + $this->documentIdentifiers = $value; + + return $this; + } + + public function setKnowledgeBaseId(?string $value): self + { + $this->knowledgeBaseId = $value; + + return $this; + } + + private function requestBody(): array + { + $payload = []; + + if (null === $v = $this->documentIdentifiers) { + throw new InvalidArgument(\sprintf('Missing parameter "documentIdentifiers" for "%s". The value cannot be null.', __CLASS__)); + } + + $index = -1; + $payload['documentIdentifiers'] = []; + foreach ($v as $listValue) { + ++$index; + $payload['documentIdentifiers'][$index] = $listValue->requestBody(); + } + + return $payload; + } +} diff --git a/src/Service/BedrockAgent/src/Input/IngestKnowledgeBaseDocumentsRequest.php b/src/Service/BedrockAgent/src/Input/IngestKnowledgeBaseDocumentsRequest.php new file mode 100644 index 000000000..cee070946 --- /dev/null +++ b/src/Service/BedrockAgent/src/Input/IngestKnowledgeBaseDocumentsRequest.php @@ -0,0 +1,192 @@ +, + * '@region'?: string|null, + * } $input + */ + public function __construct(array $input = []) + { + $this->knowledgeBaseId = $input['knowledgeBaseId'] ?? null; + $this->dataSourceId = $input['dataSourceId'] ?? null; + $this->clientToken = $input['clientToken'] ?? null; + $this->documents = isset($input['documents']) ? array_map([KnowledgeBaseDocument::class, 'create'], $input['documents']) : null; + parent::__construct($input); + } + + /** + * @param array{ + * knowledgeBaseId?: string, + * dataSourceId?: string, + * clientToken?: string|null, + * documents?: array, + * '@region'?: string|null, + * }|IngestKnowledgeBaseDocumentsRequest $input + */ + public static function create($input): self + { + return $input instanceof self ? $input : new self($input); + } + + public function getClientToken(): ?string + { + return $this->clientToken; + } + + public function getDataSourceId(): ?string + { + return $this->dataSourceId; + } + + /** + * @return KnowledgeBaseDocument[] + */ + public function getDocuments(): array + { + return $this->documents ?? []; + } + + public function getKnowledgeBaseId(): ?string + { + return $this->knowledgeBaseId; + } + + /** + * @internal + */ + public function request(): Request + { + // Prepare headers + $headers = [ + 'Content-Type' => 'application/json', + 'Accept' => 'application/json', + ]; + + // Prepare query + $query = []; + + // Prepare URI + $uri = []; + if (null === $v = $this->knowledgeBaseId) { + throw new InvalidArgument(\sprintf('Missing parameter "knowledgeBaseId" for "%s". The value cannot be null.', __CLASS__)); + } + $uri['knowledgeBaseId'] = $v; + if (null === $v = $this->dataSourceId) { + throw new InvalidArgument(\sprintf('Missing parameter "dataSourceId" for "%s". The value cannot be null.', __CLASS__)); + } + $uri['dataSourceId'] = $v; + $uriString = '/knowledgebases/' . rawurlencode($uri['knowledgeBaseId']) . '/datasources/' . rawurlencode($uri['dataSourceId']) . '/documents'; + + // Prepare Body + $bodyPayload = $this->requestBody(); + $body = empty($bodyPayload) ? '{}' : json_encode($bodyPayload, 4194304); + + // Return the Request + return new Request('PUT', $uriString, $query, $headers, StreamFactory::create($body)); + } + + public function setClientToken(?string $value): self + { + $this->clientToken = $value; + + return $this; + } + + public function setDataSourceId(?string $value): self + { + $this->dataSourceId = $value; + + return $this; + } + + /** + * @param KnowledgeBaseDocument[] $value + */ + public function setDocuments(array $value): self + { + $this->documents = $value; + + return $this; + } + + public function setKnowledgeBaseId(?string $value): self + { + $this->knowledgeBaseId = $value; + + return $this; + } + + private function requestBody(): array + { + $payload = []; + + if (null === $v = $this->clientToken) { + $v = uuid_create(\UUID_TYPE_RANDOM); + } + $payload['clientToken'] = $v; + if (null === $v = $this->documents) { + throw new InvalidArgument(\sprintf('Missing parameter "documents" for "%s". The value cannot be null.', __CLASS__)); + } + + $index = -1; + $payload['documents'] = []; + foreach ($v as $listValue) { + ++$index; + $payload['documents'][$index] = $listValue->requestBody(); + } + + return $payload; + } +} diff --git a/src/Service/BedrockAgent/src/Input/ListKnowledgeBaseDocumentsRequest.php b/src/Service/BedrockAgent/src/Input/ListKnowledgeBaseDocumentsRequest.php new file mode 100644 index 000000000..e1c5f1003 --- /dev/null +++ b/src/Service/BedrockAgent/src/Input/ListKnowledgeBaseDocumentsRequest.php @@ -0,0 +1,174 @@ +knowledgeBaseId = $input['knowledgeBaseId'] ?? null; + $this->dataSourceId = $input['dataSourceId'] ?? null; + $this->maxResults = $input['maxResults'] ?? null; + $this->nextToken = $input['nextToken'] ?? null; + parent::__construct($input); + } + + /** + * @param array{ + * knowledgeBaseId?: string, + * dataSourceId?: string, + * maxResults?: int|null, + * nextToken?: string|null, + * '@region'?: string|null, + * }|ListKnowledgeBaseDocumentsRequest $input + */ + public static function create($input): self + { + return $input instanceof self ? $input : new self($input); + } + + public function getDataSourceId(): ?string + { + return $this->dataSourceId; + } + + public function getKnowledgeBaseId(): ?string + { + return $this->knowledgeBaseId; + } + + public function getMaxResults(): ?int + { + return $this->maxResults; + } + + public function getNextToken(): ?string + { + return $this->nextToken; + } + + /** + * @internal + */ + public function request(): Request + { + // Prepare headers + $headers = [ + 'Content-Type' => 'application/json', + 'Accept' => 'application/json', + ]; + + // Prepare query + $query = []; + + // Prepare URI + $uri = []; + if (null === $v = $this->knowledgeBaseId) { + throw new InvalidArgument(\sprintf('Missing parameter "knowledgeBaseId" for "%s". The value cannot be null.', __CLASS__)); + } + $uri['knowledgeBaseId'] = $v; + if (null === $v = $this->dataSourceId) { + throw new InvalidArgument(\sprintf('Missing parameter "dataSourceId" for "%s". The value cannot be null.', __CLASS__)); + } + $uri['dataSourceId'] = $v; + $uriString = '/knowledgebases/' . rawurlencode($uri['knowledgeBaseId']) . '/datasources/' . rawurlencode($uri['dataSourceId']) . '/documents'; + + // Prepare Body + $bodyPayload = $this->requestBody(); + $body = empty($bodyPayload) ? '{}' : json_encode($bodyPayload, 4194304); + + // Return the Request + return new Request('POST', $uriString, $query, $headers, StreamFactory::create($body)); + } + + public function setDataSourceId(?string $value): self + { + $this->dataSourceId = $value; + + return $this; + } + + public function setKnowledgeBaseId(?string $value): self + { + $this->knowledgeBaseId = $value; + + return $this; + } + + public function setMaxResults(?int $value): self + { + $this->maxResults = $value; + + return $this; + } + + public function setNextToken(?string $value): self + { + $this->nextToken = $value; + + return $this; + } + + private function requestBody(): array + { + $payload = []; + + if (null !== $v = $this->maxResults) { + $payload['maxResults'] = $v; + } + if (null !== $v = $this->nextToken) { + $payload['nextToken'] = $v; + } + + return $payload; + } +} diff --git a/src/Service/BedrockAgent/src/Result/DeleteKnowledgeBaseDocumentsResponse.php b/src/Service/BedrockAgent/src/Result/DeleteKnowledgeBaseDocumentsResponse.php new file mode 100644 index 000000000..6b478897d --- /dev/null +++ b/src/Service/BedrockAgent/src/Result/DeleteKnowledgeBaseDocumentsResponse.php @@ -0,0 +1,85 @@ +initialize(); + + return $this->documentDetails; + } + + protected function populateResult(Response $response): void + { + $data = $response->toArray(); + + $this->documentDetails = empty($data['documentDetails']) ? [] : $this->populateResultKnowledgeBaseDocumentDetails($data['documentDetails']); + } + + private function populateResultCustomDocumentIdentifier(array $json): CustomDocumentIdentifier + { + return new CustomDocumentIdentifier([ + 'id' => (string) $json['id'], + ]); + } + + private function populateResultDocumentIdentifier(array $json): DocumentIdentifier + { + return new DocumentIdentifier([ + 'dataSourceType' => (string) $json['dataSourceType'], + 's3' => empty($json['s3']) ? null : $this->populateResultS3Location($json['s3']), + 'custom' => empty($json['custom']) ? null : $this->populateResultCustomDocumentIdentifier($json['custom']), + ]); + } + + private function populateResultKnowledgeBaseDocumentDetail(array $json): KnowledgeBaseDocumentDetail + { + return new KnowledgeBaseDocumentDetail([ + 'knowledgeBaseId' => (string) $json['knowledgeBaseId'], + 'dataSourceId' => (string) $json['dataSourceId'], + 'status' => (string) $json['status'], + 'identifier' => $this->populateResultDocumentIdentifier($json['identifier']), + 'statusReason' => isset($json['statusReason']) ? (string) $json['statusReason'] : null, + 'updatedAt' => isset($json['updatedAt']) && ($d = \DateTimeImmutable::createFromFormat(\DateTimeInterface::ATOM, $json['updatedAt'])) ? $d : null, + ]); + } + + /** + * @return KnowledgeBaseDocumentDetail[] + */ + private function populateResultKnowledgeBaseDocumentDetails(array $json): array + { + $items = []; + foreach ($json as $item) { + $items[] = $this->populateResultKnowledgeBaseDocumentDetail($item); + } + + return $items; + } + + private function populateResultS3Location(array $json): S3Location + { + return new S3Location([ + 'uri' => (string) $json['uri'], + ]); + } +} diff --git a/src/Service/BedrockAgent/src/Result/GetKnowledgeBaseDocumentsResponse.php b/src/Service/BedrockAgent/src/Result/GetKnowledgeBaseDocumentsResponse.php new file mode 100644 index 000000000..5f3157b86 --- /dev/null +++ b/src/Service/BedrockAgent/src/Result/GetKnowledgeBaseDocumentsResponse.php @@ -0,0 +1,85 @@ +initialize(); + + return $this->documentDetails; + } + + protected function populateResult(Response $response): void + { + $data = $response->toArray(); + + $this->documentDetails = empty($data['documentDetails']) ? [] : $this->populateResultKnowledgeBaseDocumentDetails($data['documentDetails']); + } + + private function populateResultCustomDocumentIdentifier(array $json): CustomDocumentIdentifier + { + return new CustomDocumentIdentifier([ + 'id' => (string) $json['id'], + ]); + } + + private function populateResultDocumentIdentifier(array $json): DocumentIdentifier + { + return new DocumentIdentifier([ + 'dataSourceType' => (string) $json['dataSourceType'], + 's3' => empty($json['s3']) ? null : $this->populateResultS3Location($json['s3']), + 'custom' => empty($json['custom']) ? null : $this->populateResultCustomDocumentIdentifier($json['custom']), + ]); + } + + private function populateResultKnowledgeBaseDocumentDetail(array $json): KnowledgeBaseDocumentDetail + { + return new KnowledgeBaseDocumentDetail([ + 'knowledgeBaseId' => (string) $json['knowledgeBaseId'], + 'dataSourceId' => (string) $json['dataSourceId'], + 'status' => (string) $json['status'], + 'identifier' => $this->populateResultDocumentIdentifier($json['identifier']), + 'statusReason' => isset($json['statusReason']) ? (string) $json['statusReason'] : null, + 'updatedAt' => isset($json['updatedAt']) && ($d = \DateTimeImmutable::createFromFormat(\DateTimeInterface::ATOM, $json['updatedAt'])) ? $d : null, + ]); + } + + /** + * @return KnowledgeBaseDocumentDetail[] + */ + private function populateResultKnowledgeBaseDocumentDetails(array $json): array + { + $items = []; + foreach ($json as $item) { + $items[] = $this->populateResultKnowledgeBaseDocumentDetail($item); + } + + return $items; + } + + private function populateResultS3Location(array $json): S3Location + { + return new S3Location([ + 'uri' => (string) $json['uri'], + ]); + } +} diff --git a/src/Service/BedrockAgent/src/Result/IngestKnowledgeBaseDocumentsResponse.php b/src/Service/BedrockAgent/src/Result/IngestKnowledgeBaseDocumentsResponse.php new file mode 100644 index 000000000..02dafbcf2 --- /dev/null +++ b/src/Service/BedrockAgent/src/Result/IngestKnowledgeBaseDocumentsResponse.php @@ -0,0 +1,85 @@ +initialize(); + + return $this->documentDetails; + } + + protected function populateResult(Response $response): void + { + $data = $response->toArray(); + + $this->documentDetails = empty($data['documentDetails']) ? [] : $this->populateResultKnowledgeBaseDocumentDetails($data['documentDetails']); + } + + private function populateResultCustomDocumentIdentifier(array $json): CustomDocumentIdentifier + { + return new CustomDocumentIdentifier([ + 'id' => (string) $json['id'], + ]); + } + + private function populateResultDocumentIdentifier(array $json): DocumentIdentifier + { + return new DocumentIdentifier([ + 'dataSourceType' => (string) $json['dataSourceType'], + 's3' => empty($json['s3']) ? null : $this->populateResultS3Location($json['s3']), + 'custom' => empty($json['custom']) ? null : $this->populateResultCustomDocumentIdentifier($json['custom']), + ]); + } + + private function populateResultKnowledgeBaseDocumentDetail(array $json): KnowledgeBaseDocumentDetail + { + return new KnowledgeBaseDocumentDetail([ + 'knowledgeBaseId' => (string) $json['knowledgeBaseId'], + 'dataSourceId' => (string) $json['dataSourceId'], + 'status' => (string) $json['status'], + 'identifier' => $this->populateResultDocumentIdentifier($json['identifier']), + 'statusReason' => isset($json['statusReason']) ? (string) $json['statusReason'] : null, + 'updatedAt' => isset($json['updatedAt']) && ($d = \DateTimeImmutable::createFromFormat(\DateTimeInterface::ATOM, $json['updatedAt'])) ? $d : null, + ]); + } + + /** + * @return KnowledgeBaseDocumentDetail[] + */ + private function populateResultKnowledgeBaseDocumentDetails(array $json): array + { + $items = []; + foreach ($json as $item) { + $items[] = $this->populateResultKnowledgeBaseDocumentDetail($item); + } + + return $items; + } + + private function populateResultS3Location(array $json): S3Location + { + return new S3Location([ + 'uri' => (string) $json['uri'], + ]); + } +} diff --git a/src/Service/BedrockAgent/src/Result/ListKnowledgeBaseDocumentsResponse.php b/src/Service/BedrockAgent/src/Result/ListKnowledgeBaseDocumentsResponse.php new file mode 100644 index 000000000..c88ea04b4 --- /dev/null +++ b/src/Service/BedrockAgent/src/Result/ListKnowledgeBaseDocumentsResponse.php @@ -0,0 +1,151 @@ + + */ +class ListKnowledgeBaseDocumentsResponse extends Result implements \IteratorAggregate +{ + /** + * A list of objects, each of which contains information about the documents that were retrieved. + * + * @var KnowledgeBaseDocumentDetail[] + */ + private $documentDetails; + + /** + * If the total number of results is greater than the `maxResults` value provided in the request, use this token when + * making another request in the `nextToken` field to return the next batch of results. + * + * @var string|null + */ + private $nextToken; + + /** + * @param bool $currentPageOnly When true, iterates over items of the current page. Otherwise also fetch items in the next pages. + * + * @return iterable + */ + public function getDocumentDetails(bool $currentPageOnly = false): iterable + { + if ($currentPageOnly) { + $this->initialize(); + yield from $this->documentDetails; + + return; + } + + $client = $this->awsClient; + if (!$client instanceof BedrockAgentClient) { + throw new InvalidArgument('missing client injected in paginated result'); + } + if (!$this->input instanceof ListKnowledgeBaseDocumentsRequest) { + throw new InvalidArgument('missing last request injected in paginated result'); + } + $input = clone $this->input; + $page = $this; + while (true) { + $page->initialize(); + if (null !== $page->nextToken) { + $input->setNextToken($page->nextToken); + + $this->registerPrefetch($nextPage = $client->listKnowledgeBaseDocuments($input)); + } else { + $nextPage = null; + } + + yield from $page->documentDetails; + + if (null === $nextPage) { + break; + } + + $this->unregisterPrefetch($nextPage); + $page = $nextPage; + } + } + + /** + * Iterates over documentDetails. + * + * @return \Traversable + */ + public function getIterator(): \Traversable + { + yield from $this->getDocumentDetails(); + } + + public function getNextToken(): ?string + { + $this->initialize(); + + return $this->nextToken; + } + + protected function populateResult(Response $response): void + { + $data = $response->toArray(); + + $this->documentDetails = $this->populateResultKnowledgeBaseDocumentDetails($data['documentDetails'] ?? []); + $this->nextToken = isset($data['nextToken']) ? (string) $data['nextToken'] : null; + } + + private function populateResultCustomDocumentIdentifier(array $json): CustomDocumentIdentifier + { + return new CustomDocumentIdentifier([ + 'id' => (string) $json['id'], + ]); + } + + private function populateResultDocumentIdentifier(array $json): DocumentIdentifier + { + return new DocumentIdentifier([ + 'dataSourceType' => (string) $json['dataSourceType'], + 's3' => empty($json['s3']) ? null : $this->populateResultS3Location($json['s3']), + 'custom' => empty($json['custom']) ? null : $this->populateResultCustomDocumentIdentifier($json['custom']), + ]); + } + + private function populateResultKnowledgeBaseDocumentDetail(array $json): KnowledgeBaseDocumentDetail + { + return new KnowledgeBaseDocumentDetail([ + 'knowledgeBaseId' => (string) $json['knowledgeBaseId'], + 'dataSourceId' => (string) $json['dataSourceId'], + 'status' => (string) $json['status'], + 'identifier' => $this->populateResultDocumentIdentifier($json['identifier']), + 'statusReason' => isset($json['statusReason']) ? (string) $json['statusReason'] : null, + 'updatedAt' => isset($json['updatedAt']) && ($d = \DateTimeImmutable::createFromFormat(\DateTimeInterface::ATOM, $json['updatedAt'])) ? $d : null, + ]); + } + + /** + * @return KnowledgeBaseDocumentDetail[] + */ + private function populateResultKnowledgeBaseDocumentDetails(array $json): array + { + $items = []; + foreach ($json as $item) { + $items[] = $this->populateResultKnowledgeBaseDocumentDetail($item); + } + + return $items; + } + + private function populateResultS3Location(array $json): S3Location + { + return new S3Location([ + 'uri' => (string) $json['uri'], + ]); + } +} diff --git a/src/Service/BedrockAgent/src/ValueObject/ByteContentDoc.php b/src/Service/BedrockAgent/src/ValueObject/ByteContentDoc.php new file mode 100644 index 000000000..cfbc4f7ac --- /dev/null +++ b/src/Service/BedrockAgent/src/ValueObject/ByteContentDoc.php @@ -0,0 +1,103 @@ +mimeType = $input['mimeType'] ?? $this->throwException(new InvalidArgument('Missing required field "mimeType".')); + $this->data = $input['data'] ?? $this->throwException(new InvalidArgument('Missing required field "data".')); + } + + /** + * @param array{ + * mimeType: string, + * data: string, + * }|ByteContentDoc $input + */ + public static function create($input): self + { + return $input instanceof self ? $input : new self($input); + } + + public function getData(): string + { + return $this->data; + } + + public function getMimeType(): string + { + return $this->mimeType; + } + + /** + * @internal + */ + public function requestBody(): array + { + $payload = []; + $v = $this->mimeType; + $payload['mimeType'] = $v; + $v = $this->data; + $payload['data'] = base64_encode($v); + + return $payload; + } + + /** + * @return never + */ + private function throwException(\Throwable $exception) + { + throw $exception; + } +} diff --git a/src/Service/BedrockAgent/src/ValueObject/CustomContent.php b/src/Service/BedrockAgent/src/ValueObject/CustomContent.php new file mode 100644 index 000000000..f8c333a34 --- /dev/null +++ b/src/Service/BedrockAgent/src/ValueObject/CustomContent.php @@ -0,0 +1,124 @@ +customDocumentIdentifier = isset($input['customDocumentIdentifier']) ? CustomDocumentIdentifier::create($input['customDocumentIdentifier']) : $this->throwException(new InvalidArgument('Missing required field "customDocumentIdentifier".')); + $this->sourceType = $input['sourceType'] ?? $this->throwException(new InvalidArgument('Missing required field "sourceType".')); + $this->s3Location = isset($input['s3Location']) ? CustomS3Location::create($input['s3Location']) : null; + $this->inlineContent = isset($input['inlineContent']) ? InlineContent::create($input['inlineContent']) : null; + } + + /** + * @param array{ + * customDocumentIdentifier: CustomDocumentIdentifier|array, + * sourceType: CustomSourceType::*, + * s3Location?: CustomS3Location|array|null, + * inlineContent?: InlineContent|array|null, + * }|CustomContent $input + */ + public static function create($input): self + { + return $input instanceof self ? $input : new self($input); + } + + public function getCustomDocumentIdentifier(): CustomDocumentIdentifier + { + return $this->customDocumentIdentifier; + } + + public function getInlineContent(): ?InlineContent + { + return $this->inlineContent; + } + + public function getS3Location(): ?CustomS3Location + { + return $this->s3Location; + } + + /** + * @return CustomSourceType::* + */ + public function getSourceType(): string + { + return $this->sourceType; + } + + /** + * @internal + */ + public function requestBody(): array + { + $payload = []; + $v = $this->customDocumentIdentifier; + $payload['customDocumentIdentifier'] = $v->requestBody(); + $v = $this->sourceType; + if (!CustomSourceType::exists($v)) { + throw new InvalidArgument(\sprintf('Invalid parameter "sourceType" for "%s". The value "%s" is not a valid "CustomSourceType".', __CLASS__, $v)); + } + $payload['sourceType'] = $v; + if (null !== $v = $this->s3Location) { + $payload['s3Location'] = $v->requestBody(); + } + if (null !== $v = $this->inlineContent) { + $payload['inlineContent'] = $v->requestBody(); + } + + return $payload; + } + + /** + * @return never + */ + private function throwException(\Throwable $exception) + { + throw $exception; + } +} diff --git a/src/Service/BedrockAgent/src/ValueObject/CustomDocumentIdentifier.php b/src/Service/BedrockAgent/src/ValueObject/CustomDocumentIdentifier.php new file mode 100644 index 000000000..4c6563e52 --- /dev/null +++ b/src/Service/BedrockAgent/src/ValueObject/CustomDocumentIdentifier.php @@ -0,0 +1,63 @@ +id = $input['id'] ?? $this->throwException(new InvalidArgument('Missing required field "id".')); + } + + /** + * @param array{ + * id: string, + * }|CustomDocumentIdentifier $input + */ + public static function create($input): self + { + return $input instanceof self ? $input : new self($input); + } + + public function getId(): string + { + return $this->id; + } + + /** + * @internal + */ + public function requestBody(): array + { + $payload = []; + $v = $this->id; + $payload['id'] = $v; + + return $payload; + } + + /** + * @return never + */ + private function throwException(\Throwable $exception) + { + throw $exception; + } +} diff --git a/src/Service/BedrockAgent/src/ValueObject/CustomS3Location.php b/src/Service/BedrockAgent/src/ValueObject/CustomS3Location.php new file mode 100644 index 000000000..3267a9192 --- /dev/null +++ b/src/Service/BedrockAgent/src/ValueObject/CustomS3Location.php @@ -0,0 +1,82 @@ +uri = $input['uri'] ?? $this->throwException(new InvalidArgument('Missing required field "uri".')); + $this->bucketOwnerAccountId = $input['bucketOwnerAccountId'] ?? null; + } + + /** + * @param array{ + * uri: string, + * bucketOwnerAccountId?: string|null, + * }|CustomS3Location $input + */ + public static function create($input): self + { + return $input instanceof self ? $input : new self($input); + } + + public function getBucketOwnerAccountId(): ?string + { + return $this->bucketOwnerAccountId; + } + + public function getUri(): string + { + return $this->uri; + } + + /** + * @internal + */ + public function requestBody(): array + { + $payload = []; + $v = $this->uri; + $payload['uri'] = $v; + if (null !== $v = $this->bucketOwnerAccountId) { + $payload['bucketOwnerAccountId'] = $v; + } + + return $payload; + } + + /** + * @return never + */ + private function throwException(\Throwable $exception) + { + throw $exception; + } +} diff --git a/src/Service/BedrockAgent/src/ValueObject/DocumentContent.php b/src/Service/BedrockAgent/src/ValueObject/DocumentContent.php new file mode 100644 index 000000000..aa7e3b425 --- /dev/null +++ b/src/Service/BedrockAgent/src/ValueObject/DocumentContent.php @@ -0,0 +1,107 @@ +dataSourceType = $input['dataSourceType'] ?? $this->throwException(new InvalidArgument('Missing required field "dataSourceType".')); + $this->custom = isset($input['custom']) ? CustomContent::create($input['custom']) : null; + $this->s3 = isset($input['s3']) ? S3Content::create($input['s3']) : null; + } + + /** + * @param array{ + * dataSourceType: ContentDataSourceType::*, + * custom?: CustomContent|array|null, + * s3?: S3Content|array|null, + * }|DocumentContent $input + */ + public static function create($input): self + { + return $input instanceof self ? $input : new self($input); + } + + public function getCustom(): ?CustomContent + { + return $this->custom; + } + + /** + * @return ContentDataSourceType::* + */ + public function getDataSourceType(): string + { + return $this->dataSourceType; + } + + public function getS3(): ?S3Content + { + return $this->s3; + } + + /** + * @internal + */ + public function requestBody(): array + { + $payload = []; + $v = $this->dataSourceType; + if (!ContentDataSourceType::exists($v)) { + throw new InvalidArgument(\sprintf('Invalid parameter "dataSourceType" for "%s". The value "%s" is not a valid "ContentDataSourceType".', __CLASS__, $v)); + } + $payload['dataSourceType'] = $v; + if (null !== $v = $this->custom) { + $payload['custom'] = $v->requestBody(); + } + if (null !== $v = $this->s3) { + $payload['s3'] = $v->requestBody(); + } + + return $payload; + } + + /** + * @return never + */ + private function throwException(\Throwable $exception) + { + throw $exception; + } +} diff --git a/src/Service/BedrockAgent/src/ValueObject/DocumentIdentifier.php b/src/Service/BedrockAgent/src/ValueObject/DocumentIdentifier.php new file mode 100644 index 000000000..a827e4933 --- /dev/null +++ b/src/Service/BedrockAgent/src/ValueObject/DocumentIdentifier.php @@ -0,0 +1,106 @@ +dataSourceType = $input['dataSourceType'] ?? $this->throwException(new InvalidArgument('Missing required field "dataSourceType".')); + $this->s3 = isset($input['s3']) ? S3Location::create($input['s3']) : null; + $this->custom = isset($input['custom']) ? CustomDocumentIdentifier::create($input['custom']) : null; + } + + /** + * @param array{ + * dataSourceType: ContentDataSourceType::*, + * s3?: S3Location|array|null, + * custom?: CustomDocumentIdentifier|array|null, + * }|DocumentIdentifier $input + */ + public static function create($input): self + { + return $input instanceof self ? $input : new self($input); + } + + public function getCustom(): ?CustomDocumentIdentifier + { + return $this->custom; + } + + /** + * @return ContentDataSourceType::* + */ + public function getDataSourceType(): string + { + return $this->dataSourceType; + } + + public function getS3(): ?S3Location + { + return $this->s3; + } + + /** + * @internal + */ + public function requestBody(): array + { + $payload = []; + $v = $this->dataSourceType; + if (!ContentDataSourceType::exists($v)) { + throw new InvalidArgument(\sprintf('Invalid parameter "dataSourceType" for "%s". The value "%s" is not a valid "ContentDataSourceType".', __CLASS__, $v)); + } + $payload['dataSourceType'] = $v; + if (null !== $v = $this->s3) { + $payload['s3'] = $v->requestBody(); + } + if (null !== $v = $this->custom) { + $payload['custom'] = $v->requestBody(); + } + + return $payload; + } + + /** + * @return never + */ + private function throwException(\Throwable $exception) + { + throw $exception; + } +} diff --git a/src/Service/BedrockAgent/src/ValueObject/DocumentMetadata.php b/src/Service/BedrockAgent/src/ValueObject/DocumentMetadata.php new file mode 100644 index 000000000..18fffba76 --- /dev/null +++ b/src/Service/BedrockAgent/src/ValueObject/DocumentMetadata.php @@ -0,0 +1,116 @@ +|null, + * s3Location?: CustomS3Location|array|null, + * } $input + */ + public function __construct(array $input) + { + $this->type = $input['type'] ?? $this->throwException(new InvalidArgument('Missing required field "type".')); + $this->inlineAttributes = isset($input['inlineAttributes']) ? array_map([MetadataAttribute::class, 'create'], $input['inlineAttributes']) : null; + $this->s3Location = isset($input['s3Location']) ? CustomS3Location::create($input['s3Location']) : null; + } + + /** + * @param array{ + * type: MetadataSourceType::*, + * inlineAttributes?: array|null, + * s3Location?: CustomS3Location|array|null, + * }|DocumentMetadata $input + */ + public static function create($input): self + { + return $input instanceof self ? $input : new self($input); + } + + /** + * @return MetadataAttribute[] + */ + public function getInlineAttributes(): array + { + return $this->inlineAttributes ?? []; + } + + public function getS3Location(): ?CustomS3Location + { + return $this->s3Location; + } + + /** + * @return MetadataSourceType::* + */ + public function getType(): string + { + return $this->type; + } + + /** + * @internal + */ + public function requestBody(): array + { + $payload = []; + $v = $this->type; + if (!MetadataSourceType::exists($v)) { + throw new InvalidArgument(\sprintf('Invalid parameter "type" for "%s". The value "%s" is not a valid "MetadataSourceType".', __CLASS__, $v)); + } + $payload['type'] = $v; + if (null !== $v = $this->inlineAttributes) { + $index = -1; + $payload['inlineAttributes'] = []; + foreach ($v as $listValue) { + ++$index; + $payload['inlineAttributes'][$index] = $listValue->requestBody(); + } + } + if (null !== $v = $this->s3Location) { + $payload['s3Location'] = $v->requestBody(); + } + + return $payload; + } + + /** + * @return never + */ + private function throwException(\Throwable $exception) + { + throw $exception; + } +} diff --git a/src/Service/BedrockAgent/src/ValueObject/InlineContent.php b/src/Service/BedrockAgent/src/ValueObject/InlineContent.php new file mode 100644 index 000000000..44117a25c --- /dev/null +++ b/src/Service/BedrockAgent/src/ValueObject/InlineContent.php @@ -0,0 +1,107 @@ +type = $input['type'] ?? $this->throwException(new InvalidArgument('Missing required field "type".')); + $this->byteContent = isset($input['byteContent']) ? ByteContentDoc::create($input['byteContent']) : null; + $this->textContent = isset($input['textContent']) ? TextContentDoc::create($input['textContent']) : null; + } + + /** + * @param array{ + * type: InlineContentType::*, + * byteContent?: ByteContentDoc|array|null, + * textContent?: TextContentDoc|array|null, + * }|InlineContent $input + */ + public static function create($input): self + { + return $input instanceof self ? $input : new self($input); + } + + public function getByteContent(): ?ByteContentDoc + { + return $this->byteContent; + } + + public function getTextContent(): ?TextContentDoc + { + return $this->textContent; + } + + /** + * @return InlineContentType::* + */ + public function getType(): string + { + return $this->type; + } + + /** + * @internal + */ + public function requestBody(): array + { + $payload = []; + $v = $this->type; + if (!InlineContentType::exists($v)) { + throw new InvalidArgument(\sprintf('Invalid parameter "type" for "%s". The value "%s" is not a valid "InlineContentType".', __CLASS__, $v)); + } + $payload['type'] = $v; + if (null !== $v = $this->byteContent) { + $payload['byteContent'] = $v->requestBody(); + } + if (null !== $v = $this->textContent) { + $payload['textContent'] = $v->requestBody(); + } + + return $payload; + } + + /** + * @return never + */ + private function throwException(\Throwable $exception) + { + throw $exception; + } +} diff --git a/src/Service/BedrockAgent/src/ValueObject/KnowledgeBaseDocument.php b/src/Service/BedrockAgent/src/ValueObject/KnowledgeBaseDocument.php new file mode 100644 index 000000000..b47ac687c --- /dev/null +++ b/src/Service/BedrockAgent/src/ValueObject/KnowledgeBaseDocument.php @@ -0,0 +1,81 @@ +metadata = isset($input['metadata']) ? DocumentMetadata::create($input['metadata']) : null; + $this->content = isset($input['content']) ? DocumentContent::create($input['content']) : $this->throwException(new InvalidArgument('Missing required field "content".')); + } + + /** + * @param array{ + * metadata?: DocumentMetadata|array|null, + * content: DocumentContent|array, + * }|KnowledgeBaseDocument $input + */ + public static function create($input): self + { + return $input instanceof self ? $input : new self($input); + } + + public function getContent(): DocumentContent + { + return $this->content; + } + + public function getMetadata(): ?DocumentMetadata + { + return $this->metadata; + } + + /** + * @internal + */ + public function requestBody(): array + { + $payload = []; + if (null !== $v = $this->metadata) { + $payload['metadata'] = $v->requestBody(); + } + $v = $this->content; + $payload['content'] = $v->requestBody(); + + return $payload; + } + + /** + * @return never + */ + private function throwException(\Throwable $exception) + { + throw $exception; + } +} diff --git a/src/Service/BedrockAgent/src/ValueObject/KnowledgeBaseDocumentDetail.php b/src/Service/BedrockAgent/src/ValueObject/KnowledgeBaseDocumentDetail.php new file mode 100644 index 000000000..b110208e3 --- /dev/null +++ b/src/Service/BedrockAgent/src/ValueObject/KnowledgeBaseDocumentDetail.php @@ -0,0 +1,144 @@ +knowledgeBaseId = $input['knowledgeBaseId'] ?? $this->throwException(new InvalidArgument('Missing required field "knowledgeBaseId".')); + $this->dataSourceId = $input['dataSourceId'] ?? $this->throwException(new InvalidArgument('Missing required field "dataSourceId".')); + $this->status = $input['status'] ?? $this->throwException(new InvalidArgument('Missing required field "status".')); + $this->identifier = isset($input['identifier']) ? DocumentIdentifier::create($input['identifier']) : $this->throwException(new InvalidArgument('Missing required field "identifier".')); + $this->statusReason = $input['statusReason'] ?? null; + $this->updatedAt = $input['updatedAt'] ?? null; + } + + /** + * @param array{ + * knowledgeBaseId: string, + * dataSourceId: string, + * status: DocumentStatus::*, + * identifier: DocumentIdentifier|array, + * statusReason?: string|null, + * updatedAt?: \DateTimeImmutable|null, + * }|KnowledgeBaseDocumentDetail $input + */ + public static function create($input): self + { + return $input instanceof self ? $input : new self($input); + } + + public function getDataSourceId(): string + { + return $this->dataSourceId; + } + + public function getIdentifier(): DocumentIdentifier + { + return $this->identifier; + } + + public function getKnowledgeBaseId(): string + { + return $this->knowledgeBaseId; + } + + /** + * @return DocumentStatus::* + */ + public function getStatus(): string + { + return $this->status; + } + + public function getStatusReason(): ?string + { + return $this->statusReason; + } + + public function getUpdatedAt(): ?\DateTimeImmutable + { + return $this->updatedAt; + } + + /** + * @return never + */ + private function throwException(\Throwable $exception) + { + throw $exception; + } +} diff --git a/src/Service/BedrockAgent/src/ValueObject/MetadataAttribute.php b/src/Service/BedrockAgent/src/ValueObject/MetadataAttribute.php new file mode 100644 index 000000000..80caf5627 --- /dev/null +++ b/src/Service/BedrockAgent/src/ValueObject/MetadataAttribute.php @@ -0,0 +1,80 @@ +key = $input['key'] ?? $this->throwException(new InvalidArgument('Missing required field "key".')); + $this->value = isset($input['value']) ? MetadataAttributeValue::create($input['value']) : $this->throwException(new InvalidArgument('Missing required field "value".')); + } + + /** + * @param array{ + * key: string, + * value: MetadataAttributeValue|array, + * }|MetadataAttribute $input + */ + public static function create($input): self + { + return $input instanceof self ? $input : new self($input); + } + + public function getKey(): string + { + return $this->key; + } + + public function getValue(): MetadataAttributeValue + { + return $this->value; + } + + /** + * @internal + */ + public function requestBody(): array + { + $payload = []; + $v = $this->key; + $payload['key'] = $v; + $v = $this->value; + $payload['value'] = $v->requestBody(); + + return $payload; + } + + /** + * @return never + */ + private function throwException(\Throwable $exception) + { + throw $exception; + } +} diff --git a/src/Service/BedrockAgent/src/ValueObject/MetadataAttributeValue.php b/src/Service/BedrockAgent/src/ValueObject/MetadataAttributeValue.php new file mode 100644 index 000000000..1cfd7262e --- /dev/null +++ b/src/Service/BedrockAgent/src/ValueObject/MetadataAttributeValue.php @@ -0,0 +1,150 @@ +type = $input['type'] ?? $this->throwException(new InvalidArgument('Missing required field "type".')); + $this->numberValue = $input['numberValue'] ?? null; + $this->booleanValue = $input['booleanValue'] ?? null; + $this->stringValue = $input['stringValue'] ?? null; + $this->stringListValue = $input['stringListValue'] ?? null; + } + + /** + * @param array{ + * type: MetadataValueType::*, + * numberValue?: float|null, + * booleanValue?: bool|null, + * stringValue?: string|null, + * stringListValue?: string[]|null, + * }|MetadataAttributeValue $input + */ + public static function create($input): self + { + return $input instanceof self ? $input : new self($input); + } + + public function getBooleanValue(): ?bool + { + return $this->booleanValue; + } + + public function getNumberValue(): ?float + { + return $this->numberValue; + } + + /** + * @return string[] + */ + public function getStringListValue(): array + { + return $this->stringListValue ?? []; + } + + public function getStringValue(): ?string + { + return $this->stringValue; + } + + /** + * @return MetadataValueType::* + */ + public function getType(): string + { + return $this->type; + } + + /** + * @internal + */ + public function requestBody(): array + { + $payload = []; + $v = $this->type; + if (!MetadataValueType::exists($v)) { + throw new InvalidArgument(\sprintf('Invalid parameter "type" for "%s". The value "%s" is not a valid "MetadataValueType".', __CLASS__, $v)); + } + $payload['type'] = $v; + if (null !== $v = $this->numberValue) { + $payload['numberValue'] = $v; + } + if (null !== $v = $this->booleanValue) { + $payload['booleanValue'] = (bool) $v; + } + if (null !== $v = $this->stringValue) { + $payload['stringValue'] = $v; + } + if (null !== $v = $this->stringListValue) { + $index = -1; + $payload['stringListValue'] = []; + foreach ($v as $listValue) { + ++$index; + $payload['stringListValue'][$index] = $listValue; + } + } + + return $payload; + } + + /** + * @return never + */ + private function throwException(\Throwable $exception) + { + throw $exception; + } +} diff --git a/src/Service/BedrockAgent/src/ValueObject/S3Content.php b/src/Service/BedrockAgent/src/ValueObject/S3Content.php new file mode 100644 index 000000000..0184ec284 --- /dev/null +++ b/src/Service/BedrockAgent/src/ValueObject/S3Content.php @@ -0,0 +1,63 @@ +s3Location = isset($input['s3Location']) ? S3Location::create($input['s3Location']) : $this->throwException(new InvalidArgument('Missing required field "s3Location".')); + } + + /** + * @param array{ + * s3Location: S3Location|array, + * }|S3Content $input + */ + public static function create($input): self + { + return $input instanceof self ? $input : new self($input); + } + + public function getS3Location(): S3Location + { + return $this->s3Location; + } + + /** + * @internal + */ + public function requestBody(): array + { + $payload = []; + $v = $this->s3Location; + $payload['s3Location'] = $v->requestBody(); + + return $payload; + } + + /** + * @return never + */ + private function throwException(\Throwable $exception) + { + throw $exception; + } +} diff --git a/src/Service/BedrockAgent/src/ValueObject/S3Location.php b/src/Service/BedrockAgent/src/ValueObject/S3Location.php new file mode 100644 index 000000000..c2beb8896 --- /dev/null +++ b/src/Service/BedrockAgent/src/ValueObject/S3Location.php @@ -0,0 +1,63 @@ +uri = $input['uri'] ?? $this->throwException(new InvalidArgument('Missing required field "uri".')); + } + + /** + * @param array{ + * uri: string, + * }|S3Location $input + */ + public static function create($input): self + { + return $input instanceof self ? $input : new self($input); + } + + public function getUri(): string + { + return $this->uri; + } + + /** + * @internal + */ + public function requestBody(): array + { + $payload = []; + $v = $this->uri; + $payload['uri'] = $v; + + return $payload; + } + + /** + * @return never + */ + private function throwException(\Throwable $exception) + { + throw $exception; + } +} diff --git a/src/Service/BedrockAgent/src/ValueObject/TextContentDoc.php b/src/Service/BedrockAgent/src/ValueObject/TextContentDoc.php new file mode 100644 index 000000000..b423b4976 --- /dev/null +++ b/src/Service/BedrockAgent/src/ValueObject/TextContentDoc.php @@ -0,0 +1,63 @@ +data = $input['data'] ?? $this->throwException(new InvalidArgument('Missing required field "data".')); + } + + /** + * @param array{ + * data: string, + * }|TextContentDoc $input + */ + public static function create($input): self + { + return $input instanceof self ? $input : new self($input); + } + + public function getData(): string + { + return $this->data; + } + + /** + * @internal + */ + public function requestBody(): array + { + $payload = []; + $v = $this->data; + $payload['data'] = $v; + + return $payload; + } + + /** + * @return never + */ + private function throwException(\Throwable $exception) + { + throw $exception; + } +} diff --git a/src/Service/BedrockAgent/src/ValueObject/ValidationExceptionField.php b/src/Service/BedrockAgent/src/ValueObject/ValidationExceptionField.php new file mode 100644 index 000000000..7b08026e9 --- /dev/null +++ b/src/Service/BedrockAgent/src/ValueObject/ValidationExceptionField.php @@ -0,0 +1,66 @@ +name = $input['name'] ?? $this->throwException(new InvalidArgument('Missing required field "name".')); + $this->message = $input['message'] ?? $this->throwException(new InvalidArgument('Missing required field "message".')); + } + + /** + * @param array{ + * name: string, + * message: string, + * }|ValidationExceptionField $input + */ + public static function create($input): self + { + return $input instanceof self ? $input : new self($input); + } + + public function getMessage(): string + { + return $this->message; + } + + public function getName(): string + { + return $this->name; + } + + /** + * @return never + */ + private function throwException(\Throwable $exception) + { + throw $exception; + } +} diff --git a/src/Service/BedrockAgent/tests/.gitignore b/src/Service/BedrockAgent/tests/.gitignore new file mode 100644 index 000000000..e69de29bb diff --git a/src/Service/BedrockAgent/tests/Integration/BedrockAgentClientTest.php b/src/Service/BedrockAgent/tests/Integration/BedrockAgentClientTest.php new file mode 100644 index 000000000..766034ac8 --- /dev/null +++ b/src/Service/BedrockAgent/tests/Integration/BedrockAgentClientTest.php @@ -0,0 +1,167 @@ +getClient(); + + $input = new DeleteKnowledgeBaseDocumentsRequest([ + 'knowledgeBaseId' => 'change me', + 'dataSourceId' => 'change me', + 'clientToken' => 'change me', + 'documentIdentifiers' => [new DocumentIdentifier([ + 'dataSourceType' => 'change me', + 's3' => new S3Location([ + 'uri' => 'change me', + ]), + 'custom' => new CustomDocumentIdentifier([ + 'id' => 'change me', + ]), + ])], + ]); + $result = $client->deleteKnowledgeBaseDocuments($input); + + $result->resolve(); + + // self::assertTODO(expected, $result->getDocumentDetails()); + } + + public function testGetKnowledgeBaseDocuments(): void + { + $client = $this->getClient(); + + $input = new GetKnowledgeBaseDocumentsRequest([ + 'knowledgeBaseId' => 'change me', + 'dataSourceId' => 'change me', + 'documentIdentifiers' => [new DocumentIdentifier([ + 'dataSourceType' => 'change me', + 's3' => new S3Location([ + 'uri' => 'change me', + ]), + 'custom' => new CustomDocumentIdentifier([ + 'id' => 'change me', + ]), + ])], + ]); + $result = $client->getKnowledgeBaseDocuments($input); + + $result->resolve(); + + // self::assertTODO(expected, $result->getDocumentDetails()); + } + + public function testIngestKnowledgeBaseDocuments(): void + { + $client = $this->getClient(); + + $input = new IngestKnowledgeBaseDocumentsRequest([ + 'knowledgeBaseId' => 'change me', + 'dataSourceId' => 'change me', + 'clientToken' => 'change me', + 'documents' => [new KnowledgeBaseDocument([ + 'metadata' => new DocumentMetadata([ + 'type' => 'change me', + 'inlineAttributes' => [new MetadataAttribute([ + 'key' => 'change me', + 'value' => new MetadataAttributeValue([ + 'type' => 'change me', + 'numberValue' => 1337, + 'booleanValue' => false, + 'stringValue' => 'change me', + 'stringListValue' => ['change me'], + ]), + ])], + 's3Location' => new CustomS3Location([ + 'uri' => 'change me', + 'bucketOwnerAccountId' => 'change me', + ]), + ]), + 'content' => new DocumentContent([ + 'dataSourceType' => 'change me', + 'custom' => new CustomContent([ + 'customDocumentIdentifier' => new CustomDocumentIdentifier([ + 'id' => 'change me', + ]), + 'sourceType' => 'change me', + 's3Location' => new CustomS3Location([ + 'uri' => 'change me', + 'bucketOwnerAccountId' => 'change me', + ]), + 'inlineContent' => new InlineContent([ + 'type' => 'change me', + 'byteContent' => new ByteContentDoc([ + 'mimeType' => 'change me', + 'data' => 'change me', + ]), + 'textContent' => new TextContentDoc([ + 'data' => 'change me', + ]), + ]), + ]), + 's3' => new S3Content([ + 's3Location' => new S3Location([ + 'uri' => 'change me', + ]), + ]), + ]), + ])], + ]); + $result = $client->ingestKnowledgeBaseDocuments($input); + + $result->resolve(); + + // self::assertTODO(expected, $result->getDocumentDetails()); + } + + public function testListKnowledgeBaseDocuments(): void + { + $client = $this->getClient(); + + $input = new ListKnowledgeBaseDocumentsRequest([ + 'knowledgeBaseId' => 'change me', + 'dataSourceId' => 'change me', + 'maxResults' => 1337, + 'nextToken' => 'change me', + ]); + $result = $client->listKnowledgeBaseDocuments($input); + + $result->resolve(); + + // self::assertTODO(expected, $result->getDocumentDetails()); + self::assertSame('changeIt', $result->getNextToken()); + } + + private function getClient(): BedrockAgentClient + { + self::markTestSkipped('There is no docker image available for BedrockAgent.'); + + return new BedrockAgentClient([ + 'endpoint' => 'http://localhost', + ], new NullProvider()); + } +} diff --git a/src/Service/BedrockAgent/tests/Unit/BedrockAgentClientTest.php b/src/Service/BedrockAgent/tests/Unit/BedrockAgentClientTest.php new file mode 100644 index 000000000..f61cdc389 --- /dev/null +++ b/src/Service/BedrockAgent/tests/Unit/BedrockAgentClientTest.php @@ -0,0 +1,93 @@ + 'kb-1234567890abcdef', + 'dataSourceId' => 'ds-abcdef1234567890', + 'documentIdentifiers' => [new DocumentIdentifier([ + 'dataSourceType' => ContentDataSourceType::S3, + ])], + ]); + $result = $client->deleteKnowledgeBaseDocuments($input); + + self::assertInstanceOf(DeleteKnowledgeBaseDocumentsResponse::class, $result); + self::assertFalse($result->info()['resolved']); + } + + public function testGetKnowledgeBaseDocuments(): void + { + $client = new BedrockAgentClient([], new NullProvider(), new MockHttpClient()); + + $input = new GetKnowledgeBaseDocumentsRequest([ + 'knowledgeBaseId' => 'kb-1234567890abcdef', + 'dataSourceId' => 'ds-abcdef1234567890', + 'documentIdentifiers' => [new DocumentIdentifier([ + 'dataSourceType' => ContentDataSourceType::S3, + ])], + ]); + $result = $client->getKnowledgeBaseDocuments($input); + + self::assertInstanceOf(GetKnowledgeBaseDocumentsResponse::class, $result); + self::assertFalse($result->info()['resolved']); + } + + public function testIngestKnowledgeBaseDocuments(): void + { + $client = new BedrockAgentClient([], new NullProvider(), new MockHttpClient()); + + $input = new IngestKnowledgeBaseDocumentsRequest([ + 'knowledgeBaseId' => 'kb-1234567890abcdef', + 'dataSourceId' => 'ds-abcdef1234567890', + 'documents' => [new KnowledgeBaseDocument([ + 'content' => new DocumentContent([ + 'dataSourceType' => ContentDataSourceType::S3, + ]), + ])], + ]); + $result = $client->ingestKnowledgeBaseDocuments($input); + + self::assertInstanceOf(IngestKnowledgeBaseDocumentsResponse::class, $result); + self::assertFalse($result->info()['resolved']); + } + + public function testListKnowledgeBaseDocuments(): void + { + $client = new BedrockAgentClient([], new NullProvider(), new MockHttpClient()); + + $input = new ListKnowledgeBaseDocumentsRequest([ + 'knowledgeBaseId' => 'kb-1234567890abcdef', + 'dataSourceId' => 'ds-abcdef1234567890', + 'documentIdentifiers' => [new DocumentIdentifier([ + 'dataSourceType' => ContentDataSourceType::S3, + ])], + ]); + $result = $client->listKnowledgeBaseDocuments($input); + + self::assertInstanceOf(ListKnowledgeBaseDocumentsResponse::class, $result); + self::assertFalse($result->info()['resolved']); + } +} diff --git a/src/Service/BedrockAgent/tests/Unit/Input/DeleteKnowledgeBaseDocumentsRequestTest.php b/src/Service/BedrockAgent/tests/Unit/Input/DeleteKnowledgeBaseDocumentsRequestTest.php new file mode 100644 index 000000000..f05424520 --- /dev/null +++ b/src/Service/BedrockAgent/tests/Unit/Input/DeleteKnowledgeBaseDocumentsRequestTest.php @@ -0,0 +1,55 @@ + 'kb-1234567890abcdef', + 'dataSourceId' => 'ds-abcdef1234567890', + 'clientToken' => 'token-1234', + 'documentIdentifiers' => [new DocumentIdentifier([ + 'dataSourceType' => ContentDataSourceType::S3, + 's3' => new S3Location([ + 'uri' => 's3://my-bucket/documents/', + ]), + 'custom' => new CustomDocumentIdentifier([ + 'id' => 'custom-doc-001', + ]), + ])], + ]); + + // see https://docs.aws.amazon.com/bedrock/latest/APIReference/API_agent_DeleteKnowledgeBaseDocuments.html + $expected = ' + POST /knowledgebases/kb-1234567890abcdef/datasources/ds-abcdef1234567890/documents/deleteDocuments HTTP/1.1 + Content-Type: application/json + Accept: application/json + + { + "clientToken": "token-1234", + "documentIdentifiers": [ + { + "dataSourceType": "S3", + "s3": { + "uri": "s3://my-bucket/documents/" + }, + "custom": { + "id": "custom-doc-001" + } + } + ] + } + '; + + self::assertRequestEqualsHttpRequest($expected, $input->request()); + } +} diff --git a/src/Service/BedrockAgent/tests/Unit/Input/GetKnowledgeBaseDocumentsRequestTest.php b/src/Service/BedrockAgent/tests/Unit/Input/GetKnowledgeBaseDocumentsRequestTest.php new file mode 100644 index 000000000..1d1306fca --- /dev/null +++ b/src/Service/BedrockAgent/tests/Unit/Input/GetKnowledgeBaseDocumentsRequestTest.php @@ -0,0 +1,53 @@ + 'kb-1234567890abcdef', + 'dataSourceId' => 'ds-abcdef1234567890', + 'documentIdentifiers' => [new DocumentIdentifier([ + 'dataSourceType' => ContentDataSourceType::S3, + 's3' => new S3Location([ + 'uri' => 's3://my-bucket/documents/', + ]), + 'custom' => new CustomDocumentIdentifier([ + 'id' => 'custom-doc-001', + ]), + ])], + ]); + + // see https://docs.aws.amazon.com/bedrock/latest/APIReference/API_agent_GetKnowledgeBaseDocuments.html + $expected = ' + POST /knowledgebases/kb-1234567890abcdef/datasources/ds-abcdef1234567890/documents/getDocuments HTTP/1.1 + Content-Type: application/json + Accept: application/json + + { + "documentIdentifiers": [ + { + "dataSourceType": "S3", + "s3": { + "uri": "s3://my-bucket/documents/" + }, + "custom": { + "id": "custom-doc-001" + } + } + ] + } + '; + + self::assertRequestEqualsHttpRequest($expected, $input->request()); + } +} diff --git a/src/Service/BedrockAgent/tests/Unit/Input/IngestKnowledgeBaseDocumentsRequestTest.php b/src/Service/BedrockAgent/tests/Unit/Input/IngestKnowledgeBaseDocumentsRequestTest.php new file mode 100644 index 000000000..d918417ea --- /dev/null +++ b/src/Service/BedrockAgent/tests/Unit/Input/IngestKnowledgeBaseDocumentsRequestTest.php @@ -0,0 +1,141 @@ + 'kb-1234567890abcdef', + 'dataSourceId' => 'ds-abcdef1234567890', + 'clientToken' => 'token-1234', + 'documents' => [new KnowledgeBaseDocument([ + 'metadata' => new DocumentMetadata([ + 'type' => MetadataSourceType::IN_LINE_ATTRIBUTE, + 'inlineAttributes' => [new MetadataAttribute([ + 'key' => 'author', + 'value' => new MetadataAttributeValue([ + 'type' => MetadataValueType::STRING, + 'stringValue' => 'John Doe', + ]), + ])], + 's3Location' => new CustomS3Location([ + 'uri' => 's3://my-bucket/documents/', + 'bucketOwnerAccountId' => 'account-1234', + ]), + ]), + 'content' => new DocumentContent([ + 'dataSourceType' => ContentDataSourceType::S3, + 'custom' => new CustomContent([ + 'customDocumentIdentifier' => new CustomDocumentIdentifier([ + 'id' => 'custom-doc-001', + ]), + 'sourceType' => CustomSourceType::IN_LINE, + 's3Location' => new CustomS3Location([ + 'uri' => 's3://my-bucket/documents/', + 'bucketOwnerAccountId' => 'account-1234', + ]), + 'inlineContent' => new InlineContent([ + 'type' => InlineContentType::TEXT, + 'byteContent' => new ByteContentDoc([ + 'mimeType' => 'application/pdf', + 'data' => 'base64-pdf-data', + ]), + 'textContent' => new TextContentDoc([ + 'data' => 'Document text content', + ]), + ]), + ]), + 's3' => new S3Content([ + 's3Location' => new S3Location([ + 'uri' => 's3://my-bucket/documents/', + ]), + ]), + ]), + ])], + ]); + + // see https://docs.aws.amazon.com/bedrock/latest/APIReference/API_agent_IngestKnowledgeBaseDocuments.html + $expected = ' + PUT /knowledgebases/kb-1234567890abcdef/datasources/ds-abcdef1234567890/documents HTTP/1.1 + Content-Type: application/json + Accept: application/json + + { + "clientToken": "token-1234", + "documents": [ + { + "metadata": { + "type": "IN_LINE_ATTRIBUTE", + "inlineAttributes": [ + { + "key": "author", + "value": { + "type": "STRING", + "stringValue": "John Doe" + } + } + ], + "s3Location": { + "uri": "s3://my-bucket/documents/", + "bucketOwnerAccountId": "account-1234" + } + }, + "content": { + "dataSourceType": "S3", + "custom": { + "customDocumentIdentifier": { + "id": "custom-doc-001" + }, + "sourceType": "IN_LINE", + "s3Location": { + "uri": "s3://my-bucket/documents/", + "bucketOwnerAccountId": "account-1234" + }, + "inlineContent": { + "type": "TEXT", + "byteContent": { + "mimeType": "application/pdf", + "data": "YmFzZTY0LXBkZi1kYXRh" + }, + "textContent": { + "data": "Document text content" + } + } + }, + "s3": { + "s3Location": { + "uri": "s3://my-bucket/documents/" + } + } + } + } + ] + } + '; + + self::assertRequestEqualsHttpRequest($expected, $input->request()); + } +} diff --git a/src/Service/BedrockAgent/tests/Unit/Input/ListKnowledgeBaseDocumentsRequestTest.php b/src/Service/BedrockAgent/tests/Unit/Input/ListKnowledgeBaseDocumentsRequestTest.php new file mode 100644 index 000000000..7eadd9e6b --- /dev/null +++ b/src/Service/BedrockAgent/tests/Unit/Input/ListKnowledgeBaseDocumentsRequestTest.php @@ -0,0 +1,33 @@ + 'kb-1234567890abcdef', + 'dataSourceId' => 'ds-abcdef1234567890', + 'maxResults' => 50, + 'nextToken' => 'token-1234', + ]); + + // see https://docs.aws.amazon.com/bedrock/latest/APIReference/API_agent_ListKnowledgeBaseDocuments.html + $expected = ' + POST /knowledgebases/kb-1234567890abcdef/datasources/ds-abcdef1234567890/documents HTTP/1.1 + Content-Type: application/json + Accept: application/json + + { + "maxResults": 50, + "nextToken": "token-1234" + } + '; + + self::assertRequestEqualsHttpRequest($expected, $input->request()); + } +} diff --git a/src/Service/BedrockAgent/tests/Unit/Result/DeleteKnowledgeBaseDocumentsResponseTest.php b/src/Service/BedrockAgent/tests/Unit/Result/DeleteKnowledgeBaseDocumentsResponseTest.php new file mode 100644 index 000000000..e069fa534 --- /dev/null +++ b/src/Service/BedrockAgent/tests/Unit/Result/DeleteKnowledgeBaseDocumentsResponseTest.php @@ -0,0 +1,52 @@ +request('POST', 'http://localhost/knowledgebases/kb-1234567890abcdef/datasources/ds-abcdef1234567890/documents/deleteDocuments'), $client, new NullLogger()) + ); + + self::assertCount(1, $result->getDocumentDetails()); + + $detail = $result->getDocumentDetails()[0]; + self::assertSame('kb-1234567890abcdef', $detail->getKnowledgeBaseId()); + self::assertSame('ds-abcdef1234567890', $detail->getDataSourceId()); + self::assertSame(DocumentStatus::DELETING, $detail->getStatus()); + self::assertSame('S3', $detail->getIdentifier()->getDataSourceType()); + self::assertSame('s3://my-bucket/documents/doc1.pdf', $detail->getIdentifier()->getS3()->getUri()); + self::assertSame('custom-doc-001', $detail->getIdentifier()->getCustom()->getId()); + self::assertSame('Deleted successfully', $detail->getStatusReason()); + self::assertSame('2024-06-01T12:00:00Z', $detail->getUpdatedAt()->format('Y-m-d\TH:i:s\Z')); + } +} diff --git a/src/Service/BedrockAgent/tests/Unit/Result/GetKnowledgeBaseDocumentsResponseTest.php b/src/Service/BedrockAgent/tests/Unit/Result/GetKnowledgeBaseDocumentsResponseTest.php new file mode 100644 index 000000000..6e80e4853 --- /dev/null +++ b/src/Service/BedrockAgent/tests/Unit/Result/GetKnowledgeBaseDocumentsResponseTest.php @@ -0,0 +1,52 @@ +request('POST', '/knowledgebases/kb-1234567890abcdef/datasources/ds-abcdef1234567890/documents/getDocuments'), $client, new NullLogger()) + ); + + self::assertCount(1, $result->getDocumentDetails()); + + $detail = $result->getDocumentDetails()[0]; + self::assertSame('kb-1234567890abcdef', $detail->getKnowledgeBaseId()); + self::assertSame('ds-abcdef1234567890', $detail->getDataSourceId()); + self::assertSame(DocumentStatus::INDEXED, $detail->getStatus()); + self::assertSame('S3', $detail->getIdentifier()->getDataSourceType()); + self::assertSame('s3://my-bucket/documents/doc1.pdf', $detail->getIdentifier()->getS3()->getUri()); + self::assertSame('custom-doc-001', $detail->getIdentifier()->getCustom()->getId()); + self::assertSame('Document indexed successfully', $detail->getStatusReason()); + self::assertSame('2024-06-01T12:00:00Z', $detail->getUpdatedAt()->format('Y-m-d\TH:i:s\Z')); + } +} diff --git a/src/Service/BedrockAgent/tests/Unit/Result/IngestKnowledgeBaseDocumentsResponseTest.php b/src/Service/BedrockAgent/tests/Unit/Result/IngestKnowledgeBaseDocumentsResponseTest.php new file mode 100644 index 000000000..e9ec66b9e --- /dev/null +++ b/src/Service/BedrockAgent/tests/Unit/Result/IngestKnowledgeBaseDocumentsResponseTest.php @@ -0,0 +1,52 @@ +request('PUT', '/knowledgebases/kb-1234567890abcdef/datasources/ds-abcdef1234567890/documents'), $client, new NullLogger()) + ); + + self::assertCount(1, $result->getDocumentDetails()); + + $detail = $result->getDocumentDetails()[0]; + self::assertSame('kb-1234567890abcdef', $detail->getKnowledgeBaseId()); + self::assertSame('ds-abcdef1234567890', $detail->getDataSourceId()); + self::assertSame(DocumentStatus::INDEXED, $detail->getStatus()); + self::assertSame('S3', $detail->getIdentifier()->getDataSourceType()); + self::assertSame('s3://my-bucket/documents/doc1.pdf', $detail->getIdentifier()->getS3()->getUri()); + self::assertSame('custom-doc-001', $detail->getIdentifier()->getCustom()->getId()); + self::assertSame('Document indexed successfully', $detail->getStatusReason()); + self::assertSame('2024-06-01T12:00:00Z', $detail->getUpdatedAt()->format('Y-m-d\TH:i:s\Z')); + } +} diff --git a/src/Service/BedrockAgent/tests/Unit/Result/ListKnowledgeBaseDocumentsResponseTest.php b/src/Service/BedrockAgent/tests/Unit/Result/ListKnowledgeBaseDocumentsResponseTest.php new file mode 100644 index 000000000..de0d8811d --- /dev/null +++ b/src/Service/BedrockAgent/tests/Unit/Result/ListKnowledgeBaseDocumentsResponseTest.php @@ -0,0 +1,59 @@ +request('POST', '/knowledgebases/kb-1234567890abcdef/datasources/ds-abcdef1234567890/documents'), $client, new NullLogger()), + new BedrockAgentClient([]), + new ListKnowledgeBaseDocumentsRequest(['knowledgeBaseId' => 'kb-1234567890abcdef', 'dataSourceId' => 'ds-abcdef1234567890']) + ); + + $details = iterator_to_array($result->getDocumentDetails(true)); + self::assertCount(1, $details); + + $detail = $details[0]; + self::assertSame('kb-1234567890abcdef', $detail->getKnowledgeBaseId()); + self::assertSame('ds-abcdef1234567890', $detail->getDataSourceId()); + self::assertSame(DocumentStatus::INDEXED, $detail->getStatus()); + self::assertSame('S3', $detail->getIdentifier()->getDataSourceType()); + self::assertSame('s3://my-bucket/documents/doc1.pdf', $detail->getIdentifier()->getS3()->getUri()); + self::assertSame('custom-doc-001', $detail->getIdentifier()->getCustom()->getId()); + self::assertSame('Document indexed successfully', $detail->getStatusReason()); + self::assertSame('2024-06-01T12:00:00Z', $detail->getUpdatedAt()->format('Y-m-d\TH:i:s\Z')); + self::assertSame('foobar', $result->getNextToken()); + } +}