Explore o novo chatbot do Developer Center! O MongoDB AI chatbot pode ser acessado na parte superior da sua navegação para responder a todas as suas perguntas sobre o MongoDB .

Saiba por que o MongoDB foi selecionado como um líder no 2024 Gartner_Magic Quadrupnt()
Desenvolvedor do MongoDB
Central de desenvolvedor do MongoDBchevron-right
Idiomaschevron-right
Gochevron-right

Desenvolvendo skills da Alexa com MongoDB e Golang

Nic Raboy9 min read • Published Jan 17, 2022 • Updated Apr 03, 2024
AWSGo
Ícone do FacebookÍcone do Twitterícone do linkedin
Avalie esse Tutorial
star-empty
star-empty
star-empty
star-empty
star-empty
A popularização do Amazon Alexa e assistentes virtuais em geral não há dúvidas, enormes. Ter um aplicativo web e um aplicativo móvel não é mais suficiente para a maioria das organizações, e agora você precisa começar a oferecer suporte a aplicativos operados por voz.
Então, o que é necessário para criar algo para a Alexa? Quão diferente é criar um aplicativo da web?
Neste tutorial, vamos ver como criar uma Amazon Alexa Habilite, também conhecida como aplicativo Alexa, que interage com um cluster MongoDB usando a linguagem de programação Go (Golang) e o AWS Lambda.

Os requisitos

Alguns requisitos devem ser atendidos antes de iniciar este tutorial:
  • O Golang deve ser instalado e configurado
  • Um cluster do MongoDB Atlas
Se você não tiver um cluster doMongoDB Atlas, poderá configurar um gratuitamente. Para este exemplo, um cluster M0 é mais que suficiente.
Já tem uma conta na AWS? O Atlas oferece suporte ao pagamento por uso por meio do AWS Marketplace (AWS MP) sem qualquer compromisso inicial — basta
Inscreva-se no MongoDB Atlas por meio do AWS Marketplace.
Certifique-se de que o Atlas cluster tenha os endereços IP adequados na lista de acesso à rede para serviços da AWS. Se o AWS Lambda não puder acessar seu cluster, as solicitações feitas pelo Alexa falharão.
Ter um Amazon Echo ou outro dispositivo habilitado para Amazon Alexa não é necessário para ser bem-sucedido com este tutorial. A Amazon oferece um simulador realmente ótimo que pode ser usado diretamente no navegador da web.

Projetando uma habilidade da Alexa com um termo de invocação e amostras de declarações

Quando se trata de criar uma habilidade com a Alexa, não importa se você começa com o código ou com o design. Para este tutorial, começaremos pelo design, diretamente no Amazon Developer Portal para a Alexa.
Entre no portal e escolha criar uma nova habilidade personalizada. Depois de criar a habilidade, você será direcionado a um painel com vários itens da lista de verificação:
Na lista de verificação, você deve observar o seguinte:
  • Nome da invocação
  • Intenção, amostras e slots
  • Endpoint
Existem outros itens, sendo um opcional e o outro sendo verificado naturalmente à medida que os outros são concluídos.
A primeira etapa é definir o nome da invocação. Este é o nome que os usuários usarão quando falarem com seu assistente virtual. Não deve ser confundido com o nome da habilidade porque os dois não precisam corresponder. O nome da habilidade é o que apareceria no mercado online.
Para o nosso nome de invocação, vamos usar gerente de receita, algo que seja fácil de lembrar e fácil de pronunciar. Com o nome da invocação pronto, podemos antecipar o uso da Skill da seguinte forma:
1Alexa, ask Recipe Manager to INTENT
O usuário não falaria literalmente INTENT no comando. A intenção é o comando que será definido por meio de enunciados de exemplo, também conhecidos como frases ou dados de exemplo. Você pode, e provavelmente deve, ter várias intenções para sua habilidade.
Vamos começar criando uma intenção intitulada GetIngredientsForRecipeIntent com os seguintes exemplos de declarações:
1what ingredients do i need for {recipe}
2what do i need to cook {recipe}
3to cook {recipe} what ingredients do i need
Há algumas coisas a serem observadas sobre as frases acima:
  • A tag{recipe} é uma variável de slot que será definida pelo usuário quando falada.
  • Todas as frases faladas possíveis para executar o comando devem ser listadas.
