在命令行上运行 Alexa 应用程序。在 Slack 中运行它们。在任何地方运行它们!支持 Amazon Alexa 技能和意图。
$ npm install chatskills
Chatskills 是在 Amazon 之外运行 Alexa 应用程序的一种快速、简单的方法。轻松创建您的技能和意图并直接在命令行上运行它们!
Chatskills 不需要服务器,可以直接在控制台中运行。它还可以在网络、Slack 或任何地方运行。它处理来自多个用户的请求并维护会话内存。当用户开始与其中一项技能对话时,该技能将继续在会话上下文中执行,直到该技能终止。
这是在命令行上运行的 Amazon Alexa 应用程序的外观。
> 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?
在此示例中,用户访问三种不同的技能:你好、星座和有趣。
使用聊天技巧很容易。使用 Alexa 语法添加新技能,然后创建一些意图。这是一个简单的例子。
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 ) ;
} ) ;
在上面的示例中,话语语法自动扩展以匹配以下短语:
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
...
要使用此技能与聊天机器人交互,请说出任何目标短语。在上面的示例中,我们使用了短语“to say hi”,但您可以与任何生成的短语进行匹配。例如:
> 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!
要创建在控制台本地运行的聊天机器人,只需包含一个用于读取输入的循环即可。
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 ) ;
} ) ;
}
如果您在技能中使用异步调用(例如请求等),那么您将需要使用异步循环,而不是上面的 while 循环。这是一个例子。
您不必只使用控制台!您可以在任何地方运行聊天机器人,例如 Slack。请参阅此处查看完整示例。
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 ) ;
}
} ) ;
}
} ) ;
技能是您的聊天机器人可以运行的程序。它们由意图组成,而意图又由话语(与用户输入匹配的短语)、响应和会话内存组成。每个技能都可以访问会话内存,因此您可以存储和检索变量以帮助智能地响应用户。
这是创建名为“星座”的新技能的示例。
var horoscope = chatskills . app ( 'horoscope' ) ;
技能是由意图组成的。这是将用户的输入与一系列话语进行匹配的地方。当找到匹配时,该意图就会被执行。意图可以通过调用req.get('variable')
和req.set('variable', value)
来获取/设置用户会话中的变量。意图可以通过调用res.say('hello')
来输出响应。
以下是为技能“星座”创建新意图的示例。
horoscope . intent ( 'predict' , {
'slots' : { 'SIGN' : 'LITERAL' } ,
'utterances' : [ 'for {signs|SIGN}' ]
} ,
function ( req , res ) {
res . say ( 'Things are looking up today for ' + req . get ( 'SIGN' ) + '.' ) ;
}
) ;
这个意图可以像这样交互:
> chatskills, ask horoscope for Scorpio
Things are looking up today for Scorpio.
有两种方法可以开始运行技能。
启动技能的第一种方法是创建一个意图,例如“跑”。这会让你输入:“chatskills,要求 [skillname] 运行。”。如果意图的返回值为 true(以保持会话处于活动状态),您的技能现在将运行。
“跑”技能的一个例子可以在猜谜游戏中找到。
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 ) ;
}
) ;
启动技能的第二种方法是创建一个启动方法以在启动应用程序时自动运行。然后只需调用chatskills.launch(app)
即可启动您的技能。您可以传递技能或技能名称。您还可以提供可选的唯一 sessionId。
示例: chatskills.launch(app)
或chatskills.launch('horoscope')
或chatskills.launch('horoscope', 'some-unique-id')
。
这是一个完整的例子。
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 ) ;
} ) ;
}
当用户提供输入时,输入会与每项技能及其意图列表进行匹配。找到匹配项后,新会话开始,并且技能开始执行。
当用户开始会话时,激活的技能的意图可以获取/设置会话内的变量值。这允许您存储和检索数据。
当会话对用户开放时,来自用户的所有输入都将定向到激活的技能。以这种方式,用户不需要重新请求技能(“chatskills,问好打招呼”)。相反,用户可以简单地提供文本,该文本将与当前正在执行的技能的意图相匹配。
Intent 可以通过返回true
或调用res.shouldEndSession(false)
来保持会话打开,并通过返回false
或调用res.shouldEndSession(true)
来结束会话。 Intent 也可以省略 return 语句,这与返回 false 相同。
有关使用会话的示例,请参阅星座技能。请注意,意图询问用户一个问题,然后返回 true 以保持会话继续。只有在给出有效响应后,意图才会返回 false,从而结束会话。
总之,当用户会话打开时,来自用户的所有输入都将定向到技能。当用户会话结束时,必须以“chatskills,询问[SKILL]文本”的格式接收来自用户的输入,以执行新技能。
默认会话超时是 1 小时内没有用户输入。要更改会话超时,请设置chatskills.timeout = 3600
,其中该值以秒为单位指定。要禁用会话超时,请将值设置为 0。
默认聊天机器人名称是“chatskills”。所有执行技能的请求都必须以聊天机器人名称开头。例如,“chatskills,问好打招呼”。要自定义聊天机器人名称,请使用以下命令:
chatskills . name ( 'awesome' ) ;
要显示警告和错误,请设置chatskills.verbose = true
。
Chatskills 使用 alexa-app 根据您的意图生成许多示例话语。有关话语的更详细描述,请参见此处。
传递具有两个属性的对象:槽和话语。
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 ) { ... }
) ;
slot 对象是一个简单的名称:类型映射。该类型必须是 Amazon 支持的槽类型之一:LITERAL、NUMBER、DATE、TIME、DURATION
作为亚马逊不再支持的LITERAL
槽类型的替代品,建议使用自定义槽类型来代替。以下是为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!' ) ;
}
) ;
您可以使用语法{-|CustomTypeName}
在话语中包含自定义槽类型。这表明该术语应来自自定义槽类型的值列表。在上面的示例中,话语使用术语{-|DragonType}
,指示术语应来自值列表(如下所示)。对于聊天技能,不需要提供值列表 - 自定义槽类型将接受任何单词并用作其值。
如果发布到 Amazon Alexa 服务,您可以通过指定类型名称和值列表来为DragonType
提供自定义槽类型。例如:
类型: DRAGONTYPE
价值观:
golden
fire
ice
water
snow
请注意,chatskills 和 Amazon Alexa 实际上会接受自定义槽值的任何单词。它不必与值列表中的单词匹配。通过这种方式,自定义槽类型类似于LITERAL
。
话语语法允许您仅使用几个自动扩展的样本来生成许多(数百甚至数千)样本话语。可以在话语数组中传递任意数量的样本话语。以下是一些示例话语宏以及它们将扩展为的内容。
"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}"
这使您可以定义多种方式来说出一个短语,但可以组合成一个示例话语
"{what is the|what's the|check the} status"
=>
"what is the status"
"what's the status"
"check the status"
捕获数字槽值时,生成许多具有不同数值的样本话语会很有帮助
"buy {2-5|NUMBER} items"
=>
"buy {two|NUMBER} items"
"buy {three|NUMBER} items"
"buy {four|NUMBER} items"
"buy {five|NUMBER} items"
数字范围也可以逐步增加
"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"
多个意图可能使用相同的可能值列表,因此您希望将它们定义在一个位置,而不是在每个意图模式中。使用应用程序的词典。
app.dictionary = {"colors":["red","green","blue"]};
...
"my favorite color is {colors|FAVEORITE_COLOR}"
"I like {colors|COLOR}"
您可以通过处理响应方法中返回的卡片对象来显示 Amazon Alexa Home Cards。使用 Alexa-app 时,主页卡将显示在您移动设备上的 Amazon Alexa 应用程序中。使用 chatskills 时,可以在chatskills.respond()
回调方法中处理 home 卡,该方法返回两个参数: response
和card
。
使用卡片对象,您可以按照您希望的任何方式显示卡片的文本和图像。例如,如果在 Slack 中托管您的聊天技能应用程序,您可能希望将图像显示为嵌入式媒体。同样,如果在控制台上作为文本聊天机器人托管,您可能只想将卡片输出为文本。
下面是一个例子。
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 + ']' ) ;
}
} ) ;
麻省理工学院
科里·贝克尔 http://www.primaryobjects.com/kory-becker