software.amazon.awssdk.services.lexruntime.DefaultLexRuntimeClient Maven / Gradle / Ivy
Show all versions of lexruntime Show documentation
/*
* Copyright 2014-2019 Amazon.com, Inc. or its affiliates. All Rights Reserved.
*
* Licensed under the Apache License, Version 2.0 (the "License"). You may not use this file except in compliance with
* the License. A copy of the License is located at
*
* http://aws.amazon.com/apache2.0
*
* or in the "license" file accompanying this file. This file is distributed on an "AS IS" BASIS, WITHOUT WARRANTIES OR
* CONDITIONS OF ANY KIND, either express or implied. See the License for the specific language governing permissions
* and limitations under the License.
*/
package software.amazon.awssdk.services.lexruntime;
import java.util.function.Consumer;
import software.amazon.awssdk.annotations.Generated;
import software.amazon.awssdk.annotations.SdkInternalApi;
import software.amazon.awssdk.auth.signer.Aws4UnsignedPayloadSigner;
import software.amazon.awssdk.awscore.AwsRequestOverrideConfiguration;
import software.amazon.awssdk.awscore.client.handler.AwsSyncClientHandler;
import software.amazon.awssdk.awscore.exception.AwsServiceException;
import software.amazon.awssdk.core.client.config.SdkClientConfiguration;
import software.amazon.awssdk.core.client.handler.ClientExecutionParams;
import software.amazon.awssdk.core.client.handler.SyncClientHandler;
import software.amazon.awssdk.core.exception.SdkClientException;
import software.amazon.awssdk.core.http.HttpResponseHandler;
import software.amazon.awssdk.core.runtime.transform.StreamingRequestMarshaller;
import software.amazon.awssdk.core.signer.Signer;
import software.amazon.awssdk.core.sync.RequestBody;
import software.amazon.awssdk.core.sync.ResponseTransformer;
import software.amazon.awssdk.protocols.core.ExceptionMetadata;
import software.amazon.awssdk.protocols.json.AwsJsonProtocol;
import software.amazon.awssdk.protocols.json.AwsJsonProtocolFactory;
import software.amazon.awssdk.protocols.json.BaseAwsJsonProtocolFactory;
import software.amazon.awssdk.protocols.json.JsonOperationMetadata;
import software.amazon.awssdk.services.lexruntime.model.BadGatewayException;
import software.amazon.awssdk.services.lexruntime.model.BadRequestException;
import software.amazon.awssdk.services.lexruntime.model.ConflictException;
import software.amazon.awssdk.services.lexruntime.model.DependencyFailedException;
import software.amazon.awssdk.services.lexruntime.model.InternalFailureException;
import software.amazon.awssdk.services.lexruntime.model.LexRuntimeException;
import software.amazon.awssdk.services.lexruntime.model.LexRuntimeRequest;
import software.amazon.awssdk.services.lexruntime.model.LimitExceededException;
import software.amazon.awssdk.services.lexruntime.model.LoopDetectedException;
import software.amazon.awssdk.services.lexruntime.model.NotAcceptableException;
import software.amazon.awssdk.services.lexruntime.model.NotFoundException;
import software.amazon.awssdk.services.lexruntime.model.PostContentRequest;
import software.amazon.awssdk.services.lexruntime.model.PostContentResponse;
import software.amazon.awssdk.services.lexruntime.model.PostTextRequest;
import software.amazon.awssdk.services.lexruntime.model.PostTextResponse;
import software.amazon.awssdk.services.lexruntime.model.RequestTimeoutException;
import software.amazon.awssdk.services.lexruntime.model.UnsupportedMediaTypeException;
import software.amazon.awssdk.services.lexruntime.transform.PostContentRequestMarshaller;
import software.amazon.awssdk.services.lexruntime.transform.PostTextRequestMarshaller;
/**
* Internal implementation of {@link LexRuntimeClient}.
*
* @see LexRuntimeClient#builder()
*/
@Generated("software.amazon.awssdk:codegen")
@SdkInternalApi
final class DefaultLexRuntimeClient implements LexRuntimeClient {
private final SyncClientHandler clientHandler;
private final AwsJsonProtocolFactory protocolFactory;
private final SdkClientConfiguration clientConfiguration;
protected DefaultLexRuntimeClient(SdkClientConfiguration clientConfiguration) {
this.clientHandler = new AwsSyncClientHandler(clientConfiguration);
this.clientConfiguration = clientConfiguration;
this.protocolFactory = init(AwsJsonProtocolFactory.builder()).build();
}
@Override
public final String serviceName() {
return SERVICE_NAME;
}
/**
*
* Sends user input (text or speech) to Amazon Lex. Clients use this API to send text and audio requests to Amazon
* Lex at runtime. Amazon Lex interprets the user input using the machine learning model that it built for the bot.
*
*
* The PostContent
operation supports audio input at 8kHz and 16kHz. You can use 8kHz audio to achieve
* higher speech recognition accuracy in telephone audio applications.
*
*
* In response, Amazon Lex returns the next message to convey to the user. Consider the following example messages:
*
*
* -
*
* For a user input "I would like a pizza," Amazon Lex might return a response with a message eliciting slot data
* (for example, PizzaSize
): "What size pizza would you like?".
*
*
* -
*
* After the user provides all of the pizza order information, Amazon Lex might return a response with a message to
* get user confirmation: "Order the pizza?".
*
*
* -
*
* After the user replies "Yes" to the confirmation prompt, Amazon Lex might return a conclusion statement:
* "Thank you, your cheese pizza has been ordered.".
*
*
*
*
* Not all Amazon Lex messages require a response from the user. For example, conclusion statements do not require a
* response. Some messages require only a yes or no response. In addition to the message
, Amazon Lex
* provides additional context about the message in the response that you can use to enhance client behavior, such
* as displaying the appropriate client user interface. Consider the following examples:
*
*
* -
*
* If the message is to elicit slot data, Amazon Lex returns the following context information:
*
*
* -
*
* x-amz-lex-dialog-state
header set to ElicitSlot
*
*
* -
*
* x-amz-lex-intent-name
header set to the intent name in the current context
*
*
* -
*
* x-amz-lex-slot-to-elicit
header set to the slot name for which the message
is eliciting
* information
*
*
* -
*
* x-amz-lex-slots
header set to a map of slots configured for the intent with their current values
*
*
*
*
* -
*
* If the message is a confirmation prompt, the x-amz-lex-dialog-state
header is set to
* Confirmation
and the x-amz-lex-slot-to-elicit
header is omitted.
*
*
* -
*
* If the message is a clarification prompt configured for the intent, indicating that the user intent is not
* understood, the x-amz-dialog-state
header is set to ElicitIntent
and the
* x-amz-slot-to-elicit
header is omitted.
*
*
*
*
* In addition, Amazon Lex also returns your application-specific sessionAttributes
. For more
* information, see Managing Conversation
* Context.
*
*
* @param postContentRequest
* @param requestBody
* The content to send to the service. A {@link RequestBody} can be created using one of several factory
* methods for various sources of data. For example, to create a request body from a file you can do the
* following.
*
*
* {@code RequestBody.fromFile(new File("myfile.txt"))}
*
*
* See documentation in {@link RequestBody} for additional details and which sources of data are supported.
* The service documentation for the request content is as follows '
*
* User input in PCM or Opus audio format or text format as described in the Content-Type
HTTP
* header.
*
*
* You can stream audio data to Amazon Lex or you can create a local buffer that captures all of the audio
* data before sending. In general, you get better performance if you stream audio data rather than buffering
* the data locally.
*
* '
* @param responseTransformer
* Functional interface for processing the streamed response content. The unmarshalled PostContentResponse
* and an InputStream to the response content are provided as parameters to the callback. The callback may
* return a transformed type which will be the return value of this method. See
* {@link software.amazon.awssdk.core.sync.ResponseTransformer} for details on implementing this interface
* and for links to pre-canned implementations for common scenarios like downloading to a file. The service
* documentation for the response content is as follows '
*
* The prompt (or statement) to convey to the user. This is based on the bot configuration and context. For
* example, if Amazon Lex did not understand the user intent, it sends the clarificationPrompt
* configured for the bot. If the intent requires confirmation before taking the fulfillment action, it sends
* the confirmationPrompt
. Another example: Suppose that the Lambda function successfully
* fulfilled the intent, and sent a message to convey to the user. Then Amazon Lex sends that message in the
* response.
*
* '.
* @return The transformed result of the ResponseTransformer.
* @throws NotFoundException
* The resource (such as the Amazon Lex bot or an alias) that is referred to is not found.
* @throws BadRequestException
* Request validation failed, there is no usable message in the context, or the bot build failed, is still
* in progress, or contains unbuilt changes.
* @throws LimitExceededException
* Exceeded a limit.
* @throws InternalFailureException
* Internal service error. Retry the call.
* @throws ConflictException
* Two clients are using the same AWS account, Amazon Lex bot, and user ID.
* @throws UnsupportedMediaTypeException
* The Content-Type header (PostContent
API) has an invalid value.
* @throws NotAcceptableException
* The accept header in the request does not have a valid value.
* @throws RequestTimeoutException
* The input speech is too long.
* @throws DependencyFailedException
* One of the dependencies, such as AWS Lambda or Amazon Polly, threw an exception. For example,
*
* -
*
* If Amazon Lex does not have sufficient permissions to call a Lambda function.
*
*
* -
*
* If a Lambda function takes longer than 30 seconds to execute.
*
*
* -
*
* If a fulfillment Lambda function returns a Delegate
dialog action without removing any slot
* values.
*
*
* @throws BadGatewayException
* Either the Amazon Lex bot is still building, or one of the dependent services (Amazon Polly, AWS Lambda)
* failed with an internal service error.
* @throws LoopDetectedException
* This exception is not used.
* @throws SdkException
* Base class for all exceptions that can be thrown by the SDK (both service and client). Can be used for
* catch all scenarios.
* @throws SdkClientException
* If any client side error occurs such as an IO related failure, failure to get credentials, etc.
* @throws LexRuntimeException
* Base class for all service exceptions. Unknown exceptions will be thrown as an instance of this type.
* @sample LexRuntimeClient.PostContent
* @see AWS API
* Documentation
*/
@Override
public ReturnT postContent(PostContentRequest postContentRequest, RequestBody requestBody,
ResponseTransformer responseTransformer) throws NotFoundException, BadRequestException,
LimitExceededException, InternalFailureException, ConflictException, UnsupportedMediaTypeException,
NotAcceptableException, RequestTimeoutException, DependencyFailedException, BadGatewayException,
LoopDetectedException, AwsServiceException, SdkClientException, LexRuntimeException {
postContentRequest = applySignerOverride(postContentRequest, Aws4UnsignedPayloadSigner.create());
JsonOperationMetadata operationMetadata = JsonOperationMetadata.builder().hasStreamingSuccessResponse(true)
.isPayloadJson(false).build();
HttpResponseHandler responseHandler = protocolFactory.createResponseHandler(operationMetadata,
PostContentResponse::builder);
HttpResponseHandler errorResponseHandler = createErrorResponseHandler(protocolFactory,
operationMetadata);
return clientHandler.execute(
new ClientExecutionParams()
.withOperationName("PostContent")
.withResponseHandler(responseHandler)
.withErrorResponseHandler(errorResponseHandler)
.withInput(postContentRequest)
.withRequestBody(requestBody)
.withMarshaller(
new StreamingRequestMarshaller(new PostContentRequestMarshaller(
protocolFactory), requestBody)), responseTransformer);
}
/**
*
* Sends user input (text-only) to Amazon Lex. Client applications can use this API to send requests to Amazon Lex
* at runtime. Amazon Lex then interprets the user input using the machine learning model it built for the bot.
*
*
* In response, Amazon Lex returns the next message
to convey to the user an optional
* responseCard
to display. Consider the following example messages:
*
*
* -
*
* For a user input "I would like a pizza", Amazon Lex might return a response with a message eliciting slot data
* (for example, PizzaSize): "What size pizza would you like?"
*
*
* -
*
* After the user provides all of the pizza order information, Amazon Lex might return a response with a message to
* obtain user confirmation "Proceed with the pizza order?".
*
*
* -
*
* After the user replies to a confirmation prompt with a "yes", Amazon Lex might return a conclusion statement:
* "Thank you, your cheese pizza has been ordered.".
*
*
*
*
* Not all Amazon Lex messages require a user response. For example, a conclusion statement does not require a
* response. Some messages require only a "yes" or "no" user response. In addition to the message
,
* Amazon Lex provides additional context about the message in the response that you might use to enhance client
* behavior, for example, to display the appropriate client user interface. These are the slotToElicit
,
* dialogState
, intentName
, and slots
fields in the response. Consider the
* following examples:
*
*
* -
*
* If the message is to elicit slot data, Amazon Lex returns the following context information:
*
*
* -
*
* dialogState
set to ElicitSlot
*
*
* -
*
* intentName
set to the intent name in the current context
*
*
* -
*
* slotToElicit
set to the slot name for which the message
is eliciting information
*
*
* -
*
* slots
set to a map of slots, configured for the intent, with currently known values
*
*
*
*
* -
*
* If the message is a confirmation prompt, the dialogState
is set to ConfirmIntent and
* SlotToElicit
is set to null.
*
*
* -
*
* If the message is a clarification prompt (configured for the intent) that indicates that user intent is not
* understood, the dialogState
is set to ElicitIntent and slotToElicit
is set to null.
*
*
*
*
* In addition, Amazon Lex also returns your application-specific sessionAttributes
. For more
* information, see Managing Conversation
* Context.
*
*
* @param postTextRequest
* @return Result of the PostText operation returned by the service.
* @throws NotFoundException
* The resource (such as the Amazon Lex bot or an alias) that is referred to is not found.
* @throws BadRequestException
* Request validation failed, there is no usable message in the context, or the bot build failed, is still
* in progress, or contains unbuilt changes.
* @throws LimitExceededException
* Exceeded a limit.
* @throws InternalFailureException
* Internal service error. Retry the call.
* @throws ConflictException
* Two clients are using the same AWS account, Amazon Lex bot, and user ID.
* @throws DependencyFailedException
* One of the dependencies, such as AWS Lambda or Amazon Polly, threw an exception. For example,
*
* -
*
* If Amazon Lex does not have sufficient permissions to call a Lambda function.
*
*
* -
*
* If a Lambda function takes longer than 30 seconds to execute.
*
*
* -
*
* If a fulfillment Lambda function returns a Delegate
dialog action without removing any slot
* values.
*
*
* @throws BadGatewayException
* Either the Amazon Lex bot is still building, or one of the dependent services (Amazon Polly, AWS Lambda)
* failed with an internal service error.
* @throws LoopDetectedException
* This exception is not used.
* @throws SdkException
* Base class for all exceptions that can be thrown by the SDK (both service and client). Can be used for
* catch all scenarios.
* @throws SdkClientException
* If any client side error occurs such as an IO related failure, failure to get credentials, etc.
* @throws LexRuntimeException
* Base class for all service exceptions. Unknown exceptions will be thrown as an instance of this type.
* @sample LexRuntimeClient.PostText
* @see AWS API
* Documentation
*/
@Override
public PostTextResponse postText(PostTextRequest postTextRequest) throws NotFoundException, BadRequestException,
LimitExceededException, InternalFailureException, ConflictException, DependencyFailedException, BadGatewayException,
LoopDetectedException, AwsServiceException, SdkClientException, LexRuntimeException {
JsonOperationMetadata operationMetadata = JsonOperationMetadata.builder().hasStreamingSuccessResponse(false)
.isPayloadJson(true).build();
HttpResponseHandler responseHandler = protocolFactory.createResponseHandler(operationMetadata,
PostTextResponse::builder);
HttpResponseHandler errorResponseHandler = createErrorResponseHandler(protocolFactory,
operationMetadata);
return clientHandler.execute(new ClientExecutionParams().withOperationName("PostText")
.withResponseHandler(responseHandler).withErrorResponseHandler(errorResponseHandler).withInput(postTextRequest)
.withMarshaller(new PostTextRequestMarshaller(protocolFactory)));
}
private HttpResponseHandler createErrorResponseHandler(BaseAwsJsonProtocolFactory protocolFactory,
JsonOperationMetadata operationMetadata) {
return protocolFactory.createErrorResponseHandler(operationMetadata);
}
private > T init(T builder) {
return builder
.clientConfiguration(clientConfiguration)
.defaultServiceExceptionSupplier(LexRuntimeException::builder)
.protocol(AwsJsonProtocol.REST_JSON)
.protocolVersion("1.1")
.registerModeledException(
ExceptionMetadata.builder().errorCode("DependencyFailedException")
.exceptionBuilderSupplier(DependencyFailedException::builder).httpStatusCode(424).build())
.registerModeledException(
ExceptionMetadata.builder().errorCode("ConflictException")
.exceptionBuilderSupplier(ConflictException::builder).httpStatusCode(409).build())
.registerModeledException(
ExceptionMetadata.builder().errorCode("NotFoundException")
.exceptionBuilderSupplier(NotFoundException::builder).httpStatusCode(404).build())
.registerModeledException(
ExceptionMetadata.builder().errorCode("InternalFailureException")
.exceptionBuilderSupplier(InternalFailureException::builder).httpStatusCode(500).build())
.registerModeledException(
ExceptionMetadata.builder().errorCode("RequestTimeoutException")
.exceptionBuilderSupplier(RequestTimeoutException::builder).httpStatusCode(408).build())
.registerModeledException(
ExceptionMetadata.builder().errorCode("UnsupportedMediaTypeException")
.exceptionBuilderSupplier(UnsupportedMediaTypeException::builder).httpStatusCode(415).build())
.registerModeledException(
ExceptionMetadata.builder().errorCode("NotAcceptableException")
.exceptionBuilderSupplier(NotAcceptableException::builder).httpStatusCode(406).build())
.registerModeledException(
ExceptionMetadata.builder().errorCode("BadRequestException")
.exceptionBuilderSupplier(BadRequestException::builder).httpStatusCode(400).build())
.registerModeledException(
ExceptionMetadata.builder().errorCode("LimitExceededException")
.exceptionBuilderSupplier(LimitExceededException::builder).httpStatusCode(429).build())
.registerModeledException(
ExceptionMetadata.builder().errorCode("BadGatewayException")
.exceptionBuilderSupplier(BadGatewayException::builder).httpStatusCode(502).build())
.registerModeledException(
ExceptionMetadata.builder().errorCode("LoopDetectedException")
.exceptionBuilderSupplier(LoopDetectedException::builder).httpStatusCode(508).build());
}
@Override
public void close() {
clientHandler.close();
}
private T applySignerOverride(T request, Signer signer) {
if (request.overrideConfiguration().flatMap(c -> c.signer()).isPresent()) {
return request;
}
Consumer signerOverride = b -> b.signer(signer).build();
AwsRequestOverrideConfiguration overrideConfiguration = request.overrideConfiguration()
.map(c -> c.toBuilder().applyMutation(signerOverride).build())
.orElse((AwsRequestOverrideConfiguration.builder().applyMutation(signerOverride).build()));
return (T) request.toBuilder().overrideConfiguration(overrideConfiguration).build();
}
}