A Alexa opera com base no aprendizado de máquina, portanto, quanto mais dados de amostra, melhor. Ao definir a variável {recipe} , ela deve ser atribuída a um tipo deAMAZON.Food.
Quando tudo dito e feito, você pode executar a intenção fazendo algo como:
1Alexa, ask Recipe Manager what do I need to cook Chocolate Chip Cookies
Ter uma intenção em seu Alexa Skill não é divertido, portanto, vamos criar outra intenção com seu próprio conjunto de frases de exemplo. Escolha criar uma nova intenção intitulada GetRecipeFromIngredientsIntent com os seguintes exemplos de frases:
1what can i cook with {ingredientone} and {ingredienttwo}
2what are some recipes with {ingredientone} and {ingredienttwo}
3if i have {ingredientone} and {ingredienttwo} what can i cook
Desta vez, estamos usando duas variáveis de slot em vez de uma. Como mencionado anteriormente, é provavelmente uma boa ideia adicionar significativamente mais declarações de amostra para obter os melhores resultados. A Alexa precisa ser capaz de processar os dados a serem enviados para sua função Lambda.
Neste momento, a configuração no Portal do Desenvolvedor da Alexa está quase concluída. A exceção é o endpoint que ainda não existe.

Construindo uma função Lambda com Golang e MongoDB

