O documento apresenta um codelab sobre Actions on Google, Dialogflow e Firebase. O codelab inclui três projetos: um bot de piadas de animais, um bot de criptomoedas e um bot de pedidos de pizza. Os projetos demonstram conceitos como intenções, entidades, webhooks, funções do Firebase e permissões de usuário.
2. ✓ Utilizar e demonstrar os princípios de interfaces de voz e conversa
✓ Componentes de uma conversa:
✓ Intenções, Entidades e Ações
✓ Webhooks e conteúdo dinâmico
✓ Funções de negócio rodando no Firebase
✓ Permissões e dados do usuário
✓ Surface API
O que vamos aprender
Visão geral das ferramentas Actions on Google, Dialogflow e Firebase
4. O que vamos fazer
3 projetos envolvendo diversos conceitos do Actions on Google e Dialogflow
✓ AnimalJoker
• Piadas de animais
• Sem programação e mostrando os princípios de interfaces de voz e conversa.
✓ Cryptocurrency bot
• Informações sobre moedas digitais como o Bitcoin e Ethereum
• Webhooks e conteúdo dinâmico
• Funções de negócio rodando no Firebase
✓ Pizza bot
• Bot para pedido de pizza
• Permissões e dados do usuário
• Surface API
8. 8
AnimalJoker
Entidades - Entity
• Entidades são valores que queremos obter do que o usuário está
dizendo.
• Pense em campos em um formulário.
• O Dialogflow vai automaticamente extrai-los.
• Quanto mais exemplos você der, mais assertivo será o algoritmo
de Machine Learning
• Plurais não são necessários, o Dialogflow consegue inferir.
10. 10
AnimalJoker
Intenções - Intent
• As intenções são ativadas de acordo com o que o usuário diz.
• Pense em nas mais diferentes formas que usuário vai usar para uma mesma intenção
de atividade.
• Quanto mais exemplos você der, mais assertivo será o algoritmo de Machine Learning
• Por exemplo, para ouvir piadas o usuário pode falar de diversas formas:
• Please tell jokes of dogs
• Tell jokes about cats
• Tiger jokes
• Do you know jokes about lions ?
• A cat joke please
14. 14
AnimalJoker
Respostas
• Com o Dialogflow conseguimos colocar respostas padrões
• Não são dinâmicas, mas dando várias opções você tem uma
sensação de ser mais real a conversa.
• Podemos usar as variáveis capturadas.
• Podemos continuar ou não a conversa.
35. 35
Cryptocurrency Bot
Escrever o backend da nossa aplicação - Dois caminhos
• Usar o editor direto no DialogFlow
• Mais limitado, porém vai ser o suficiente para este Codelab
• Deploy direto pelo console
• Criar uma pasta no seu computador e rodar `firebase init`
• Associar com o projeto do Dialogflow
• Instalar libs usando NPM
• Rode `firebase deploy` para enviar o seu código
37. 37
Cryptocurrency Bot
Deploy da primeira versão do webhook
const functions = require('firebase-functions');
const { DialogflowApp } = require('actions-on-google');
const ACTION_PRICE = 'price';
38. 38
Cryptocurrency Bot
Deploy da primeira versão do webhook
function priceHandler(assistant) {
const msg = 'Getting current price via Firebase';
assistant.tell(msg);
}
exports.dialogflowFirebaseFulfillment = functions.https.onRequest(
(req, res) => {
const assistant = new DialogflowApp({ request: req, response: res });
const actionMap = new Map();
actionMap.set(ACTION_PRICE, priceHandler);
assistant.handleRequest(actionMap);
}
);
40. 40
Cryptocurrency Bot
Obtendo as variáveis passadas pelo usuário
const ARG_CRYPTO_CURRENCY = 'CryptoCurrency';
const ARG_CURRENCY = 'Currency';
let cryptoCurrency = assistant.getArgument(ARG_CRYPTO_CURRENCY);
let currency = assistant.getArgument(ARG_CURRENCY) || 'USD';
const msg = `Getting current price for ${cryptoCurrency} in ${
currency
} via Firebase`;
🛠
41. 41
Cryptocurrency Bot
Fazendo chamadas a um serviço externo
• Vamos usar o módulo node-fetch
• Padrão fetch do ES6, mais fácil de se utilizar
• API a ser consultada:
• https://api.cryptonator.com/api/ticker/btc-brl
• https://api.cryptonator.com/api/ticker/doge-usd
• https://api.cryptonator.com/api/ticker/eth-eur
• https://api.cryptonator.com/api/ticker/{CryptoCurrency}-{Currency}
• Lembre-se de dar uma resposta ao usuário se algo der errado.
42. 42
Cryptocurrency Bot
Trecho de código para fazer chamada a API
const fetch = require('node-fetch');
const BASE_API_URL = 'https://api.cryptonator.com/api';
const TICKER_METHOD = '/ticker';
const url = BASE_API_URL + TICKER_METHOD + `/${cryptoCurrency}-${currency}`;
fetch(url)
.then(res => res.json())
.then(res => {
// Faz algo com a resposta
})
.catch(res => {
const msg = `Sorry, I cannot get the current price for ${
formattedCryptoCurrency
} right now. Try again later.`;
assistant.tell(msg);
});
45. t
45
Cryptocurrency Bot
[Extra] Contas sem cartão de credito não podem fazer chamada a url externa 😫
const CRYPTO_CURRENCY_PRICES = {
doge: {
brl: 0.01,
eur: 0.00229419,
usd: 0.00271395
},
btc: {
brl: 56200.0,
eur: 13495.25949889,
usd: 16047.28556707
},
eth: {
brl: 1559.53188079,
eur: 372.98900227,
usd: 426.70409479
}
};
46. t
46
Cryptocurrency Bot
[Extra] Contas sem cartão de credito não podem fazer chamada a url externa 😫
const formattedCryptoCurrency =
CRYPTO_CURRENCY_NAMES[cryptoCurrency] || cryptoCurrency;
const formattedCurrency = currency.toUpperCase();
let price = CRYPTO_CURRENCY_PRICES[cryptoCurrency][currency];
const formattedPrice = parseFloat(price).toFixed(2);
const msg = `Right now the price of a ${formattedCryptoCurrency} is ${
formattedPrice
} ${formattedCurrency}.`;
assistant.tell(msg);
47. 47
Cryptocurrency Bot
Eventos e mensagem de inicio de conversa
• Eventos podem acionar Intents
• O mais tradicional é o de boas vindas e inicio
de chat
48. 48
Cryptocurrency Bot
Textos de sugestão
• Use na maior parte das vezes que for esperar
resposta do usuário
• Quando houver poucas escolhas
• Quando houver escolhas demais, mostre as
mais populares
49. 49
Cryptocurrency Bot
Textos de sugestão
const SUGGESTIONS = [
'How much bitcoin costs',
'dogecoin in brl',
'ethereum in eur'
];
function welcomeHandler(assistant) {
const msg = assistant
.buildRichResponse()
.addSimpleResponse(
'Welcome to CryptoCurrency Bot. Do you like to know the price for which
cryptocurrency ?'
)
.addSuggestions(SUGGESTIONS);
assistant.ask(msg);
}
🛠
50. 50
Fim do P2 - Cryptocurrency Bot
Integrando o Dialogflow com Firebase e
Actions on Google
51. 51
P3 - Pizza Bot
Tornando a experiência mais intima
com o usuário
52. 52
Pizza Bot
Crie o Agent no DialogFlow e importe o modelo disponibilizado
https://github.com/alvarowolfx/codelab-aog/03-pizza-bot
54. 54
Pizza Bot
Overview das entidades e intenções
• Entity
• Type, Toppings, Size, Sauce, Crust
• Intent order.pizza
• O usuário escolhe sabor, tamanho, espessura, adicionais, molho e hora
da entrega.
• Usa prompts para perguntar os items obrigatórios
• Intent user.data
• Confirma pedido com os dados do usuário e endereço.
55. 55
Pizza bot
Reforce a conversa lembrando sobre o usuário
function welcomeHandler(assistant) {
const userId = assistant.getUser().userId;
let welcoming = 'Welcome to Mamma Mia Pizza, is awesome to have you
back!';
if (assistant.getLastSeen()) {
welcoming = 'Welcome to Mamma Mia Pizza!';
}
welcoming += ' What pizza do you want today ?';
assistant.ask(welcoming);
}
57. 57
Pizza bot
Suport a diferentes Superficies (Surface API)
let hasScreen =
app.hasSurfaceCapability(app.SurfaceCapabilities.SCREEN_OUTPUT);
let hasAudio =
app.hasSurfaceCapability(app.SurfaceCapabilities.AUDIO_OUTPUT);
58. 58
Pizza bot
Suporte a voz e texto
let welcoming = 'Welcome to Mamma Mia Pizza, is awesome to
have you back!';
if (assistant.getLastSeen()) {
welcoming = 'Welcome to Mamma Mia Pizza!';
}
welcoming += ' What pizza do you want today ?';
assistant.ask({
speech: welcoming + ' Peperoni and Margherita are pretty
popular!',
displayText: welcoming
});
}
🛠
59. 59
Pizza bot
Suporte a voz, texto e sugestões
function isScreenAvailable(assistant) {
return assistant.hasAvailableSurfaceCapabilities(
assistant.SurfaceCapabilities.SCREEN_OUTPUT
);
}
if (isScreenAvailable(assistant)) {
let msg = assistant
.buildRichResponse()
.addSimpleResponse(welcoming)
.addSuggestions(['margherita', 'peperoni', 'marinara']);
assistant.ask(msg);
} else {
assistant.ask({
speech: welcoming + ' Peperoni and Margherita are pretty popular!',
displayText: welcoming
});
}
🛠
60. 60
Pizza Bot
Conheça o usuário, com sua permissão é claro
Google Home Mobile Device
NAME Registered device user’s full
name
Registered device user’s full
name
DEVICE_COARSE_LOCATION Zip code and city N/A
DEVICE_PRECISE_LOCATION Coordinates and street address Coordinates
let permission = app.SupportedPermissions.DEVICE_COARSE_LOCATION;
app.askForPermission('To find pizzas near you', permission);
61. 61
Pizza Bot
function orderPizzaHandler(assistant) {
const order = getOrder(assistant);
assistant.setContext(CTX_ORDER_PIZZA, 5, { order });
if (order.address) {
assistant.askForPermission(
'To complete your order we need you name',
assistant.SupportedPermissions.NAME
);
} else {
assistant.askForPermissions(
'To complete your order we need you name and your location',
[
assistant.SupportedPermissions.DEVICE_PRECISE_LOCATION,
assistant.SupportedPermissions.NAME
]
);
}
} 🛠
63. 63
Pizza Bot
Outros eventos e Intents especiais
• Metodos askWith e askFor
• Permission, List, Carousel, SignIn, etc
64. 64
Pizza Bot
function userDataHandler(assistant) {
let order = assistant.getContextArgument(CTX_ORDER_PIZZA, 'order');
if (order) {
order = order.value;
}
if (assistant.isPermissionGranted()) {
if (!order.address) {
order.location = assistant.getDeviceLocation();
order.address = order.location.address;
}
order.name = assistant.getUserName().displayName;
assistant.tell(
`Your order has been received ${order.name}. Soon your ${
order.type
} pizza will arrive.`
);
}
} 🛠
65. • Cloud-hosted NoSQL database
• Synchronization & conflict
resolution
• Access directly from your app
69. 69
Pizza Bot
> firebase init
> npm install actions-on-google
> firebase deploy
• Criar uma pasta no seu computador e rodar `firebase init`
• Associar com o projeto do Dialogflow
• Instalar libs usando NPM dentro da pasta functions
• Rode `firebase deploy` para enviar o seu código
Configurar projeto local do Firebase
70. 70
Pizza Bot
const admin = require('firebase-admin');
admin.initializeApp(functions.config().firebase);
const db = admin.database();
Necessário quando utiliza APIs diretas do Firebase
71. 71
Pizza Bot
function getUser(userId) {
return db
.ref(`users/${userId}`)
.once('value')
.then(snapshot => snapshot.val());
}
function saveOrder(order) {
return db.ref('orders').push(order);
}
function saveUserData(userId, displayName, location, address) {
delete location.address;
return db.ref(`users/${userId}`).set({
displayName,
location: location || {},
address: address || ''
});
}
Salvando dados do usuário e do pedido no Firebase Database
72. 72
Pizza Bot
const userId = assistant.getUser().userId;
order.name = assistant.getUserName().displayName;
order.userId = userId;
const saveUserPromise = saveUserData(
userId,
order.name,
order.location,
order.adress
);
const saveOrderPromise = saveOrder(order);
Promise.all([saveUserPromise, saveOrderPromise])
.then(() => {
tellOrderInfo(assistant, order);
})
.catch(e => {
assistant.tell('Sorry, but something bad happened with your order.');
});
Salvando o pedido no intent de UserData
🛠
73. 73
Pizza Bot
function orderPizzaHandler(assistant) {
const order = getOrder(assistant);
const userId = assistant.getUser().userId;
getUser(userId).then(user => {
if (user) {
order.userId = userId;
order.name = user.displayName;
order.address = user.address;
order.location = user.location;
saveOrder(order).then(() => {
tellOrderInfo(assistant, order);
});
} else {
/* PEDE PERMISSÃO */
}
});
}
Verifica se já conhece o usuário e não pede por permissões
🛠
78. 78
Pizza Bot
Até mesmo uma aplicação ligada com o bot
https://pizza-a0bec.firebaseapp.com
79. 79
Pizza Bot
> npm build
> firebase deploy
• Depois do `firebase init` o projeto tem uma pasta `public`
• Todo conteúdo dessa pasta fica disponível no Hosting
• HTTPS
• Url *firebaseapp.com
Firebase hosting - Hospedagem de conteúdo estático
80. 80
Fim do P3 - Pizza Bot
Tornando a experiência mais intima
com o usuário