O blog da AWS
Construindo aplicações Serverless com .NET, AWS Lambda e Amazon Translate para automatizar traduções
Por Leonardo Bonato Bizaro, Professional Services Intern, WWCO ProServe LATAM.
Processos de tradução de conteúdo normalmente são ainda um desafio. Mesmo que tenhamos softwares que aliam uma grande base de conhecimento de linguagens e ferramentas de tradução que se baseiam em aprendizado de máquina e automação, ainda precisamos do olhar humano para entender nuânces, pequenas alterações que fazem parte de regionalismos e da linguaguem coloquial de cada lugar. Mas isso tudo não pode impedir que os processo se tornem cada vez melhores e mais robustos. E, com certeza, mais rápidos.
E é essa a ideia que iremos propor nesse artigo. Constantemente, vemos vários clientes com o processo de tradução de grandes textos e websites sendo realizado de forma manual, onde o próprio usuário deve criar uma nova versão para a língua desejada e traduzir todo o conteúdo disponibilizado. Esta situação faz com que o autor necessite de conhecimento da linguagem alvo para traduzir e/ou revisar seu próprio texto ou averiguar manualmente, parágrafo por parágrafo, a tradução realizada por alguma ferramenta utilizada, afim de validar as concordâncias semânticas. Para trazer melhorias e automação à este processo, foi desenvolvida uma solução com o intuito de utilizar o próprio recurso do Amazon Translate para traduzir, de forma automática, todo o conteúdo de um site, independentemente de seu tamanho; e também criando ao final do processo um arquivo já formatado e traduzido, para ser enviado de forma automatizada para a revisão humana, gerando um ganho de tempo considerável no processo final. E, inclusive, disponibilizando o recurso para quem não tem conhecimentos no uso do Amazon Translate.
A solução foi construída utilizando recursos de bibliotecas open source e nuget packages disponibilizados pela própria AWS, de forma a buscar o conteúdo desejado apenas fornecendo o link da página da internet (como blogs, por exemplo). Depois disso, uma Lambda Function foi codificada para baixar o conteúdo, formatá-lo para manter todo o texto padronizado em formato .DOC (usando bibliotecas LibreOffice), realizar a tradução do texto para a linguagem de destino e então salvar o arquivo final em um S3 bucket desejado, podendo ser disponibilizado ao usuário que realizou a requisição. Esse processo final ainda pode ter mais automações caso você tenha, por exemplo, um sistema que recebe requests HTTP ou emails disparados por uma solução de Pub/Sub, como é o caso do Amazon SNS.
Visão geral da Solução
Figura 1 – Infraestrutura da solução
A solução mostrada acima é composta de três etapas:
- Download dos recursos HTML;
- Criação do Documento e upload para o S3;
- Execução de Job de Tradução.
Todas estas etapas possuem tratativa de exceção e são realizadas pela Lambda de forma assíncrona, ou seja, sem esperar uma tarefa finalizar para começar a próxima, o que deixa o código mais rápido já que passa a não depender de uma resposta final quando uma requisição acontece.
No momento em que o Job de Tradução do Amazon Translate muda de estado, um evento presente no Amazon EventBridge pode ser acionado automaticamente através da regra TranslationJobRule, que tem como alvo alertar os usuários através do Amazon SNS, onde os endpoints estão definidos.
Pré-requisitos
- Uma Conta AWS deve ser utilizada para criação e configuração da ferramenta.
- Conhecimento prévio na utilização de recursos e serviços AWS.
- Realizar o download dos Packages Nuget open source necessários, que são: System.CodeDom; AWSSDK.Core; Amazon.Lambda.Core; AWSSDK.S3; AWSSDK.Translate; FSharp.Core; CsQuery.
- Configuração do perfil de usuário pelo comando configure do AWS CLI, que foi utilizado para realizar o deploy da solução via .NET CLI.
- Conhecimento em C# e Visual Studio.
Passo a passo
Este passo a passo descreve todo a configuração e operação da Lambda Function e sua atuação nos outros serviços AWS utilizados na infraestrutura. A aplicação foi criada em .NET 6.0 e utiliza um FunctionHandler principal para a Lambda, que vai ser responsável por chamar os outros métodos da aplicação.
Figura 1 – Função principal da aplicação.
Um importante detalhe é que dentro desta solução existe uma classe interna denominada Html, que é responsável por manter a formatação do texto que será extraído da página web utilizada como fonte. Essa classe tem o objetivo de manter o documento formatado de acordo com o mesmo padrão utilizado pelo site, e alcança esse objetivo inserindo um style CSS ao início do arquivo, como mostrado abaixo:
Figura 2 – Método responsável pela formatação do texto dentro da classe Html.
Desta forma, a aplicação reconhece o título principal do texto e identifica cada parágrafo como um chapter, mantendo dentro do body o formato desejado e o título de cada seção usando a tag h1, e o texto da seção em h2.
Figura 3 – Método responsável pela formatação do texto dentro da classe Html.
Esta classe interna é então utilizada dentro da solução da Lambda para ser aplicada no que diz respeito ao reconhecimento do texto que será obtido pelo link do conteúdo desejado.
Figura 4 – Utilização da classe Html.
O método principal FuncEval é responsável por transformar a entrada da Lambda (formatada em JSON) em um objeto .NET e reconhecer cada elemento referente à source (link do conteúdo de fonte), output (S3 bucket desejado para armazenamento), source language (linguagem atual do conteúdo) e target language (desejada pelo usuário). Esses nomes sublinhados são os nomes de cada uma das inserções que a interação com o usuário fará na aplicação.
Com a deserialização efetuada e cada elemento do objeto reconhecido, o programa chama os métodos DownloadHtml necessário para a extrair as informações desejadas do HTML. Na sequência é invocado o método CreateTempFile que irá formatar este conteúdo e criar um arquivo temporário em .doc; e por fim o método SaveDocument responsável por salvar o conteúdo no S3 bucket e iniciar o Job de tradução.
Figura 5 – Estrutura do método principal chamado pelo FunctionHandler.
- Download dos recursos HTML: Dentro do método DownloadHtml, é utilizado o link do website para efetuar a busca do conteúdo desejado utilizando a classe WebClient. Todo o recurso obtido é atribuido em uma string que será manipulada pela biblioteca CsQuery através da classe CQ. Com esse recurso, podemos filtrar o conteúdo e extrair apenas as sessões e tags HTML pertinentes aos parágrafos de texto. Neste exemplo, podemos extrair todo o conteúdo de um blog da AWS ao pegar toda a string presente dentro da tag article de classe blog-post.
Figura 6 – Método DownloadHtml e seu funcionamento.
Desta forma, é possível ignorar todo o conteúdo anterior que não condiz com a nossa necessidade, que está fora do article.
Figura 7 – Exemplo de estrutura HTML padrão de um blog AWS.
Dentro desta tag article, é possível ainda fazer uma separação de conteúdo maior através da section de classe blog-post-content, onde ficam localizados todos os parágrafos deste blog, separados pela tag <p>. Também é possível separar as linhas pertinentes aos temas/títulos de cada parte do texto, que ficam presentes dentro da tag <h2>.
Figura 8 – Método DownloadHtml e seu funcionamento
O retorno deste método é um objeto da classe Html contendo todo o texto da página web e seu conteúdo separado em capítulos, onde cada capítulo é um parágrafo já separado de forma ordenada dentro de uma Tuple.
Figura 9 – Método DownloadHtml e seu funcionamento
- Criação do Documento e upload para o S3: Agora, com o conteúdo extraído corretamente na classe Html, podemos chamar o método Este método irá criar um arquivo temporário dentro dos repositórios da Lambda, e então será escrito neste arquivo todo o conteúdo do objeto Html que já foi formatado conforme os padrões do site através do método TransformText já mencionado.
Figura 10 – Método CreateTempFile e seu funcionamento.
Com o arquivo temporário criado, o método SaveDocument é chamado para inserir este arquivo em um S3 bucket definido através do input feito pelo usuário na Lambda. Será necessário então criar uma instância de S3Client e uma requisição de PutObject, definindo o objeto que será enviado em uma requisição assíncrona:
Figura 11 – Método SaveDocument e seu funcionamento.
Com o arquivo na linguagem fonte já armazenado no S3 bucket, podemos iniciar o processo de tradução ao chamar o método TranslateDocument.
- Execução de Job de Tradução: Dentro do método de tradução, iremos criar um novo objeto da classe AmazonTranslateClient para poder iniciar os jobs de tradução, e realizar o mesmo com a classe AmazonIdentityManagementServiceClient para requisitar uma IAM Role que deverá ter as políticas necessárias para dar permissão ao Amazon Translate:
Figura 12 – Método TranslateDocument e seu funcionamento.
Desta forma, é possível iniciar uma requisição ao Amazon Translate através da classe StartTextTranslationJobRequest, que utilizará como critérios:
- JobName a ser atribuido com o nome desejado para o Job;
- DataAcessRoleArn que deve corresponder ao ARN da Role que será utilizada pelo Translate;
- InputDataConfig contendo a URI do documento presente no S3 bucket que será utilizado, além da especificação do tipo de conteúdo (neste caso, text/html);
- OutputDataConfig que corresponde ao S3 URI de saída do novo arquivo traduzido;
- SourceLanguageCode e TargetLanguageCodes, sendo a linguagem fonte e a linguagem destino, respectivamente.
Figura 13 – Funcionamento da requisição de tradução no método TranslateDocument.
A IAM Role que será utilizada pelo Amazon Translate deverá ser ajustada de forma a possuir à sua respectiva trust policy relacionada ao IAM Principal translate.amazonaws.com para a Action de sts:AssumeRole. A política de permissão deve atribuir acesso aos recursos do Amazon S3 para realizar as ações de GetObject e PutObject no bucket de destino.
No que diz respeito à Lambda, a IAM Role de execução deve possuir políticas voltadas para o acesso aos recursos do Amazon Translate, S3, e especialmente a Action de iam:PassRole, para que a Lambda tenha permissão de atribuir a IAM Role citada anteriormente ao Job do Amazon Translate. Com estas atribuições de acesso, é possível testar e já utilizar a Lambda dentro do ambiente AWS.
Figura 13 – Exemplo de execução da Lambda.
Com o TextTranslateJobId disponibilizado no output da execução da Lambda, é possível visualizar o Job dentro do Amazon Translate.
Figura 13 – Detalhes da execução de um Job no Amazon Translate.
É possível visualizar o destino do arquivo traduzido no campo “Output file location”, que levará ao bucket S3 selecionado nos parâmetros de execução da Lambda.
Figura 14 – Resultado da tradução disponível no S3.
Ao baixar o documento, podemos observar que a tradução do arquivo funcionou, sem compremeter a formatação original do HTML.
Figura 15 – Arquivo final traduzido e pronto para utilizado.
Recursos Adicionais
Se uma das finalidades da solução tiver objetivo de automatizar uma resposta ao consumidor desta Lambda, é possível criar uma regra dentro do Amazon EventBridge que irá realizar uma ação em resposta ao próprio evento de mudança de estado do Job do Amazon Translate; e como Target direcionar para um tópico do Amazon SNS.
Figura 16 – Exemplo de Rule sendo aplicada dentro do Amazon EventBridge.
Este tópico do SNS pode ter como Subscriptions o email do próprio usuário que utilizou a solução, ou até mesmo um Endpoint em HTTP para enviar mensagens de notificação em uma solicitação HTTP POST.
Figura 17 – Exemplo de tópico configurado no Amazon Simple Notification Service para atender a Rule do EventBridge.
Remoção da Solução
Se não houver mais interesse em manter a solução disponível em sua conta AWS, é necessário apenas apagar os recursos criados pelos serviços utilizados, removendo a Lambda Function criada, o bucket S3 utilizado para armazenar os arquivos, e as IAM Roles e Policies criadas dentro do IAM. Também é possível remover todos os logs gerados dentro do Amazon CloudWatch durante as execuções.
Conclusão
Com o desenvolvimento desta solução, é possível realizar a tradução de qualquer texto disponibilizado em um site da web e criar um documento formatado do texto traduzido de forma automatizada. Uma tarefa que era realizada de forma manual e que demandava uma série de processos para ser realizada, agora pode ser feita automaticamente através da implementação desta solução, permitindo criar várias versões dos seus conteúdos para qualquer língua desejada e em larga escala.
Sobre o autor
Leonardo Bonato Bizaro é Professional Services Intern no time de ProServe LATAM. Presente desde março, vem abraçando a grande oportunidade recebida através da constante busca de experiência e aprendizado na AWS para crescimento e desenvolvimento profissional.
Revisores
Bruno Lopes é Senior Solutions Architect no time da AWS LATAM. Trabalha com soluções de TI há mais de 14 anos, tendo em seu portfólio inúmeras experiências em workloads Microsoft, ambientes híbridos e capacitação técnica de clientes como Technical Trainer e Evangelista. Agora atua como um Arquiteto de Soluções, unindo todas as capacidades para desburocratizar a adoção das melhores tecnologias afim de ajudar os clientes em seus desafios diários.
Luciano Bernardes trabalha atualmente como Sr Solutions Architect na AWS, especializado em workloads Microsoft. Com 15 anos de experiência no mercado, trabalhou a maior parte em consultoria técnica especializada em Microsoft, em clientes de várias verticais, com demandas voltadas para infraestrutura on-premises e em nuvem. Como SA, trabalha próximo a clientes e parceiros de consultoria em LATAM, para apoiá-los em tomadas de decisão e revisão de arquitetura de workoads Microsoft na nuvem AWS.