Alexa, na maioria das vezes, deve ser capaz de direcionar solicitações, então agora precisamos criar nosso back-end para recebê-las e processá-las. É aqui que o Lambda, Go e o MongoDB entram em ação.
Supondo que o Golang tenha sido instalado e configurado corretamente, crie um novo projeto dentro do seu $GOPATH e, dentro desse projeto, crie um arquivoprincipal.go. Como código padrão para dar o primeiro passo, esse arquivo deve conter o seguinte:
1package main
2
3func main() { }
Com o código boilerplate adicionado, agora podemos instalar o driver MongoDB Go . Para fazer isso, você poderia, em teoria, fazer um go get, mas a abordagem preferida no momento é usar a ferramenta de gerenciamento de pacotesdep para Go. Para fazer isso, depois de instalar a ferramenta, execute o seguinte:
1dep init
2dep ensure -add "go.mongodb.org/mongo-driver/mongo"
Estamos usando dep para que a versão do driver que estamos usando em nosso projeto seja bloqueada por versão.
Além do MongoDB Go driver do , também precisaremos obter o Amazon Web Services Lambda SDK para Go , bem como um SDK não oficial para a Alexa, já que não existe nenhum SDK oficial. Para fazer isso, podemos executar:
1dep ensure -add "github.com/arienmalec/alexa-go"
2dep ensure -add "github.com/aws/aws-lambda-go/lambda"
Com as dependências disponíveis, podemos modificar o arquivomain.godo projeto. Abra o arquivo e adicione o seguinte código:
1package main
2
3import (
4 "context"
5 "os"
6
7 "go.mongodb.org/mongo-driver/mongo"
8 "go.mongodb.org/mongo-driver/mongo/options"
9)
10
11// Stores a handle to the collection being used by the Lambda function
12type Connection struct {
13 collection *mongo.Collection
14}
15
16func main() {
17 ctx := context.Background()
18 client, err := mongo.Connect(ctx, options.Client().ApplyURI(os.Getenv("ATLAS_URI")))
19 if err != nil {
20 panic(err)
21 }
22
23 defer client.Disconnect(ctx)
24
25 connection := Connection{
26 collection: client.Database("alexa").Collection("recipes"),
27 }
28}
Na função main, estamos criando um cliente usando a connection string de nosso cluster. Nesse caso, estou usando uma variável de ambiente no meu computador que aponta para o cluster MongoDB Atlas. Sinta-se livre para configurar essa connection string da maneira que você se sentir mais confiante.
Ao conectar, obtemos o identificador de uma coleçãorecipes para um banco de dadosalexa e o armazenamos em uma estrutura de dados Connection . Como não gravaremos nenhum dado neste exemplo, tanto o banco de dadosalexa quanto a coleçãorecipes deverão existir antes da execução deste aplicativo.
Você pode conferir mais informações sobre como se conectar ao MongoDB com a linguagem de programação Go em um tutorial anterior que escrevi.
Então, por que estamos armazenando o identificador da collection em uma estrutura de dadosConnection ?
O AWS Lambda se comporta de forma um pouco diferente quando se trata de aplicativos web. Em vez de executar a funçãomain e permanecer ativas enquanto seu servidor permanecer ativo, as funções do Lambda tendem a ser suspensas ou encerradas quando não são usadas. Por esse motivo, não podemos confiar que nossa conexão esteja disponível e também não queremos estabelecer muitas conexões com nosso banco de dados no cenário em que nossa função não foi encerrada. Para lidar com isso, podemos passar a conexão de nossa funçãomain para nossa função lógica.
Vamos fazer uma alteração para ver isso em ação:
1package main
2
3import (
4 "context"
5 "os"
6
7 "github.com/arienmalec/alexa-go"
8 "github.com/aws/aws-lambda-go/lambda"
9 "go.mongodb.org/mongo-driver/mongo"
10 "go.mongodb.org/mongo-driver/mongo/options"
11)
12
13// Stores a handle to the collection being used by the Lambda function
14type Connection struct {
15 collection *mongo.Collection
16}
17
18func (connection Connection) IntentDispatcher(ctx context.Context, request alexa.Request) (alexa.Response, error) {
19 // Alexa logic here...
20}
21
22func main() {
23 ctx := context.Background()
24 client, err := mongo.Connect(ctx, options.Client().ApplyURI(os.Getenv("ATLAS_URI")))
25 if err != nil {
26 panic(err)
27 }
28
29 defer client.Disconnect(ctx)
30
31 connection := Connection{
32 collection: client.Database("alexa").Collection("recipes"),
33 }
34
35 lambda.Start(connection.IntentDispatcher)
36}
Observe no código acima que adicionamos uma chamadalambda.Start em nossa funçãomain que aponta para uma funçãoIntentDispatcher. Estamos projetando essa função para usar as informações de conexão estabelecidas na função main que, com base em nosso conhecimento do Lambda, podem não ser executadas sempre que a função for executada.
Então, temos a base para nossa habilidade com a Alexa. Agora precisamos projetar a lógica para cada uma de nossas intenções que foram definidas anteriormente no Alexa Developer Portal.
Como essa será uma habilidade relacionada à receita, vamos modelar nossos documentos do MongoDB da seguinte forma:
1{
2 "_id": ObjectID("234232358943"),
3 "name": "chocolate chip cookies",
4 "ingredients": [
5 "flour",
6 "egg",
7 "sugar",
8 "chocolate"
9 ]
10}
Não há dúvidas de que nossos documentos poderiam ser mais bizarros, mas para este exemplo funcionará bem. Dentro do cluster MongoDB Atlas, crie o banco de dadosalexa se ele ainda não existir e adicione um documento modelado como o acima em uma coleção dereceitas.
No arquivo main.go do projeto, adicione a seguinte estrutura de dados:
1// A data structure representation of the collection schema
2type Recipe struct {
3 ID primitive.ObjectID `bson:"_id"`
4 Name string `bson:"name"`
5 Ingredients []string `bson:"ingredients"`
6}
Com o driver Go do MongoDB, podemos anotar as estruturas de dados do Go com o BSON para que possamos mapear facilmente entre os dois. Esseticamente, torna nossa vida muito mais fácil ao trabalhar com MongoDB e Go.
Vamos retornar à função IntentDispatcher:
1func (connection Connection) IntentDispatcher(ctx context.Context, request alexa.Request) (alexa.Response, error) {
2 var response alexa.Response
3 switch request.Body.Intent.Name {
4 case "GetIngredientsForRecipeIntent":
5 case "GetRecipeFromIngredientsIntent":
6 default:
7 response = alexa.NewSimpleResponse("Unknown Request", "The intent was unrecognized")
8 }
9 return response, nil
10}
Lembre-se das duas intenções do Alexa Developer Portal? Precisamos atribuir lógica a eles.
Essenciais, vamos fazer alguma lógica de banco de dados e, em seguida, usar a funçãoNewSimpleResponse para criar uma resposta para os resultados.
Vamos começar com a lógicaGetIngredientsForRecipeIntent:
1case "GetIngredientsForRecipeIntent":
2 var recipe Recipe
3 recipeName := request.Body.Intent.Slots["recipe"].Value
4 if recipeName == "" {
5 return alexa.Response{}, errors.New("Recipe name is not present in the request")
6 }
7 if err := connection.collection.FindOne(ctx, bson.M{"name": recipeName}).Decode(&recipe); err != nil {
8 return alexa.Response{}, err
9 }
10 response = alexa.NewSimpleResponse("Ingredients", strings.Join(recipe.Ingredients, ", "))
No snippet acima, estamos obtendo a variável de slot que foi passada e estamos emitindo uma consulta FindOnecontra a coleção. O filtro para a consulta diz que o camponame do documento deve corresponder à receita que foi passada como uma variável de slot.
Se houver uma correspondência, estaremos serializando a matriz de ingredientes em uma string e a retornaremos para Alexa. Em teoria, a Alexa deve ler de volta a lista de ingredientes separados por vírgulas.
Agora vamos dar uma olhada na lógica de intençãoGetRecipeFromIngredientsIntent:
1case "GetRecipeFromIngredientsIntent":
2 var recipes []Recipe
3 ingredient1 := request.Body.Intent.Slots["ingredientone"].Value
4 ingredient2 := request.Body.Intent.Slots["ingredienttwo"].Value
5 cursor, err := connection.collection.Find(ctx, bson.M{
6 "ingredients": bson.D{
7 {"$all", bson.A{ingredient1, ingredient2}},
8 },
9 })
10 if err != nil {
11 return alexa.Response{}, err
12 }
13 if err = cursor.All(ctx, &recipes); err != nil {
14 return alexa.Response{}, err
15 }
16 var recipeList []string
17 for _, recipe := range recipes {
18 recipeList = append(recipeList, recipe.Name)
19 }
20 response = alexa.NewSimpleResponse("Recipes", strings.Join(recipeList, ", "))
No snippet acima, estamos pegando as duas variáveis de slot que representam os ingredientes e as estamos usando em uma consulta Findna coleção. Desta vez, estamos usando o operador$all porque queremos filtrar todas as receitas que contenham ambos os ingredientes em qualquer lugar da matriz.
Com os resultados do Find, podemos criar uma array dos nomes das receitas e serializá-la em uma string para ser retornada como parte da resposta do Alexa.
Se você quiser obter mais informações sobre os comandosFind e FindOne para Go e MongoDB, confira meu tutorial de como ler documentos sobre o assunto.
Embora possa parecer simples, o código do Alexa Skill está realmente completo. Codificamos cenários para cada uma das duas intenções que configuramos no Alexa Developer Portal. Poderíamos melhorar o que fizemos ou criar mais intenções, mas está fora do escopo do que queremos realizar.
Agora que temos nosso aplicativo, precisamos construí-lo para o Lambda.
Execute os seguintes comandos:
1GOOS=linux go build
2zip handler.zip ./project-name
Então, o que está acontecendo nos comandos acima? Primeiro, estamos construindo um binário compatível com Linux. Estamos fazendo isso porque, se você estiver desenvolvendo no Mac ou Windows, vai acabar com um binário incompatível. Ao definir o sistema operacional, estamos contando ao Go para o que construir.
Para obter mais informações sobre a compilação cruzada com o Go, consulte minha publicação Cross Compiling Golang Applications For Use On A Raspberry Pi.
Em seguida, estamos criando um arquivo do nosso binário. É importante substituir o project-name pelo do seu nome binário real. É importante lembrar o nome do arquivo conforme ele é usado no painel do Lambda.
Ao optar por criar uma nova função do Lambda na AWS, certifique-se de que Go é a tecnologia de desenvolvimento. Escolha carregar o arquivo ZIP e adicione o nome do binário como o manipulador.
Agora se trata de vincular Alexa a Lambda.
Anote o valorARN de sua função Lambda. Ele será adicionado no Portal Alexa. Além disso, certifique-se de adicionar o Alexa Skills Kit como um trigger da função. É tão simples quanto selecioná-lo na lista.
Volte para o Alexa Developer Portal e escolha o item da lista de verificação do Endpoint . Adicione o valor do ARN à região padrão e escolha criar a habilidade usando o botãoConstruir modelo .
Quando a criação da habilidade estiver concluída, você poderá testá-la usando o simulador que a Amazon oferece como parte do Alexa Developer Portal. Esse simulador pode ser acessado usando a guiaTeste no portal.
Se você usou os mesmos exemplos de enunciados que eu tenho, tente inserir algo assim:
1ask recipe manager what can i cook with flour and sugar
2ask recipe manager what chocolate chip cookies requires
Claro, a suposição é que você também tem entradas de coleção para biscoitos de chocolate e os vários ingredientes que usei acima. Sinta-se livre para modificar os termos variáveis com os de seus próprios dados.

