From 6d0cdcb28dba75374d38672fa066b009cbad0a1b Mon Sep 17 00:00:00 2001 From: Victor Thuillier Date: Fri, 14 Mar 2025 18:13:49 +0100 Subject: [PATCH 01/10] Create Converse operation for BedrockRuntime client --- .idea/.gitignore | 8 + docs/clients/bedrock-runtime.md | 25 + manifest.json | 1 + src/Service/BedrockRuntime/composer.json | 1 + .../src/BedrockRuntimeClient.php | 95 +++ .../src/Enum/ConversationRole.php | 17 + .../src/Enum/DocumentFormat.php | 31 + .../Enum/GuardrailContentFilterConfidence.php | 21 + .../Enum/GuardrailContentFilterStrength.php | 21 + .../src/Enum/GuardrailContentFilterType.php | 25 + .../src/Enum/GuardrailContentPolicyAction.php | 15 + ...GuardrailContextualGroundingFilterType.php | 17 + ...ardrailContextualGroundingPolicyAction.php | 17 + .../GuardrailConverseContentQualifier.php | 19 + .../src/Enum/GuardrailConverseImageFormat.php | 17 + .../src/Enum/GuardrailManagedWordType.php | 15 + .../src/Enum/GuardrailPiiEntityType.php | 75 ++ ...rdrailSensitiveInformationPolicyAction.php | 17 + .../src/Enum/GuardrailTopicPolicyAction.php | 15 + .../src/Enum/GuardrailTopicType.php | 15 + .../src/Enum/GuardrailTrace.php | 17 + .../src/Enum/GuardrailWordPolicyAction.php | 15 + .../BedrockRuntime/src/Enum/ImageFormat.php | 21 + .../BedrockRuntime/src/Enum/StopReason.php | 25 + .../src/Enum/ToolResultStatus.php | 17 + .../BedrockRuntime/src/Enum/VideoFormat.php | 31 + .../src/Input/ConverseRequest.php | 464 +++++++++++ .../src/Result/ConverseResponse.php | 730 ++++++++++++++++++ .../src/ValueObject/AnyToolChoice.php | 27 + .../src/ValueObject/AutoToolChoice.php | 28 + .../src/ValueObject/ContentBlock.php | 192 +++++ .../src/ValueObject/ConverseMetrics.php | 53 ++ .../src/ValueObject/ConverseOutput.php | 43 ++ .../src/ValueObject/ConverseTrace.php | 58 ++ .../src/ValueObject/Document.php | 24 + .../src/ValueObject/DocumentBlock.php | 113 +++ .../src/ValueObject/DocumentSource.php | 54 ++ .../src/ValueObject/GuardrailAssessment.php | 116 +++ .../ValueObject/GuardrailConfiguration.php | 107 +++ .../ValueObject/GuardrailContentFilter.php | 112 +++ .../GuardrailContentPolicyAssessment.php | 54 ++ .../GuardrailContextualGroundingFilter.php | 104 +++ ...ailContextualGroundingPolicyAssessment.php | 44 ++ .../GuardrailConverseContentBlock.php | 75 ++ .../GuardrailConverseImageBlock.php | 87 +++ .../GuardrailConverseImageSource.php | 54 ++ .../GuardrailConverseTextBlock.php | 94 +++ .../src/ValueObject/GuardrailCoverage.php | 56 ++ .../src/ValueObject/GuardrailCustomWord.php | 70 ++ .../ValueObject/GuardrailImageCoverage.php | 56 ++ .../GuardrailInvocationMetrics.php | 71 ++ .../src/ValueObject/GuardrailManagedWord.php | 89 +++ .../ValueObject/GuardrailPiiEntityFilter.php | 89 +++ .../src/ValueObject/GuardrailRegexFilter.php | 100 +++ ...ilSensitiveInformationPolicyAssessment.php | 72 ++ .../GuardrailTextCharactersCoverage.php | 56 ++ .../src/ValueObject/GuardrailTopic.php | 89 +++ .../GuardrailTopicPolicyAssessment.php | 54 ++ .../ValueObject/GuardrailTraceAssessment.php | 80 ++ .../src/ValueObject/GuardrailUsage.php | 126 +++ .../GuardrailWordPolicyAssessment.php | 72 ++ .../src/ValueObject/ImageBlock.php | 87 +++ .../src/ValueObject/ImageSource.php | 54 ++ .../ValueObject/InferenceConfiguration.php | 143 ++++ .../src/ValueObject/Message.php | 106 +++ .../ValueObject/PerformanceConfiguration.php | 63 ++ .../src/ValueObject/PromptRouterTrace.php | 41 + .../src/ValueObject/PromptVariableValues.php | 57 ++ .../src/ValueObject/ReasoningContentBlock.php | 75 ++ .../src/ValueObject/ReasoningTextBlock.php | 82 ++ .../src/ValueObject/S3Location.php | 81 ++ .../src/ValueObject/SpecificToolChoice.php | 65 ++ .../src/ValueObject/SystemContentBlock.php | 77 ++ .../src/ValueObject/TokenUsage.php | 81 ++ .../BedrockRuntime/src/ValueObject/Tool.php | 57 ++ .../src/ValueObject/ToolChoice.php | 91 +++ .../src/ValueObject/ToolConfiguration.php | 94 +++ .../src/ValueObject/ToolInputSchema.php | 56 ++ .../src/ValueObject/ToolResultBlock.php | 117 +++ .../ValueObject/ToolResultContentBlock.php | 128 +++ .../src/ValueObject/ToolSpecification.php | 98 +++ .../src/ValueObject/ToolUseBlock.php | 98 +++ .../src/ValueObject/VideoBlock.php | 87 +++ .../src/ValueObject/VideoSource.php | 73 ++ .../Integration/BedrockRuntimeClientTest.php | 196 +++++ .../tests/Unit/BedrockRuntimeClientTest.php | 15 + .../tests/Unit/Input/ConverseRequestTest.php | 373 +++++++++ .../Unit/Result/ConverseResponseTest.php | 34 + 88 files changed, 6835 insertions(+) create mode 100644 .idea/.gitignore create mode 100644 src/Service/BedrockRuntime/src/Enum/ConversationRole.php create mode 100644 src/Service/BedrockRuntime/src/Enum/DocumentFormat.php create mode 100644 src/Service/BedrockRuntime/src/Enum/GuardrailContentFilterConfidence.php create mode 100644 src/Service/BedrockRuntime/src/Enum/GuardrailContentFilterStrength.php create mode 100644 src/Service/BedrockRuntime/src/Enum/GuardrailContentFilterType.php create mode 100644 src/Service/BedrockRuntime/src/Enum/GuardrailContentPolicyAction.php create mode 100644 src/Service/BedrockRuntime/src/Enum/GuardrailContextualGroundingFilterType.php create mode 100644 src/Service/BedrockRuntime/src/Enum/GuardrailContextualGroundingPolicyAction.php create mode 100644 src/Service/BedrockRuntime/src/Enum/GuardrailConverseContentQualifier.php create mode 100644 src/Service/BedrockRuntime/src/Enum/GuardrailConverseImageFormat.php create mode 100644 src/Service/BedrockRuntime/src/Enum/GuardrailManagedWordType.php create mode 100644 src/Service/BedrockRuntime/src/Enum/GuardrailPiiEntityType.php create mode 100644 src/Service/BedrockRuntime/src/Enum/GuardrailSensitiveInformationPolicyAction.php create mode 100644 src/Service/BedrockRuntime/src/Enum/GuardrailTopicPolicyAction.php create mode 100644 src/Service/BedrockRuntime/src/Enum/GuardrailTopicType.php create mode 100644 src/Service/BedrockRuntime/src/Enum/GuardrailTrace.php create mode 100644 src/Service/BedrockRuntime/src/Enum/GuardrailWordPolicyAction.php create mode 100644 src/Service/BedrockRuntime/src/Enum/ImageFormat.php create mode 100644 src/Service/BedrockRuntime/src/Enum/StopReason.php create mode 100644 src/Service/BedrockRuntime/src/Enum/ToolResultStatus.php create mode 100644 src/Service/BedrockRuntime/src/Enum/VideoFormat.php create mode 100644 src/Service/BedrockRuntime/src/Input/ConverseRequest.php create mode 100644 src/Service/BedrockRuntime/src/Result/ConverseResponse.php create mode 100644 src/Service/BedrockRuntime/src/ValueObject/AnyToolChoice.php create mode 100644 src/Service/BedrockRuntime/src/ValueObject/AutoToolChoice.php create mode 100644 src/Service/BedrockRuntime/src/ValueObject/ContentBlock.php create mode 100644 src/Service/BedrockRuntime/src/ValueObject/ConverseMetrics.php create mode 100644 src/Service/BedrockRuntime/src/ValueObject/ConverseOutput.php create mode 100644 src/Service/BedrockRuntime/src/ValueObject/ConverseTrace.php create mode 100644 src/Service/BedrockRuntime/src/ValueObject/Document.php create mode 100644 src/Service/BedrockRuntime/src/ValueObject/DocumentBlock.php create mode 100644 src/Service/BedrockRuntime/src/ValueObject/DocumentSource.php create mode 100644 src/Service/BedrockRuntime/src/ValueObject/GuardrailAssessment.php create mode 100644 src/Service/BedrockRuntime/src/ValueObject/GuardrailConfiguration.php create mode 100644 src/Service/BedrockRuntime/src/ValueObject/GuardrailContentFilter.php create mode 100644 src/Service/BedrockRuntime/src/ValueObject/GuardrailContentPolicyAssessment.php create mode 100644 src/Service/BedrockRuntime/src/ValueObject/GuardrailContextualGroundingFilter.php create mode 100644 src/Service/BedrockRuntime/src/ValueObject/GuardrailContextualGroundingPolicyAssessment.php create mode 100644 src/Service/BedrockRuntime/src/ValueObject/GuardrailConverseContentBlock.php create mode 100644 src/Service/BedrockRuntime/src/ValueObject/GuardrailConverseImageBlock.php create mode 100644 src/Service/BedrockRuntime/src/ValueObject/GuardrailConverseImageSource.php create mode 100644 src/Service/BedrockRuntime/src/ValueObject/GuardrailConverseTextBlock.php create mode 100644 src/Service/BedrockRuntime/src/ValueObject/GuardrailCoverage.php create mode 100644 src/Service/BedrockRuntime/src/ValueObject/GuardrailCustomWord.php create mode 100644 src/Service/BedrockRuntime/src/ValueObject/GuardrailImageCoverage.php create mode 100644 src/Service/BedrockRuntime/src/ValueObject/GuardrailInvocationMetrics.php create mode 100644 src/Service/BedrockRuntime/src/ValueObject/GuardrailManagedWord.php create mode 100644 src/Service/BedrockRuntime/src/ValueObject/GuardrailPiiEntityFilter.php create mode 100644 src/Service/BedrockRuntime/src/ValueObject/GuardrailRegexFilter.php create mode 100644 src/Service/BedrockRuntime/src/ValueObject/GuardrailSensitiveInformationPolicyAssessment.php create mode 100644 src/Service/BedrockRuntime/src/ValueObject/GuardrailTextCharactersCoverage.php create mode 100644 src/Service/BedrockRuntime/src/ValueObject/GuardrailTopic.php create mode 100644 src/Service/BedrockRuntime/src/ValueObject/GuardrailTopicPolicyAssessment.php create mode 100644 src/Service/BedrockRuntime/src/ValueObject/GuardrailTraceAssessment.php create mode 100644 src/Service/BedrockRuntime/src/ValueObject/GuardrailUsage.php create mode 100644 src/Service/BedrockRuntime/src/ValueObject/GuardrailWordPolicyAssessment.php create mode 100644 src/Service/BedrockRuntime/src/ValueObject/ImageBlock.php create mode 100644 src/Service/BedrockRuntime/src/ValueObject/ImageSource.php create mode 100644 src/Service/BedrockRuntime/src/ValueObject/InferenceConfiguration.php create mode 100644 src/Service/BedrockRuntime/src/ValueObject/Message.php create mode 100644 src/Service/BedrockRuntime/src/ValueObject/PerformanceConfiguration.php create mode 100644 src/Service/BedrockRuntime/src/ValueObject/PromptRouterTrace.php create mode 100644 src/Service/BedrockRuntime/src/ValueObject/PromptVariableValues.php create mode 100644 src/Service/BedrockRuntime/src/ValueObject/ReasoningContentBlock.php create mode 100644 src/Service/BedrockRuntime/src/ValueObject/ReasoningTextBlock.php create mode 100644 src/Service/BedrockRuntime/src/ValueObject/S3Location.php create mode 100644 src/Service/BedrockRuntime/src/ValueObject/SpecificToolChoice.php create mode 100644 src/Service/BedrockRuntime/src/ValueObject/SystemContentBlock.php create mode 100644 src/Service/BedrockRuntime/src/ValueObject/TokenUsage.php create mode 100644 src/Service/BedrockRuntime/src/ValueObject/Tool.php create mode 100644 src/Service/BedrockRuntime/src/ValueObject/ToolChoice.php create mode 100644 src/Service/BedrockRuntime/src/ValueObject/ToolConfiguration.php create mode 100644 src/Service/BedrockRuntime/src/ValueObject/ToolInputSchema.php create mode 100644 src/Service/BedrockRuntime/src/ValueObject/ToolResultBlock.php create mode 100644 src/Service/BedrockRuntime/src/ValueObject/ToolResultContentBlock.php create mode 100644 src/Service/BedrockRuntime/src/ValueObject/ToolSpecification.php create mode 100644 src/Service/BedrockRuntime/src/ValueObject/ToolUseBlock.php create mode 100644 src/Service/BedrockRuntime/src/ValueObject/VideoBlock.php create mode 100644 src/Service/BedrockRuntime/src/ValueObject/VideoSource.php create mode 100644 src/Service/BedrockRuntime/tests/Unit/Input/ConverseRequestTest.php create mode 100644 src/Service/BedrockRuntime/tests/Unit/Result/ConverseResponseTest.php diff --git a/.idea/.gitignore b/.idea/.gitignore new file mode 100644 index 000000000..13566b81b --- /dev/null +++ b/.idea/.gitignore @@ -0,0 +1,8 @@ +# Default ignored files +/shelf/ +/workspace.xml +# Editor-based HTTP Client requests +/httpRequests/ +# Datasource local storage ignored files +/dataSources/ +/dataSources.local.xml diff --git a/docs/clients/bedrock-runtime.md b/docs/clients/bedrock-runtime.md index f690ca3fc..434f9cf3d 100644 --- a/docs/clients/bedrock-runtime.md +++ b/docs/clients/bedrock-runtime.md @@ -41,3 +41,28 @@ echo $response['content'][0]['text']; ``` more information [InvokeModel](https://docs.aws.amazon.com/bedrock/latest/APIReference/API_runtime_InvokeModel.html) + +### Converse + +```php +use AsyncAws\BedrockRuntime\BedrockRuntimeClient; +use AsyncAws\BedrockRuntime\Input\ConverseRequest; +use AsyncAws\BedrockRuntime\ValueObject\ContentBlock; +use AsyncAws\BedrockRuntime\ValueObject\Message; + +$bedrockRuntime = new BedrockRuntimeClient(); + +$result = $bedrockRuntime->converse(new ConverseRequest([ + 'modelId' => 'us.anthropic.claude-3-7-sonnet-20250219-v1:0', + 'messages' => [new Message([ + 'role' => 'user', + 'content' => [new ContentBlock([ + 'text' => 'Write me a love poem.' + ])], + ])] +])); + +echo $result->getOutput()->getMessage()->getContent()[0]->getText(); + +``` +more information [Converse](https://docs.aws.amazon.com/bedrock/latest/APIReference/API_runtime_Converse.html) diff --git a/manifest.json b/manifest.json index 5d4787f01..15cb0af0f 100644 --- a/manifest.json +++ b/manifest.json @@ -71,6 +71,7 @@ "example": "https://raw.githubusercontent.com/aws/aws-sdk-php/${LATEST}/src/data/bedrock-runtime/2023-09-30/examples-1.json", "api-reference": "https://docs.aws.amazon.com/bedrock/latest/APIReference", "methods": [ + "Converse", "InvokeModel" ] }, diff --git a/src/Service/BedrockRuntime/composer.json b/src/Service/BedrockRuntime/composer.json index 93ab0a6fc..77b81b573 100644 --- a/src/Service/BedrockRuntime/composer.json +++ b/src/Service/BedrockRuntime/composer.json @@ -12,6 +12,7 @@ ], "require": { "php": "^7.2.5 || ^8.0", + "ext-json": "*", "async-aws/core": "^1.9" }, "autoload": { diff --git a/src/Service/BedrockRuntime/src/BedrockRuntimeClient.php b/src/Service/BedrockRuntime/src/BedrockRuntimeClient.php index ad61d58cc..a2a12868f 100644 --- a/src/Service/BedrockRuntime/src/BedrockRuntimeClient.php +++ b/src/Service/BedrockRuntime/src/BedrockRuntimeClient.php @@ -14,8 +14,18 @@ use AsyncAws\BedrockRuntime\Exception\ServiceUnavailableException; use AsyncAws\BedrockRuntime\Exception\ThrottlingException; use AsyncAws\BedrockRuntime\Exception\ValidationException; +use AsyncAws\BedrockRuntime\Input\ConverseRequest; use AsyncAws\BedrockRuntime\Input\InvokeModelRequest; +use AsyncAws\BedrockRuntime\Result\ConverseResponse; use AsyncAws\BedrockRuntime\Result\InvokeModelResponse; +use AsyncAws\BedrockRuntime\ValueObject\Document; +use AsyncAws\BedrockRuntime\ValueObject\GuardrailConfiguration; +use AsyncAws\BedrockRuntime\ValueObject\InferenceConfiguration; +use AsyncAws\BedrockRuntime\ValueObject\Message; +use AsyncAws\BedrockRuntime\ValueObject\PerformanceConfiguration; +use AsyncAws\BedrockRuntime\ValueObject\PromptVariableValues; +use AsyncAws\BedrockRuntime\ValueObject\SystemContentBlock; +use AsyncAws\BedrockRuntime\ValueObject\ToolConfiguration; use AsyncAws\Core\AbstractApi; use AsyncAws\Core\AwsError\AwsErrorFactoryInterface; use AsyncAws\Core\AwsError\JsonRestAwsErrorFactory; @@ -24,6 +34,91 @@ class BedrockRuntimeClient extends AbstractApi { + /** + * Sends messages to the specified Amazon Bedrock model. `Converse` provides a consistent interface that works with all + * models that support messages. This allows you to write code once and use it with different models. If a model has + * unique inference parameters, you can also pass those unique parameters to the model. + * + * Amazon Bedrock doesn't store any text, images, or documents that you provide as content. The data is only used to + * generate the response. + * + * You can submit a prompt by including it in the `messages` field, specifying the `modelId` of a foundation model or + * inference profile to run inference on it, and including any other fields that are relevant to your use case. + * + * You can also submit a prompt from Prompt management by specifying the ARN of the prompt version and including a map + * of variables to values in the `promptVariables` field. You can append more messages to the prompt by using the + * `messages` field. If you use a prompt from Prompt management, you can't include the following fields in the request: + * `additionalModelRequestFields`, `inferenceConfig`, `system`, or `toolConfig`. Instead, these fields must be defined + * through Prompt management. For more information, see Use a prompt from Prompt management [^1]. + * + * For information about the Converse API, see *Use the Converse API* in the *Amazon Bedrock User Guide*. To use a + * guardrail, see *Use a guardrail with the Converse API* in the *Amazon Bedrock User Guide*. To use a tool with a + * model, see *Tool use (Function calling)* in the *Amazon Bedrock User Guide* + * + * For example code, see *Converse API examples* in the *Amazon Bedrock User Guide*. + * + * This operation requires permission for the `bedrock:InvokeModel` action. + * + * ! To deny all inference access to resources that you specify in the modelId field, you need to deny access to the + * ! `bedrock:InvokeModel` and `bedrock:InvokeModelWithResponseStream` actions. Doing this also denies access to the + * ! resource through the base inference actions (InvokeModel [^2] and InvokeModelWithResponseStream [^3]). For more + * ! information see Deny access for inference on specific models [^4]. + * + * For troubleshooting some of the common errors you might encounter when using the `Converse` API, see Troubleshooting + * Amazon Bedrock API Error Codes [^5] in the Amazon Bedrock User Guide + * + * [^1]: https://docs.aws.amazon.com/bedrock/latest/userguide/prompt-management-use.html + * [^2]: https://docs.aws.amazon.com/bedrock/latest/APIReference/API_runtime_InvokeModel.html + * [^3]: https://docs.aws.amazon.com/bedrock/latest/APIReference/API_runtime_InvokeModelWithResponseStream.html + * [^4]: https://docs.aws.amazon.com/bedrock/latest/userguide/security_iam_id-based-policy-examples.html#security_iam_id-based-policy-examples-deny-inference + * [^5]: https://docs.aws.amazon.com/bedrock/latest/userguide/troubleshooting-api-error-codes.html + * + * @see https://docs.aws.amazon.com/bedrock/latest/APIReference/API_Converse.html + * @see https://docs.aws.amazon.com/aws-sdk-php/v3/api/api-bedrock-runtime-2023-09-30.html#converse + * + * @param array{ + * modelId: string, + * messages?: null|array, + * system?: null|array, + * inferenceConfig?: null|InferenceConfiguration|array, + * toolConfig?: null|ToolConfiguration|array, + * guardrailConfig?: null|GuardrailConfiguration|array, + * additionalModelRequestFields?: null|Document|array, + * promptVariables?: null|array, + * additionalModelResponseFieldPaths?: null|string[], + * requestMetadata?: null|array, + * performanceConfig?: null|PerformanceConfiguration|array, + * '@region'?: string|null, + * }|ConverseRequest $input + * + * @throws AccessDeniedException + * @throws ResourceNotFoundException + * @throws ThrottlingException + * @throws ModelTimeoutException + * @throws InternalServerException + * @throws ServiceUnavailableException + * @throws ValidationException + * @throws ModelNotReadyException + * @throws ModelErrorException + */ + public function converse($input): ConverseResponse + { + $input = ConverseRequest::create($input); + $response = $this->getResponse($input->request(), new RequestContext(['operation' => 'Converse', 'region' => $input->getRegion(), 'exceptionMapping' => [ + 'AccessDeniedException' => AccessDeniedException::class, + 'ResourceNotFoundException' => ResourceNotFoundException::class, + 'ThrottlingException' => ThrottlingException::class, + 'ModelTimeoutException' => ModelTimeoutException::class, + 'InternalServerException' => InternalServerException::class, + 'ServiceUnavailableException' => ServiceUnavailableException::class, + 'ValidationException' => ValidationException::class, + 'ModelNotReadyException' => ModelNotReadyException::class, + 'ModelErrorException' => ModelErrorException::class, + ]])); + + return new ConverseResponse($response); + } + /** * Invokes the specified Amazon Bedrock model to run inference using the prompt and inference parameters provided in the * request body. You use model inference to generate text, images, and embeddings. diff --git a/src/Service/BedrockRuntime/src/Enum/ConversationRole.php b/src/Service/BedrockRuntime/src/Enum/ConversationRole.php new file mode 100644 index 000000000..30f0929c7 --- /dev/null +++ b/src/Service/BedrockRuntime/src/Enum/ConversationRole.php @@ -0,0 +1,17 @@ + true, + self::USER => true, + ][$value]); + } +} diff --git a/src/Service/BedrockRuntime/src/Enum/DocumentFormat.php b/src/Service/BedrockRuntime/src/Enum/DocumentFormat.php new file mode 100644 index 000000000..efdae4d01 --- /dev/null +++ b/src/Service/BedrockRuntime/src/Enum/DocumentFormat.php @@ -0,0 +1,31 @@ + true, + self::DOC => true, + self::DOCX => true, + self::HTML => true, + self::MD => true, + self::PDF => true, + self::TXT => true, + self::XLS => true, + self::XLSX => true, + ][$value]); + } +} diff --git a/src/Service/BedrockRuntime/src/Enum/GuardrailContentFilterConfidence.php b/src/Service/BedrockRuntime/src/Enum/GuardrailContentFilterConfidence.php new file mode 100644 index 000000000..dff88782f --- /dev/null +++ b/src/Service/BedrockRuntime/src/Enum/GuardrailContentFilterConfidence.php @@ -0,0 +1,21 @@ + true, + self::LOW => true, + self::MEDIUM => true, + self::NONE => true, + ][$value]); + } +} diff --git a/src/Service/BedrockRuntime/src/Enum/GuardrailContentFilterStrength.php b/src/Service/BedrockRuntime/src/Enum/GuardrailContentFilterStrength.php new file mode 100644 index 000000000..a78caafdb --- /dev/null +++ b/src/Service/BedrockRuntime/src/Enum/GuardrailContentFilterStrength.php @@ -0,0 +1,21 @@ + true, + self::LOW => true, + self::MEDIUM => true, + self::NONE => true, + ][$value]); + } +} diff --git a/src/Service/BedrockRuntime/src/Enum/GuardrailContentFilterType.php b/src/Service/BedrockRuntime/src/Enum/GuardrailContentFilterType.php new file mode 100644 index 000000000..b3a251c97 --- /dev/null +++ b/src/Service/BedrockRuntime/src/Enum/GuardrailContentFilterType.php @@ -0,0 +1,25 @@ + true, + self::INSULTS => true, + self::MISCONDUCT => true, + self::PROMPT_ATTACK => true, + self::SEXUAL => true, + self::VIOLENCE => true, + ][$value]); + } +} diff --git a/src/Service/BedrockRuntime/src/Enum/GuardrailContentPolicyAction.php b/src/Service/BedrockRuntime/src/Enum/GuardrailContentPolicyAction.php new file mode 100644 index 000000000..e514bcdf7 --- /dev/null +++ b/src/Service/BedrockRuntime/src/Enum/GuardrailContentPolicyAction.php @@ -0,0 +1,15 @@ + true, + ][$value]); + } +} diff --git a/src/Service/BedrockRuntime/src/Enum/GuardrailContextualGroundingFilterType.php b/src/Service/BedrockRuntime/src/Enum/GuardrailContextualGroundingFilterType.php new file mode 100644 index 000000000..c0f460d88 --- /dev/null +++ b/src/Service/BedrockRuntime/src/Enum/GuardrailContextualGroundingFilterType.php @@ -0,0 +1,17 @@ + true, + self::RELEVANCE => true, + ][$value]); + } +} diff --git a/src/Service/BedrockRuntime/src/Enum/GuardrailContextualGroundingPolicyAction.php b/src/Service/BedrockRuntime/src/Enum/GuardrailContextualGroundingPolicyAction.php new file mode 100644 index 000000000..f328fcbfd --- /dev/null +++ b/src/Service/BedrockRuntime/src/Enum/GuardrailContextualGroundingPolicyAction.php @@ -0,0 +1,17 @@ + true, + self::NONE => true, + ][$value]); + } +} diff --git a/src/Service/BedrockRuntime/src/Enum/GuardrailConverseContentQualifier.php b/src/Service/BedrockRuntime/src/Enum/GuardrailConverseContentQualifier.php new file mode 100644 index 000000000..2647c3570 --- /dev/null +++ b/src/Service/BedrockRuntime/src/Enum/GuardrailConverseContentQualifier.php @@ -0,0 +1,19 @@ + true, + self::GUARD_CONTENT => true, + self::QUERY => true, + ][$value]); + } +} diff --git a/src/Service/BedrockRuntime/src/Enum/GuardrailConverseImageFormat.php b/src/Service/BedrockRuntime/src/Enum/GuardrailConverseImageFormat.php new file mode 100644 index 000000000..27bc5ccd5 --- /dev/null +++ b/src/Service/BedrockRuntime/src/Enum/GuardrailConverseImageFormat.php @@ -0,0 +1,17 @@ + true, + self::PNG => true, + ][$value]); + } +} diff --git a/src/Service/BedrockRuntime/src/Enum/GuardrailManagedWordType.php b/src/Service/BedrockRuntime/src/Enum/GuardrailManagedWordType.php new file mode 100644 index 000000000..b26945c91 --- /dev/null +++ b/src/Service/BedrockRuntime/src/Enum/GuardrailManagedWordType.php @@ -0,0 +1,15 @@ + true, + ][$value]); + } +} diff --git a/src/Service/BedrockRuntime/src/Enum/GuardrailPiiEntityType.php b/src/Service/BedrockRuntime/src/Enum/GuardrailPiiEntityType.php new file mode 100644 index 000000000..a75c4a985 --- /dev/null +++ b/src/Service/BedrockRuntime/src/Enum/GuardrailPiiEntityType.php @@ -0,0 +1,75 @@ + true, + self::AGE => true, + self::AWS_ACCESS_KEY => true, + self::AWS_SECRET_KEY => true, + self::CA_HEALTH_NUMBER => true, + self::CA_SOCIAL_INSURANCE_NUMBER => true, + self::CREDIT_DEBIT_CARD_CVV => true, + self::CREDIT_DEBIT_CARD_EXPIRY => true, + self::CREDIT_DEBIT_CARD_NUMBER => true, + self::DRIVER_ID => true, + self::EMAIL => true, + self::INTERNATIONAL_BANK_ACCOUNT_NUMBER => true, + self::IP_ADDRESS => true, + self::LICENSE_PLATE => true, + self::MAC_ADDRESS => true, + self::NAME => true, + self::PASSWORD => true, + self::PHONE => true, + self::PIN => true, + self::SWIFT_CODE => true, + self::UK_NATIONAL_HEALTH_SERVICE_NUMBER => true, + self::UK_NATIONAL_INSURANCE_NUMBER => true, + self::UK_UNIQUE_TAXPAYER_REFERENCE_NUMBER => true, + self::URL => true, + self::USERNAME => true, + self::US_BANK_ACCOUNT_NUMBER => true, + self::US_BANK_ROUTING_NUMBER => true, + self::US_INDIVIDUAL_TAX_IDENTIFICATION_NUMBER => true, + self::US_PASSPORT_NUMBER => true, + self::US_SOCIAL_SECURITY_NUMBER => true, + self::VEHICLE_IDENTIFICATION_NUMBER => true, + ][$value]); + } +} diff --git a/src/Service/BedrockRuntime/src/Enum/GuardrailSensitiveInformationPolicyAction.php b/src/Service/BedrockRuntime/src/Enum/GuardrailSensitiveInformationPolicyAction.php new file mode 100644 index 000000000..876474e91 --- /dev/null +++ b/src/Service/BedrockRuntime/src/Enum/GuardrailSensitiveInformationPolicyAction.php @@ -0,0 +1,17 @@ + true, + self::BLOCKED => true, + ][$value]); + } +} diff --git a/src/Service/BedrockRuntime/src/Enum/GuardrailTopicPolicyAction.php b/src/Service/BedrockRuntime/src/Enum/GuardrailTopicPolicyAction.php new file mode 100644 index 000000000..73fa7280b --- /dev/null +++ b/src/Service/BedrockRuntime/src/Enum/GuardrailTopicPolicyAction.php @@ -0,0 +1,15 @@ + true, + ][$value]); + } +} diff --git a/src/Service/BedrockRuntime/src/Enum/GuardrailTopicType.php b/src/Service/BedrockRuntime/src/Enum/GuardrailTopicType.php new file mode 100644 index 000000000..a916866a1 --- /dev/null +++ b/src/Service/BedrockRuntime/src/Enum/GuardrailTopicType.php @@ -0,0 +1,15 @@ + true, + ][$value]); + } +} diff --git a/src/Service/BedrockRuntime/src/Enum/GuardrailTrace.php b/src/Service/BedrockRuntime/src/Enum/GuardrailTrace.php new file mode 100644 index 000000000..b6d47f17c --- /dev/null +++ b/src/Service/BedrockRuntime/src/Enum/GuardrailTrace.php @@ -0,0 +1,17 @@ + true, + self::ENABLED => true, + ][$value]); + } +} diff --git a/src/Service/BedrockRuntime/src/Enum/GuardrailWordPolicyAction.php b/src/Service/BedrockRuntime/src/Enum/GuardrailWordPolicyAction.php new file mode 100644 index 000000000..f1981c075 --- /dev/null +++ b/src/Service/BedrockRuntime/src/Enum/GuardrailWordPolicyAction.php @@ -0,0 +1,15 @@ + true, + ][$value]); + } +} diff --git a/src/Service/BedrockRuntime/src/Enum/ImageFormat.php b/src/Service/BedrockRuntime/src/Enum/ImageFormat.php new file mode 100644 index 000000000..cb77b60ec --- /dev/null +++ b/src/Service/BedrockRuntime/src/Enum/ImageFormat.php @@ -0,0 +1,21 @@ + true, + self::JPEG => true, + self::PNG => true, + self::WEBP => true, + ][$value]); + } +} diff --git a/src/Service/BedrockRuntime/src/Enum/StopReason.php b/src/Service/BedrockRuntime/src/Enum/StopReason.php new file mode 100644 index 000000000..8e221350f --- /dev/null +++ b/src/Service/BedrockRuntime/src/Enum/StopReason.php @@ -0,0 +1,25 @@ + true, + self::END_TURN => true, + self::GUARDRAIL_INTERVENED => true, + self::MAX_TOKENS => true, + self::STOP_SEQUENCE => true, + self::TOOL_USE => true, + ][$value]); + } +} diff --git a/src/Service/BedrockRuntime/src/Enum/ToolResultStatus.php b/src/Service/BedrockRuntime/src/Enum/ToolResultStatus.php new file mode 100644 index 000000000..8eb0b580a --- /dev/null +++ b/src/Service/BedrockRuntime/src/Enum/ToolResultStatus.php @@ -0,0 +1,17 @@ + true, + self::SUCCESS => true, + ][$value]); + } +} diff --git a/src/Service/BedrockRuntime/src/Enum/VideoFormat.php b/src/Service/BedrockRuntime/src/Enum/VideoFormat.php new file mode 100644 index 000000000..64f39060f --- /dev/null +++ b/src/Service/BedrockRuntime/src/Enum/VideoFormat.php @@ -0,0 +1,31 @@ + true, + self::MKV => true, + self::MOV => true, + self::MPEG => true, + self::MPG => true, + self::MP_4 => true, + self::THREE_GP => true, + self::WEBM => true, + self::WMV => true, + ][$value]); + } +} diff --git a/src/Service/BedrockRuntime/src/Input/ConverseRequest.php b/src/Service/BedrockRuntime/src/Input/ConverseRequest.php new file mode 100644 index 000000000..08f31f0fb --- /dev/null +++ b/src/Service/BedrockRuntime/src/Input/ConverseRequest.php @@ -0,0 +1,464 @@ +|null + */ + private $promptVariables; + + /** + * Additional model parameters field paths to return in the response. `Converse` and `ConverseStream` return the + * requested fields as a JSON Pointer object in the `additionalModelResponseFields` field. The following is example JSON + * for `additionalModelResponseFieldPaths`. + * + * `[ "/stop_sequence" ]` + * + * For information about the JSON Pointer syntax, see the Internet Engineering Task Force (IETF) [^1] documentation. + * + * `Converse` and `ConverseStream` reject an empty JSON Pointer or incorrectly structured JSON Pointer with a `400` + * error code. if the JSON Pointer is valid, but the requested field is not in the model response, it is ignored by + * `Converse`. + * + * [^1]: https://datatracker.ietf.org/doc/html/rfc6901 + * + * @var string[]|null + */ + private $additionalModelResponseFieldPaths; + + /** + * Key-value pairs that you can use to filter invocation logs. + * + * @var array|null + */ + private $requestMetadata; + + /** + * Model performance settings for the request. + * + * @var PerformanceConfiguration|null + */ + private $performanceConfig; + + /** + * @param array{ + * modelId?: string, + * messages?: null|array, + * system?: null|array, + * inferenceConfig?: null|InferenceConfiguration|array, + * toolConfig?: null|ToolConfiguration|array, + * guardrailConfig?: null|GuardrailConfiguration|array, + * additionalModelRequestFields?: null|Document|array, + * promptVariables?: null|array, + * additionalModelResponseFieldPaths?: null|string[], + * requestMetadata?: null|array, + * performanceConfig?: null|PerformanceConfiguration|array, + * '@region'?: string|null, + * } $input + */ + public function __construct(array $input = []) + { + $this->modelId = $input['modelId'] ?? null; + $this->messages = isset($input['messages']) ? array_map([Message::class, 'create'], $input['messages']) : null; + $this->system = isset($input['system']) ? array_map([SystemContentBlock::class, 'create'], $input['system']) : null; + $this->inferenceConfig = isset($input['inferenceConfig']) ? InferenceConfiguration::create($input['inferenceConfig']) : null; + $this->toolConfig = isset($input['toolConfig']) ? ToolConfiguration::create($input['toolConfig']) : null; + $this->guardrailConfig = isset($input['guardrailConfig']) ? GuardrailConfiguration::create($input['guardrailConfig']) : null; + $this->additionalModelRequestFields = isset($input['additionalModelRequestFields']) ? Document::create($input['additionalModelRequestFields']) : null; + + if (isset($input['promptVariables'])) { + $this->promptVariables = []; + foreach ($input['promptVariables'] as $key => $item) { + $this->promptVariables[$key] = PromptVariableValues::create($item); + } + } + $this->additionalModelResponseFieldPaths = $input['additionalModelResponseFieldPaths'] ?? null; + $this->requestMetadata = $input['requestMetadata'] ?? null; + $this->performanceConfig = isset($input['performanceConfig']) ? PerformanceConfiguration::create($input['performanceConfig']) : null; + parent::__construct($input); + } + + /** + * @param array{ + * modelId?: string, + * messages?: null|array, + * system?: null|array, + * inferenceConfig?: null|InferenceConfiguration|array, + * toolConfig?: null|ToolConfiguration|array, + * guardrailConfig?: null|GuardrailConfiguration|array, + * additionalModelRequestFields?: null|Document|array, + * promptVariables?: null|array, + * additionalModelResponseFieldPaths?: null|string[], + * requestMetadata?: null|array, + * performanceConfig?: null|PerformanceConfiguration|array, + * '@region'?: string|null, + * }|ConverseRequest $input + */ + public static function create($input): self + { + return $input instanceof self ? $input : new self($input); + } + + public function getAdditionalModelRequestFields(): ?Document + { + return $this->additionalModelRequestFields; + } + + /** + * @return string[] + */ + public function getAdditionalModelResponseFieldPaths(): array + { + return $this->additionalModelResponseFieldPaths ?? []; + } + + public function getGuardrailConfig(): ?GuardrailConfiguration + { + return $this->guardrailConfig; + } + + public function getInferenceConfig(): ?InferenceConfiguration + { + return $this->inferenceConfig; + } + + /** + * @return Message[] + */ + public function getMessages(): array + { + return $this->messages ?? []; + } + + public function getModelId(): ?string + { + return $this->modelId; + } + + public function getPerformanceConfig(): ?PerformanceConfiguration + { + return $this->performanceConfig; + } + + /** + * @return array + */ + public function getPromptVariables(): array + { + return $this->promptVariables ?? []; + } + + /** + * @return array + */ + public function getRequestMetadata(): array + { + return $this->requestMetadata ?? []; + } + + /** + * @return SystemContentBlock[] + */ + public function getSystem(): array + { + return $this->system ?? []; + } + + public function getToolConfig(): ?ToolConfiguration + { + return $this->toolConfig; + } + + /** + * @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->modelId) { + throw new InvalidArgument(\sprintf('Missing parameter "modelId" for "%s". The value cannot be null.', __CLASS__)); + } + $uri['modelId'] = $v; + $uriString = '/model/' . rawurlencode($uri['modelId']) . '/converse'; + + // 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 setAdditionalModelRequestFields(?Document $value): self + { + $this->additionalModelRequestFields = $value; + + return $this; + } + + /** + * @param string[] $value + */ + public function setAdditionalModelResponseFieldPaths(array $value): self + { + $this->additionalModelResponseFieldPaths = $value; + + return $this; + } + + public function setGuardrailConfig(?GuardrailConfiguration $value): self + { + $this->guardrailConfig = $value; + + return $this; + } + + public function setInferenceConfig(?InferenceConfiguration $value): self + { + $this->inferenceConfig = $value; + + return $this; + } + + /** + * @param Message[] $value + */ + public function setMessages(array $value): self + { + $this->messages = $value; + + return $this; + } + + public function setModelId(?string $value): self + { + $this->modelId = $value; + + return $this; + } + + public function setPerformanceConfig(?PerformanceConfiguration $value): self + { + $this->performanceConfig = $value; + + return $this; + } + + /** + * @param array $value + */ + public function setPromptVariables(array $value): self + { + $this->promptVariables = $value; + + return $this; + } + + /** + * @param array $value + */ + public function setRequestMetadata(array $value): self + { + $this->requestMetadata = $value; + + return $this; + } + + /** + * @param SystemContentBlock[] $value + */ + public function setSystem(array $value): self + { + $this->system = $value; + + return $this; + } + + public function setToolConfig(?ToolConfiguration $value): self + { + $this->toolConfig = $value; + + return $this; + } + + private function requestBody(): array + { + $payload = []; + + if (null !== $v = $this->messages) { + $index = -1; + $payload['messages'] = []; + foreach ($v as $listValue) { + ++$index; + $payload['messages'][$index] = $listValue->requestBody(); + } + } + if (null !== $v = $this->system) { + $index = -1; + $payload['system'] = []; + foreach ($v as $listValue) { + ++$index; + $payload['system'][$index] = $listValue->requestBody(); + } + } + if (null !== $v = $this->inferenceConfig) { + $payload['inferenceConfig'] = $v->requestBody(); + } + if (null !== $v = $this->toolConfig) { + $payload['toolConfig'] = $v->requestBody(); + } + if (null !== $v = $this->guardrailConfig) { + $payload['guardrailConfig'] = $v->requestBody(); + } + if (null !== $v = $this->additionalModelRequestFields) { + $payload['additionalModelRequestFields'] = $v->requestBody(); + } + if (null !== $v = $this->promptVariables) { + if (empty($v)) { + $payload['promptVariables'] = new \stdClass(); + } else { + $payload['promptVariables'] = []; + foreach ($v as $name => $mv) { + $payload['promptVariables'][$name] = $mv->requestBody(); + } + } + } + if (null !== $v = $this->additionalModelResponseFieldPaths) { + $index = -1; + $payload['additionalModelResponseFieldPaths'] = []; + foreach ($v as $listValue) { + ++$index; + $payload['additionalModelResponseFieldPaths'][$index] = $listValue; + } + } + if (null !== $v = $this->requestMetadata) { + if (empty($v)) { + $payload['requestMetadata'] = new \stdClass(); + } else { + $payload['requestMetadata'] = []; + foreach ($v as $name => $mv) { + $payload['requestMetadata'][$name] = $mv; + } + } + } + if (null !== $v = $this->performanceConfig) { + $payload['performanceConfig'] = $v->requestBody(); + } + + return $payload; + } +} diff --git a/src/Service/BedrockRuntime/src/Result/ConverseResponse.php b/src/Service/BedrockRuntime/src/Result/ConverseResponse.php new file mode 100644 index 000000000..8edbdcea4 --- /dev/null +++ b/src/Service/BedrockRuntime/src/Result/ConverseResponse.php @@ -0,0 +1,730 @@ +initialize(); + + return $this->additionalModelResponseFields; + } + + public function getMetrics(): ConverseMetrics + { + $this->initialize(); + + return $this->metrics; + } + + public function getOutput(): ConverseOutput + { + $this->initialize(); + + return $this->output; + } + + public function getPerformanceConfig(): ?PerformanceConfiguration + { + $this->initialize(); + + return $this->performanceConfig; + } + + /** + * @return StopReason::* + */ + public function getStopReason(): string + { + $this->initialize(); + + return $this->stopReason; + } + + public function getTrace(): ?ConverseTrace + { + $this->initialize(); + + return $this->trace; + } + + public function getUsage(): TokenUsage + { + $this->initialize(); + + return $this->usage; + } + + protected function populateResult(Response $response): void + { + $data = $response->toArray(); + + $this->output = $this->populateResultConverseOutput($data['output']); + $this->stopReason = (string) $data['stopReason']; + $this->usage = $this->populateResultTokenUsage($data['usage']); + $this->metrics = $this->populateResultConverseMetrics($data['metrics']); + $this->additionalModelResponseFields = empty($data['additionalModelResponseFields']) ? null : $this->populateResultDocument($data['additionalModelResponseFields']); + $this->trace = empty($data['trace']) ? null : $this->populateResultConverseTrace($data['trace']); + $this->performanceConfig = empty($data['performanceConfig']) ? null : $this->populateResultPerformanceConfiguration($data['performanceConfig']); + } + + private function populateResultContentBlock(array $json): ContentBlock + { + return new ContentBlock([ + 'text' => isset($json['text']) ? (string) $json['text'] : null, + 'image' => empty($json['image']) ? null : $this->populateResultImageBlock($json['image']), + 'document' => empty($json['document']) ? null : $this->populateResultDocumentBlock($json['document']), + 'video' => empty($json['video']) ? null : $this->populateResultVideoBlock($json['video']), + 'toolUse' => empty($json['toolUse']) ? null : $this->populateResultToolUseBlock($json['toolUse']), + 'toolResult' => empty($json['toolResult']) ? null : $this->populateResultToolResultBlock($json['toolResult']), + 'guardContent' => empty($json['guardContent']) ? null : $this->populateResultGuardrailConverseContentBlock($json['guardContent']), + 'reasoningContent' => empty($json['reasoningContent']) ? null : $this->populateResultReasoningContentBlock($json['reasoningContent']), + ]); + } + + /** + * @return ContentBlock[] + */ + private function populateResultContentBlocks(array $json): array + { + $items = []; + foreach ($json as $item) { + $items[] = $this->populateResultContentBlock($item); + } + + return $items; + } + + private function populateResultConverseMetrics(array $json): ConverseMetrics + { + return new ConverseMetrics([ + 'latencyMs' => (int) $json['latencyMs'], + ]); + } + + private function populateResultConverseOutput(array $json): ConverseOutput + { + return new ConverseOutput([ + 'message' => empty($json['message']) ? null : $this->populateResultMessage($json['message']), + ]); + } + + private function populateResultConverseTrace(array $json): ConverseTrace + { + return new ConverseTrace([ + 'guardrail' => empty($json['guardrail']) ? null : $this->populateResultGuardrailTraceAssessment($json['guardrail']), + 'promptRouter' => empty($json['promptRouter']) ? null : $this->populateResultPromptRouterTrace($json['promptRouter']), + ]); + } + + private function populateResultDocument(array $json): Document + { + return new Document([ + ]); + } + + private function populateResultDocumentBlock(array $json): DocumentBlock + { + return new DocumentBlock([ + 'format' => (string) $json['format'], + 'name' => (string) $json['name'], + 'source' => $this->populateResultDocumentSource($json['source']), + ]); + } + + private function populateResultDocumentSource(array $json): DocumentSource + { + return new DocumentSource([ + 'bytes' => isset($json['bytes']) ? base64_decode((string) $json['bytes']) : null, + ]); + } + + private function populateResultGuardrailAssessment(array $json): GuardrailAssessment + { + return new GuardrailAssessment([ + 'topicPolicy' => empty($json['topicPolicy']) ? null : $this->populateResultGuardrailTopicPolicyAssessment($json['topicPolicy']), + 'contentPolicy' => empty($json['contentPolicy']) ? null : $this->populateResultGuardrailContentPolicyAssessment($json['contentPolicy']), + 'wordPolicy' => empty($json['wordPolicy']) ? null : $this->populateResultGuardrailWordPolicyAssessment($json['wordPolicy']), + 'sensitiveInformationPolicy' => empty($json['sensitiveInformationPolicy']) ? null : $this->populateResultGuardrailSensitiveInformationPolicyAssessment($json['sensitiveInformationPolicy']), + 'contextualGroundingPolicy' => empty($json['contextualGroundingPolicy']) ? null : $this->populateResultGuardrailContextualGroundingPolicyAssessment($json['contextualGroundingPolicy']), + 'invocationMetrics' => empty($json['invocationMetrics']) ? null : $this->populateResultGuardrailInvocationMetrics($json['invocationMetrics']), + ]); + } + + /** + * @return GuardrailAssessment[] + */ + private function populateResultGuardrailAssessmentList(array $json): array + { + $items = []; + foreach ($json as $item) { + $items[] = $this->populateResultGuardrailAssessment($item); + } + + return $items; + } + + /** + * @return array + */ + private function populateResultGuardrailAssessmentListMap(array $json): array + { + $items = []; + foreach ($json as $name => $value) { + $items[(string) $name] = $this->populateResultGuardrailAssessmentList($value); + } + + return $items; + } + + /** + * @return array + */ + private function populateResultGuardrailAssessmentMap(array $json): array + { + $items = []; + foreach ($json as $name => $value) { + $items[(string) $name] = $this->populateResultGuardrailAssessment($value); + } + + return $items; + } + + private function populateResultGuardrailContentFilter(array $json): GuardrailContentFilter + { + return new GuardrailContentFilter([ + 'type' => (string) $json['type'], + 'confidence' => (string) $json['confidence'], + 'filterStrength' => isset($json['filterStrength']) ? (string) $json['filterStrength'] : null, + 'action' => (string) $json['action'], + ]); + } + + /** + * @return GuardrailContentFilter[] + */ + private function populateResultGuardrailContentFilterList(array $json): array + { + $items = []; + foreach ($json as $item) { + $items[] = $this->populateResultGuardrailContentFilter($item); + } + + return $items; + } + + private function populateResultGuardrailContentPolicyAssessment(array $json): GuardrailContentPolicyAssessment + { + return new GuardrailContentPolicyAssessment([ + 'filters' => $this->populateResultGuardrailContentFilterList($json['filters']), + ]); + } + + private function populateResultGuardrailContextualGroundingFilter(array $json): GuardrailContextualGroundingFilter + { + return new GuardrailContextualGroundingFilter([ + 'type' => (string) $json['type'], + 'threshold' => (float) $json['threshold'], + 'score' => (float) $json['score'], + 'action' => (string) $json['action'], + ]); + } + + /** + * @return GuardrailContextualGroundingFilter[] + */ + private function populateResultGuardrailContextualGroundingFilters(array $json): array + { + $items = []; + foreach ($json as $item) { + $items[] = $this->populateResultGuardrailContextualGroundingFilter($item); + } + + return $items; + } + + private function populateResultGuardrailContextualGroundingPolicyAssessment(array $json): GuardrailContextualGroundingPolicyAssessment + { + return new GuardrailContextualGroundingPolicyAssessment([ + 'filters' => !isset($json['filters']) ? null : $this->populateResultGuardrailContextualGroundingFilters($json['filters']), + ]); + } + + private function populateResultGuardrailConverseContentBlock(array $json): GuardrailConverseContentBlock + { + return new GuardrailConverseContentBlock([ + 'text' => empty($json['text']) ? null : $this->populateResultGuardrailConverseTextBlock($json['text']), + 'image' => empty($json['image']) ? null : $this->populateResultGuardrailConverseImageBlock($json['image']), + ]); + } + + /** + * @return list + */ + private function populateResultGuardrailConverseContentQualifierList(array $json): array + { + $items = []; + foreach ($json as $item) { + $a = isset($item) ? (string) $item : null; + if (null !== $a) { + $items[] = $a; + } + } + + return $items; + } + + private function populateResultGuardrailConverseImageBlock(array $json): GuardrailConverseImageBlock + { + return new GuardrailConverseImageBlock([ + 'format' => (string) $json['format'], + 'source' => $this->populateResultGuardrailConverseImageSource($json['source']), + ]); + } + + private function populateResultGuardrailConverseImageSource(array $json): GuardrailConverseImageSource + { + return new GuardrailConverseImageSource([ + 'bytes' => isset($json['bytes']) ? base64_decode((string) $json['bytes']) : null, + ]); + } + + private function populateResultGuardrailConverseTextBlock(array $json): GuardrailConverseTextBlock + { + return new GuardrailConverseTextBlock([ + 'text' => (string) $json['text'], + 'qualifiers' => !isset($json['qualifiers']) ? null : $this->populateResultGuardrailConverseContentQualifierList($json['qualifiers']), + ]); + } + + private function populateResultGuardrailCoverage(array $json): GuardrailCoverage + { + return new GuardrailCoverage([ + 'textCharacters' => empty($json['textCharacters']) ? null : $this->populateResultGuardrailTextCharactersCoverage($json['textCharacters']), + 'images' => empty($json['images']) ? null : $this->populateResultGuardrailImageCoverage($json['images']), + ]); + } + + private function populateResultGuardrailCustomWord(array $json): GuardrailCustomWord + { + return new GuardrailCustomWord([ + 'match' => (string) $json['match'], + 'action' => (string) $json['action'], + ]); + } + + /** + * @return GuardrailCustomWord[] + */ + private function populateResultGuardrailCustomWordList(array $json): array + { + $items = []; + foreach ($json as $item) { + $items[] = $this->populateResultGuardrailCustomWord($item); + } + + return $items; + } + + private function populateResultGuardrailImageCoverage(array $json): GuardrailImageCoverage + { + return new GuardrailImageCoverage([ + 'guarded' => isset($json['guarded']) ? (int) $json['guarded'] : null, + 'total' => isset($json['total']) ? (int) $json['total'] : null, + ]); + } + + private function populateResultGuardrailInvocationMetrics(array $json): GuardrailInvocationMetrics + { + return new GuardrailInvocationMetrics([ + 'guardrailProcessingLatency' => isset($json['guardrailProcessingLatency']) ? (int) $json['guardrailProcessingLatency'] : null, + 'usage' => empty($json['usage']) ? null : $this->populateResultGuardrailUsage($json['usage']), + 'guardrailCoverage' => empty($json['guardrailCoverage']) ? null : $this->populateResultGuardrailCoverage($json['guardrailCoverage']), + ]); + } + + private function populateResultGuardrailManagedWord(array $json): GuardrailManagedWord + { + return new GuardrailManagedWord([ + 'match' => (string) $json['match'], + 'type' => (string) $json['type'], + 'action' => (string) $json['action'], + ]); + } + + /** + * @return GuardrailManagedWord[] + */ + private function populateResultGuardrailManagedWordList(array $json): array + { + $items = []; + foreach ($json as $item) { + $items[] = $this->populateResultGuardrailManagedWord($item); + } + + return $items; + } + + private function populateResultGuardrailPiiEntityFilter(array $json): GuardrailPiiEntityFilter + { + return new GuardrailPiiEntityFilter([ + 'match' => (string) $json['match'], + 'type' => (string) $json['type'], + 'action' => (string) $json['action'], + ]); + } + + /** + * @return GuardrailPiiEntityFilter[] + */ + private function populateResultGuardrailPiiEntityFilterList(array $json): array + { + $items = []; + foreach ($json as $item) { + $items[] = $this->populateResultGuardrailPiiEntityFilter($item); + } + + return $items; + } + + private function populateResultGuardrailRegexFilter(array $json): GuardrailRegexFilter + { + return new GuardrailRegexFilter([ + 'name' => isset($json['name']) ? (string) $json['name'] : null, + 'match' => isset($json['match']) ? (string) $json['match'] : null, + 'regex' => isset($json['regex']) ? (string) $json['regex'] : null, + 'action' => (string) $json['action'], + ]); + } + + /** + * @return GuardrailRegexFilter[] + */ + private function populateResultGuardrailRegexFilterList(array $json): array + { + $items = []; + foreach ($json as $item) { + $items[] = $this->populateResultGuardrailRegexFilter($item); + } + + return $items; + } + + private function populateResultGuardrailSensitiveInformationPolicyAssessment(array $json): GuardrailSensitiveInformationPolicyAssessment + { + return new GuardrailSensitiveInformationPolicyAssessment([ + 'piiEntities' => $this->populateResultGuardrailPiiEntityFilterList($json['piiEntities']), + 'regexes' => $this->populateResultGuardrailRegexFilterList($json['regexes']), + ]); + } + + private function populateResultGuardrailTextCharactersCoverage(array $json): GuardrailTextCharactersCoverage + { + return new GuardrailTextCharactersCoverage([ + 'guarded' => isset($json['guarded']) ? (int) $json['guarded'] : null, + 'total' => isset($json['total']) ? (int) $json['total'] : null, + ]); + } + + private function populateResultGuardrailTopic(array $json): GuardrailTopic + { + return new GuardrailTopic([ + 'name' => (string) $json['name'], + 'type' => (string) $json['type'], + 'action' => (string) $json['action'], + ]); + } + + /** + * @return GuardrailTopic[] + */ + private function populateResultGuardrailTopicList(array $json): array + { + $items = []; + foreach ($json as $item) { + $items[] = $this->populateResultGuardrailTopic($item); + } + + return $items; + } + + private function populateResultGuardrailTopicPolicyAssessment(array $json): GuardrailTopicPolicyAssessment + { + return new GuardrailTopicPolicyAssessment([ + 'topics' => $this->populateResultGuardrailTopicList($json['topics']), + ]); + } + + private function populateResultGuardrailTraceAssessment(array $json): GuardrailTraceAssessment + { + return new GuardrailTraceAssessment([ + 'modelOutput' => !isset($json['modelOutput']) ? null : $this->populateResultModelOutputs($json['modelOutput']), + 'inputAssessment' => !isset($json['inputAssessment']) ? null : $this->populateResultGuardrailAssessmentMap($json['inputAssessment']), + 'outputAssessments' => !isset($json['outputAssessments']) ? null : $this->populateResultGuardrailAssessmentListMap($json['outputAssessments']), + ]); + } + + private function populateResultGuardrailUsage(array $json): GuardrailUsage + { + return new GuardrailUsage([ + 'topicPolicyUnits' => (int) $json['topicPolicyUnits'], + 'contentPolicyUnits' => (int) $json['contentPolicyUnits'], + 'wordPolicyUnits' => (int) $json['wordPolicyUnits'], + 'sensitiveInformationPolicyUnits' => (int) $json['sensitiveInformationPolicyUnits'], + 'sensitiveInformationPolicyFreeUnits' => (int) $json['sensitiveInformationPolicyFreeUnits'], + 'contextualGroundingPolicyUnits' => (int) $json['contextualGroundingPolicyUnits'], + ]); + } + + private function populateResultGuardrailWordPolicyAssessment(array $json): GuardrailWordPolicyAssessment + { + return new GuardrailWordPolicyAssessment([ + 'customWords' => $this->populateResultGuardrailCustomWordList($json['customWords']), + 'managedWordLists' => $this->populateResultGuardrailManagedWordList($json['managedWordLists']), + ]); + } + + private function populateResultImageBlock(array $json): ImageBlock + { + return new ImageBlock([ + 'format' => (string) $json['format'], + 'source' => $this->populateResultImageSource($json['source']), + ]); + } + + private function populateResultImageSource(array $json): ImageSource + { + return new ImageSource([ + 'bytes' => isset($json['bytes']) ? base64_decode((string) $json['bytes']) : null, + ]); + } + + private function populateResultMessage(array $json): Message + { + return new Message([ + 'role' => (string) $json['role'], + 'content' => $this->populateResultContentBlocks($json['content']), + ]); + } + + /** + * @return string[] + */ + private function populateResultModelOutputs(array $json): array + { + $items = []; + foreach ($json as $item) { + $a = isset($item) ? (string) $item : null; + if (null !== $a) { + $items[] = $a; + } + } + + return $items; + } + + private function populateResultPerformanceConfiguration(array $json): PerformanceConfiguration + { + return new PerformanceConfiguration([ + 'latency' => isset($json['latency']) ? (string) $json['latency'] : null, + ]); + } + + private function populateResultPromptRouterTrace(array $json): PromptRouterTrace + { + return new PromptRouterTrace([ + 'invokedModelId' => isset($json['invokedModelId']) ? (string) $json['invokedModelId'] : null, + ]); + } + + private function populateResultReasoningContentBlock(array $json): ReasoningContentBlock + { + return new ReasoningContentBlock([ + 'reasoningText' => empty($json['reasoningText']) ? null : $this->populateResultReasoningTextBlock($json['reasoningText']), + 'redactedContent' => isset($json['redactedContent']) ? base64_decode((string) $json['redactedContent']) : null, + ]); + } + + private function populateResultReasoningTextBlock(array $json): ReasoningTextBlock + { + return new ReasoningTextBlock([ + 'text' => (string) $json['text'], + 'signature' => isset($json['signature']) ? (string) $json['signature'] : null, + ]); + } + + private function populateResultS3Location(array $json): S3Location + { + return new S3Location([ + 'uri' => (string) $json['uri'], + 'bucketOwner' => isset($json['bucketOwner']) ? (string) $json['bucketOwner'] : null, + ]); + } + + private function populateResultTokenUsage(array $json): TokenUsage + { + return new TokenUsage([ + 'inputTokens' => (int) $json['inputTokens'], + 'outputTokens' => (int) $json['outputTokens'], + 'totalTokens' => (int) $json['totalTokens'], + ]); + } + + private function populateResultToolResultBlock(array $json): ToolResultBlock + { + return new ToolResultBlock([ + 'toolUseId' => (string) $json['toolUseId'], + 'content' => $this->populateResultToolResultContentBlocks($json['content']), + 'status' => isset($json['status']) ? (string) $json['status'] : null, + ]); + } + + private function populateResultToolResultContentBlock(array $json): ToolResultContentBlock + { + return new ToolResultContentBlock([ + 'json' => empty($json['json']) ? null : $this->populateResultDocument($json['json']), + 'text' => isset($json['text']) ? (string) $json['text'] : null, + 'image' => empty($json['image']) ? null : $this->populateResultImageBlock($json['image']), + 'document' => empty($json['document']) ? null : $this->populateResultDocumentBlock($json['document']), + 'video' => empty($json['video']) ? null : $this->populateResultVideoBlock($json['video']), + ]); + } + + /** + * @return ToolResultContentBlock[] + */ + private function populateResultToolResultContentBlocks(array $json): array + { + $items = []; + foreach ($json as $item) { + $items[] = $this->populateResultToolResultContentBlock($item); + } + + return $items; + } + + private function populateResultToolUseBlock(array $json): ToolUseBlock + { + return new ToolUseBlock([ + 'toolUseId' => (string) $json['toolUseId'], + 'name' => (string) $json['name'], + 'input' => $this->populateResultDocument($json['input']), + ]); + } + + private function populateResultVideoBlock(array $json): VideoBlock + { + return new VideoBlock([ + 'format' => (string) $json['format'], + 'source' => $this->populateResultVideoSource($json['source']), + ]); + } + + private function populateResultVideoSource(array $json): VideoSource + { + return new VideoSource([ + 'bytes' => isset($json['bytes']) ? base64_decode((string) $json['bytes']) : null, + 's3Location' => empty($json['s3Location']) ? null : $this->populateResultS3Location($json['s3Location']), + ]); + } +} diff --git a/src/Service/BedrockRuntime/src/ValueObject/AnyToolChoice.php b/src/Service/BedrockRuntime/src/ValueObject/AnyToolChoice.php new file mode 100644 index 000000000..576208dfd --- /dev/null +++ b/src/Service/BedrockRuntime/src/ValueObject/AnyToolChoice.php @@ -0,0 +1,27 @@ + This field is only supported by Anthropic Claude 3 models. + * + * @var ImageBlock|null + */ + private $image; + + /** + * A document to include in the message. + * + * @var DocumentBlock|null + */ + private $document; + + /** + * Video to include in the message. + * + * @var VideoBlock|null + */ + private $video; + + /** + * Information about a tool use request from a model. + * + * @var ToolUseBlock|null + */ + private $toolUse; + + /** + * The result for a tool request that a model makes. + * + * @var ToolResultBlock|null + */ + private $toolResult; + + /** + * Contains the content to assess with the guardrail. If you don't specify `guardContent` in a call to the Converse API, + * the guardrail (if passed in the Converse API) assesses the entire message. + * + * For more information, see *Use a guardrail with the Converse API* in the *Amazon Bedrock User Guide*. ``` + *

