Construye un bot de traducción en 30 min o menos
Tags: español, aws, machinelearning, python
Published: 2023-10-23 18:51:48

🇻🇪🇨🇱 [Dev.to](https://dev.to/elizabethfuentes12) [Linkedin](https://www.linkedin.com/in/lizfue/) [GitHub](https://github.com/elizabethfuentes12/) [Twitter](https://twitter.com/elizabethfue12) [Instagram](https://www.instagram.com/elifue.tech) [Youtube](https://www.youtube.com/channel/UCr0Gnc-t30m4xyrvsQpNp2Q)
[Linktr](https://linktr.ee/elizabethfuentesleone)

> ✅ **Blog original:** [Build A Translator App in 30 Min or Less](https://community.aws/tutorials/build-your-own-translator-app-in-less-30-min)

---

**Descripción**: Utiliza Amazon Translate, Amazon Comprehend, Amazon Lambda, Amazon Polly y Amazon Lex para darle vida a una aplicación de traducción y probarla en 30 minutos o menos.

---
Puede que media hora no parezca tiempo suficiente para un proyecto importante, pero es tiempo suficiente para crear y probar una aplicación de lenguaje en AWS. Hay cientos de aplicaciones de traducción que nos ayudan a relacionarnos con diversas culturas, personas y los más de 7000 idiomas que se hablan en todo el mundo. Sin embargo, crear tu propia aplicación te brinda experiencia práctica. Crear algo usted mismo pieza por pieza es donde ocurre el verdadero aprendizaje: la clave es adquirir nuevas habilidades y desarrollarlas a través de la práctica.

En este blog, crearás una aplicación de traducción. En solo unos pocos pasos, puede crear uno capaz de identificar el idioma de entrada, traducir a varios idiomas y generar archivos de audio con la pronunciación correcta. Lo guiaré paso a paso sobre cómo combinar los servicios de AWS para darle vida a su aplicación y probarla.


| Attributes                |                                   |
| ------------------- | -------------------------------------- |
| ✅ AWS Level        | Intermediate - 200                         |
| ⏱ Time to complete  | 30 minutes                             |
| 💰 Cost to complete | [AWS Free Tier](https://aws.amazon.com/free/)      |
| 🧩 Prerequisites    | - [AWS Account](https://aws.amazon.com/resources/create-account/?sc_channel=el&sc_campaign=datamlwave&sc_content=cicdcfnaws&sc_geo=mult&sc_country=mult&sc_outcome=acq) <br>-  [Foundational knowledge of Python](https://catalog.us-east-1.prod.workshops.aws/workshops/3d705026-9edc-40e8-b353-bdabb116c89c/)    |                           |


## Lo que vas a aprender

- Cómo utilizar el servicio de Inteligencia Artificial para detectar el idioma dominante en los textos.
- Cómo utilizar el servicio de Inteligencia Artificial para traducir texto.
- Cómo utilizar el servicio de Inteligencia Artificial para convertir texto en voz realista.
- Cómo crear un bot de interfaces conversacionales de Inteligencia Artificial para manejar solicitudes de traducción.

## Descripción general de la solució

In this tutorial you are going to create a translator chatbot app, with [Amazon Lex](https://aws.amazon.com/lex/) that will handle the frontend interaction with the user, and the backend will be in charge of an [AWS Lambda Function](https://aws.amazon.com/lambda/) with the [AWS SDK for Python library Boto3](https://aws.amazon.com/sdk-for-python/) code using the following AWS services:

- [Amazon Comprehend](https://aws.amazon.com/comprehend/) encargado de detectar el idioma ingresado.
- [Amazon Translate](https://aws.amazon.com/translate/) traducirá al idioma deseado.
- [Amazon Polly](https://aws.amazon.com/polly/) entrega el audio con la pronunciación correcta.

![Diagram translator chatbot app"](https://community.aws/_next/image?url=https%3A%2F%2Fcommunity.aws%2Fraw-post-images%2Ftutorials%2Fbuild-your-own-translator-app-in-less-30-min%2Fimages%2Ffig_1.png&w=1920&q=75) <div align="center"> Fig 1. Diagram translator chatbot app. </div> 

### Constrúyelo en siete partes

- **Parte 1** - Crea la función que detecta el idioma y lo traduce al idioma deseado 🌎.
- **Parte 2** - Crea la función para convertir texto en voz realista 🦜.
- **Parte 3** - Configurar la interfaz del Chatbot con [Amazon Lex](https://aws.amazon.com/lex/)🤖.
- **Parte 4** - Construya la interfaz entre el backend y el frontend.
- **Parte 5** - Integrar el Backend con el Frontend.
- **Parte 6** - ¡Hagámoslo funcionar!
- **Parte 7** - Implementa tu aplicación de traducción.

Quizás dudes de la velocidad de esta construcción. Pero sigue leyendo, descubrirás que se puede hacer en menos de 30 minutos.

**¡Empecemos!**

## Parte 1: Crea la función que detecta el idioma y lo traduzca al idioma deseado 🌎

En esta parte, utilizará dos servicios de IA totalmente gestionados, [Amazon Translate] (https://aws.amazon.com/translate/) para traducir documentos de texto no estructurado (UTF-8) [idiomas comunes] (https://docs.aws.amazon.com/translate/latest/dg/what-is-languages.html) o para crear aplicaciones que funcionen en varios idiomas con [TranslateText](https://boto3.amazonaws.com/v1/documentation/api/1.9.42/reference/services/translate.html#Translate.Client.translate_text) desde [Boto3 Translate client](https://boto3.amazonaws.com/v1/documentation/api/1.9.42/reference/services/translate.html) y [Amazon Comprehend](https://aws.amazon.com/comprehend/) para detectar el idioma dominante del texto que desea traducir mediante la API [DetectDominantLanguage](https://boto3.amazonaws.com/v1/documentation/api/latest/reference/services/comprehend/client/detect_dominant_language.html#detect-dominant-language?) de [Boto3 Comprehend client](https://boto3.amazonaws.com/v1/documentation/api/latest/reference/services/comprehend.html). 

También puedes utilizar Amazon Translate para determinar el idioma de origen del texto. Para ello, realizas una llamada interna a Amazon Comprehend para determinar el idioma de origen, ya te explicaré cómo hacerlo. 


### Se requieren parámetros para la API TranslateText

- **Texto (string) **: el texto que se va a traducir.
- **SourceLanguageCode (string) :** Uno de los [códigos de idioma admitidos](https://docs.aws.amazon.com/translate/latest/dg/what-is-languages.html) del texto fuente. Si especificas **auto**, Amazon Translate llamará a Amazon Comprehend para determinar el idioma de origen ✅.
- **targetLanguageCode (string) :** Uno de los códigos de idioma admitidos para el texto de destino.

### Funciones para llamar a TranslateText y realizar la traducción: 

```python
import boto3

translate_client = boto3.client('translate')

def TranslateText (text,language):
    response = translate_client.translate_text(
    Text=text,
    SourceLanguageCode="auto",
    TargetLanguageCode=language  
)
    text_ready =  response['TranslatedText'] 
    return text_ready
```

## Parte 2: Crea la función para convertir el texto en voz realista  🦜

Para crear la función de conversión de texto a voz, utilizará [Amazon Polly](https://aws.amazon.com/polly/), un servicio de IA que utiliza tecnologías avanzadas de aprendizaje profundo para sintetizar el habla humana con un sonido natural. Permite a los desarrolladores convertir el texto en voz realista que se puede integrar en sus aplicaciones.

En esta parte, utilizarás el [cliente Polly de Boto3](https://boto3.amazonaws.com/v1/documentation/api/latest/reference/services/polly.html) para llamar a las API [StartSpeechSynthesistTask](https://boto3.amazonaws.com/v1/documentation/api/latest/reference/services/polly/client/start_speech_synthesis_task.html) y [GetSpeechSynthesistTask](https://boto3.amazonaws.com/v1/documentation/api/latest/reference/services/polly/client/get_speech_synthesis_task.html) para recuperar información de SpeechSynthesistTask en función de su identificador de tareas. Proporciona el estado y un enlace al [Amazon S3 Bucket](https://aws.amazon.com/s3/) que contiene el resultado de la tarea. 

![converts text into lifelike speech](https://community.aws/_next/image?url=https%3A%2F%2Fcommunity.aws%2Fraw-post-images%2Ftutorials%2Fbuild-your-own-translator-app-in-less-30-min%2Fimages%2Ffig_2.png&w=1920&q=75)
<div align="center"> Fig 2. Converts text into lifelike speech.</div>



### Parámetros para las API de Amazon Lex

|StartSpeechSynthesisTask Parameters | GetSpeechSynthesisTask Parameter|
| ------------------- | -------------------------------------- |
| <ul><li>**OutputFormat(string)**: el valor al que se devolverá el resultado y puede ser: *json*,*mp3*, *ogg_vorbis* or *pcm*. <li>**OutputS3BucketName (string)**: Es el nombre del bucket de [Amazon S3](https://aws.amazon.com/s3/) en el que se guardará el archivo de salida. <li>**Text (string)**: El texto de entrada que se va a sintetizar. <li>**Engine (string)**: Especifica el motor (estándar o neuronal) que Amazon Polly debe utilizar al procesar el texto de entrada para la síntesis de voz. <li>**VoiceId (string)**: [Voice ID](https://docs.aws.amazon.com/polly/latest/dg/voicelist.html) se utiliza para la síntesis. </li></ul>|  <ul><li>**TaskId (string)**: Este es el identificador generado por Amazon Polly para una tarea de síntesis de voz.</li></ul>|
|||

Amazon Polly admite [varios idiomas](https://docs.aws.amazon.com/polly/latest/dg/voicelist.html) y voces que permiten que la voz sintetizada suene de forma muy natural y humana. Para generar el mejor audio debemos elegir la voz adecuada para cada idioma. Usa los siguientes diccionarios en Python:

```python
#Match the language code from Amazon Translate with the right voice from Amazon Polly.

def get_target_voice(language):
    to_polly_voice = dict( [ ('en', 'Amy'), ('es', 'Conchita'), ('fr', 'Chantal'), ('pt-PT', 'Cristiano'),('it', 'Giorgio'),("sr","Carmen"),("zh","Hiujin") ] )
    target_voice = to_polly_voice[language]
    return target_voice
```

### Functions to Calls the Amazon Lex APIs

- StartSpeechSynthesisTask:

```python
import boto3
polly_client = boto3.client('polly')
def start_taskID(target_voice,bucket_name,text):
    response = polly_client.start_speech_synthesis_task(
                    VoiceId=target_voice,
                    OutputS3BucketName = bucket_name,
                    OutputFormat= "mp3", 
                    Text= text,
                    Engine= "standard")

    task_id = response['SynthesisTask']['TaskId']
    object_name = response['SynthesisTask']['OutputUri'].split("/")[-1] 
    return task_id, object_name
```
- GetSpeechSynthesisTask:

```python
import time
def get_speech_synthesis(task_id):
    max_time = time.time() + 2 
    while time.time() < max_time:
        response_task = polly_client.get_speech_synthesis_task(
        TaskId=task_id
        )
        status = response_task['SynthesisTask']['TaskStatus']
        print("Polly SynthesisTask: {}".format(status))
        if status == "completed" or status == "failed":
            if status == "failed": 
                TaskStatusReason = response_task['SynthesisTask']['TaskStatusReason']
                print("TaskStatusReason: {}".format(TaskStatusReason))
            else:
                value= response_task['SynthesisTask']['OutputUri']
                print("OutputUri: {}".format(value))
            break
            
    time.sleep(2)
    return status
```

> 🚨**Note:** Esta aplicación no esperará a que se ejecute SpeechSynthesistTask, ya que la duración depende de la longitud del texto. GetSpeechSynthesistAsk solo muestra el estado del identificador de la tarea.


### Como generar una URL prefirmada para acceder al archivo de audio desde cualquier lugar

De forma predeterminada, los archivos de un bucket de S3 son privados y solo el propietario del objeto tiene permiso para acceder a ellos. Sin embargo, el propietario del objeto puede compartir objetos con otras personas [creando una URL prefirmada](https://docs.aws.amazon.com/AmazonS3/latest/userguide/ShareObjectPreSignedURL.html). En el caso de la aplicación, utilice la API [GeneratePresignedURL](https://boto3.amazonaws.com/v1/documentation/api/latest/reference/services/s3/client/generate_presigned_url.html) de [Boto3 S3 client](https://boto3.amazonaws.com/v1/documentation/api/latest/reference/services/s3.html): 

```python
s3_client = boto3.client("s3")

def create_presigned_url(bucket_name, object_name, expiration=3600):
    value = object_name.split("/")[-1]
    response = s3_client.generate_presigned_url('get_object',
                                                    Params={'Bucket': bucket_name,
                                                            'Key': value},
                                                    ExpiresIn=expiration)
    return response
``` 

Hasta este punto, has aprendido a desarrollar el backend de una aplicación que puede aceptar la entrada de texto, traducirla a un idioma de salida elegido y producir audio con la pronunciación correcta. En el futuro, nos centraremos en crear la interfaz de usuario para que los usuarios puedan utilizar las funciones de traducción y conversión de texto a voz.

## Parte 3: Configurar la interfaz del chatbot con [Amazon Lex] (https://aws.amazon.com/lex/) 

[Amazon Lex](https://aws.amazon.com/lex/) es un servicio de AWS que permite a los desarrolladores crear interfaces de conversación para aplicaciones mediante voz y texto. Ofrece la amplia funcionalidad y flexibilidad de la comprensión del lenguaje natural (NLU) y el reconocimiento automático de voz (ASR), y simplifica la creación de experiencias de conversación naturales para las aplicaciones sin necesidad de conocimientos especializados de inteligencia artificial o aprendizaje automático. También se puede integrar con dispositivos móviles, web, [centro de contacto](https://docs.aws.amazon.com/lexv2/latest/dg/contact-center.html), [plataforma de mensajería](https://docs.aws.amazon.com/lexv2/latest/dg/deploying-messaging-platform.html) y otros servicios de AWS, como [funciones de AWS Lambda](https://docs.aws.amazon.com/lexv2/latest/dg/lambda.html).

[Lex](https://docs.aws.amazon.com/lexv2/latest/dg/how-it-works.html), tiene los siguientes componentes:

<table>
<tr>
<th> Componente </th> <th> Descripción </th> <th> Valor </th>
</tr>
<tr>
<td><b> Language </b></td> <td> Puede seleccionar cualquier [idioma y compatible con Amazon Lex V2.](https://docs.aws.amazon.com/lexv2/latest/dg/how-languages.html) </td><td> English (US) </td></tr>
<tr>
<td><b> Intent </b></td> <td> Una intención representa una acción que el usuario quiere realizar </td><td> TranslateIntent </td></tr>
<tr>
 <td><b> Slot types </b></td> <td> Permita que un bot Lex recopile dinámicamente datos de los usuarios durante un flujo de conversación para completar acciones y proporcionar respuestas personalizadas. Existen [tipos de ranuras integradas](https://docs.aws.amazon.com/lex/latest/dg/howitworks-builtins-slots.html) y [tipos de ranuras personalizadas](https://docs.aws.amazon.com/lex/latest/dg/howitworks-custom-slots.html). En este tutorial, crearás ranuras personalizadas. </td><td> <ul><li>text_to_translate: the text you want to translate. </li><li>	language: el idioma al que quieres traducir el texto. </li></ul> </td></tr>
<tr>
<td><b> Utterances </b></td> <td> Indique la intención del usuario, active el chat. Debe estar en el idioma del chatbot</td> <td><ul><li> I want to translate </li>, <li>quiero hacer una traducción</li><li> I want to translate to {language}</li></ul> </td>
</tr>
</table>

### Crear un bot de Amazon Lex

Follow the steps below to set up [Amazon Lex](https://aws.amazon.com/lex/) on the console:
 
 1. Inicie sesión en la consola de administración de AWS y abra [Amazon Lex console](https://console.aws.amazon.com/lex/)
 2. Siga las instrucciones [To create an Amazon Lex V2 bot (Console)](https://docs.aws.amazon.com/lexv2/latest/dg/exercise-1.html#:~:text=To%20create%20an%20Amazon%20Lex%20V2%20bot%20(Console)) para el **Creation method** selecciona **Create a blank bot** y [To add a language to a bot](https://docs.aws.amazon.com/lexv2/latest/dg/exercise-1.html#:~:text=To%20add%20a%20language%20to%20a%20bot)

El siguiente paso es crear el flujo de la conversación utilizando la información de los componentes. 

El idioma ya se seleccionó en el paso anterior, así que cambia el nombre de Intent en **Intent details** -> **Intent Name** y luego **Save Intent**, ahora crea el Slots type (`text_to_translate`, `language`).


### Crear el Slot Types

1. En el menú de la izquierda, selecciona **Slot types**, ahora **Add slot type** y selecciona **Add blank** slot type. 
2. Incluye los siguientes parámetros para cada tipo de ranura:

|Parameter|`language`|`text_to_translate`|
|--|--|--|
|**Slot type name**|language|text_to_translate|
|**Slot value resolution**|built-in slot type|Restringir a valores de ranuras|
|**Slot type values**|[0-9][a-z][A-Z] |**Value**: Language Code  - **new Value**: Language ([Encuentre el código de idioma y los valores de idioma aquí](https://docs.aws.amazon.com/translate/latest/dg/what-is-languages.html)) - Añade tantos como quieras|
|**Image result** | ![Slot language](https://community.aws/raw-post-images/tutorials/build-your-own-translator-app-in-less-30-min/images/fig_4.png) <div align="center">Fig 3. Slot `language` type. </div> |![Slot language](https://community.aws/raw-post-images/tutorials/build-your-own-translator-app-in-less-30-min/images/fig_3.png) <div align="center">Fig 4. Slot `text_to_translate` type. </div> |
    

### Configurar la intención

Configura el intento de traducción para cumplir con la solicitud de un usuario de realizar una traducción con los siguientes valores:

- **Sample utterances:** Escriba los valores de las expresiones
- **Slots:** Seleccione Añadir ranura y complete la siguiente información:

|Parameter|`language`|`text_to_translate`|
|--|--|--|
|**Name**|language|text_to_translate|
|**Slot type**|language|Restringir a valores de ranuras|
|**Prompts**| What language do you want to translate? | What do you want to translate? Just type and I'll tell you the language... magic!|
|**Image result** | ![Slot language](
![Image description](https://dev-to-uploads.s3.amazonaws.com/uploads/articles/jpn1lfecz9usxuri2z7d.png)

) <div align="center">Fig 5. Slot language required for intent fulfillment. </div> |![Slot language](https://community.aws/raw-post-images/tutorials/build-your-own-translator-app-in-less-30-min/images/fig_6.png) <div align="center">Fig 6. Slot language required for intent fulfillment. </div> |    

>🚨**Important:** El orden importa, asegúrate de que el tipo `language` sea el primer espacio que se requiera. 

Este bot invocará una función de Lambda como [enlace de código de diálogo](https://docs.aws.amazon.com/lexv2/latest/dg/paths-code-hook.html), para validar la entrada del usuario y cumplir con la intención. Para ello, seleccione Utilizar una función de Lambda para la inicialización y la validación (figura 7).

![Slot language](https://community.aws/_next/image?url=https%3A%2F%2Fcommunity.aws%2Fraw-post-images%2Ftutorials%2Fbuild-your-own-translator-app-in-less-30-min%2Fimages%2Ffig_7.png&w=1920&q=75) <div align="center">Fig 7. Use a Lambda function for initialization and validation. </div> 

Para terminar de crear el chatbot, selecciona **Save intent** y luego **Build** arriba a la izquierda.

>👩🏻‍💻**Note:** Cuando construyes un bot Lex, lo estás reentrenando con configuraciones y lógicas actualizadas, lo que le permite aprender de los nuevos parámetros.

### 🥳🚀 ¡Enhorabuena por crear tu bot! Sigue las instrucciones para probarlo en [este enlace](https://docs.aws.amazon.com/lexv2/latest/dg/test-bot.html). 

## Part 4 - A construir la interfaz entre el backend y el frontend

La interacción del backend al frontend se gestionará mediante estados específicos denominados [Acción de diálogo](https://docs.aws.amazon.com/lex/latest/dg/API_runtime_DialogAction.html). Hace referencia a la siguiente acción que el bot debe realizar en su interacción con el usuario. Los valores posibles son:

- **ConfirmIntent** - La siguiente acción es preguntar al usuario si la intención está completa y lista para cumplirse. Se trata de una pregunta de sí/no, como «¿Realizar el pedido?»
- **Close** - Indica que no habrá respuesta del usuario. Por ejemplo, la afirmación «Su pedido se ha realizado» no requiere respuesta.
- **Delegate** - Amazon Lex determina la siguiente acción.
- **ElicitIntent** - La siguiente acción es determinar la intención que el usuario quiere cumplir.
- **ElicitSlot** - La siguiente acción es obtener un valor de slot del usuario.

### Los tres estados principales del flujo de conversación

![Slots created](
![Image description](https://dev-to-uploads.s3.amazonaws.com/uploads/articles/n1c6p3gyvnfbaz18zyqh.png)
<div align="center">Fig 8. Conversation flow. </div> 

1. El usuario inicia la Intent, activando la función Lambda que siempre está escuchando. Lambda no recibe el valor de `language` esperado, por lo que **Delegate** delegará a Lex la tarea de seguir gestionando la conversación al activar el espacio de `language`.
2. El usuario proporciona el idioma y Lex interpreta el valor como un código de idioma. La función Lambda ve el valor del `language` y le pide a Lex que **ElicitSlot** `text_to_translate`.
3. El usuario proporciona el texto a traducir. Como el texto es variable e impredecible, Lex no puede interpretarlo como el valor `text_to_translate`. Por lo tanto, la función Lambda interpreta el texto en lugar de Lex e inicia el proceso de traducción y conversión de texto a voz. Por último, responde a Lex con una **ElicitIntent** que contiene el texto traducido y un enlace prefirmado.

Para integrar el backend y el frontend, la función Lambda necesita interpretar el formato de los eventos de salida de Lex, que se pasan a la función Lambda como eventos de entrada. La [guía para desarrolladores sobre la interpretación del formato de los eventos de entrada](https://docs.aws.amazon.com/lexv2/latest/dg/lambda-input-format.html) proporciona más detalles. En este tutorial, aprenderá a extraer la información necesaria de los eventos de entrada para que la aplicación de traducción funcione.

Para empezar, la función Lambda debe extraer los valores de [interpretaciones](https://docs.aws.amazon.com/lexv2/latest/APIReference/API_runtime_Interpretation.html) y con las posibles coincidencias con el enunciado del usuario: 

```python
def get_intent(intent_request):
    interpretations = intent_request['interpretations'];
    if len(interpretations) > 0:
        return interpretations[0]['intent']
    else:
        return None;
```
La `interpretation` es una matriz con los valores de las ranuras y el estado de la conversación. 

Para extraer los valores de las ranuras interpretados por Lex, utilice la siguiente función: 

```python
def get_slot(slotname, intent, **kwargs):
    try:
        slot = intent['slots'].get(slotname)
        if not slot:
            return None
        slotvalue = slot.get('value')
        if slotvalue:
            interpretedValue = slotvalue.get('interpretedValue')
            originalValue = slotvalue.get('originalValue')
            if kwargs.get('preference') == 'interpretedValue':
                return interpretedValue
            elif kwargs.get('preference') == 'originalValue':
                return originalValue
            # where there is no preference
            elif interpretedValue:
                return interpretedValue
            else:
                return originalValue
        else:
            return None
    except:
        return None
```
    
Para mantener el diálogo entre la función Lambda y Lex, es necesario conocer el contexto que un usuario utiliza en una sesión ([`ActiveContexts`](https://docs.aws.amazon.com/lexv2/latest/APIReference/API_runtime_ActiveContext.html)) dentro del valor del estado de la sesión del usuario ([`sessionState`](https://docs.aws.amazon.com/lexv2/latest/APIReference/API_runtime_SessionState.html)). Para obtenerlo, usa:
```python
def get_active_contexts(event):
    try:
        return event['sessionState'].get('activeContexts')
    except:
        return []
```
Necesita la información de contexto específica de la sesión[`sessionAttributes`](https://docs.aws.amazon.com/lexv2/latest/APIReference/API_runtime_SessionState.html#:~:text=Required%3A%20No-,sessionAttributes,-Map%20of%20key):

```python
def get_session_attributes(event):
    try:
        return event['sessionState']['sessionAttributes']
    except:
        return {}
```

Para enviar el estado DialogAction, utilice esta definición de función:

<table>
<tr>
<th> DialogueAction State  </th> <th> Function Definition </th>
</tr>
<tr>
<td><b> Delegate </b></td> 
<td>

```python
def remove_inactive_context(context_list):
    if not context_list:
        return context_list
    new_context = []
    for context in context_list:
        time_to_live = context.get('timeToLive')
        if  time_to_live and time_to_live.get('turnsToLive') != 0:
            new_context.append(context)
    return new_context
def delegate(active_contexts, session_attributes, intent):
    print ('delegate!')
    active_contexts = remove_inactive_context(active_contexts)
    return {
        'sessionState': {
            'activeContexts': active_contexts,
            'sessionAttributes': session_attributes,
            'dialogAction': {
                'type': 'Delegate'
            },
            'intent': intent,
            'state': 'ReadyForFulfillment'
        },
    }
``` 

</td>
</tr>
<td><b> ElicitSlot</b></td> 
<td>

```python
def elicit_slot(slotToElicit, active_contexts, session_attributes, intent, messages):
    intent['state'] = 'InProgress'
    active_contexts = remove_inactive_context(active_contexts)
    if not session_attributes:
        session_attributes = {}
    session_attributes['previous_message'] = json.dumps(messages)
    session_attributes['previous_dialog_action_type'] = 'ElicitSlot'
    session_attributes['previous_slot_to_elicit'] = slotToElicit
    
    return {
        'sessionState': {
            'sessionAttributes': session_attributes,
            'activeContexts': active_contexts,
            'dialogAction': {
                'type': 'ElicitSlot',
                'slotToElicit': slotToElicit
            },
            'intent': intent
        },
    }
``` 
</td>
</tr>
<td><b> ElicitIntent</b></td> 
<td>

```python
def elicit_intent(active_contexts, session_attributes, intent, messages):
    intent['state'] = 'Fulfilled'
    active_contexts = remove_inactive_context(active_contexts)
    if not session_attributes:
        session_attributes = {}
    session_attributes['previous_message'] = json.dumps(messages)
    session_attributes['previous_dialog_action_type'] = 'ElicitIntent'
    session_attributes['previous_slot_to_elicit'] = None
    session_attributes['previous_intent'] = intent['name']
    
    return {
        'sessionState': {
            'sessionAttributes': session_attributes,
            'activeContexts': active_contexts,
            'dialogAction': {
                'type': 'ElicitIntent'
            },
            "state": "Fulfilled"
        },
        'requestAttributes': {},
     'messages': messages
    }
``` 
</td>
</tr>
</table>


Con las funciones de backend y frontend integradas, ¡es hora de integrarlas!

## Part 5 - Integra el backend con el frontend

Con todo el código creado en las partes anteriores, ensamblará la función Lambda de la siguiente manera.

### Lambda Handler Code

```python
def lambda_handler(event, context):
    print(event)
    #Lambda Function Input Event and Response Format
    interpretations = event['interpretations']
    intent_name = interpretations[0]['intent']['name']
    intent = get_intent(event)
    #need it to Response Format
    active_contexts = get_active_contexts(event) 
    session_attributes = get_session_attributes(event) 
    previous_slot_to_elicit = session_attributes.get("previous_slot_to_elicit") #to find out when Amazon Lex is asking for text_to_translate and join the conversation.
    print(session_attributes)
    
    if intent_name == 'TranslateIntent':
        print(intent_name)
        print(intent)
        language = get_slot('language',intent)
        text_to_translate = get_slot("text_to_translate",intent)
        print(language,text_to_translate)

        if language == None:
            print(language,text_to_translate)
            return delegate(active_contexts, session_attributes, intent)
            
        if (text_to_translate == None) and (language != None) and (previous_slot_to_elicit != "text_to_translate"):
            print(language,text_to_translate)
            response = "What text do you want to translate?"
            messages =  [{'contentType': 'PlainText', 'content': response}]
            print(elicit_slot("text_to_translate", active_contexts, session_attributes, intent, messages))
            return elicit_slot("text_to_translate", active_contexts, session_attributes, intent, messages)
            
        if previous_slot_to_elicit == "text_to_translate": 
            print("diferente a none")
            text_to_translate = event["inputTranscript"]
            text_ready = TranslateText(text_to_translate,language)
            target_voice = get_target_voice(language)
            object_name,task_id = start_taskID(target_voice,bucket_name,text_ready)
            
            url_short = create_presigned_url(bucket_name, object_name, expiration=3600)
            
            print ("text_ready: ", text_ready)
            status = get_speech_synthesis(task_id)
            
            response = f"The translate text is: {text_ready}. Hear the pronunciation here {url_short} "
            messages =  [{'contentType': 'PlainText', 'content': response}]
            
            print(elicit_intent(active_contexts, session_attributes, intent, messages))
            return elicit_intent(active_contexts, session_attributes, intent, messages)
```

>🚨**Important:**  Importe las bibliotecas necesarias, defina el nombre del bucket_name e inicialice los clientes de Boto3 desde los servicios de AWS y **Deploy** para guardar.

### Lambda Function Permissions

Para permitir que la función Lambda invoque los servicios y recursos de AWS, se debe crear un rol de ejecución con los permisos necesarios. Siga estos pasos para crearlo:

1. Ingresa a [Functions page](https://console.aws.amazon.com/lambda/home#/functions) en la consola de Lambda, y selecciona el nombre de la función.
2. Selecciona **Configuration**, y luego **Permissions**, click sobre **Role name** (Fig. 9).

![Slots created](https://community.aws/_next/image?url=https%3A%2F%2Fcommunity.aws%2Fraw-post-images%2Ftutorials%2Fbuild-your-own-translator-app-in-less-30-min%2Fimages%2Ffig_9.png&w=1920&q=75)
<div align="center">Fig 9. Role name. </div> 

3. En la consola de administración de identidad y acceso (IAM), ve a **Add Permision** --> **Create inline policy**
4. Selecciona JSON, en el Policy editor. Pega el siguiente JSON: 

```json
{
	"Version": "2012-10-17",
	"Statement": [
		{
			"Sid": "VisualEditor0",
			"Effect": "Allow",
			"Action": [
				"polly:SynthesizeSpeech",
				"polly:StartSpeechSynthesisTask",
                "polly:GetSpeechSynthesisTask",
				"comprehend:DetectDominantLanguage",
				"translate:TranslateText"
			],
			"Resource": "*"
		},
		{
			"Sid": "VisualEditor1",
			"Effect": "Allow",
			"Action": [
				"s3:PutObject",
				"s3:GetObject"
			],
			"Resource": [
				"arn:aws:s3:::YOU-BUCKET-NAME/*",
				"arn:aws:s3:::YOU-BUCKET-NAME"
			]
		}
	]
}
```

> 🚨**Important:**  Reemplaza **YOU-BUCKET-NAME** por el nombre de tu bucket.

5. Selecciona **Next**, y escribre el nombre de la politica en *Policy name* y luego **Create policy**.


## Part 6 - ¡Hagamos que funcione!

### Adjuntar una función Lambda a un alias de bot

Para activar una función de Lambda cuando un usuario interactúa con Amazon Lex, debe adjuntar la función a un alias de bot [siguiendo estos pasos](https://docs.aws.amazon.com/lexv2/latest/dg/lambda-attach.html):

1. Abre la [consola Amazon Lex](https://console.aws.amazon.com/lex) y elige el nombre del bot que se creó en **Parte 2**.  
2. En el panel izquierdo, elija **Aliases**, elija el nombre del alias (figura 10).

![Choose Aliases name](https://community.aws/_next/image?url=https%3A%2F%2Fcommunity.aws%2Fraw-post-images%2Ftutorials%2Fbuild-your-own-translator-app-in-less-30-min%2Fimages%2Ffig_10.png&w=1920&q=75)
<div align="center">Fig 10. Choose Aliases name. </div> 

3. En la lista de idiomas admitidos, selecciona el idioma (English (US)).

4. Selecciona el nombre de la función de Lambda que va a utilizar y, a continuación, selecciona la versión o el alias de la función y luego **Save**.

![La Lambda function es invocada por la inicialización, validación, y fulfillment.](https://community.aws/_next/image?url=https%3A%2F%2Fcommunity.aws%2Fraw-post-images%2Ftutorials%2Fbuild-your-own-translator-app-in-less-30-min%2Fimages%2Ffig_11.png&w=1920&q=75)
<div align="center">Fig 11. The Lambda function is invoked for initialization, validation, and fulfillment. </div>

Par finalizar la integracion, click en **Build** para crear y configurar el bot utilizando la nueva lógica, una vez finalizado el proceso de construcción, puedes [probar el bot](https://docs.aws.amazon.com/lexv2/latest/dg/test-bot.html)(Fig.12). 

![Testing the bot.](https://community.aws/_next/image?url=https%3A%2F%2Fcommunity.aws%2Fraw-post-images%2Ftutorials%2Fbuild-your-own-translator-app-in-less-30-min%2Fimages%2Ffig_12.png&w=1200&q=75)
<div align="center">Fig 12. Testing the bot. </div>


## Part 7 - Deploy Your Translator App

Ahora tienes un bot de interfaz conversacional para traductores funcional con conversión de texto a voz que creaste y probaste rápidamente con Amazon Lex. Sin embargo, solo se puede acceder a él a través de la consola y ha trabajado con una versión preliminar. 

El borrador es la copia funcional de tu bot. Solo puedes actualizar la versión Draft y, hasta que publiques tu primera versión, Draft es la única versión del bot que tienes. 

Debes crear versiones inmutables para que tu bot entre en producción. Una versión es una instantánea numerada de tu trabajo que puedes publicar para utilizarla en diferentes partes de tu flujo de trabajo, como el desarrollo, la implementación de la versión beta y la producción. 

Un alias es un indicador de una versión específica de un bot. Con un alias, puedes actualizar fácilmente la versión que utilizan tus aplicaciones cliente sin tener que cambiar ningún código. Los alias le permiten dirigir sin problemas el tráfico a diferentes versiones según sea necesario.

Ahora que te he explicado qué es una versión, aprenderás a crear versiones de tu bot y a asignarle el alias. 

### Pasos para crear una versión

 1. Ve a tu **Bot**, luego, en el panel izquierdo, selecciona **Bot version** y selecciona **Create version** (Fig. 13).  

![Create a new bot version.](https://community.aws/_next/image?url=https%3A%2F%2Fcommunity.aws%2Fraw-post-images%2Ftutorials%2Fbuild-your-own-translator-app-in-less-30-min%2Fimages%2Ffig_13.png&w=1920&q=75)
<div align="center">Fig 13. Create a new bot version. </div>

2. Crea una versión de Bot y selecciona **Create**.
3. Luego a **Deployment** --> **Aliases** y selecciona **Create Alias**. 
4. Denominado de Alias y asociado a una versión, elige la nueva versión (Fig. 14), y selecciona **Create**. 

![Associate with a version, choose the new version.](https://community.aws/_next/image?url=https%3A%2F%2Fcommunity.aws%2Fraw-post-images%2Ftutorials%2Fbuild-your-own-translator-app-in-less-30-min%2Fimages%2Ffig_14.png&w=1920&q=75)
<div align="center">Fig 14. Associate with a version, choose the new version. </div>

### Integre su bot con una aplicación

Ya tienes todo lo que necesitas para integrar tu bot con plataformas de mensajería, aplicaciones móviles y sitios web, crea tu aplicación siguiendo algunas de estas instrucciones:

- [Uso de una aplicación Java para interactuar con un bot de Amazon Lex](https://docs.aws.amazon.com/lexv2/latest/dg/deploy-java.html). 
- [Integración de un bot de Amazon Lex con una plataforma de mensajería](https://docs.aws.amazon.com/lexv2/latest/dg/deploying-messaging-platform.html) ([Facebook](https://docs.aws.amazon.com/lexv2/latest/dg/deploy-facebook-messenger.html), [Slack](https://docs.aws.amazon.com/lexv2/latest/dg/deploy-slack.html), [Twilio](https://docs.aws.amazon.com/lexv2/latest/dg/deploy-twilio-sms.html)). 
- [Integración de un bot de Amazon Lex con un centro de contacto](https://docs.aws.amazon.com/lexv2/latest/dg/contact-center.html) ([Amazon Chime SDK](https://docs.aws.amazon.com/lexv2/latest/dg/contact-center-chime.html), [Amazon Connect](https://docs.aws.amazon.com/lexv2/latest/dg/contact-center-connect.html), [Genesys Cloud](https://docs.aws.amazon.com/lexv2/latest/dg/contact-center-genesys.html)). 
- [Web UI for Your Chatbot](https://aws.amazon.com/blogs/machine-learning/deploy-a-web-ui-for-your-chatbot/). 


## Conclusión

Espero que la creación de esta aplicación multilingüe con AWS haya sido una experiencia reveladora para ti. Al utilizar Amazon Comprehend, Amazon Translate, Amazon Polly y Amazon Lex, pudiste crear una potente herramienta de traducción con capacidades de conversión de texto a voz en poco tiempo. 

El proceso demostró lo fácil que es integrar la IA de AWS a través de las funciones de AWS Lambda. Con algunos conocimientos de programación, cualquiera puede crear aplicaciones sofisticadas, como la traducción de idiomas y la síntesis de voz.

Experimentar de forma práctica es la mejor manera de adquirir habilidades. Aunque ya existen aplicaciones de traducción, crear tu propia solución impulsa el aprendizaje. Construir las cosas por ti mismo es más importante que si ya lo has hecho.

### 🚀 Continue Learning

Para obtener más información sobre [Código de muestra de Amazon Polly](https://docs.aws.amazon.com/polly/latest/dg/sample-code-overall.html).

- También puede obtener más información sobre [Todo lo que hacen Amazon Comprehend, Rekognition, Textract, Polly, Transcribe y otros](https://community.aws/posts/all-the-things-that-comprehend-rekognition-textract-polly-transcribe-and-others-do).

- Consulta algunos ejemplos de Amazon Translate [ejemplos de código](https://github.com/aws-samples/document-translation). [más ejemplos de código](https://docs.aws.amazon.com/translate/latest/dg/examples.html).

---
🇻🇪🇨🇱 [Dev.to](https://dev.to/elizabethfuentes12) [Linkedin](https://www.linkedin.com/in/lizfue/) [GitHub](https://github.com/elizabethfuentes12/) [Twitter](https://twitter.com/elizabethfue12) [Instagram](https://www.instagram.com/elifue.tech) [Youtube](https://www.youtube.com/channel/UCr0Gnc-t30m4xyrvsQpNp2Q)
[Linktr](https://linktr.ee/elizabethfuentesleone)