Conclusão

Você acabou de ver como criar uma habilidade da Alexa com MongoDB, Golang e AWS Lambda. É ótimo saber desenvolver aplicativos para assistentes de voz como o Alexa, pois eles estão se tornando cada vez mais populares, e o lado bom é que não são mais difíceis do que escrever aplicativos padrão.
Como mencionado anteriormente, o MongoDB Atlas torna o emparelhamento MongoDB com Lambda e Alexa muito conveniente. Você pode usar o nível gratuito ou fazer o upgrade para algo melhor.
Se você quiser expandir seu conhecimento do Alexa com Go e obter mais práticas, confira um tutorial anterior que criei intitulado Construa uma habilidade do Alexa com Golang e AWS Lambda.

Ícone do FacebookÍcone do Twitterícone do linkedin
Avalie esse Tutorial
star-empty
star-empty
star-empty
star-empty
star-empty
Relacionado
Tutorial

Interagir com o MongoDB em uma função Amazon Web Services Lambda usando o Go


Aug 29, 2024 | 6 min read
Tutorial

Noções básicas de HTTP com Go 1.22


Apr 23, 2024 | 7 min read
Início rápido

Transações ACID multidocumento no MongoDB com Go


Apr 03, 2024 | 6 min read
Tutorial

Servidores HTTP persistindo dados no MongoDB


Sep 04, 2024 | 5 min read
Sumário