+ * ``` + * + * @var GuardrailConverseContentBlock|null + */ + private $guardContent; + + /** + * Contains content regarding the reasoning that is carried out by the model. Reasoning refers to a Chain of Thought + * (CoT) that the model generates to enhance the accuracy of its final response. + * + * @var ReasoningContentBlock|null + */ + private $reasoningContent; + + /** + * @param array{ + * text?: null|string, + * image?: null|ImageBlock|array, + * document?: null|DocumentBlock|array, + * video?: null|VideoBlock|array, + * toolUse?: null|ToolUseBlock|array, + * toolResult?: null|ToolResultBlock|array, + * guardContent?: null|GuardrailConverseContentBlock|array, + * reasoningContent?: null|ReasoningContentBlock|array, + * } $input + */ + public function __construct(array $input) + { + $this->text = $input['text'] ?? null; + $this->image = isset($input['image']) ? ImageBlock::create($input['image']) : null; + $this->document = isset($input['document']) ? DocumentBlock::create($input['document']) : null; + $this->video = isset($input['video']) ? VideoBlock::create($input['video']) : null; + $this->toolUse = isset($input['toolUse']) ? ToolUseBlock::create($input['toolUse']) : null; + $this->toolResult = isset($input['toolResult']) ? ToolResultBlock::create($input['toolResult']) : null; + $this->guardContent = isset($input['guardContent']) ? GuardrailConverseContentBlock::create($input['guardContent']) : null; + $this->reasoningContent = isset($input['reasoningContent']) ? ReasoningContentBlock::create($input['reasoningContent']) : null; + } + + /** + * @param array{ + * text?: null|string, + * image?: null|ImageBlock|array, + * document?: null|DocumentBlock|array, + * video?: null|VideoBlock|array, + * toolUse?: null|ToolUseBlock|array, + * toolResult?: null|ToolResultBlock|array, + * guardContent?: null|GuardrailConverseContentBlock|array, + * reasoningContent?: null|ReasoningContentBlock|array, + * }|ContentBlock $input + */ + public static function create($input): self + { + return $input instanceof self ? $input : new self($input); + } + + public function getDocument(): ?DocumentBlock + { + return $this->document; + } + + public function getGuardContent(): ?GuardrailConverseContentBlock + { + return $this->guardContent; + } + + public function getImage(): ?ImageBlock + { + return $this->image; + } + + public function getReasoningContent(): ?ReasoningContentBlock + { + return $this->reasoningContent; + } + + public function getText(): ?string + { + return $this->text; + } + + public function getToolResult(): ?ToolResultBlock + { + return $this->toolResult; + } + + public function getToolUse(): ?ToolUseBlock + { + return $this->toolUse; + } + + public function getVideo(): ?VideoBlock + { + return $this->video; + } + + /** + * @internal + */ + public function requestBody(): array + { + $payload = []; + if (null !== $v = $this->text) { + $payload['text'] = $v; + } + if (null !== $v = $this->image) { + $payload['image'] = $v->requestBody(); + } + if (null !== $v = $this->document) { + $payload['document'] = $v->requestBody(); + } + if (null !== $v = $this->video) { + $payload['video'] = $v->requestBody(); + } + if (null !== $v = $this->toolUse) { + $payload['toolUse'] = $v->requestBody(); + } + if (null !== $v = $this->toolResult) { + $payload['toolResult'] = $v->requestBody(); + } + if (null !== $v = $this->guardContent) { + $payload['guardContent'] = $v->requestBody(); + } + if (null !== $v = $this->reasoningContent) { + $payload['reasoningContent'] = $v->requestBody(); + } + + return $payload; + } +} diff --git a/src/Service/BedrockRuntime/src/ValueObject/ConverseMetrics.php b/src/Service/BedrockRuntime/src/ValueObject/ConverseMetrics.php new file mode 100644 index 000000000..e460c4ad6 --- /dev/null +++ b/src/Service/BedrockRuntime/src/ValueObject/ConverseMetrics.php @@ -0,0 +1,53 @@ +latencyMs = $input['latencyMs'] ?? $this->throwException(new InvalidArgument('Missing required field "latencyMs".')); + } + + /** + * @param array{ + * latencyMs: int, + * }|ConverseMetrics $input + */ + public static function create($input): self + { + return $input instanceof self ? $input : new self($input); + } + + public function getLatencyMs(): int + { + return $this->latencyMs; + } + + /** + * @return never + */ + private function throwException(\Throwable $exception) + { + throw $exception; + } +} diff --git a/src/Service/BedrockRuntime/src/ValueObject/ConverseOutput.php b/src/Service/BedrockRuntime/src/ValueObject/ConverseOutput.php new file mode 100644 index 000000000..a196c7384 --- /dev/null +++ b/src/Service/BedrockRuntime/src/ValueObject/ConverseOutput.php @@ -0,0 +1,43 @@ +message = isset($input['message']) ? Message::create($input['message']) : null; + } + + /** + * @param array{ + * message?: null|Message|array, + * }|ConverseOutput $input + */ + public static function create($input): self + { + return $input instanceof self ? $input : new self($input); + } + + public function getMessage(): ?Message + { + return $this->message; + } +} diff --git a/src/Service/BedrockRuntime/src/ValueObject/ConverseTrace.php b/src/Service/BedrockRuntime/src/ValueObject/ConverseTrace.php new file mode 100644 index 000000000..e80c49d1a --- /dev/null +++ b/src/Service/BedrockRuntime/src/ValueObject/ConverseTrace.php @@ -0,0 +1,58 @@ +guardrail = isset($input['guardrail']) ? GuardrailTraceAssessment::create($input['guardrail']) : null; + $this->promptRouter = isset($input['promptRouter']) ? PromptRouterTrace::create($input['promptRouter']) : null; + } + + /** + * @param array{ + * guardrail?: null|GuardrailTraceAssessment|array, + * promptRouter?: null|PromptRouterTrace|array, + * }|ConverseTrace $input + */ + public static function create($input): self + { + return $input instanceof self ? $input : new self($input); + } + + public function getGuardrail(): ?GuardrailTraceAssessment + { + return $this->guardrail; + } + + public function getPromptRouter(): ?PromptRouterTrace + { + return $this->promptRouter; + } +} diff --git a/src/Service/BedrockRuntime/src/ValueObject/Document.php b/src/Service/BedrockRuntime/src/ValueObject/Document.php new file mode 100644 index 000000000..05e034948 --- /dev/null +++ b/src/Service/BedrockRuntime/src/ValueObject/Document.php @@ -0,0 +1,24 @@ + This field is vulnerable to prompt injections, because the model might inadvertently interpret it as instructions. + * > Therefore, we recommend that you specify a neutral name. + * + * @var string + */ + private $name; + + /** + * Contains the content of the document. + * + * @var DocumentSource + */ + private $source; + + /** + * @param array{ + * format: DocumentFormat::*, + * name: string, + * source: DocumentSource|array, + * } $input + */ + public function __construct(array $input) + { + $this->format = $input['format'] ?? $this->throwException(new InvalidArgument('Missing required field "format".')); + $this->name = $input['name'] ?? $this->throwException(new InvalidArgument('Missing required field "name".')); + $this->source = isset($input['source']) ? DocumentSource::create($input['source']) : $this->throwException(new InvalidArgument('Missing required field "source".')); + } + + /** + * @param array{ + * format: DocumentFormat::*, + * name: string, + * source: DocumentSource|array, + * }|DocumentBlock $input + */ + public static function create($input): self + { + return $input instanceof self ? $input : new self($input); + } + + /** + * @return DocumentFormat::* + */ + public function getFormat(): string + { + return $this->format; + } + + public function getName(): string + { + return $this->name; + } + + public function getSource(): DocumentSource + { + return $this->source; + } + + /** + * @internal + */ + public function requestBody(): array + { + $payload = []; + $v = $this->format; + if (!DocumentFormat::exists($v)) { + throw new InvalidArgument(\sprintf('Invalid parameter "format" for "%s". The value "%s" is not a valid "DocumentFormat".', __CLASS__, $v)); + } + $payload['format'] = $v; + $v = $this->name; + $payload['name'] = $v; + $v = $this->source; + $payload['source'] = $v->requestBody(); + + return $payload; + } + + /** + * @return never + */ + private function throwException(\Throwable $exception) + { + throw $exception; + } +} diff --git a/src/Service/BedrockRuntime/src/ValueObject/DocumentSource.php b/src/Service/BedrockRuntime/src/ValueObject/DocumentSource.php new file mode 100644 index 000000000..86d4b29f3 --- /dev/null +++ b/src/Service/BedrockRuntime/src/ValueObject/DocumentSource.php @@ -0,0 +1,54 @@ +bytes = $input['bytes'] ?? null; + } + + /** + * @param array{ + * bytes?: null|string, + * }|DocumentSource $input + */ + public static function create($input): self + { + return $input instanceof self ? $input : new self($input); + } + + public function getBytes(): ?string + { + return $this->bytes; + } + + /** + * @internal + */ + public function requestBody(): array + { + $payload = []; + if (null !== $v = $this->bytes) { + $payload['bytes'] = base64_encode($v); + } + + return $payload; + } +} diff --git a/src/Service/BedrockRuntime/src/ValueObject/GuardrailAssessment.php b/src/Service/BedrockRuntime/src/ValueObject/GuardrailAssessment.php new file mode 100644 index 000000000..33b193a0d --- /dev/null +++ b/src/Service/BedrockRuntime/src/ValueObject/GuardrailAssessment.php @@ -0,0 +1,116 @@ +topicPolicy = isset($input['topicPolicy']) ? GuardrailTopicPolicyAssessment::create($input['topicPolicy']) : null; + $this->contentPolicy = isset($input['contentPolicy']) ? GuardrailContentPolicyAssessment::create($input['contentPolicy']) : null; + $this->wordPolicy = isset($input['wordPolicy']) ? GuardrailWordPolicyAssessment::create($input['wordPolicy']) : null; + $this->sensitiveInformationPolicy = isset($input['sensitiveInformationPolicy']) ? GuardrailSensitiveInformationPolicyAssessment::create($input['sensitiveInformationPolicy']) : null; + $this->contextualGroundingPolicy = isset($input['contextualGroundingPolicy']) ? GuardrailContextualGroundingPolicyAssessment::create($input['contextualGroundingPolicy']) : null; + $this->invocationMetrics = isset($input['invocationMetrics']) ? GuardrailInvocationMetrics::create($input['invocationMetrics']) : null; + } + + /** + * @param array{ + * topicPolicy?: null|GuardrailTopicPolicyAssessment|array, + * contentPolicy?: null|GuardrailContentPolicyAssessment|array, + * wordPolicy?: null|GuardrailWordPolicyAssessment|array, + * sensitiveInformationPolicy?: null|GuardrailSensitiveInformationPolicyAssessment|array, + * contextualGroundingPolicy?: null|GuardrailContextualGroundingPolicyAssessment|array, + * invocationMetrics?: null|GuardrailInvocationMetrics|array, + * }|GuardrailAssessment $input + */ + public static function create($input): self + { + return $input instanceof self ? $input : new self($input); + } + + public function getContentPolicy(): ?GuardrailContentPolicyAssessment + { + return $this->contentPolicy; + } + + public function getContextualGroundingPolicy(): ?GuardrailContextualGroundingPolicyAssessment + { + return $this->contextualGroundingPolicy; + } + + public function getInvocationMetrics(): ?GuardrailInvocationMetrics + { + return $this->invocationMetrics; + } + + public function getSensitiveInformationPolicy(): ?GuardrailSensitiveInformationPolicyAssessment + { + return $this->sensitiveInformationPolicy; + } + + public function getTopicPolicy(): ?GuardrailTopicPolicyAssessment + { + return $this->topicPolicy; + } + + public function getWordPolicy(): ?GuardrailWordPolicyAssessment + { + return $this->wordPolicy; + } +} diff --git a/src/Service/BedrockRuntime/src/ValueObject/GuardrailConfiguration.php b/src/Service/BedrockRuntime/src/ValueObject/GuardrailConfiguration.php new file mode 100644 index 000000000..a9d787d90 --- /dev/null +++ b/src/Service/BedrockRuntime/src/ValueObject/GuardrailConfiguration.php @@ -0,0 +1,107 @@ +guardrailIdentifier = $input['guardrailIdentifier'] ?? $this->throwException(new InvalidArgument('Missing required field "guardrailIdentifier".')); + $this->guardrailVersion = $input['guardrailVersion'] ?? $this->throwException(new InvalidArgument('Missing required field "guardrailVersion".')); + $this->trace = $input['trace'] ?? null; + } + + /** + * @param array{ + * guardrailIdentifier: string, + * guardrailVersion: string, + * trace?: null|GuardrailTrace::*, + * }|GuardrailConfiguration $input + */ + public static function create($input): self + { + return $input instanceof self ? $input : new self($input); + } + + public function getGuardrailIdentifier(): string + { + return $this->guardrailIdentifier; + } + + public function getGuardrailVersion(): string + { + return $this->guardrailVersion; + } + + /** + * @return GuardrailTrace::*|null + */ + public function getTrace(): ?string + { + return $this->trace; + } + + /** + * @internal + */ + public function requestBody(): array + { + $payload = []; + $v = $this->guardrailIdentifier; + $payload['guardrailIdentifier'] = $v; + $v = $this->guardrailVersion; + $payload['guardrailVersion'] = $v; + if (null !== $v = $this->trace) { + if (!GuardrailTrace::exists($v)) { + throw new InvalidArgument(\sprintf('Invalid parameter "trace" for "%s". The value "%s" is not a valid "GuardrailTrace".', __CLASS__, $v)); + } + $payload['trace'] = $v; + } + + return $payload; + } + + /** + * @return never + */ + private function throwException(\Throwable $exception) + { + throw $exception; + } +} diff --git a/src/Service/BedrockRuntime/src/ValueObject/GuardrailContentFilter.php b/src/Service/BedrockRuntime/src/ValueObject/GuardrailContentFilter.php new file mode 100644 index 000000000..3bb776408 --- /dev/null +++ b/src/Service/BedrockRuntime/src/ValueObject/GuardrailContentFilter.php @@ -0,0 +1,112 @@ +type = $input['type'] ?? $this->throwException(new InvalidArgument('Missing required field "type".')); + $this->confidence = $input['confidence'] ?? $this->throwException(new InvalidArgument('Missing required field "confidence".')); + $this->filterStrength = $input['filterStrength'] ?? null; + $this->action = $input['action'] ?? $this->throwException(new InvalidArgument('Missing required field "action".')); + } + + /** + * @param array{ + * type: GuardrailContentFilterType::*, + * confidence: GuardrailContentFilterConfidence::*, + * filterStrength?: null|GuardrailContentFilterStrength::*, + * action: GuardrailContentPolicyAction::*, + * }|GuardrailContentFilter $input + */ + public static function create($input): self + { + return $input instanceof self ? $input : new self($input); + } + + /** + * @return GuardrailContentPolicyAction::* + */ + public function getAction(): string + { + return $this->action; + } + + /** + * @return GuardrailContentFilterConfidence::* + */ + public function getConfidence(): string + { + return $this->confidence; + } + + /** + * @return GuardrailContentFilterStrength::*|null + */ + public function getFilterStrength(): ?string + { + return $this->filterStrength; + } + + /** + * @return GuardrailContentFilterType::* + */ + public function getType(): string + { + return $this->type; + } + + /** + * @return never + */ + private function throwException(\Throwable $exception) + { + throw $exception; + } +} diff --git a/src/Service/BedrockRuntime/src/ValueObject/GuardrailContentPolicyAssessment.php b/src/Service/BedrockRuntime/src/ValueObject/GuardrailContentPolicyAssessment.php new file mode 100644 index 000000000..ca2d6a867 --- /dev/null +++ b/src/Service/BedrockRuntime/src/ValueObject/GuardrailContentPolicyAssessment.php @@ -0,0 +1,54 @@ +, + * } $input + */ + public function __construct(array $input) + { + $this->filters = isset($input['filters']) ? array_map([GuardrailContentFilter::class, 'create'], $input['filters']) : $this->throwException(new InvalidArgument('Missing required field "filters".')); + } + + /** + * @param array{ + * filters: array, + * }|GuardrailContentPolicyAssessment $input + */ + public static function create($input): self + { + return $input instanceof self ? $input : new self($input); + } + + /** + * @return GuardrailContentFilter[] + */ + public function getFilters(): array + { + return $this->filters; + } + + /** + * @return never + */ + private function throwException(\Throwable $exception) + { + throw $exception; + } +} diff --git a/src/Service/BedrockRuntime/src/ValueObject/GuardrailContextualGroundingFilter.php b/src/Service/BedrockRuntime/src/ValueObject/GuardrailContextualGroundingFilter.php new file mode 100644 index 000000000..f052be46b --- /dev/null +++ b/src/Service/BedrockRuntime/src/ValueObject/GuardrailContextualGroundingFilter.php @@ -0,0 +1,104 @@ +type = $input['type'] ?? $this->throwException(new InvalidArgument('Missing required field "type".')); + $this->threshold = $input['threshold'] ?? $this->throwException(new InvalidArgument('Missing required field "threshold".')); + $this->score = $input['score'] ?? $this->throwException(new InvalidArgument('Missing required field "score".')); + $this->action = $input['action'] ?? $this->throwException(new InvalidArgument('Missing required field "action".')); + } + + /** + * @param array{ + * type: GuardrailContextualGroundingFilterType::*, + * threshold: float, + * score: float, + * action: GuardrailContextualGroundingPolicyAction::*, + * }|GuardrailContextualGroundingFilter $input + */ + public static function create($input): self + { + return $input instanceof self ? $input : new self($input); + } + + /** + * @return GuardrailContextualGroundingPolicyAction::* + */ + public function getAction(): string + { + return $this->action; + } + + public function getScore(): float + { + return $this->score; + } + + public function getThreshold(): float + { + return $this->threshold; + } + + /** + * @return GuardrailContextualGroundingFilterType::* + */ + public function getType(): string + { + return $this->type; + } + + /** + * @return never + */ + private function throwException(\Throwable $exception) + { + throw $exception; + } +} diff --git a/src/Service/BedrockRuntime/src/ValueObject/GuardrailContextualGroundingPolicyAssessment.php b/src/Service/BedrockRuntime/src/ValueObject/GuardrailContextualGroundingPolicyAssessment.php new file mode 100644 index 000000000..f64a89051 --- /dev/null +++ b/src/Service/BedrockRuntime/src/ValueObject/GuardrailContextualGroundingPolicyAssessment.php @@ -0,0 +1,44 @@ +, + * } $input + */ + public function __construct(array $input) + { + $this->filters = isset($input['filters']) ? array_map([GuardrailContextualGroundingFilter::class, 'create'], $input['filters']) : null; + } + + /** + * @param array{ + * filters?: null|array, + * }|GuardrailContextualGroundingPolicyAssessment $input + */ + public static function create($input): self + { + return $input instanceof self ? $input : new self($input); + } + + /** + * @return GuardrailContextualGroundingFilter[] + */ + public function getFilters(): array + { + return $this->filters ?? []; + } +} diff --git a/src/Service/BedrockRuntime/src/ValueObject/GuardrailConverseContentBlock.php b/src/Service/BedrockRuntime/src/ValueObject/GuardrailConverseContentBlock.php new file mode 100644 index 000000000..7eeec638e --- /dev/null +++ b/src/Service/BedrockRuntime/src/ValueObject/GuardrailConverseContentBlock.php @@ -0,0 +1,75 @@ +text = isset($input['text']) ? GuardrailConverseTextBlock::create($input['text']) : null; + $this->image = isset($input['image']) ? GuardrailConverseImageBlock::create($input['image']) : null; + } + + /** + * @param array{ + * text?: null|GuardrailConverseTextBlock|array, + * image?: null|GuardrailConverseImageBlock|array, + * }|GuardrailConverseContentBlock $input + */ + public static function create($input): self + { + return $input instanceof self ? $input : new self($input); + } + + public function getImage(): ?GuardrailConverseImageBlock + { + return $this->image; + } + + public function getText(): ?GuardrailConverseTextBlock + { + return $this->text; + } + + /** + * @internal + */ + public function requestBody(): array + { + $payload = []; + if (null !== $v = $this->text) { + $payload['text'] = $v->requestBody(); + } + if (null !== $v = $this->image) { + $payload['image'] = $v->requestBody(); + } + + return $payload; + } +} diff --git a/src/Service/BedrockRuntime/src/ValueObject/GuardrailConverseImageBlock.php b/src/Service/BedrockRuntime/src/ValueObject/GuardrailConverseImageBlock.php new file mode 100644 index 000000000..724a85c89 --- /dev/null +++ b/src/Service/BedrockRuntime/src/ValueObject/GuardrailConverseImageBlock.php @@ -0,0 +1,87 @@ +format = $input['format'] ?? $this->throwException(new InvalidArgument('Missing required field "format".')); + $this->source = isset($input['source']) ? GuardrailConverseImageSource::create($input['source']) : $this->throwException(new InvalidArgument('Missing required field "source".')); + } + + /** + * @param array{ + * format: GuardrailConverseImageFormat::*, + * source: GuardrailConverseImageSource|array, + * }|GuardrailConverseImageBlock $input + */ + public static function create($input): self + { + return $input instanceof self ? $input : new self($input); + } + + /** + * @return GuardrailConverseImageFormat::* + */ + public function getFormat(): string + { + return $this->format; + } + + public function getSource(): GuardrailConverseImageSource + { + return $this->source; + } + + /** + * @internal + */ + public function requestBody(): array + { + $payload = []; + $v = $this->format; + if (!GuardrailConverseImageFormat::exists($v)) { + throw new InvalidArgument(\sprintf('Invalid parameter "format" for "%s". The value "%s" is not a valid "GuardrailConverseImageFormat".', __CLASS__, $v)); + } + $payload['format'] = $v; + $v = $this->source; + $payload['source'] = $v->requestBody(); + + return $payload; + } + + /** + * @return never + */ + private function throwException(\Throwable $exception) + { + throw $exception; + } +} diff --git a/src/Service/BedrockRuntime/src/ValueObject/GuardrailConverseImageSource.php b/src/Service/BedrockRuntime/src/ValueObject/GuardrailConverseImageSource.php new file mode 100644 index 000000000..c9ae5ac6f --- /dev/null +++ b/src/Service/BedrockRuntime/src/ValueObject/GuardrailConverseImageSource.php @@ -0,0 +1,54 @@ +bytes = $input['bytes'] ?? null; + } + + /** + * @param array{ + * bytes?: null|string, + * }|GuardrailConverseImageSource $input + */ + public static function create($input): self + { + return $input instanceof self ? $input : new self($input); + } + + public function getBytes(): ?string + { + return $this->bytes; + } + + /** + * @internal + */ + public function requestBody(): array + { + $payload = []; + if (null !== $v = $this->bytes) { + $payload['bytes'] = base64_encode($v); + } + + return $payload; + } +} diff --git a/src/Service/BedrockRuntime/src/ValueObject/GuardrailConverseTextBlock.php b/src/Service/BedrockRuntime/src/ValueObject/GuardrailConverseTextBlock.php new file mode 100644 index 000000000..6287a9d29 --- /dev/null +++ b/src/Service/BedrockRuntime/src/ValueObject/GuardrailConverseTextBlock.php @@ -0,0 +1,94 @@ +|null + */ + private $qualifiers; + + /** + * @param array{ + * text: string, + * qualifiers?: null|array, + * } $input + */ + public function __construct(array $input) + { + $this->text = $input['text'] ?? $this->throwException(new InvalidArgument('Missing required field "text".')); + $this->qualifiers = $input['qualifiers'] ?? null; + } + + /** + * @param array{ + * text: string, + * qualifiers?: null|array, + * }|GuardrailConverseTextBlock $input + */ + public static function create($input): self + { + return $input instanceof self ? $input : new self($input); + } + + /** + * @return list + */ + public function getQualifiers(): array + { + return $this->qualifiers ?? []; + } + + public function getText(): string + { + return $this->text; + } + + /** + * @internal + */ + public function requestBody(): array + { + $payload = []; + $v = $this->text; + $payload['text'] = $v; + if (null !== $v = $this->qualifiers) { + $index = -1; + $payload['qualifiers'] = []; + foreach ($v as $listValue) { + ++$index; + if (!GuardrailConverseContentQualifier::exists($listValue)) { + throw new InvalidArgument(\sprintf('Invalid parameter "qualifiers" for "%s". The value "%s" is not a valid "GuardrailConverseContentQualifier".', __CLASS__, $listValue)); + } + $payload['qualifiers'][$index] = $listValue; + } + } + + return $payload; + } + + /** + * @return never + */ + private function throwException(\Throwable $exception) + { + throw $exception; + } +} diff --git a/src/Service/BedrockRuntime/src/ValueObject/GuardrailCoverage.php b/src/Service/BedrockRuntime/src/ValueObject/GuardrailCoverage.php new file mode 100644 index 000000000..9a9661e3e --- /dev/null +++ b/src/Service/BedrockRuntime/src/ValueObject/GuardrailCoverage.php @@ -0,0 +1,56 @@ +textCharacters = isset($input['textCharacters']) ? GuardrailTextCharactersCoverage::create($input['textCharacters']) : null; + $this->images = isset($input['images']) ? GuardrailImageCoverage::create($input['images']) : null; + } + + /** + * @param array{ + * textCharacters?: null|GuardrailTextCharactersCoverage|array, + * images?: null|GuardrailImageCoverage|array, + * }|GuardrailCoverage $input + */ + public static function create($input): self + { + return $input instanceof self ? $input : new self($input); + } + + public function getImages(): ?GuardrailImageCoverage + { + return $this->images; + } + + public function getTextCharacters(): ?GuardrailTextCharactersCoverage + { + return $this->textCharacters; + } +} diff --git a/src/Service/BedrockRuntime/src/ValueObject/GuardrailCustomWord.php b/src/Service/BedrockRuntime/src/ValueObject/GuardrailCustomWord.php new file mode 100644 index 000000000..dff190f2a --- /dev/null +++ b/src/Service/BedrockRuntime/src/ValueObject/GuardrailCustomWord.php @@ -0,0 +1,70 @@ +match = $input['match'] ?? $this->throwException(new InvalidArgument('Missing required field "match".')); + $this->action = $input['action'] ?? $this->throwException(new InvalidArgument('Missing required field "action".')); + } + + /** + * @param array{ + * match: string, + * action: GuardrailWordPolicyAction::*, + * }|GuardrailCustomWord $input + */ + public static function create($input): self + { + return $input instanceof self ? $input : new self($input); + } + + /** + * @return GuardrailWordPolicyAction::* + */ + public function getAction(): string + { + return $this->action; + } + + public function getMatch(): string + { + return $this->match; + } + + /** + * @return never + */ + private function throwException(\Throwable $exception) + { + throw $exception; + } +} diff --git a/src/Service/BedrockRuntime/src/ValueObject/GuardrailImageCoverage.php b/src/Service/BedrockRuntime/src/ValueObject/GuardrailImageCoverage.php new file mode 100644 index 000000000..481fde435 --- /dev/null +++ b/src/Service/BedrockRuntime/src/ValueObject/GuardrailImageCoverage.php @@ -0,0 +1,56 @@ +guarded = $input['guarded'] ?? null; + $this->total = $input['total'] ?? null; + } + + /** + * @param array{ + * guarded?: null|int, + * total?: null|int, + * }|GuardrailImageCoverage $input + */ + public static function create($input): self + { + return $input instanceof self ? $input : new self($input); + } + + public function getGuarded(): ?int + { + return $this->guarded; + } + + public function getTotal(): ?int + { + return $this->total; + } +} diff --git a/src/Service/BedrockRuntime/src/ValueObject/GuardrailInvocationMetrics.php b/src/Service/BedrockRuntime/src/ValueObject/GuardrailInvocationMetrics.php new file mode 100644 index 000000000..125d703a4 --- /dev/null +++ b/src/Service/BedrockRuntime/src/ValueObject/GuardrailInvocationMetrics.php @@ -0,0 +1,71 @@ +guardrailProcessingLatency = $input['guardrailProcessingLatency'] ?? null; + $this->usage = isset($input['usage']) ? GuardrailUsage::create($input['usage']) : null; + $this->guardrailCoverage = isset($input['guardrailCoverage']) ? GuardrailCoverage::create($input['guardrailCoverage']) : null; + } + + /** + * @param array{ + * guardrailProcessingLatency?: null|int, + * usage?: null|GuardrailUsage|array, + * guardrailCoverage?: null|GuardrailCoverage|array, + * }|GuardrailInvocationMetrics $input + */ + public static function create($input): self + { + return $input instanceof self ? $input : new self($input); + } + + public function getGuardrailCoverage(): ?GuardrailCoverage + { + return $this->guardrailCoverage; + } + + public function getGuardrailProcessingLatency(): ?int + { + return $this->guardrailProcessingLatency; + } + + public function getUsage(): ?GuardrailUsage + { + return $this->usage; + } +} diff --git a/src/Service/BedrockRuntime/src/ValueObject/GuardrailManagedWord.php b/src/Service/BedrockRuntime/src/ValueObject/GuardrailManagedWord.php new file mode 100644 index 000000000..773d96feb --- /dev/null +++ b/src/Service/BedrockRuntime/src/ValueObject/GuardrailManagedWord.php @@ -0,0 +1,89 @@ +match = $input['match'] ?? $this->throwException(new InvalidArgument('Missing required field "match".')); + $this->type = $input['type'] ?? $this->throwException(new InvalidArgument('Missing required field "type".')); + $this->action = $input['action'] ?? $this->throwException(new InvalidArgument('Missing required field "action".')); + } + + /** + * @param array{ + * match: string, + * type: GuardrailManagedWordType::*, + * action: GuardrailWordPolicyAction::*, + * }|GuardrailManagedWord $input + */ + public static function create($input): self + { + return $input instanceof self ? $input : new self($input); + } + + /** + * @return GuardrailWordPolicyAction::* + */ + public function getAction(): string + { + return $this->action; + } + + public function getMatch(): string + { + return $this->match; + } + + /** + * @return GuardrailManagedWordType::* + */ + public function getType(): string + { + return $this->type; + } + + /** + * @return never + */ + private function throwException(\Throwable $exception) + { + throw $exception; + } +} diff --git a/src/Service/BedrockRuntime/src/ValueObject/GuardrailPiiEntityFilter.php b/src/Service/BedrockRuntime/src/ValueObject/GuardrailPiiEntityFilter.php new file mode 100644 index 000000000..bc6e81a87 --- /dev/null +++ b/src/Service/BedrockRuntime/src/ValueObject/GuardrailPiiEntityFilter.php @@ -0,0 +1,89 @@ +match = $input['match'] ?? $this->throwException(new InvalidArgument('Missing required field "match".')); + $this->type = $input['type'] ?? $this->throwException(new InvalidArgument('Missing required field "type".')); + $this->action = $input['action'] ?? $this->throwException(new InvalidArgument('Missing required field "action".')); + } + + /** + * @param array{ + * match: string, + * type: GuardrailPiiEntityType::*, + * action: GuardrailSensitiveInformationPolicyAction::*, + * }|GuardrailPiiEntityFilter $input + */ + public static function create($input): self + { + return $input instanceof self ? $input : new self($input); + } + + /** + * @return GuardrailSensitiveInformationPolicyAction::* + */ + public function getAction(): string + { + return $this->action; + } + + public function getMatch(): string + { + return $this->match; + } + + /** + * @return GuardrailPiiEntityType::* + */ + public function getType(): string + { + return $this->type; + } + + /** + * @return never + */ + private function throwException(\Throwable $exception) + { + throw $exception; + } +} diff --git a/src/Service/BedrockRuntime/src/ValueObject/GuardrailRegexFilter.php b/src/Service/BedrockRuntime/src/ValueObject/GuardrailRegexFilter.php new file mode 100644 index 000000000..5ba11564c --- /dev/null +++ b/src/Service/BedrockRuntime/src/ValueObject/GuardrailRegexFilter.php @@ -0,0 +1,100 @@ +name = $input['name'] ?? null; + $this->match = $input['match'] ?? null; + $this->regex = $input['regex'] ?? null; + $this->action = $input['action'] ?? $this->throwException(new InvalidArgument('Missing required field "action".')); + } + + /** + * @param array{ + * name?: null|string, + * match?: null|string, + * regex?: null|string, + * action: GuardrailSensitiveInformationPolicyAction::*, + * }|GuardrailRegexFilter $input + */ + public static function create($input): self + { + return $input instanceof self ? $input : new self($input); + } + + /** + * @return GuardrailSensitiveInformationPolicyAction::* + */ + public function getAction(): string + { + return $this->action; + } + + public function getMatch(): ?string + { + return $this->match; + } + + public function getName(): ?string + { + return $this->name; + } + + public function getRegex(): ?string + { + return $this->regex; + } + + /** + * @return never + */ + private function throwException(\Throwable $exception) + { + throw $exception; + } +} diff --git a/src/Service/BedrockRuntime/src/ValueObject/GuardrailSensitiveInformationPolicyAssessment.php b/src/Service/BedrockRuntime/src/ValueObject/GuardrailSensitiveInformationPolicyAssessment.php new file mode 100644 index 000000000..d663842c2 --- /dev/null +++ b/src/Service/BedrockRuntime/src/ValueObject/GuardrailSensitiveInformationPolicyAssessment.php @@ -0,0 +1,72 @@ +, + * regexes: array, + * } $input + */ + public function __construct(array $input) + { + $this->piiEntities = isset($input['piiEntities']) ? array_map([GuardrailPiiEntityFilter::class, 'create'], $input['piiEntities']) : $this->throwException(new InvalidArgument('Missing required field "piiEntities".')); + $this->regexes = isset($input['regexes']) ? array_map([GuardrailRegexFilter::class, 'create'], $input['regexes']) : $this->throwException(new InvalidArgument('Missing required field "regexes".')); + } + + /** + * @param array{ + * piiEntities: array, + * regexes: array, + * }|GuardrailSensitiveInformationPolicyAssessment $input + */ + public static function create($input): self + { + return $input instanceof self ? $input : new self($input); + } + + /** + * @return GuardrailPiiEntityFilter[] + */ + public function getPiiEntities(): array + { + return $this->piiEntities; + } + + /** + * @return GuardrailRegexFilter[] + */ + public function getRegexes(): array + { + return $this->regexes; + } + + /** + * @return never + */ + private function throwException(\Throwable $exception) + { + throw $exception; + } +} diff --git a/src/Service/BedrockRuntime/src/ValueObject/GuardrailTextCharactersCoverage.php b/src/Service/BedrockRuntime/src/ValueObject/GuardrailTextCharactersCoverage.php new file mode 100644 index 000000000..bba6096a0 --- /dev/null +++ b/src/Service/BedrockRuntime/src/ValueObject/GuardrailTextCharactersCoverage.php @@ -0,0 +1,56 @@ +guarded = $input['guarded'] ?? null; + $this->total = $input['total'] ?? null; + } + + /** + * @param array{ + * guarded?: null|int, + * total?: null|int, + * }|GuardrailTextCharactersCoverage $input + */ + public static function create($input): self + { + return $input instanceof self ? $input : new self($input); + } + + public function getGuarded(): ?int + { + return $this->guarded; + } + + public function getTotal(): ?int + { + return $this->total; + } +} diff --git a/src/Service/BedrockRuntime/src/ValueObject/GuardrailTopic.php b/src/Service/BedrockRuntime/src/ValueObject/GuardrailTopic.php new file mode 100644 index 000000000..23e33b621 --- /dev/null +++ b/src/Service/BedrockRuntime/src/ValueObject/GuardrailTopic.php @@ -0,0 +1,89 @@ +name = $input['name'] ?? $this->throwException(new InvalidArgument('Missing required field "name".')); + $this->type = $input['type'] ?? $this->throwException(new InvalidArgument('Missing required field "type".')); + $this->action = $input['action'] ?? $this->throwException(new InvalidArgument('Missing required field "action".')); + } + + /** + * @param array{ + * name: string, + * type: GuardrailTopicType::*, + * action: GuardrailTopicPolicyAction::*, + * }|GuardrailTopic $input + */ + public static function create($input): self + { + return $input instanceof self ? $input : new self($input); + } + + /** + * @return GuardrailTopicPolicyAction::* + */ + public function getAction(): string + { + return $this->action; + } + + public function getName(): string + { + return $this->name; + } + + /** + * @return GuardrailTopicType::* + */ + public function getType(): string + { + return $this->type; + } + + /** + * @return never + */ + private function throwException(\Throwable $exception) + { + throw $exception; + } +} diff --git a/src/Service/BedrockRuntime/src/ValueObject/GuardrailTopicPolicyAssessment.php b/src/Service/BedrockRuntime/src/ValueObject/GuardrailTopicPolicyAssessment.php new file mode 100644 index 000000000..8d19bbc35 --- /dev/null +++ b/src/Service/BedrockRuntime/src/ValueObject/GuardrailTopicPolicyAssessment.php @@ -0,0 +1,54 @@ +, + * } $input + */ + public function __construct(array $input) + { + $this->topics = isset($input['topics']) ? array_map([GuardrailTopic::class, 'create'], $input['topics']) : $this->throwException(new InvalidArgument('Missing required field "topics".')); + } + + /** + * @param array{ + * topics: array, + * }|GuardrailTopicPolicyAssessment $input + */ + public static function create($input): self + { + return $input instanceof self ? $input : new self($input); + } + + /** + * @return GuardrailTopic[] + */ + public function getTopics(): array + { + return $this->topics; + } + + /** + * @return never + */ + private function throwException(\Throwable $exception) + { + throw $exception; + } +} diff --git a/src/Service/BedrockRuntime/src/ValueObject/GuardrailTraceAssessment.php b/src/Service/BedrockRuntime/src/ValueObject/GuardrailTraceAssessment.php new file mode 100644 index 000000000..e7ff41453 --- /dev/null +++ b/src/Service/BedrockRuntime/src/ValueObject/GuardrailTraceAssessment.php @@ -0,0 +1,80 @@ +|null + */ + private $inputAssessment; + + /** + * the output assessments. + * + * @var array|null + */ + private $outputAssessments; + + /** + * @param array{ + * modelOutput?: null|string[], + * inputAssessment?: null|array, + * outputAssessments?: null|array, + * } $input + */ + public function __construct(array $input) + { + $this->modelOutput = $input['modelOutput'] ?? null; + $this->inputAssessment = isset($input['inputAssessment']) ? array_map([GuardrailAssessment::class, 'create'], $input['inputAssessment']) : null; + $this->outputAssessments = $input['outputAssessments'] ?? null; + } + + /** + * @param array{ + * modelOutput?: null|string[], + * inputAssessment?: null|array, + * outputAssessments?: null|array, + * }|GuardrailTraceAssessment $input + */ + public static function create($input): self + { + return $input instanceof self ? $input : new self($input); + } + + /** + * @return array + */ + public function getInputAssessment(): array + { + return $this->inputAssessment ?? []; + } + + /** + * @return string[] + */ + public function getModelOutput(): array + { + return $this->modelOutput ?? []; + } + + /** + * @return array + */ + public function getOutputAssessments(): array + { + return $this->outputAssessments ?? []; + } +} diff --git a/src/Service/BedrockRuntime/src/ValueObject/GuardrailUsage.php b/src/Service/BedrockRuntime/src/ValueObject/GuardrailUsage.php new file mode 100644 index 000000000..f079cf817 --- /dev/null +++ b/src/Service/BedrockRuntime/src/ValueObject/GuardrailUsage.php @@ -0,0 +1,126 @@ +topicPolicyUnits = $input['topicPolicyUnits'] ?? $this->throwException(new InvalidArgument('Missing required field "topicPolicyUnits".')); + $this->contentPolicyUnits = $input['contentPolicyUnits'] ?? $this->throwException(new InvalidArgument('Missing required field "contentPolicyUnits".')); + $this->wordPolicyUnits = $input['wordPolicyUnits'] ?? $this->throwException(new InvalidArgument('Missing required field "wordPolicyUnits".')); + $this->sensitiveInformationPolicyUnits = $input['sensitiveInformationPolicyUnits'] ?? $this->throwException(new InvalidArgument('Missing required field "sensitiveInformationPolicyUnits".')); + $this->sensitiveInformationPolicyFreeUnits = $input['sensitiveInformationPolicyFreeUnits'] ?? $this->throwException(new InvalidArgument('Missing required field "sensitiveInformationPolicyFreeUnits".')); + $this->contextualGroundingPolicyUnits = $input['contextualGroundingPolicyUnits'] ?? $this->throwException(new InvalidArgument('Missing required field "contextualGroundingPolicyUnits".')); + } + + /** + * @param array{ + * topicPolicyUnits: int, + * contentPolicyUnits: int, + * wordPolicyUnits: int, + * sensitiveInformationPolicyUnits: int, + * sensitiveInformationPolicyFreeUnits: int, + * contextualGroundingPolicyUnits: int, + * }|GuardrailUsage $input + */ + public static function create($input): self + { + return $input instanceof self ? $input : new self($input); + } + + public function getContentPolicyUnits(): int + { + return $this->contentPolicyUnits; + } + + public function getContextualGroundingPolicyUnits(): int + { + return $this->contextualGroundingPolicyUnits; + } + + public function getSensitiveInformationPolicyFreeUnits(): int + { + return $this->sensitiveInformationPolicyFreeUnits; + } + + public function getSensitiveInformationPolicyUnits(): int + { + return $this->sensitiveInformationPolicyUnits; + } + + public function getTopicPolicyUnits(): int + { + return $this->topicPolicyUnits; + } + + public function getWordPolicyUnits(): int + { + return $this->wordPolicyUnits; + } + + /** + * @return never + */ + private function throwException(\Throwable $exception) + { + throw $exception; + } +} diff --git a/src/Service/BedrockRuntime/src/ValueObject/GuardrailWordPolicyAssessment.php b/src/Service/BedrockRuntime/src/ValueObject/GuardrailWordPolicyAssessment.php new file mode 100644 index 000000000..91222ec34 --- /dev/null +++ b/src/Service/BedrockRuntime/src/ValueObject/GuardrailWordPolicyAssessment.php @@ -0,0 +1,72 @@ +, + * managedWordLists: array, + * } $input + */ + public function __construct(array $input) + { + $this->customWords = isset($input['customWords']) ? array_map([GuardrailCustomWord::class, 'create'], $input['customWords']) : $this->throwException(new InvalidArgument('Missing required field "customWords".')); + $this->managedWordLists = isset($input['managedWordLists']) ? array_map([GuardrailManagedWord::class, 'create'], $input['managedWordLists']) : $this->throwException(new InvalidArgument('Missing required field "managedWordLists".')); + } + + /** + * @param array{ + * customWords: array, + * managedWordLists: array, + * }|GuardrailWordPolicyAssessment $input + */ + public static function create($input): self + { + return $input instanceof self ? $input : new self($input); + } + + /** + * @return GuardrailCustomWord[] + */ + public function getCustomWords(): array + { + return $this->customWords; + } + + /** + * @return GuardrailManagedWord[] + */ + public function getManagedWordLists(): array + { + return $this->managedWordLists; + } + + /** + * @return never + */ + private function throwException(\Throwable $exception) + { + throw $exception; + } +} diff --git a/src/Service/BedrockRuntime/src/ValueObject/ImageBlock.php b/src/Service/BedrockRuntime/src/ValueObject/ImageBlock.php new file mode 100644 index 000000000..dc40abc35 --- /dev/null +++ b/src/Service/BedrockRuntime/src/ValueObject/ImageBlock.php @@ -0,0 +1,87 @@ +format = $input['format'] ?? $this->throwException(new InvalidArgument('Missing required field "format".')); + $this->source = isset($input['source']) ? ImageSource::create($input['source']) : $this->throwException(new InvalidArgument('Missing required field "source".')); + } + + /** + * @param array{ + * format: ImageFormat::*, + * source: ImageSource|array, + * }|ImageBlock $input + */ + public static function create($input): self + { + return $input instanceof self ? $input : new self($input); + } + + /** + * @return ImageFormat::* + */ + public function getFormat(): string + { + return $this->format; + } + + public function getSource(): ImageSource + { + return $this->source; + } + + /** + * @internal + */ + public function requestBody(): array + { + $payload = []; + $v = $this->format; + if (!ImageFormat::exists($v)) { + throw new InvalidArgument(\sprintf('Invalid parameter "format" for "%s". The value "%s" is not a valid "ImageFormat".', __CLASS__, $v)); + } + $payload['format'] = $v; + $v = $this->source; + $payload['source'] = $v->requestBody(); + + return $payload; + } + + /** + * @return never + */ + private function throwException(\Throwable $exception) + { + throw $exception; + } +} diff --git a/src/Service/BedrockRuntime/src/ValueObject/ImageSource.php b/src/Service/BedrockRuntime/src/ValueObject/ImageSource.php new file mode 100644 index 000000000..f35fb3027 --- /dev/null +++ b/src/Service/BedrockRuntime/src/ValueObject/ImageSource.php @@ -0,0 +1,54 @@ +bytes = $input['bytes'] ?? null; + } + + /** + * @param array{ + * bytes?: null|string, + * }|ImageSource $input + */ + public static function create($input): self + { + return $input instanceof self ? $input : new self($input); + } + + public function getBytes(): ?string + { + return $this->bytes; + } + + /** + * @internal + */ + public function requestBody(): array + { + $payload = []; + if (null !== $v = $this->bytes) { + $payload['bytes'] = base64_encode($v); + } + + return $payload; + } +} diff --git a/src/Service/BedrockRuntime/src/ValueObject/InferenceConfiguration.php b/src/Service/BedrockRuntime/src/ValueObject/InferenceConfiguration.php new file mode 100644 index 000000000..d47bee61e --- /dev/null +++ b/src/Service/BedrockRuntime/src/ValueObject/InferenceConfiguration.php @@ -0,0 +1,143 @@ +maxTokens = $input['maxTokens'] ?? null; + $this->temperature = $input['temperature'] ?? null; + $this->topP = $input['topP'] ?? null; + $this->stopSequences = $input['stopSequences'] ?? null; + } + + /** + * @param array{ + * maxTokens?: null|int, + * temperature?: null|float, + * topP?: null|float, + * stopSequences?: null|string[], + * }|InferenceConfiguration $input + */ + public static function create($input): self + { + return $input instanceof self ? $input : new self($input); + } + + public function getMaxTokens(): ?int + { + return $this->maxTokens; + } + + /** + * @return string[] + */ + public function getStopSequences(): array + { + return $this->stopSequences ?? []; + } + + public function getTemperature(): ?float + { + return $this->temperature; + } + + public function getTopP(): ?float + { + return $this->topP; + } + + /** + * @internal + */ + public function requestBody(): array + { + $payload = []; + if (null !== $v = $this->maxTokens) { + $payload['maxTokens'] = $v; + } + if (null !== $v = $this->temperature) { + $payload['temperature'] = $v; + } + if (null !== $v = $this->topP) { + $payload['topP'] = $v; + } + if (null !== $v = $this->stopSequences) { + $index = -1; + $payload['stopSequences'] = []; + foreach ($v as $listValue) { + ++$index; + $payload['stopSequences'][$index] = $listValue; + } + } + + return $payload; + } +} diff --git a/src/Service/BedrockRuntime/src/ValueObject/Message.php b/src/Service/BedrockRuntime/src/ValueObject/Message.php new file mode 100644 index 000000000..966ab5cc3 --- /dev/null +++ b/src/Service/BedrockRuntime/src/ValueObject/Message.php @@ -0,0 +1,106 @@ +, + * } $input + */ + public function __construct(array $input) + { + $this->role = $input['role'] ?? $this->throwException(new InvalidArgument('Missing required field "role".')); + $this->content = isset($input['content']) ? array_map([ContentBlock::class, 'create'], $input['content']) : $this->throwException(new InvalidArgument('Missing required field "content".')); + } + + /** + * @param array{ + * role: ConversationRole::*, + * content: array, + * }|Message $input + */ + public static function create($input): self + { + return $input instanceof self ? $input : new self($input); + } + + /** + * @return ContentBlock[] + */ + public function getContent(): array + { + return $this->content; + } + + /** + * @return ConversationRole::* + */ + public function getRole(): string + { + return $this->role; + } + + /** + * @internal + */ + public function requestBody(): array + { + $payload = []; + $v = $this->role; + if (!ConversationRole::exists($v)) { + throw new InvalidArgument(\sprintf('Invalid parameter "role" for "%s". The value "%s" is not a valid "ConversationRole".', __CLASS__, $v)); + } + $payload['role'] = $v; + $v = $this->content; + + $index = -1; + $payload['content'] = []; + foreach ($v as $listValue) { + ++$index; + $payload['content'][$index] = $listValue->requestBody(); + } + + return $payload; + } + + /** + * @return never + */ + private function throwException(\Throwable $exception) + { + throw $exception; + } +} diff --git a/src/Service/BedrockRuntime/src/ValueObject/PerformanceConfiguration.php b/src/Service/BedrockRuntime/src/ValueObject/PerformanceConfiguration.php new file mode 100644 index 000000000..c70a7756e --- /dev/null +++ b/src/Service/BedrockRuntime/src/ValueObject/PerformanceConfiguration.php @@ -0,0 +1,63 @@ +latency = $input['latency'] ?? null; + } + + /** + * @param array{ + * latency?: null|PerformanceConfigLatency::*, + * }|PerformanceConfiguration $input + */ + public static function create($input): self + { + return $input instanceof self ? $input : new self($input); + } + + /** + * @return PerformanceConfigLatency::*|null + */ + public function getLatency(): ?string + { + return $this->latency; + } + + /** + * @internal + */ + public function requestBody(): array + { + $payload = []; + if (null !== $v = $this->latency) { + if (!PerformanceConfigLatency::exists($v)) { + throw new InvalidArgument(\sprintf('Invalid parameter "latency" for "%s". The value "%s" is not a valid "PerformanceConfigLatency".', __CLASS__, $v)); + } + $payload['latency'] = $v; + } + + return $payload; + } +} diff --git a/src/Service/BedrockRuntime/src/ValueObject/PromptRouterTrace.php b/src/Service/BedrockRuntime/src/ValueObject/PromptRouterTrace.php new file mode 100644 index 000000000..a093f701b --- /dev/null +++ b/src/Service/BedrockRuntime/src/ValueObject/PromptRouterTrace.php @@ -0,0 +1,41 @@ +invokedModelId = $input['invokedModelId'] ?? null; + } + + /** + * @param array{ + * invokedModelId?: null|string, + * }|PromptRouterTrace $input + */ + public static function create($input): self + { + return $input instanceof self ? $input : new self($input); + } + + public function getInvokedModelId(): ?string + { + return $this->invokedModelId; + } +} diff --git a/src/Service/BedrockRuntime/src/ValueObject/PromptVariableValues.php b/src/Service/BedrockRuntime/src/ValueObject/PromptVariableValues.php new file mode 100644 index 000000000..a229d18db --- /dev/null +++ b/src/Service/BedrockRuntime/src/ValueObject/PromptVariableValues.php @@ -0,0 +1,57 @@ +text = $input['text'] ?? null; + } + + /** + * @param array{ + * text?: null|string, + * }|PromptVariableValues $input + */ + public static function create($input): self + { + return $input instanceof self ? $input : new self($input); + } + + public function getText(): ?string + { + return $this->text; + } + + /** + * @internal + */ + public function requestBody(): array + { + $payload = []; + if (null !== $v = $this->text) { + $payload['text'] = $v; + } + + return $payload; + } +} diff --git a/src/Service/BedrockRuntime/src/ValueObject/ReasoningContentBlock.php b/src/Service/BedrockRuntime/src/ValueObject/ReasoningContentBlock.php new file mode 100644 index 000000000..4a3cbab0f --- /dev/null +++ b/src/Service/BedrockRuntime/src/ValueObject/ReasoningContentBlock.php @@ -0,0 +1,75 @@ +reasoningText = isset($input['reasoningText']) ? ReasoningTextBlock::create($input['reasoningText']) : null; + $this->redactedContent = $input['redactedContent'] ?? null; + } + + /** + * @param array{ + * reasoningText?: null|ReasoningTextBlock|array, + * redactedContent?: null|string, + * }|ReasoningContentBlock $input + */ + public static function create($input): self + { + return $input instanceof self ? $input : new self($input); + } + + public function getReasoningText(): ?ReasoningTextBlock + { + return $this->reasoningText; + } + + public function getRedactedContent(): ?string + { + return $this->redactedContent; + } + + /** + * @internal + */ + public function requestBody(): array + { + $payload = []; + if (null !== $v = $this->reasoningText) { + $payload['reasoningText'] = $v->requestBody(); + } + if (null !== $v = $this->redactedContent) { + $payload['redactedContent'] = base64_encode($v); + } + + return $payload; + } +} diff --git a/src/Service/BedrockRuntime/src/ValueObject/ReasoningTextBlock.php b/src/Service/BedrockRuntime/src/ValueObject/ReasoningTextBlock.php new file mode 100644 index 000000000..7d0befd2c --- /dev/null +++ b/src/Service/BedrockRuntime/src/ValueObject/ReasoningTextBlock.php @@ -0,0 +1,82 @@ +text = $input['text'] ?? $this->throwException(new InvalidArgument('Missing required field "text".')); + $this->signature = $input['signature'] ?? null; + } + + /** + * @param array{ + * text: string, + * signature?: null|string, + * }|ReasoningTextBlock $input + */ + public static function create($input): self + { + return $input instanceof self ? $input : new self($input); + } + + public function getSignature(): ?string + { + return $this->signature; + } + + public function getText(): string + { + return $this->text; + } + + /** + * @internal + */ + public function requestBody(): array + { + $payload = []; + $v = $this->text; + $payload['text'] = $v; + if (null !== $v = $this->signature) { + $payload['signature'] = $v; + } + + return $payload; + } + + /** + * @return never + */ + private function throwException(\Throwable $exception) + { + throw $exception; + } +} diff --git a/src/Service/BedrockRuntime/src/ValueObject/S3Location.php b/src/Service/BedrockRuntime/src/ValueObject/S3Location.php new file mode 100644 index 000000000..932631bc0 --- /dev/null +++ b/src/Service/BedrockRuntime/src/ValueObject/S3Location.php @@ -0,0 +1,81 @@ +uri = $input['uri'] ?? $this->throwException(new InvalidArgument('Missing required field "uri".')); + $this->bucketOwner = $input['bucketOwner'] ?? null; + } + + /** + * @param array{ + * uri: string, + * bucketOwner?: null|string, + * }|S3Location $input + */ + public static function create($input): self + { + return $input instanceof self ? $input : new self($input); + } + + public function getBucketOwner(): ?string + { + return $this->bucketOwner; + } + + public function getUri(): string + { + return $this->uri; + } + + /** + * @internal + */ + public function requestBody(): array + { + $payload = []; + $v = $this->uri; + $payload['uri'] = $v; + if (null !== $v = $this->bucketOwner) { + $payload['bucketOwner'] = $v; + } + + return $payload; + } + + /** + * @return never + */ + private function throwException(\Throwable $exception) + { + throw $exception; + } +} diff --git a/src/Service/BedrockRuntime/src/ValueObject/SpecificToolChoice.php b/src/Service/BedrockRuntime/src/ValueObject/SpecificToolChoice.php new file mode 100644 index 000000000..da6ddedb1 --- /dev/null +++ b/src/Service/BedrockRuntime/src/ValueObject/SpecificToolChoice.php @@ -0,0 +1,65 @@ + This field is only supported by Anthropic Claude 3 models. + */ +final class SpecificToolChoice +{ + /** + * The name of the tool that the model must request. + * + * @var string + */ + private $name; + + /** + * @param array{ + * name: string, + * } $input + */ + public function __construct(array $input) + { + $this->name = $input['name'] ?? $this->throwException(new InvalidArgument('Missing required field "name".')); + } + + /** + * @param array{ + * name: string, + * }|SpecificToolChoice $input + */ + public static function create($input): self + { + return $input instanceof self ? $input : new self($input); + } + + public function getName(): string + { + return $this->name; + } + + /** + * @internal + */ + public function requestBody(): array + { + $payload = []; + $v = $this->name; + $payload['name'] = $v; + + return $payload; + } + + /** + * @return never + */ + private function throwException(\Throwable $exception) + { + throw $exception; + } +} diff --git a/src/Service/BedrockRuntime/src/ValueObject/SystemContentBlock.php b/src/Service/BedrockRuntime/src/ValueObject/SystemContentBlock.php new file mode 100644 index 000000000..5b7c524c2 --- /dev/null +++ b/src/Service/BedrockRuntime/src/ValueObject/SystemContentBlock.php @@ -0,0 +1,77 @@ +text = $input['text'] ?? null; + $this->guardContent = isset($input['guardContent']) ? GuardrailConverseContentBlock::create($input['guardContent']) : null; + } + + /** + * @param array{ + * text?: null|string, + * guardContent?: null|GuardrailConverseContentBlock|array, + * }|SystemContentBlock $input + */ + public static function create($input): self + { + return $input instanceof self ? $input : new self($input); + } + + public function getGuardContent(): ?GuardrailConverseContentBlock + { + return $this->guardContent; + } + + public function getText(): ?string + { + return $this->text; + } + + /** + * @internal + */ + public function requestBody(): array + { + $payload = []; + if (null !== $v = $this->text) { + $payload['text'] = $v; + } + if (null !== $v = $this->guardContent) { + $payload['guardContent'] = $v->requestBody(); + } + + return $payload; + } +} diff --git a/src/Service/BedrockRuntime/src/ValueObject/TokenUsage.php b/src/Service/BedrockRuntime/src/ValueObject/TokenUsage.php new file mode 100644 index 000000000..8a514d070 --- /dev/null +++ b/src/Service/BedrockRuntime/src/ValueObject/TokenUsage.php @@ -0,0 +1,81 @@ +inputTokens = $input['inputTokens'] ?? $this->throwException(new InvalidArgument('Missing required field "inputTokens".')); + $this->outputTokens = $input['outputTokens'] ?? $this->throwException(new InvalidArgument('Missing required field "outputTokens".')); + $this->totalTokens = $input['totalTokens'] ?? $this->throwException(new InvalidArgument('Missing required field "totalTokens".')); + } + + /** + * @param array{ + * inputTokens: int, + * outputTokens: int, + * totalTokens: int, + * }|TokenUsage $input + */ + public static function create($input): self + { + return $input instanceof self ? $input : new self($input); + } + + public function getInputTokens(): int + { + return $this->inputTokens; + } + + public function getOutputTokens(): int + { + return $this->outputTokens; + } + + public function getTotalTokens(): int + { + return $this->totalTokens; + } + + /** + * @return never + */ + private function throwException(\Throwable $exception) + { + throw $exception; + } +} diff --git a/src/Service/BedrockRuntime/src/ValueObject/Tool.php b/src/Service/BedrockRuntime/src/ValueObject/Tool.php new file mode 100644 index 000000000..fbf682232 --- /dev/null +++ b/src/Service/BedrockRuntime/src/ValueObject/Tool.php @@ -0,0 +1,57 @@ +toolSpec = isset($input['toolSpec']) ? ToolSpecification::create($input['toolSpec']) : null; + } + + /** + * @param array{ + * toolSpec?: null|ToolSpecification|array, + * }|Tool $input + */ + public static function create($input): self + { + return $input instanceof self ? $input : new self($input); + } + + public function getToolSpec(): ?ToolSpecification + { + return $this->toolSpec; + } + + /** + * @internal + */ + public function requestBody(): array + { + $payload = []; + if (null !== $v = $this->toolSpec) { + $payload['toolSpec'] = $v->requestBody(); + } + + return $payload; + } +} diff --git a/src/Service/BedrockRuntime/src/ValueObject/ToolChoice.php b/src/Service/BedrockRuntime/src/ValueObject/ToolChoice.php new file mode 100644 index 000000000..0b0c7b601 --- /dev/null +++ b/src/Service/BedrockRuntime/src/ValueObject/ToolChoice.php @@ -0,0 +1,91 @@ +auto = isset($input['auto']) ? AutoToolChoice::create($input['auto']) : null; + $this->any = isset($input['any']) ? AnyToolChoice::create($input['any']) : null; + $this->tool = isset($input['tool']) ? SpecificToolChoice::create($input['tool']) : null; + } + + /** + * @param array{ + * auto?: null|AutoToolChoice|array, + * any?: null|AnyToolChoice|array, + * tool?: null|SpecificToolChoice|array, + * }|ToolChoice $input + */ + public static function create($input): self + { + return $input instanceof self ? $input : new self($input); + } + + public function getAny(): ?AnyToolChoice + { + return $this->any; + } + + public function getAuto(): ?AutoToolChoice + { + return $this->auto; + } + + public function getTool(): ?SpecificToolChoice + { + return $this->tool; + } + + /** + * @internal + */ + public function requestBody(): array + { + $payload = []; + if (null !== $v = $this->auto) { + $payload['auto'] = $v->requestBody(); + } + if (null !== $v = $this->any) { + $payload['any'] = $v->requestBody(); + } + if (null !== $v = $this->tool) { + $payload['tool'] = $v->requestBody(); + } + + return $payload; + } +} diff --git a/src/Service/BedrockRuntime/src/ValueObject/ToolConfiguration.php b/src/Service/BedrockRuntime/src/ValueObject/ToolConfiguration.php new file mode 100644 index 000000000..0963c9e8d --- /dev/null +++ b/src/Service/BedrockRuntime/src/ValueObject/ToolConfiguration.php @@ -0,0 +1,94 @@ +, + * toolChoice?: null|ToolChoice|array, + * } $input + */ + public function __construct(array $input) + { + $this->tools = isset($input['tools']) ? array_map([Tool::class, 'create'], $input['tools']) : $this->throwException(new InvalidArgument('Missing required field "tools".')); + $this->toolChoice = isset($input['toolChoice']) ? ToolChoice::create($input['toolChoice']) : null; + } + + /** + * @param array{ + * tools: array, + * toolChoice?: null|ToolChoice|array, + * }|ToolConfiguration $input + */ + public static function create($input): self + { + return $input instanceof self ? $input : new self($input); + } + + public function getToolChoice(): ?ToolChoice + { + return $this->toolChoice; + } + + /** + * @return Tool[] + */ + public function getTools(): array + { + return $this->tools; + } + + /** + * @internal + */ + public function requestBody(): array + { + $payload = []; + $v = $this->tools; + + $index = -1; + $payload['tools'] = []; + foreach ($v as $listValue) { + ++$index; + $payload['tools'][$index] = $listValue->requestBody(); + } + + if (null !== $v = $this->toolChoice) { + $payload['toolChoice'] = $v->requestBody(); + } + + return $payload; + } + + /** + * @return never + */ + private function throwException(\Throwable $exception) + { + throw $exception; + } +} diff --git a/src/Service/BedrockRuntime/src/ValueObject/ToolInputSchema.php b/src/Service/BedrockRuntime/src/ValueObject/ToolInputSchema.php new file mode 100644 index 000000000..8a2c3f910 --- /dev/null +++ b/src/Service/BedrockRuntime/src/ValueObject/ToolInputSchema.php @@ -0,0 +1,56 @@ +json = isset($input['json']) ? Document::create($input['json']) : null; + } + + /** + * @param array{ + * json?: null|Document|array, + * }|ToolInputSchema $input + */ + public static function create($input): self + { + return $input instanceof self ? $input : new self($input); + } + + public function getJson(): ?Document + { + return $this->json; + } + + /** + * @internal + */ + public function requestBody(): array + { + $payload = []; + if (null !== $v = $this->json) { + $payload['json'] = $v->requestBody(); + } + + return $payload; + } +} diff --git a/src/Service/BedrockRuntime/src/ValueObject/ToolResultBlock.php b/src/Service/BedrockRuntime/src/ValueObject/ToolResultBlock.php new file mode 100644 index 000000000..66093349d --- /dev/null +++ b/src/Service/BedrockRuntime/src/ValueObject/ToolResultBlock.php @@ -0,0 +1,117 @@ + This field is only supported Anthropic Claude 3 models. + * + * @var ToolResultStatus::*|null + */ + private $status; + + /** + * @param array{ + * toolUseId: string, + * content: array, + * status?: null|ToolResultStatus::*, + * } $input + */ + public function __construct(array $input) + { + $this->toolUseId = $input['toolUseId'] ?? $this->throwException(new InvalidArgument('Missing required field "toolUseId".')); + $this->content = isset($input['content']) ? array_map([ToolResultContentBlock::class, 'create'], $input['content']) : $this->throwException(new InvalidArgument('Missing required field "content".')); + $this->status = $input['status'] ?? null; + } + + /** + * @param array{ + * toolUseId: string, + * content: array, + * status?: null|ToolResultStatus::*, + * }|ToolResultBlock $input + */ + public static function create($input): self + { + return $input instanceof self ? $input : new self($input); + } + + /** + * @return ToolResultContentBlock[] + */ + public function getContent(): array + { + return $this->content; + } + + /** + * @return ToolResultStatus::*|null + */ + public function getStatus(): ?string + { + return $this->status; + } + + public function getToolUseId(): string + { + return $this->toolUseId; + } + + /** + * @internal + */ + public function requestBody(): array + { + $payload = []; + $v = $this->toolUseId; + $payload['toolUseId'] = $v; + $v = $this->content; + + $index = -1; + $payload['content'] = []; + foreach ($v as $listValue) { + ++$index; + $payload['content'][$index] = $listValue->requestBody(); + } + + if (null !== $v = $this->status) { + if (!ToolResultStatus::exists($v)) { + throw new InvalidArgument(\sprintf('Invalid parameter "status" for "%s". The value "%s" is not a valid "ToolResultStatus".', __CLASS__, $v)); + } + $payload['status'] = $v; + } + + return $payload; + } + + /** + * @return never + */ + private function throwException(\Throwable $exception) + { + throw $exception; + } +} diff --git a/src/Service/BedrockRuntime/src/ValueObject/ToolResultContentBlock.php b/src/Service/BedrockRuntime/src/ValueObject/ToolResultContentBlock.php new file mode 100644 index 000000000..f8dd07e22 --- /dev/null +++ b/src/Service/BedrockRuntime/src/ValueObject/ToolResultContentBlock.php @@ -0,0 +1,128 @@ + This field is only supported by Anthropic Claude 3 models. + * + * @var ImageBlock|null + */ + private $image; + + /** + * A tool result that is a document. + * + * @var DocumentBlock|null + */ + private $document; + + /** + * A tool result that is video. + * + * @var VideoBlock|null + */ + private $video; + + /** + * @param array{ + * json?: null|Document|array, + * text?: null|string, + * image?: null|ImageBlock|array, + * document?: null|DocumentBlock|array, + * video?: null|VideoBlock|array, + * } $input + */ + public function __construct(array $input) + { + $this->json = isset($input['json']) ? Document::create($input['json']) : null; + $this->text = $input['text'] ?? null; + $this->image = isset($input['image']) ? ImageBlock::create($input['image']) : null; + $this->document = isset($input['document']) ? DocumentBlock::create($input['document']) : null; + $this->video = isset($input['video']) ? VideoBlock::create($input['video']) : null; + } + + /** + * @param array{ + * json?: null|Document|array, + * text?: null|string, + * image?: null|ImageBlock|array, + * document?: null|DocumentBlock|array, + * video?: null|VideoBlock|array, + * }|ToolResultContentBlock $input + */ + public static function create($input): self + { + return $input instanceof self ? $input : new self($input); + } + + public function getDocument(): ?DocumentBlock + { + return $this->document; + } + + public function getImage(): ?ImageBlock + { + return $this->image; + } + + public function getJson(): ?Document + { + return $this->json; + } + + public function getText(): ?string + { + return $this->text; + } + + public function getVideo(): ?VideoBlock + { + return $this->video; + } + + /** + * @internal + */ + public function requestBody(): array + { + $payload = []; + if (null !== $v = $this->json) { + $payload['json'] = $v->requestBody(); + } + if (null !== $v = $this->text) { + $payload['text'] = $v; + } + if (null !== $v = $this->image) { + $payload['image'] = $v->requestBody(); + } + if (null !== $v = $this->document) { + $payload['document'] = $v->requestBody(); + } + if (null !== $v = $this->video) { + $payload['video'] = $v->requestBody(); + } + + return $payload; + } +} diff --git a/src/Service/BedrockRuntime/src/ValueObject/ToolSpecification.php b/src/Service/BedrockRuntime/src/ValueObject/ToolSpecification.php new file mode 100644 index 000000000..fdf7bdfbb --- /dev/null +++ b/src/Service/BedrockRuntime/src/ValueObject/ToolSpecification.php @@ -0,0 +1,98 @@ +name = $input['name'] ?? $this->throwException(new InvalidArgument('Missing required field "name".')); + $this->description = $input['description'] ?? null; + $this->inputSchema = isset($input['inputSchema']) ? ToolInputSchema::create($input['inputSchema']) : $this->throwException(new InvalidArgument('Missing required field "inputSchema".')); + } + + /** + * @param array{ + * name: string, + * description?: null|string, + * inputSchema: ToolInputSchema|array, + * }|ToolSpecification $input + */ + public static function create($input): self + { + return $input instanceof self ? $input : new self($input); + } + + public function getDescription(): ?string + { + return $this->description; + } + + public function getInputSchema(): ToolInputSchema + { + return $this->inputSchema; + } + + public function getName(): string + { + return $this->name; + } + + /** + * @internal + */ + public function requestBody(): array + { + $payload = []; + $v = $this->name; + $payload['name'] = $v; + if (null !== $v = $this->description) { + $payload['description'] = $v; + } + $v = $this->inputSchema; + $payload['inputSchema'] = $v->requestBody(); + + return $payload; + } + + /** + * @return never + */ + private function throwException(\Throwable $exception) + { + throw $exception; + } +} diff --git a/src/Service/BedrockRuntime/src/ValueObject/ToolUseBlock.php b/src/Service/BedrockRuntime/src/ValueObject/ToolUseBlock.php new file mode 100644 index 000000000..8b83a05f5 --- /dev/null +++ b/src/Service/BedrockRuntime/src/ValueObject/ToolUseBlock.php @@ -0,0 +1,98 @@ +toolUseId = $input['toolUseId'] ?? $this->throwException(new InvalidArgument('Missing required field "toolUseId".')); + $this->name = $input['name'] ?? $this->throwException(new InvalidArgument('Missing required field "name".')); + $this->input = isset($input['input']) ? Document::create($input['input']) : $this->throwException(new InvalidArgument('Missing required field "input".')); + } + + /** + * @param array{ + * toolUseId: string, + * name: string, + * input: Document|array, + * }|ToolUseBlock $input + */ + public static function create($input): self + { + return $input instanceof self ? $input : new self($input); + } + + public function getInput(): Document + { + return $this->input; + } + + public function getName(): string + { + return $this->name; + } + + public function getToolUseId(): string + { + return $this->toolUseId; + } + + /** + * @internal + */ + public function requestBody(): array + { + $payload = []; + $v = $this->toolUseId; + $payload['toolUseId'] = $v; + $v = $this->name; + $payload['name'] = $v; + $v = $this->input; + $payload['input'] = $v->requestBody(); + + return $payload; + } + + /** + * @return never + */ + private function throwException(\Throwable $exception) + { + throw $exception; + } +} diff --git a/src/Service/BedrockRuntime/src/ValueObject/VideoBlock.php b/src/Service/BedrockRuntime/src/ValueObject/VideoBlock.php new file mode 100644 index 000000000..8012d5527 --- /dev/null +++ b/src/Service/BedrockRuntime/src/ValueObject/VideoBlock.php @@ -0,0 +1,87 @@ +format = $input['format'] ?? $this->throwException(new InvalidArgument('Missing required field "format".')); + $this->source = isset($input['source']) ? VideoSource::create($input['source']) : $this->throwException(new InvalidArgument('Missing required field "source".')); + } + + /** + * @param array{ + * format: VideoFormat::*, + * source: VideoSource|array, + * }|VideoBlock $input + */ + public static function create($input): self + { + return $input instanceof self ? $input : new self($input); + } + + /** + * @return VideoFormat::* + */ + public function getFormat(): string + { + return $this->format; + } + + public function getSource(): VideoSource + { + return $this->source; + } + + /** + * @internal + */ + public function requestBody(): array + { + $payload = []; + $v = $this->format; + if (!VideoFormat::exists($v)) { + throw new InvalidArgument(\sprintf('Invalid parameter "format" for "%s". The value "%s" is not a valid "VideoFormat".', __CLASS__, $v)); + } + $payload['format'] = $v; + $v = $this->source; + $payload['source'] = $v->requestBody(); + + return $payload; + } + + /** + * @return never + */ + private function throwException(\Throwable $exception) + { + throw $exception; + } +} diff --git a/src/Service/BedrockRuntime/src/ValueObject/VideoSource.php b/src/Service/BedrockRuntime/src/ValueObject/VideoSource.php new file mode 100644 index 000000000..8fc9632cf --- /dev/null +++ b/src/Service/BedrockRuntime/src/ValueObject/VideoSource.php @@ -0,0 +1,73 @@ +bytes = $input['bytes'] ?? null; + $this->s3Location = isset($input['s3Location']) ? S3Location::create($input['s3Location']) : null; + } + + /** + * @param array{ + * bytes?: null|string, + * s3Location?: null|S3Location|array, + * }|VideoSource $input + */ + public static function create($input): self + { + return $input instanceof self ? $input : new self($input); + } + + public function getBytes(): ?string + { + return $this->bytes; + } + + public function getS3Location(): ?S3Location + { + return $this->s3Location; + } + + /** + * @internal + */ + public function requestBody(): array + { + $payload = []; + if (null !== $v = $this->bytes) { + $payload['bytes'] = base64_encode($v); + } + if (null !== $v = $this->s3Location) { + $payload['s3Location'] = $v->requestBody(); + } + + return $payload; + } +} diff --git a/src/Service/BedrockRuntime/tests/Integration/BedrockRuntimeClientTest.php b/src/Service/BedrockRuntime/tests/Integration/BedrockRuntimeClientTest.php index 1588372f0..9c0a0622d 100644 --- a/src/Service/BedrockRuntime/tests/Integration/BedrockRuntimeClientTest.php +++ b/src/Service/BedrockRuntime/tests/Integration/BedrockRuntimeClientTest.php @@ -3,12 +3,208 @@ namespace AsyncAws\BedrockRuntime\Tests\Integration; use AsyncAws\BedrockRuntime\BedrockRuntimeClient; +use AsyncAws\BedrockRuntime\Input\ConverseRequest; use AsyncAws\BedrockRuntime\Input\InvokeModelRequest; +use AsyncAws\BedrockRuntime\ValueObject\AnyToolChoice; +use AsyncAws\BedrockRuntime\ValueObject\AutoToolChoice; +use AsyncAws\BedrockRuntime\ValueObject\ContentBlock; +use AsyncAws\BedrockRuntime\ValueObject\Document; +use AsyncAws\BedrockRuntime\ValueObject\DocumentBlock; +use AsyncAws\BedrockRuntime\ValueObject\DocumentSource; +use AsyncAws\BedrockRuntime\ValueObject\GuardrailConfiguration; +use AsyncAws\BedrockRuntime\ValueObject\GuardrailConverseContentBlock; +use AsyncAws\BedrockRuntime\ValueObject\GuardrailConverseImageBlock; +use AsyncAws\BedrockRuntime\ValueObject\GuardrailConverseImageSource; +use AsyncAws\BedrockRuntime\ValueObject\GuardrailConverseTextBlock; +use AsyncAws\BedrockRuntime\ValueObject\ImageBlock; +use AsyncAws\BedrockRuntime\ValueObject\ImageSource; +use AsyncAws\BedrockRuntime\ValueObject\InferenceConfiguration; +use AsyncAws\BedrockRuntime\ValueObject\Message; +use AsyncAws\BedrockRuntime\ValueObject\PerformanceConfiguration; +use AsyncAws\BedrockRuntime\ValueObject\PromptVariableValues; +use AsyncAws\BedrockRuntime\ValueObject\ReasoningContentBlock; +use AsyncAws\BedrockRuntime\ValueObject\ReasoningTextBlock; +use AsyncAws\BedrockRuntime\ValueObject\S3Location; +use AsyncAws\BedrockRuntime\ValueObject\SpecificToolChoice; +use AsyncAws\BedrockRuntime\ValueObject\SystemContentBlock; +use AsyncAws\BedrockRuntime\ValueObject\Tool; +use AsyncAws\BedrockRuntime\ValueObject\ToolChoice; +use AsyncAws\BedrockRuntime\ValueObject\ToolConfiguration; +use AsyncAws\BedrockRuntime\ValueObject\ToolInputSchema; +use AsyncAws\BedrockRuntime\ValueObject\ToolResultBlock; +use AsyncAws\BedrockRuntime\ValueObject\ToolResultContentBlock; +use AsyncAws\BedrockRuntime\ValueObject\ToolSpecification; +use AsyncAws\BedrockRuntime\ValueObject\ToolUseBlock; +use AsyncAws\BedrockRuntime\ValueObject\VideoBlock; +use AsyncAws\BedrockRuntime\ValueObject\VideoSource; use AsyncAws\Core\Credentials\NullProvider; use AsyncAws\Core\Test\TestCase; class BedrockRuntimeClientTest extends TestCase { + public function testConverse(): void + { + $client = $this->getClient(); + + $input = new ConverseRequest([ + 'modelId' => 'change me', + 'messages' => [new Message([ + 'role' => 'change me', + 'content' => [new ContentBlock([ + 'text' => 'change me', + 'image' => new ImageBlock([ + 'format' => 'change me', + 'source' => new ImageSource([ + 'bytes' => 'change me', + ]), + ]), + 'document' => new DocumentBlock([ + 'format' => 'change me', + 'name' => 'change me', + 'source' => new DocumentSource([ + 'bytes' => 'change me', + ]), + ]), + 'video' => new VideoBlock([ + 'format' => 'change me', + 'source' => new VideoSource([ + 'bytes' => 'change me', + 's3Location' => new S3Location([ + 'uri' => 'change me', + 'bucketOwner' => 'change me', + ]), + ]), + ]), + 'toolUse' => new ToolUseBlock([ + 'toolUseId' => 'change me', + 'name' => 'change me', + 'input' => new Document([ + ]), + ]), + 'toolResult' => new ToolResultBlock([ + 'toolUseId' => 'change me', + 'content' => [new ToolResultContentBlock([ + 'json' => new Document([ + ]), + 'text' => 'change me', + 'image' => new ImageBlock([ + 'format' => 'change me', + 'source' => new ImageSource([ + 'bytes' => 'change me', + ]), + ]), + 'document' => new DocumentBlock([ + 'format' => 'change me', + 'name' => 'change me', + 'source' => new DocumentSource([ + 'bytes' => 'change me', + ]), + ]), + 'video' => new VideoBlock([ + 'format' => 'change me', + 'source' => new VideoSource([ + 'bytes' => 'change me', + 's3Location' => new S3Location([ + 'uri' => 'change me', + 'bucketOwner' => 'change me', + ]), + ]), + ]), + ])], + 'status' => 'change me', + ]), + 'guardContent' => new GuardrailConverseContentBlock([ + 'text' => new GuardrailConverseTextBlock([ + 'text' => 'change me', + 'qualifiers' => ['change me'], + ]), + 'image' => new GuardrailConverseImageBlock([ + 'format' => 'change me', + 'source' => new GuardrailConverseImageSource([ + 'bytes' => 'change me', + ]), + ]), + ]), + 'reasoningContent' => new ReasoningContentBlock([ + 'reasoningText' => new ReasoningTextBlock([ + 'text' => 'change me', + 'signature' => 'change me', + ]), + 'redactedContent' => 'change me', + ]), + ])], + ])], + 'system' => [new SystemContentBlock([ + 'text' => 'change me', + 'guardContent' => new GuardrailConverseContentBlock([ + 'text' => new GuardrailConverseTextBlock([ + 'text' => 'change me', + 'qualifiers' => ['change me'], + ]), + 'image' => new GuardrailConverseImageBlock([ + 'format' => 'change me', + 'source' => new GuardrailConverseImageSource([ + 'bytes' => 'change me', + ]), + ]), + ]), + ])], + 'inferenceConfig' => new InferenceConfiguration([ + 'maxTokens' => 1337, + 'temperature' => 1337, + 'topP' => 1337, + 'stopSequences' => ['change me'], + ]), + 'toolConfig' => new ToolConfiguration([ + 'tools' => [new Tool([ + 'toolSpec' => new ToolSpecification([ + 'name' => 'change me', + 'description' => 'change me', + 'inputSchema' => new ToolInputSchema([ + 'json' => new Document([ + ]), + ]), + ]), + ])], + 'toolChoice' => new ToolChoice([ + 'auto' => new AutoToolChoice([ + ]), + 'any' => new AnyToolChoice([ + ]), + 'tool' => new SpecificToolChoice([ + 'name' => 'change me', + ]), + ]), + ]), + 'guardrailConfig' => new GuardrailConfiguration([ + 'guardrailIdentifier' => 'change me', + 'guardrailVersion' => 'change me', + 'trace' => 'change me', + ]), + 'additionalModelRequestFields' => new Document([ + ]), + 'promptVariables' => ['change me' => new PromptVariableValues([ + 'text' => 'change me', + ])], + 'additionalModelResponseFieldPaths' => ['change me'], + 'requestMetadata' => ['change me' => 'change me'], + 'performanceConfig' => new PerformanceConfiguration([ + 'latency' => 'change me', + ]), + ]); + $result = $client->converse($input); + + $result->resolve(); + + // self::assertTODO(expected, $result->getOutput()); + self::assertSame('changeIt', $result->getStopReason()); + // self::assertTODO(expected, $result->getUsage()); + // self::assertTODO(expected, $result->getMetrics()); + // self::assertTODO(expected, $result->getAdditionalModelResponseFields()); + // self::assertTODO(expected, $result->getTrace()); + // self::assertTODO(expected, $result->getPerformanceConfig()); + } + public function testInvokeModel(): void { $client = $this->getClient(); diff --git a/src/Service/BedrockRuntime/tests/Unit/BedrockRuntimeClientTest.php b/src/Service/BedrockRuntime/tests/Unit/BedrockRuntimeClientTest.php index 546765a7c..990443576 100644 --- a/src/Service/BedrockRuntime/tests/Unit/BedrockRuntimeClientTest.php +++ b/src/Service/BedrockRuntime/tests/Unit/BedrockRuntimeClientTest.php @@ -3,7 +3,9 @@ namespace AsyncAws\BedrockRuntime\Tests\Unit; use AsyncAws\BedrockRuntime\BedrockRuntimeClient; +use AsyncAws\BedrockRuntime\Input\ConverseRequest; use AsyncAws\BedrockRuntime\Input\InvokeModelRequest; +use AsyncAws\BedrockRuntime\Result\ConverseResponse; use AsyncAws\BedrockRuntime\Result\InvokeModelResponse; use AsyncAws\Core\Credentials\NullProvider; use AsyncAws\Core\Test\TestCase; @@ -11,6 +13,19 @@ class BedrockRuntimeClientTest extends TestCase { + public function testConverse(): void + { + $client = new BedrockRuntimeClient([], new NullProvider(), new MockHttpClient()); + + $input = new ConverseRequest([ + 'modelId' => 'change me', + ]); + $result = $client->converse($input); + + self::assertInstanceOf(ConverseResponse::class, $result); + self::assertFalse($result->info()['resolved']); + } + public function testInvokeModel(): void { $client = new BedrockRuntimeClient([], new NullProvider(), new MockHttpClient()); diff --git a/src/Service/BedrockRuntime/tests/Unit/Input/ConverseRequestTest.php b/src/Service/BedrockRuntime/tests/Unit/Input/ConverseRequestTest.php new file mode 100644 index 000000000..264d06038 --- /dev/null +++ b/src/Service/BedrockRuntime/tests/Unit/Input/ConverseRequestTest.php @@ -0,0 +1,373 @@ + 'change me', + 'messages' => [new Message([ + 'role' => 'user', + 'content' => [new ContentBlock([ + 'text' => 'change me', + 'image' => new ImageBlock([ + 'format' => 'png', + 'source' => new ImageSource([ + 'bytes' => 'change me', + ]), + ]), + 'document' => new DocumentBlock([ + 'format' => 'pdf', + 'name' => 'change me', + 'source' => new DocumentSource([ + 'bytes' => 'change me', + ]), + ]), + 'video' => new VideoBlock([ + 'format' => 'mkv', + 'source' => new VideoSource([ + 'bytes' => 'change me', + 's3Location' => new S3Location([ + 'uri' => 'change me', + 'bucketOwner' => 'change me', + ]), + ]), + ]), + 'toolUse' => new ToolUseBlock([ + 'toolUseId' => 'change me', + 'name' => 'change me', + 'input' => new Document([ + ]), + ]), + 'toolResult' => new ToolResultBlock([ + 'toolUseId' => 'change me', + 'content' => [new ToolResultContentBlock([ + 'json' => new Document([ + ]), + 'text' => 'change me', + 'image' => new ImageBlock([ + 'format' => 'png', + 'source' => new ImageSource([ + 'bytes' => 'change me', + ]), + ]), + 'document' => new DocumentBlock([ + 'format' => 'pdf', + 'name' => 'change me', + 'source' => new DocumentSource([ + 'bytes' => 'change me', + ]), + ]), + 'video' => new VideoBlock([ + 'format' => 'mkv', + 'source' => new VideoSource([ + 'bytes' => 'change me', + 's3Location' => new S3Location([ + 'uri' => 'change me', + 'bucketOwner' => 'change me', + ]), + ]), + ]), + ])], + 'status' => 'success', + ]), + 'guardContent' => new GuardrailConverseContentBlock([ + 'text' => new GuardrailConverseTextBlock([ + 'text' => 'change me', + 'qualifiers' => ['grounding_source'], + ]), + 'image' => new GuardrailConverseImageBlock([ + 'format' => 'png', + 'source' => new GuardrailConverseImageSource([ + 'bytes' => 'change me', + ]), + ]), + ]), + 'reasoningContent' => new ReasoningContentBlock([ + 'reasoningText' => new ReasoningTextBlock([ + 'text' => 'change me', + 'signature' => 'change me', + ]), + 'redactedContent' => 'change me', + ]), + ])], + ])], + 'system' => [new SystemContentBlock([ + 'text' => 'change me', + 'guardContent' => new GuardrailConverseContentBlock([ + 'text' => new GuardrailConverseTextBlock([ + 'text' => 'change me', + 'qualifiers' => ['grounding_source'], + ]), + 'image' => new GuardrailConverseImageBlock([ + 'format' => 'png', + 'source' => new GuardrailConverseImageSource([ + 'bytes' => 'change me', + ]), + ]), + ]), + ])], + 'inferenceConfig' => new InferenceConfiguration([ + 'maxTokens' => 1337, + 'temperature' => 1337, + 'topP' => 1337, + 'stopSequences' => ['change me'], + ]), + 'toolConfig' => new ToolConfiguration([ + 'tools' => [new Tool([ + 'toolSpec' => new ToolSpecification([ + 'name' => 'change me', + 'description' => 'change me', + 'inputSchema' => new ToolInputSchema([ + 'json' => new Document([ + ]), + ]), + ]), + ])], + 'toolChoice' => new ToolChoice([ + 'auto' => new AutoToolChoice([ + ]), + 'any' => new AnyToolChoice([ + ]), + 'tool' => new SpecificToolChoice([ + 'name' => 'change me', + ]), + ]), + ]), + 'guardrailConfig' => new GuardrailConfiguration([ + 'guardrailIdentifier' => 'change me', + 'guardrailVersion' => 'change me', + 'trace' => 'enabled', + ]), + 'additionalModelRequestFields' => new Document([ + ]), + 'promptVariables' => ['change me' => new PromptVariableValues([ + 'text' => 'change me', + ])], + 'additionalModelResponseFieldPaths' => ['change me'], + 'requestMetadata' => ['change me' => 'change me'], + 'performanceConfig' => new PerformanceConfiguration([ + 'latency' => 'standard', + ]), + ]); + + // see https://docs.aws.amazon.com/bedrock/latest/APIReference/API_Converse.html + $expected = ' + POST / HTTP/1.0 + Content-Type: application/json + + { + "messages":[ + { + "role":"user", + "content":[ + { + "text":"change me", + "image":{ + "format":"png", + "source":{ + "bytes":"Y2hhbmdlIG1l" + } + }, + "document":{ + "format":"pdf", + "name":"change me", + "source":{ + "bytes":"Y2hhbmdlIG1l" + } + }, + "video":{ + "format":"mkv", + "source":{ + "bytes":"Y2hhbmdlIG1l", + "s3Location":{ + "uri":"change me", + "bucketOwner":"change me" + } + } + }, + "toolUse":{ + "toolUseId":"change me", + "name":"change me", + "input":[ + + ] + }, + "toolResult":{ + "toolUseId":"change me", + "content":[ + { + "json":[ + + ], + "text":"change me", + "image":{ + "format":"png", + "source":{ + "bytes":"Y2hhbmdlIG1l" + } + }, + "document":{ + "format":"pdf", + "name":"change me", + "source":{ + "bytes":"Y2hhbmdlIG1l" + } + }, + "video":{ + "format":"mkv", + "source":{ + "bytes":"Y2hhbmdlIG1l", + "s3Location":{ + "uri":"change me", + "bucketOwner":"change me" + } + } + } + } + ], + "status":"success" + }, + "guardContent":{ + "text":{ + "text":"change me", + "qualifiers":[ + "grounding_source" + ] + }, + "image":{ + "format":"png", + "source":{ + "bytes":"Y2hhbmdlIG1l" + } + } + }, + "reasoningContent":{ + "reasoningText":{ + "text":"change me", + "signature":"change me" + }, + "redactedContent":"Y2hhbmdlIG1l" + } + } + ] + } + ], + "system":[ + { + "text":"change me", + "guardContent":{ + "text":{ + "text":"change me", + "qualifiers":[ + "grounding_source" + ] + }, + "image":{ + "format":"png", + "source":{ + "bytes":"Y2hhbmdlIG1l" + } + } + } + } + ], + "inferenceConfig":{ + "maxTokens":1337, + "temperature":1337, + "topP":1337, + "stopSequences":[ + "change me" + ] + }, + "toolConfig":{ + "tools":[ + { + "toolSpec":{ + "name":"change me", + "description":"change me", + "inputSchema":{ + "json":[ + + ] + } + } + } + ], + "toolChoice":{ + "auto":[ + + ], + "any":[ + + ], + "tool":{ + "name":"change me" + } + } + }, + "guardrailConfig":{ + "guardrailIdentifier":"change me", + "guardrailVersion":"change me", + "trace":"enabled" + }, + "additionalModelRequestFields":[ + + ], + "promptVariables":{ + "change me":{ + "text":"change me" + } + }, + "additionalModelResponseFieldPaths":[ + "change me" + ], + "requestMetadata":{ + "change me":"change me" + }, + "performanceConfig":{ + "latency":"standard" + } +} + '; + + self::assertRequestEqualsHttpRequest($expected, $input->request()); + } +} diff --git a/src/Service/BedrockRuntime/tests/Unit/Result/ConverseResponseTest.php b/src/Service/BedrockRuntime/tests/Unit/Result/ConverseResponseTest.php new file mode 100644 index 000000000..6916b647d --- /dev/null +++ b/src/Service/BedrockRuntime/tests/Unit/Result/ConverseResponseTest.php @@ -0,0 +1,34 @@ +request('POST', 'http://localhost'), $client, new NullLogger())); + + // self::assertTODO(expected, $result->getOutput()); + self::assertSame('changeIt', $result->getStopReason()); + // self::assertTODO(expected, $result->getUsage()); + // self::assertTODO(expected, $result->getMetrics()); + // self::assertTODO(expected, $result->getAdditionalModelResponseFields()); + // self::assertTODO(expected, $result->getTrace()); + // self::assertTODO(expected, $result->getPerformanceConfig()); + } +} From 9a0f45053dd2d0aa2700ee6fdeabb3efedfcfeff Mon Sep 17 00:00:00 2001 From: Victor Thuillier Date: Fri, 14 Mar 2025 18:16:04 +0100 Subject: [PATCH 02/10] remove .idea files --- .idea/.gitignore | 8 -------- 1 file changed, 8 deletions(-) delete mode 100644 .idea/.gitignore diff --git a/.idea/.gitignore b/.idea/.gitignore deleted file mode 100644 index 13566b81b..000000000 --- a/.idea/.gitignore +++ /dev/null @@ -1,8 +0,0 @@ -# Default ignored files -/shelf/ -/workspace.xml -# Editor-based HTTP Client requests -/httpRequests/ -# Datasource local storage ignored files -/dataSources/ -/dataSources.local.xml From da2eb1ee9c385af5a0bd238318bfeeeeafc3bfb9 Mon Sep 17 00:00:00 2001 From: Victor Thuillier Date: Fri, 14 Mar 2025 18:41:00 +0100 Subject: [PATCH 03/10] Write tests for Converse operation in BedrockRuntime --- .../Unit/Result/ConverseResponseTest.php | 298 +++++++++++++++++- 1 file changed, 287 insertions(+), 11 deletions(-) diff --git a/src/Service/BedrockRuntime/tests/Unit/Result/ConverseResponseTest.php b/src/Service/BedrockRuntime/tests/Unit/Result/ConverseResponseTest.php index 6916b647d..ba66a7b66 100644 --- a/src/Service/BedrockRuntime/tests/Unit/Result/ConverseResponseTest.php +++ b/src/Service/BedrockRuntime/tests/Unit/Result/ConverseResponseTest.php @@ -13,22 +13,298 @@ class ConverseResponseTest extends TestCase { public function testConverseResponse(): void { - self::fail('Not implemented'); - // see https://docs.aws.amazon.com/bedrock/latest/APIReference/API_Converse.html $response = new SimpleMockedResponse('{ - "change": "it" - }'); + "metrics":{ + "latencyMs":100 + }, + "output":{ + "message":{ + "content":[ + { + "role":"user", + "content":{ + "text":"Hello world!" + } + } + ] + } + }, + "performanceConfig":{ + "latency":"standard" + }, + "stopReason":"end_turn", + "trace":{ + "guardrail":{ + "inputAssessment":{ + "string":{ + "contentPolicy":{ + "filters":[ + { + "action":"string", + "confidence":"string", + "filterStrength":"string", + "type":"string" + } + ] + }, + "contextualGroundingPolicy":{ + "filters":[ + { + "action":"string", + "score":1, + "threshold":1, + "type":"string" + } + ] + }, + "invocationMetrics":{ + "guardrailCoverage":{ + "images":{ + "guarded":1000, + "total":1000 + }, + "textCharacters":{ + "guarded":1000, + "total":1000 + } + }, + "guardrailProcessingLatency":1000, + "usage":{ + "contentPolicyUnits":1000, + "contextualGroundingPolicyUnits":1000, + "sensitiveInformationPolicyFreeUnits":1000, + "sensitiveInformationPolicyUnits":1000, + "topicPolicyUnits":1000, + "wordPolicyUnits":1000 + } + }, + "sensitiveInformationPolicy":{ + "piiEntities":[ + { + "action":"string", + "match":"string", + "type":"string" + } + ], + "regexes":[ + { + "action":"string", + "match":"string", + "name":"string", + "regex":"string" + } + ] + }, + "topicPolicy":{ + "topics":[ + { + "action":"string", + "name":"string", + "type":"string" + } + ] + }, + "wordPolicy":{ + "customWords":[ + { + "action":"string", + "match":"string" + } + ], + "managedWordLists":[ + { + "action":"string", + "match":"string", + "type":"string" + } + ] + } + } + }, + "modelOutput":[ + "string" + ], + "outputAssessments":{ + "string":[ + { + "contentPolicy":{ + "filters":[ + { + "action":"string", + "confidence":"string", + "filterStrength":"string", + "type":"string" + } + ] + }, + "contextualGroundingPolicy":{ + "filters":[ + { + "action":"string", + "score":1000, + "threshold":1000, + "type":"string" + } + ] + }, + "invocationMetrics":{ + "guardrailCoverage":{ + "images":{ + "guarded":1000, + "total":1000 + }, + "textCharacters":{ + "guarded":1000, + "total":1000 + } + }, + "guardrailProcessingLatency":1000, + "usage":{ + "contentPolicyUnits":1000, + "contextualGroundingPolicyUnits":1000, + "sensitiveInformationPolicyFreeUnits":1000, + "sensitiveInformationPolicyUnits":1000, + "topicPolicyUnits":1000, + "wordPolicyUnits":1000 + } + }, + "sensitiveInformationPolicy":{ + "piiEntities":[ + { + "action":"string", + "match":"string", + "type":"string" + } + ], + "regexes":[ + { + "action":"string", + "match":"string", + "name":"string", + "regex":"string" + } + ] + }, + "topicPolicy":{ + "topics":[ + { + "action":"string", + "name":"string", + "type":"string" + } + ] + }, + "wordPolicy":{ + "customWords":[ + { + "action":"string", + "match":"string" + } + ], + "managedWordLists":[ + { + "action":"string", + "match":"string", + "type":"string" + } + ] + } + } + ] + } + }, + "promptRouter":{ + "invokedModelId":"string" + } + }, + "usage":{ + "inputTokens":1000, + "outputTokens":2000, + "totalTokens":3000 + } +}'); $client = new MockHttpClient($response); $result = new ConverseResponse(new Response($client->request('POST', 'http://localhost'), $client, new NullLogger())); - // self::assertTODO(expected, $result->getOutput()); - self::assertSame('changeIt', $result->getStopReason()); - // self::assertTODO(expected, $result->getUsage()); - // self::assertTODO(expected, $result->getMetrics()); - // self::assertTODO(expected, $result->getAdditionalModelResponseFields()); - // self::assertTODO(expected, $result->getTrace()); - // self::assertTODO(expected, $result->getPerformanceConfig()); + self::assertSame(100, $result->getMetrics()->getLatencyMs()); + self::assertSame('user', $result->getOutput()->getMessage()->getRole()); + self::assertSame('Hello world!', $result->getOutput()->getMessage()->getContent()[0]->getText()); + self::assertSame('end_turn', $result->getStopReason()); + self::assertSame('standard', $result->getPerformanceConfig()->getLatency()); + self::assertSame(1000, $result->getUsage()->getInputTokens()); + self::assertSame(2000, $result->getUsage()->getOutputTokens()); + self::assertSame(3000, $result->getUsage()->getTotalTokens()); + self::assertSame('string', $result->getTrace()->getGuardrail()->getInputAssessment()['string']->getContentPolicy()->getFilters()[0]->getAction()); + self::assertSame('string', $result->getTrace()->getGuardrail()->getInputAssessment()['string']->getContentPolicy()->getFilters()[0]->getConfidence()); + self::assertSame('string', $result->getTrace()->getGuardrail()->getInputAssessment()['string']->getContentPolicy()->getFilters()[0]->getFilterStrength()); + self::assertSame('string', $result->getTrace()->getGuardrail()->getInputAssessment()['string']->getContentPolicy()->getFilters()[0]->getType()); + self::assertSame('string', $result->getTrace()->getGuardrail()->getInputAssessment()['string']->getContextualGroundingPolicy()->getFilters()[0]->getAction()); + self::assertSame(1, $result->getTrace()->getGuardrail()->getInputAssessment()['number']->getContextualGroundingPolicy()->getFilters()[0]->getScore()); + self::assertSame(1, $result->getTrace()->getGuardrail()->getInputAssessment()['number']->getContextualGroundingPolicy()->getFilters()[0]->getThreshold()); + self::assertSame('string', $result->getTrace()->getGuardrail()->getInputAssessment()['string']->getContextualGroundingPolicy()->getFilters()[0]->getType()); + self::assertSame(1000, $result->getTrace()->getGuardrail()->getInputAssessment()['string']->getInvocationMetrics()->getGuardrailCoverage()->getImages()->getGuarded()); + self::assertSame(1000, $result->getTrace()->getGuardrail()->getInputAssessment()['string']->getInvocationMetrics()->getGuardrailCoverage()->getImages()->getTotal()); + self::assertSame(1000, $result->getTrace()->getGuardrail()->getInputAssessment()['string']->getInvocationMetrics()->getGuardrailCoverage()->getTextCharacters()->getGuarded()); + self::assertSame(1000, $result->getTrace()->getGuardrail()->getInputAssessment()['string']->getInvocationMetrics()->getGuardrailCoverage()->getTextCharacters()->getTotal()); + self::assertSame(1000, $result->getTrace()->getGuardrail()->getInputAssessment()['string']->getInvocationMetrics()->getGuardrailProcessingLatency()); + self::assertSame(1000, $result->getTrace()->getGuardrail()->getInputAssessment()['string']->getInvocationMetrics()->getUsage()->getContentPolicyUnits()); + self::assertSame(1000, $result->getTrace()->getGuardrail()->getInputAssessment()['string']->getInvocationMetrics()->getUsage()->getContextualGroundingPolicyUnits()); + self::assertSame(1000, $result->getTrace()->getGuardrail()->getInputAssessment()['string']->getInvocationMetrics()->getUsage()->getSensitiveInformationPolicyFreeUnits()); + self::assertSame(1000, $result->getTrace()->getGuardrail()->getInputAssessment()['string']->getInvocationMetrics()->getUsage()->getSensitiveInformationPolicyUnits()); + self::assertSame(1000, $result->getTrace()->getGuardrail()->getInputAssessment()['string']->getInvocationMetrics()->getUsage()->getTopicPolicyUnits()); + self::assertSame(1000, $result->getTrace()->getGuardrail()->getInputAssessment()['string']->getInvocationMetrics()->getUsage()->getWordPolicyUnits()); + self::assertSame('string', $result->getTrace()->getGuardrail()->getInputAssessment()['string']->getSensitiveInformationPolicy()->getPiiEntities()[0]->getAction()); + self::assertSame('string', $result->getTrace()->getGuardrail()->getInputAssessment()['string']->getSensitiveInformationPolicy()->getPiiEntities()[0]->getMatch()); + self::assertSame('string', $result->getTrace()->getGuardrail()->getInputAssessment()['string']->getSensitiveInformationPolicy()->getPiiEntities()[0]->getType()); + self::assertSame('string', $result->getTrace()->getGuardrail()->getInputAssessment()['string']->getSensitiveInformationPolicy()->getRegexes()[0]->getAction()); + self::assertSame('string', $result->getTrace()->getGuardrail()->getInputAssessment()['string']->getSensitiveInformationPolicy()->getRegexes()[0]->getMatch()); + self::assertSame('string', $result->getTrace()->getGuardrail()->getInputAssessment()['string']->getSensitiveInformationPolicy()->getRegexes()[0]->getName()); + self::assertSame('string', $result->getTrace()->getGuardrail()->getInputAssessment()['string']->getSensitiveInformationPolicy()->getRegexes()[0]->getRegex()); + self::assertSame('string', $result->getTrace()->getGuardrail()->getInputAssessment()['string']->getTopicPolicy()->getTopics()[0]->getAction()); + self::assertSame('string', $result->getTrace()->getGuardrail()->getInputAssessment()['string']->getTopicPolicy()->getTopics()[0]->getName()); + self::assertSame('string', $result->getTrace()->getGuardrail()->getInputAssessment()['string']->getTopicPolicy()->getTopics()[0]->getType()); + self::assertSame('string', $result->getTrace()->getGuardrail()->getInputAssessment()['string']->getWordPolicy()->getCustomWords()[0]->getAction()); + self::assertSame('string', $result->getTrace()->getGuardrail()->getInputAssessment()['string']->getWordPolicy()->getCustomWords()[0]->getMatch()); + self::assertSame('string', $result->getTrace()->getGuardrail()->getInputAssessment()['string']->getWordPolicy()->getManagedWordLists()[0]->getAction()); + self::assertSame('string', $result->getTrace()->getGuardrail()->getInputAssessment()['string']->getWordPolicy()->getManagedWordLists()[0]->getMatch()); + self::assertSame('string', $result->getTrace()->getGuardrail()->getInputAssessment()['string']->getWordPolicy()->getManagedWordLists()[0]->getType()); + self::assertSame('string', $result->getTrace()->getGuardrail()->getModelOutput()[0]); + self::assertSame('string', $result->getTrace()->getGuardrail()->getOutputAssessments()['string'][0]->getContentPolicy()->getFilters()[0]->getAction()); + self::assertSame('string', $result->getTrace()->getGuardrail()->getOutputAssessments()['string'][0]->getContentPolicy()->getFilters()[0]->getConfidence()); + self::assertSame('string', $result->getTrace()->getGuardrail()->getOutputAssessments()['string'][0]->getContentPolicy()->getFilters()[0]->getFilterStrength()); + self::assertSame('string', $result->getTrace()->getGuardrail()->getOutputAssessments()['string'][0]->getContentPolicy()->getFilters()[0]->getType()); + self::assertSame('string', $result->getTrace()->getGuardrail()->getOutputAssessments()['string'][0]->getContextualGroundingPolicy()->getFilters()[0]->getAction()); + self::assertSame(1000, $result->getTrace()->getGuardrail()->getOutputAssessments()['string'][0]->getContextualGroundingPolicy()->getFilters()[0]->getScore()); + self::assertSame(1000, $result->getTrace()->getGuardrail()->getOutputAssessments()['string'][0]->getContextualGroundingPolicy()->getFilters()[0]->getThreshold()); + self::assertSame('string', $result->getTrace()->getGuardrail()->getOutputAssessments()['string'][0]->getContextualGroundingPolicy()->getFilters()[0]->getType()); + self::assertSame(1000, $result->getTrace()->getGuardrail()->getOutputAssessments()['string'][0]->getInvocationMetrics()->getGuardrailCoverage()->getImages()->getGuarded()); + self::assertSame(1000, $result->getTrace()->getGuardrail()->getOutputAssessments()['string'][0]->getInvocationMetrics()->getGuardrailCoverage()->getImages()->getTotal()); + self::assertSame(1000, $result->getTrace()->getGuardrail()->getOutputAssessments()['string'][0]->getInvocationMetrics()->getGuardrailCoverage()->getTextCharacters()->getGuarded()); + self::assertSame(1000, $result->getTrace()->getGuardrail()->getOutputAssessments()['string'][0]->getInvocationMetrics()->getGuardrailCoverage()->getTextCharacters()->getTotal()); + self::assertSame(1000, $result->getTrace()->getGuardrail()->getOutputAssessments()['string'][0]->getInvocationMetrics()->getGuardrailProcessingLatency()); + self::assertSame(1000, $result->getTrace()->getGuardrail()->getOutputAssessments()['string'][0]->getInvocationMetrics()->getUsage()->getContentPolicyUnits()); + self::assertSame(1000, $result->getTrace()->getGuardrail()->getOutputAssessments()['string'][0]->getInvocationMetrics()->getUsage()->getContextualGroundingPolicyUnits()); + self::assertSame(1000, $result->getTrace()->getGuardrail()->getOutputAssessments()['string'][0]->getInvocationMetrics()->getUsage()->getSensitiveInformationPolicyFreeUnits()); + self::assertSame(1000, $result->getTrace()->getGuardrail()->getOutputAssessments()['string'][0]->getInvocationMetrics()->getUsage()->getSensitiveInformationPolicyUnits()); + self::assertSame(1000, $result->getTrace()->getGuardrail()->getOutputAssessments()['string'][0]->getInvocationMetrics()->getUsage()->getTopicPolicyUnits()); + self::assertSame(1000, $result->getTrace()->getGuardrail()->getOutputAssessments()['string'][0]->getInvocationMetrics()->getUsage()->getWordPolicyUnits()); + self::assertSame('string', $result->getTrace()->getGuardrail()->getOutputAssessments()['string'][0]->getSensitiveInformationPolicy()->getPiiEntities()[0]->getAction()); + self::assertSame('string', $result->getTrace()->getGuardrail()->getOutputAssessments()['string'][0]->getSensitiveInformationPolicy()->getPiiEntities()[0]->getMatch()); + self::assertSame('string', $result->getTrace()->getGuardrail()->getOutputAssessments()['string'][0]->getSensitiveInformationPolicy()->getPiiEntities()[0]->getType()); + self::assertSame('string', $result->getTrace()->getGuardrail()->getOutputAssessments()['string'][0]->getSensitiveInformationPolicy()->getRegexes()[0]->getAction()); + self::assertSame('string', $result->getTrace()->getGuardrail()->getOutputAssessments()['string'][0]->getSensitiveInformationPolicy()->getRegexes()[0]->getMatch()); + self::assertSame('string', $result->getTrace()->getGuardrail()->getOutputAssessments()['string'][0]->getSensitiveInformationPolicy()->getRegexes()[0]->getName()); + self::assertSame('string', $result->getTrace()->getGuardrail()->getOutputAssessments()['string'][0]->getSensitiveInformationPolicy()->getRegexes()[0]->getRegex()); + self::assertSame('string', $result->getTrace()->getGuardrail()->getOutputAssessments()['string'][0]->getTopicPolicy()->getTopics()[0]->getAction()); + self::assertSame('string', $result->getTrace()->getGuardrail()->getOutputAssessments()['string'][0]->getTopicPolicy()->getTopics()[0]->getName()); + self::assertSame('string', $result->getTrace()->getGuardrail()->getOutputAssessments()['string'][0]->getTopicPolicy()->getTopics()[0]->getType()); + self::assertSame('string', $result->getTrace()->getGuardrail()->getOutputAssessments()['string'][0]->getWordPolicy()->getCustomWords()[0]->getAction()); + self::assertSame('string', $result->getTrace()->getGuardrail()->getOutputAssessments()['string'][0]->getWordPolicy()->getCustomWords()[0]->getMatch()); + self::assertSame('string', $result->getTrace()->getGuardrail()->getOutputAssessments()['string'][0]->getWordPolicy()->getManagedWordLists()[0]->getAction()); + self::assertSame('string', $result->getTrace()->getGuardrail()->getOutputAssessments()['string'][0]->getWordPolicy()->getManagedWordLists()[0]->getMatch()); + self::assertSame('string', $result->getTrace()->getGuardrail()->getOutputAssessments()['string'][0]->getWordPolicy()->getManagedWordLists()[0]->getType()); + self::assertSame('string', $result->getTrace()->getPromptRouter()->getInvokedModelId()); } } From e7111dae3427900ed64c96adf6824364ad8fa17a Mon Sep 17 00:00:00 2001 From: Victor Thuillier Date: Fri, 14 Mar 2025 18:48:56 +0100 Subject: [PATCH 04/10] Fix test --- .../BedrockRuntime/tests/Unit/Input/ConverseRequestTest.php | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/src/Service/BedrockRuntime/tests/Unit/Input/ConverseRequestTest.php b/src/Service/BedrockRuntime/tests/Unit/Input/ConverseRequestTest.php index 264d06038..f4254738d 100644 --- a/src/Service/BedrockRuntime/tests/Unit/Input/ConverseRequestTest.php +++ b/src/Service/BedrockRuntime/tests/Unit/Input/ConverseRequestTest.php @@ -42,7 +42,7 @@ class ConverseRequestTest extends TestCase public function testRequest(): void { $input = new ConverseRequest([ - 'modelId' => 'change me', + 'modelId' => 'us.anthropic.claude-3-7-sonnet-20250219-v1:0', 'messages' => [new Message([ 'role' => 'user', 'content' => [new ContentBlock([ @@ -190,7 +190,7 @@ public function testRequest(): void // see https://docs.aws.amazon.com/bedrock/latest/APIReference/API_Converse.html $expected = ' - POST / HTTP/1.0 + POST /model/us.anthropic.claude-3-7-sonnet-20250219-v1:0/converse HTTP/1.0 Content-Type: application/json { From ddd7c86a0e3f12fe45ab4af07ea40765d1543b53 Mon Sep 17 00:00:00 2001 From: Victor Thuillier Date: Fri, 14 Mar 2025 18:52:03 +0100 Subject: [PATCH 05/10] Fix test --- .../BedrockRuntime/tests/Unit/Input/ConverseRequestTest.php | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/Service/BedrockRuntime/tests/Unit/Input/ConverseRequestTest.php b/src/Service/BedrockRuntime/tests/Unit/Input/ConverseRequestTest.php index f4254738d..8e0200bfb 100644 --- a/src/Service/BedrockRuntime/tests/Unit/Input/ConverseRequestTest.php +++ b/src/Service/BedrockRuntime/tests/Unit/Input/ConverseRequestTest.php @@ -190,7 +190,7 @@ public function testRequest(): void // see https://docs.aws.amazon.com/bedrock/latest/APIReference/API_Converse.html $expected = ' - POST /model/us.anthropic.claude-3-7-sonnet-20250219-v1:0/converse HTTP/1.0 + POST / HTTP/1.0 Content-Type: application/json { From b3d9b898d4b413567a99a90b709bd8dddffe7f5e Mon Sep 17 00:00:00 2001 From: Victor Thuillier Date: Fri, 14 Mar 2025 18:56:17 +0100 Subject: [PATCH 06/10] Fix test --- .../BedrockRuntime/tests/Unit/Input/ConverseRequestTest.php | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/Service/BedrockRuntime/tests/Unit/Input/ConverseRequestTest.php b/src/Service/BedrockRuntime/tests/Unit/Input/ConverseRequestTest.php index 8e0200bfb..32a882e58 100644 --- a/src/Service/BedrockRuntime/tests/Unit/Input/ConverseRequestTest.php +++ b/src/Service/BedrockRuntime/tests/Unit/Input/ConverseRequestTest.php @@ -190,7 +190,7 @@ public function testRequest(): void // see https://docs.aws.amazon.com/bedrock/latest/APIReference/API_Converse.html $expected = ' - POST / HTTP/1.0 + POST /model/us.anthropic.claude-3-7-sonnet-20250219-v1%3A0/converse HTTP/1.0 Content-Type: application/json { From ddc8ec3d3ae3ad5c3a5824688757cc95b87d5211 Mon Sep 17 00:00:00 2001 From: Victor Thuillier Date: Fri, 14 Mar 2025 19:04:15 +0100 Subject: [PATCH 07/10] Fix test --- .../BedrockRuntime/tests/Unit/Input/ConverseRequestTest.php | 1 + 1 file changed, 1 insertion(+) diff --git a/src/Service/BedrockRuntime/tests/Unit/Input/ConverseRequestTest.php b/src/Service/BedrockRuntime/tests/Unit/Input/ConverseRequestTest.php index 32a882e58..50ecd8e66 100644 --- a/src/Service/BedrockRuntime/tests/Unit/Input/ConverseRequestTest.php +++ b/src/Service/BedrockRuntime/tests/Unit/Input/ConverseRequestTest.php @@ -192,6 +192,7 @@ public function testRequest(): void $expected = ' POST /model/us.anthropic.claude-3-7-sonnet-20250219-v1%3A0/converse HTTP/1.0 Content-Type: application/json + Accept: application/json { "messages":[ From 8adb78b4a3aa9ad440183d1e6856ae0bd34f0eb2 Mon Sep 17 00:00:00 2001 From: Victor Thuillier Date: Fri, 14 Mar 2025 19:11:01 +0100 Subject: [PATCH 08/10] Fix test --- .../tests/Unit/Input/ConverseRequestTest.php | 18 ++++++------------ 1 file changed, 6 insertions(+), 12 deletions(-) diff --git a/src/Service/BedrockRuntime/tests/Unit/Input/ConverseRequestTest.php b/src/Service/BedrockRuntime/tests/Unit/Input/ConverseRequestTest.php index 50ecd8e66..48bcc111e 100644 --- a/src/Service/BedrockRuntime/tests/Unit/Input/ConverseRequestTest.php +++ b/src/Service/BedrockRuntime/tests/Unit/Input/ConverseRequestTest.php @@ -73,14 +73,12 @@ public function testRequest(): void 'toolUse' => new ToolUseBlock([ 'toolUseId' => 'change me', 'name' => 'change me', - 'input' => new Document([ - ]), + 'input' => new Document(), ]), 'toolResult' => new ToolResultBlock([ 'toolUseId' => 'change me', 'content' => [new ToolResultContentBlock([ - 'json' => new Document([ - ]), + 'json' => new Document(), 'text' => 'change me', 'image' => new ImageBlock([ 'format' => 'png', @@ -156,16 +154,13 @@ public function testRequest(): void 'name' => 'change me', 'description' => 'change me', 'inputSchema' => new ToolInputSchema([ - 'json' => new Document([ - ]), + 'json' => new Document(), ]), ]), ])], 'toolChoice' => new ToolChoice([ - 'auto' => new AutoToolChoice([ - ]), - 'any' => new AnyToolChoice([ - ]), + 'auto' => new AutoToolChoice(), + 'any' => new AnyToolChoice(), 'tool' => new SpecificToolChoice([ 'name' => 'change me', ]), @@ -176,8 +171,7 @@ public function testRequest(): void 'guardrailVersion' => 'change me', 'trace' => 'enabled', ]), - 'additionalModelRequestFields' => new Document([ - ]), + 'additionalModelRequestFields' => new Document(), 'promptVariables' => ['change me' => new PromptVariableValues([ 'text' => 'change me', ])], From 6a5e4f090980760358eb6784b799a5cb78b5a515 Mon Sep 17 00:00:00 2001 From: Victor Thuillier Date: Thu, 20 Mar 2025 12:52:30 +0100 Subject: [PATCH 09/10] fix --- .idea/async-aws.iml | 226 ++++++++++++++++ .idea/inspectionProfiles/Project_Default.xml | 75 ++++++ .idea/modules.xml | 8 + .idea/php.xml | 158 +++++++++++ .idea/phpunit.xml | 10 + .idea/vcs.xml | 6 + .idea/workspace.xml | 250 ++++++++++++++++++ .../tests/Unit/Input/ConverseRequestTest.php | 24 +- 8 files changed, 739 insertions(+), 18 deletions(-) create mode 100644 .idea/async-aws.iml create mode 100644 .idea/inspectionProfiles/Project_Default.xml create mode 100644 .idea/modules.xml create mode 100644 .idea/php.xml create mode 100644 .idea/phpunit.xml create mode 100644 .idea/vcs.xml create mode 100644 .idea/workspace.xml diff --git a/.idea/async-aws.iml b/.idea/async-aws.iml new file mode 100644 index 000000000..a91c666c2 --- /dev/null +++ b/.idea/async-aws.iml @@ -0,0 +1,226 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + \ No newline at end of file diff --git a/.idea/inspectionProfiles/Project_Default.xml b/.idea/inspectionProfiles/Project_Default.xml new file mode 100644 index 000000000..332b63ff5 --- /dev/null +++ b/.idea/inspectionProfiles/Project_Default.xml @@ -0,0 +1,75 @@ + + + + \ No newline at end of file diff --git a/.idea/modules.xml b/.idea/modules.xml new file mode 100644 index 000000000..6023900cf --- /dev/null +++ b/.idea/modules.xml @@ -0,0 +1,8 @@ + + + + + + + + \ No newline at end of file diff --git a/.idea/php.xml b/.idea/php.xml new file mode 100644 index 000000000..3bf7e2062 --- /dev/null +++ b/.idea/php.xml @@ -0,0 +1,158 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + \ No newline at end of file diff --git a/.idea/phpunit.xml b/.idea/phpunit.xml new file mode 100644 index 000000000..4f8104cfb --- /dev/null +++ b/.idea/phpunit.xml @@ -0,0 +1,10 @@ + + + + + + \ No newline at end of file diff --git a/.idea/vcs.xml b/.idea/vcs.xml new file mode 100644 index 000000000..35eb1ddfb --- /dev/null +++ b/.idea/vcs.xml @@ -0,0 +1,6 @@ + + + + + + \ No newline at end of file diff --git a/.idea/workspace.xml b/.idea/workspace.xml new file mode 100644 index 000000000..354fac0e6 --- /dev/null +++ b/.idea/workspace.xml @@ -0,0 +1,250 @@ + + + + + + + + + + + + $PROJECT_DIR$/composer.json + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + { + "associatedIndex": 3 +} + + + + { + "keyToString": { + "RunOnceActivity.ShowReadmeOnStart": "true", + "RunOnceActivity.git.unshallow": "true", + "git-widget-placeholder": "master", + "node.js.detected.package.eslint": "true", + "node.js.detected.package.tslint": "true", + "node.js.selected.package.eslint": "(autodetect)", + "node.js.selected.package.tslint": "(autodetect)", + "nodejs_package_manager_path": "npm", + "vue.rearranger.settings.migration": "true" + } +} + + + + + + + + + + + + + + + + + + + + + + 1741972268281 + + + + + + \ No newline at end of file diff --git a/src/Service/BedrockRuntime/tests/Unit/Input/ConverseRequestTest.php b/src/Service/BedrockRuntime/tests/Unit/Input/ConverseRequestTest.php index 48bcc111e..d92453750 100644 --- a/src/Service/BedrockRuntime/tests/Unit/Input/ConverseRequestTest.php +++ b/src/Service/BedrockRuntime/tests/Unit/Input/ConverseRequestTest.php @@ -221,17 +221,13 @@ public function testRequest(): void "toolUse":{ "toolUseId":"change me", "name":"change me", - "input":[ - - ] + "input":[] }, "toolResult":{ "toolUseId":"change me", "content":[ { - "json":[ - - ], + "json":[], "text":"change me", "image":{ "format":"png", @@ -319,20 +315,14 @@ public function testRequest(): void "name":"change me", "description":"change me", "inputSchema":{ - "json":[ - - ] + "json":[] } } } ], "toolChoice":{ - "auto":[ - - ], - "any":[ - - ], + "auto":[], + "any":[], "tool":{ "name":"change me" } @@ -343,9 +333,7 @@ public function testRequest(): void "guardrailVersion":"change me", "trace":"enabled" }, - "additionalModelRequestFields":[ - - ], + "additionalModelRequestFields":[], "promptVariables":{ "change me":{ "text":"change me" From e2b603568e4cdb40e588f130738655da84cbe397 Mon Sep 17 00:00:00 2001 From: Victor Thuillier Date: Thu, 20 Mar 2025 12:52:39 +0100 Subject: [PATCH 10/10] fix --- .idea/async-aws.iml | 226 ----------------- .idea/inspectionProfiles/Project_Default.xml | 75 ------ .idea/modules.xml | 8 - .idea/php.xml | 158 ------------ .idea/phpunit.xml | 10 - .idea/vcs.xml | 6 - .idea/workspace.xml | 250 ------------------- 7 files changed, 733 deletions(-) delete mode 100644 .idea/async-aws.iml delete mode 100644 .idea/inspectionProfiles/Project_Default.xml delete mode 100644 .idea/modules.xml delete mode 100644 .idea/php.xml delete mode 100644 .idea/phpunit.xml delete mode 100644 .idea/vcs.xml delete mode 100644 .idea/workspace.xml diff --git a/.idea/async-aws.iml b/.idea/async-aws.iml deleted file mode 100644 index a91c666c2..000000000 --- a/.idea/async-aws.iml +++ /dev/null @@ -1,226 +0,0 @@ - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - \ No newline at end of file diff --git a/.idea/inspectionProfiles/Project_Default.xml b/.idea/inspectionProfiles/Project_Default.xml deleted file mode 100644 index 332b63ff5..000000000 --- a/.idea/inspectionProfiles/Project_Default.xml +++ /dev/null @@ -1,75 +0,0 @@ - - - - \ No newline at end of file diff --git a/.idea/modules.xml b/.idea/modules.xml deleted file mode 100644 index 6023900cf..000000000 --- a/.idea/modules.xml +++ /dev/null @@ -1,8 +0,0 @@ - - - - - - - - \ No newline at end of file diff --git a/.idea/php.xml b/.idea/php.xml deleted file mode 100644 index 3bf7e2062..000000000 --- a/.idea/php.xml +++ /dev/null @@ -1,158 +0,0 @@ - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - \ No newline at end of file diff --git a/.idea/phpunit.xml b/.idea/phpunit.xml deleted file mode 100644 index 4f8104cfb..000000000 --- a/.idea/phpunit.xml +++ /dev/null @@ -1,10 +0,0 @@ - - - - - - \ No newline at end of file diff --git a/.idea/vcs.xml b/.idea/vcs.xml deleted file mode 100644 index 35eb1ddfb..000000000 --- a/.idea/vcs.xml +++ /dev/null @@ -1,6 +0,0 @@ - - - - - - \ No newline at end of file diff --git a/.idea/workspace.xml b/.idea/workspace.xml deleted file mode 100644 index 354fac0e6..000000000 --- a/.idea/workspace.xml +++ /dev/null @@ -1,250 +0,0 @@ - - - - - - - - - - - - $PROJECT_DIR$/composer.json - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - { - "associatedIndex": 3 -} - - - - { - "keyToString": { - "RunOnceActivity.ShowReadmeOnStart": "true", - "RunOnceActivity.git.unshallow": "true", - "git-widget-placeholder": "master", - "node.js.detected.package.eslint": "true", - "node.js.detected.package.tslint": "true", - "node.js.selected.package.eslint": "(autodetect)", - "node.js.selected.package.tslint": "(autodetect)", - "nodejs_package_manager_path": "npm", - "vue.rearranger.settings.migration": "true" - } -} - - - - - - - - - - - - - - - - - - - - - - 1741972268281 - - - - - - \ No newline at end of file