Execute aplicativos Alexa na linha de comando. Execute-os no Slack. Execute-os em qualquer lugar! Suporta habilidades e intenções do Amazon Alexa.
$ npm install chatskills
Chatskills é uma maneira rápida e fácil de executar aplicativos Alexa fora da Amazon. Crie facilmente suas habilidades e intenções e execute-as diretamente na linha de comando!
Chatskills não requer servidor e pode ser executado diretamente no console. Ele também pode ser executado na web, no Slack ou em qualquer lugar. Ele lida com solicitações de vários usuários e mantém a memória da sessão. Quando um usuário inicia uma conversa com uma das habilidades, a habilidade continua a ser executada dentro de um contexto de sessão, até que seja encerrada.
Esta é a aparência de um aplicativo Amazon Alexa, executado na linha de comando.
> chatskills, ask hello to say hi.
Hello, World!
> chatskills, ask horoscope for Scorpio.
Things are looking up today for Scorpio.
> chatskills, ask funny to tell me a joke
Knock knock.
> who's there?
Banana.
> banana who
Knock knock.
> whos there
Orange.
> orange who?
Orange you glad I didn't say banana?
Neste exemplo, o usuário acessa três habilidades diferentes: olá, horóscopo e engraçado.
Usar habilidades de bate-papo é fácil. Use a sintaxe Alexa para adicionar uma nova habilidade e, em seguida, crie algumas intenções. Aqui está um exemplo simples.
var chatskills = require ( 'chatskills' ) ;
// Create a skill.
var hello = chatskills . app ( 'hello' ) ;
// Create an intent.
hello . intent ( 'helloWorld' , {
'slots' : { } ,
'utterances' : [ '{to |}{say|speak|tell me} {hi|hello|howdy|hi there|hiya|hi ya|hey|hay|heya}' ]
} ,
function ( req , res ) {
res . say ( 'Hello, World!' ) ;
}
) ;
// Respond to input.
chatskills . respond ( 'chatskills, ask hello to say hi' , function ( response ) {
console . log ( response ) ;
} ) ;
No exemplo acima, a gramática das expressões se expande automaticamente para corresponder às seguintes frases:
helloWorld to say hi
helloWorld say hi
helloWorld to speak hi
helloWorld speak hi
helloWorld to tell me hi
helloWorld tell me hi
helloWorld to say hello
helloWorld say hello
helloWorld to speak hello
helloWorld speak hello
helloWorld to tell me hello
helloWorld tell me hello
helloWorld to say howdy
...
Para interagir com o chatbot usando esta habilidade, diga qualquer uma das frases-alvo. No exemplo acima, usamos a frase “para dizer oi”, mas você pode fazer a correspondência com qualquer uma das frases geradas. Por exemplo:
> chatskills, ask hello to tell me hi
Hello, World!
> chatskills, ask hello to say hello
Hello, World!
> chatskills, ask hello to say howdy
Hello, World!
Para criar um chatbot que rode localmente no console, basta incluir um loop para leitura de entrada.
var readlineSync = require ( 'readline-sync' ) ;
// Console client.
var text = ' ' ;
while ( text . length > 0 && text != 'quit' ) {
text = readlineSync . question ( '> ' ) ;
// Respond to input.
chatskills . respond ( text , function ( response ) {
console . log ( response ) ;
} ) ;
}
Se você estiver usando chamadas assíncronas em suas habilidades (como solicitação, etc.), você desejará usar um loop assíncrono, em vez do loop while acima. Aqui está um exemplo.
Você não precisa usar apenas o console! Você pode executar seu chatbot em qualquer lugar, como o Slack. Veja aqui um exemplo completo.
var SlackBot = require ( 'slackbots' ) ;
var bot = new SlackBot ( { token : token , name : 'awesome' } ) ;
// Listen to slack messages.
bot . on ( 'message' , function ( message ) {
// Reply to humans.
if ( message . type == 'message' && message . text && message . subtype != 'bot_message' ) {
var author = getUserById ( message . user ) ;
var channel = getChannelById ( message . channel ) ;
// Respond to input, use author.name as the session id.
chatskills . respond ( message . text , author . name , function ( response ) {
if ( channel ) {
// Public channel message.
bot . postMessageToChannel ( channel . name , response ) ;
}
else {
// Private message.
bot . postMessageToUser ( author . name , response ) ;
}
} ) ;
}
} ) ;
Habilidades são programas que seu chatbot pode executar. Eles consistem em intenções, que são compostas por enunciados (frases correspondentes à entrada do usuário), respostas e memória de sessão. Cada habilidade pode acessar a memória da sessão, para que você possa armazenar e recuperar variáveis para ajudar a responder de forma inteligente ao usuário.
Aqui está um exemplo de criação de uma nova habilidade, chamada “horóscopo”.
var horoscope = chatskills . app ( 'horoscope' ) ;
Habilidades são compostas de intenções. É aqui que a entrada do usuário é comparada com uma série de declarações. Quando uma correspondência é encontrada, essa intenção é executada. Uma intenção pode obter/definir variáveis na sessão do usuário chamando req.get('variable')
e req.set('variable', value)
. Uma intenção pode gerar uma resposta chamando res.say('hello')
.
Aqui está um exemplo de criação de uma nova intenção para a habilidade “horóscopo”.
horoscope . intent ( 'predict' , {
'slots' : { 'SIGN' : 'LITERAL' } ,
'utterances' : [ 'for {signs|SIGN}' ]
} ,
function ( req , res ) {
res . say ( 'Things are looking up today for ' + req . get ( 'SIGN' ) + '.' ) ;
}
) ;
Essa intenção pode ser interagida assim:
> chatskills, ask horoscope for Scorpio
Things are looking up today for Scorpio.
Existem duas maneiras de começar a executar uma habilidade.
A primeira maneira de iniciar uma habilidade é criar uma intenção como “executar”. Isso permitiria que você digitasse: "chatskills, peça a [skillname] para executar.". Desde que a intenção tenha um valor de retorno verdadeiro (para manter a sessão ativa), sua habilidade agora estará em execução.
Um exemplo de habilidade de "correr" pode ser encontrado no jogo de adivinhação.
app . intent ( 'run' , {
"slots" : { } ,
"utterances" : [ "{to|} {run|start|go|launch}" ]
} , function ( req , res ) {
var prompt = "Guess a number between 1 and 100!" ;
res . say ( prompt ) . reprompt ( prompt ) . shouldEndSession ( false ) ;
}
) ;
A segunda maneira de iniciar uma habilidade é criar um método de inicialização para ser executado automaticamente ao iniciar seu aplicativo. Em seguida, basta ligar para chatskills.launch(app)
para iniciar sua habilidade. Você pode passar a habilidade ou o nome da habilidade. Você também pode fornecer um sessionId exclusivo opcional.
Exemplo: chatskills.launch(app)
ou chatskills.launch('horoscope')
ou chatskills.launch('horoscope', 'some-unique-id')
.
Aqui está um exemplo completo.
var chatskills = require ( './lib/chatskills' ) ;
var readlineSync = require ( 'readline-sync' ) ;
// Create a skill.
var hello = chatskills . app ( 'hello' ) ;
// Launch method to run at startup.
hello . launch ( function ( req , res ) {
res . say ( "Ask me to say hi!" ) ;
// Keep session open.
res . shouldEndSession ( false ) ;
} ) ;
// Create an intent.
hello . intent ( 'helloWorld' , {
'slots' : { } ,
'utterances' : [ '{to |}{say|speak|tell me} {hi|hello|howdy|hi there|hiya|hi ya|hey|hay|heya}' ]
} ,
function ( req , res ) {
res . say ( 'Hello, World!' ) ;
}
) ;
// Start running our skill.
chatskills . launch ( hello ) ;
// Console client.
var text = ' ' ;
while ( text . length > 0 && text != 'quit' ) {
text = readlineSync . question ( '> ' ) ;
// Respond to input.
chatskills . respond ( text , function ( response ) {
console . log ( response ) ;
} ) ;
}
Quando um usuário fornece uma entrada, a entrada é comparada com cada habilidade e sua lista de intenções. Quando uma correspondência é encontrada, uma nova sessão é iniciada e a habilidade começa a ser executada.
Quando uma sessão é iniciada para um usuário, a intenção da habilidade ativada pode obter/definir valores variáveis dentro da sessão. Isso permite armazenar e recuperar dados.
Enquanto uma sessão estiver aberta para um usuário, todas as entradas do usuário serão direcionadas para a habilidade ativada. Dessa forma, o usuário não precisa solicitar novamente uma habilidade (“chatskills, peça olá para dizer oi”). Em vez disso, o usuário pode simplesmente fornecer um texto, que será comparado com as intenções da habilidade em execução no momento.
Uma intenção pode manter uma sessão aberta retornando true
ou chamando res.shouldEndSession(false)
e encerrar uma sessão retornando false
ou chamando res.shouldEndSession(true)
. Uma intenção também pode omitir uma instrução return, que é o mesmo que retornar falso.
Para obter um exemplo de sessão, consulte a habilidade do horóscopo. Observe que a intenção faz uma pergunta ao usuário e depois retorna true para continuar a sessão. A intenção só retorna falso quando uma resposta válida é dada, encerrando assim a sessão.
Em resumo, quando uma sessão de usuário é aberta, todas as entradas do usuário são direcionadas para a habilidade. Quando uma sessão do usuário é encerrada, a entrada do usuário deve ser recebida no formato "chatskills, ask [SKILL] text", para executar uma nova habilidade.
O tempo limite padrão da sessão é de 1 hora sem nenhuma entrada do usuário. Para alterar o tempo limite da sessão, defina chatskills.timeout = 3600
, onde o valor é especificado em segundos. Para desativar o tempo limite da sessão, defina o valor como 0.
O nome padrão do chatbot é "chatskills". Todas as solicitações para executar uma habilidade devem começar com o nome do chatbot. Por exemplo, "chatskills, peça olá para dizer oi". Para personalizar o nome do chatbot, use o seguinte:
chatskills . name ( 'awesome' ) ;
Para exibir avisos e erros, defina chatskills.verbose = true
.
Chatskills usa alexa-app para gerar muitos exemplos de declarações de suas intenções. Para uma descrição mais detalhada dos enunciados, veja aqui.
Passe um objeto com duas propriedades: slots e enunciados.
app . intent ( 'sampleIntent' ,
{
"slots" : { "NAME" : "LITERAL" , "AGE" : "NUMBER" } ,
"utterances" : [ "my {name is|name's} {names|NAME} and {I am|I'm} {1-100|AGE}{ years old|}" ]
} ,
function ( request , response ) { ... }
) ;
O objeto slots é um mapeamento simples de Nome:Tipo. O tipo deve ser um dos tipos de slot suportados pela Amazon: LITERAL, NUMBER, DATE, TIME, DURATION
Como substituto do tipo de slot LITERAL
, que não é mais compatível com a Amazon, é recomendável usar tipos de slot personalizados em seu lugar. Aqui está um exemplo de definição de um tipo de slot personalizado para DragonType
.
app . intent ( 'attack' ,
{
'slots' : { 'DragonType' : 'DRAGONTYPE' } ,
'utterances' : [ '{attack|fight|hit|use} {sword|dagger|wand} on {-|DragonType} dragon' ]
} , function ( request , response ) {
response . say ( 'You are attacking the ' + request . slot ( 'DragonType' ) + ' dragon!' ) ;
}
) ;
Você pode incluir tipos de slots personalizados em declarações usando a sintaxe {-|CustomTypeName}
. Isso indica que o termo deve vir de uma lista de valores para o tipo de slot customizado. No exemplo acima, a expressão usa o termo {-|DragonType}
, indicando que um termo deve vir da lista de valores (mostrada abaixo). Para chatskills, não é necessário fornecer uma lista de valores - qualquer palavra será aceita para um tipo de slot personalizado e usada como seu valor.
Se estiver publicando no serviço Amazon Alexa, você forneceria os tipos de slot personalizados para DragonType
especificando o nome do tipo e uma lista de valores. Por exemplo:
Tipo: DRAGONTYPE
Valores:
golden
fire
ice
water
snow
Observe que chatskills e Amazon Alexa aceitarão qualquer palavra para o valor do slot personalizado. Não precisa corresponder a uma palavra da lista de valores. Desta forma, os tipos de slots personalizados são semelhantes a LITERAL
.
A sintaxe de enunciados permite gerar muitos (centenas ou até milhares) de exemplos de enunciados usando apenas alguns exemplos que são expandidos automaticamente. Qualquer número de declarações de amostra pode ser passado na matriz de declarações. Abaixo estão alguns exemplos de macros de expressões e para onde elas serão expandidas.
"my favorite color is {red|green|blue|NAME}"
=>
"my favorite color is {red|NAME}"
"my favorite color is {green|NAME}"
"my favorite color is {blue|NAME}"
Isso permite definir várias maneiras de dizer uma frase, mas combinadas em um único exemplo de expressão
"{what is the|what's the|check the} status"
=>
"what is the status"
"what's the status"
"check the status"
Ao capturar um valor de slot numérico, é útil gerar muitos exemplos de expressões com valores numéricos diferentes
"buy {2-5|NUMBER} items"
=>
"buy {two|NUMBER} items"
"buy {three|NUMBER} items"
"buy {four|NUMBER} items"
"buy {five|NUMBER} items"
Os intervalos numéricos também podem aumentar em etapas
"buy {5-20 by 5|NUMBER} items"
=>
"buy {five|NUMBER} items"
"buy {ten|NUMBER} items"
"buy {fifteen|NUMBER} items"
"buy {twenty|NUMBER} items"
"what is your {favorite |}color"
=>
"what is your color"
"what is your favorite color"
Várias intenções podem usar a mesma lista de valores possíveis, portanto, você deseja defini-los em um só lugar, não em cada esquema de intenção. Use o dicionário do aplicativo.
app.dictionary = {"colors":["red","green","blue"]};
...
"my favorite color is {colors|FAVEORITE_COLOR}"
"I like {colors|COLOR}"
Você pode exibir os Amazon Alexa Home Cards manipulando o objeto card retornado no método de resposta. Ao usar o aplicativo Alexa, o cartão inicial será exibido no aplicativo Amazon Alexa no seu dispositivo móvel. Ao usar chatskills, o cartão inicial pode ser tratado no método de retorno de chamada chatskills.respond()
, que retorna dois argumentos: response
e card
.
Usando o objeto cartão, você pode exibir o texto e a imagem do cartão da maneira que desejar. Por exemplo, se estiver hospedando seu aplicativo chatskills no Slack, você pode querer mostrar a imagem como mídia incorporada. Da mesma forma, se estiver hospedando um chatbot de texto no console, você pode simplesmente querer gerar o cartão como texto.
Abaixo está um exemplo.
app . intent ( 'example' , {
"slots" : { } ,
"utterances" : [ "show a card" ]
} , function ( req , res ) {
// Show home card in Alexa app.
res . card ( {
type : 'Standard' ,
title : 'My Awesome Card' , // this is not required for type Simple or Standard
text : 'This is an example of an Alexa home card.' ,
image : { // image is optional
smallImageUrl : 'http://www.yoursite.com/image.jpg' , // required
largeImageUrl : null
}
} ) ;
} ) ;
// Respond to input.
chatskills . respond ( text , function ( response , card ) {
if ( ! card ) {
// Text response from res.say() method.
console . log ( response ) ;
}
else {
// Home card response from res.card() method.
console . log ( '[DISPLAYING CARD: Title=' + card . title + ', Text=' + card . text + ']' ) ;
}
} ) ;
MIT
Kory Becker http://www.primaryobjects.com/kory-becker