adellantado / bot-template-framework
轻松构建机器人场景并在Botman上运行
Requires
- botman/botman: ^2.3
README
使用Botman简化聊天机器人开发。使用一个场景文件,您可以使机器人工作。
您可以在这里找到可下载的聊天机器人示例。
例如,简单的Telegram Hello World聊天机器人
{
"name": "Hello World Chatbot",
"fallback": {
"name": "Hello Block",
"type": "block"
},
"blocks": [
{
"name": "Hello Block",
"type": "text",
"content": "Hello World!",
"template": "Hi;Hello;What's up;Good day;/start"
}
],
"drivers": [
{
"name": "Telegram",
"token": "590000000:AAHp5XAGrpIyZynnIjcLKJSwUpPu0b1FXEY"
}
]
}
用法
-
使用composer安装包
composer require adellantado/bot-template-framework
-
将您的聊天机器人场景模板template.json文件添加到storage/app
-
添加驱动到配置文件
$this->app->singleton('botman', function ($app) { $config = TemplateEngine::getConfig(file_get_contents(storage_path('app/template.json'))); return BotManFactory::create($config); });
-
在Botman之前调用listen()到模板引擎
$botman = resolve('botman'); $templateEngine = new TemplateEngine(file_get_contents(storage_path('app/template.json')), $botman); $templateEngine->listen(); // Start listening $botman->listen();
场景文件结构
// template.json
{
"name": "Chatbot Name",
"fallback": "This is fallback message",
"blocks": [
{
"name": "Simple Text Block",
"type": "text",
"content": "Hi, this is simple text message"
},
{
...
}
],
"drivers": [
{
"name": "Telegram",
"token": "<your-telegram-token>"
},
{
...
}
]
}
使用块,您可以描述要执行的动作和数据,例如发送文本或图像,请求用户的位置或提问
在驱动程序中,您设置机器人想要工作的平台,例如Facebook或Telegram
块
有21种类型的块
text, image, menu, audio, video, file, location, attachment, carousel, list, request, ask, intent, if, method, extend, idle, save, random, payload, validate
每个块都扩展了抽象块,它具有以下属性
{
"name": "Block Name",
"type": "idle",
"template": "Image;Show image;Want to see an image",
"typing": "1s",
"drivers": "any;!telegram",
"locale": "en",
"options": {"someProperty": "someValue"}
"next": "Next Block Name"
},
name
- (必需) 块的名称,用于标识块;
type
- (必需) 块的类型(例如图像,文本 ..);
template
- (可选) 识别聊天机器人会对其做出反应的关键短语(请参阅$botman->hear());
typing
- (可选) 在运行块之前在聊天中显示打字效果;
drivers
- (可选) 对于某些驱动程序排除/包含块执行(例如,'any'或'*' - 对所有驱动程序运行,'facebook;telegram' - 对telegram和facebook运行,'any;!telegram' - 对任何驱动程序运行,但不是telegram);
locale
- (可选) 将块分配给特定区域设置,类似于命名空间。例如,您用区域设置'zh'描述块,然后复制带有区域设置'ge'的翻译块;
options
- (可选) 设置某些特定于驱动程序的属性;
next
- (可选) 执行链中下一个块要执行的名字
文本块
发送简单的文本响应
{
"name": "Greetings",
"type": "text",
"content": "Hi! Nice to meet you {{user.firstName}};Hi there, {{user.firstName}}",
"template": "Hello;Hi;Good day",
"typing": "1s"
}
注意:了解变量
图像块
使用描述和按钮或没有按钮绘制图像
{
"name": "Logo",
"type": "image",
"content": {
"text": "This is the logo;Our logo is following",
"url": "https://logo.com/logo.jpg",
"buttons": {
"Callback": "Learn More"
}
},
"template": "Show me the logo"
}
url
- (必需) 图像URL;
text
- (可选) 图像描述;
buttons
- (可选) 在图像下添加按钮;
注意:了解菜单块
菜单块
1.显示按钮
{
"name": "Menu Block",
"type": "menu",
"content": {
"text": "This is a simple menu; This is a menu",
"buttons": [
{"Callback": "Learn More"},
{
"https://website.com/": "Visit Website",
"Ask Support": "Ask Support"
}
]
}
}
注意:按钮可能因驱动程序而异(在官方文档中了解更多信息)
例如:Telegram
Format #1
"buttons": [
{ This is a simple menu
"https://website.com/": "Visit Website", ==> ------------------------------------
"Ask Support": "Ask Support" | Visit Website | Ask Support |
} ------------------------------------
]
Format #2
"buttons": [
{ This is a simple menu
"https://website.com/": "Visit Website" ==> ---------------------
},{ | Visit Website |
"Ask Support": "Ask Support" ---------------------
} | Ask Support |
] ---------------------
例如:Facebook - 在一个菜单中只有3个按钮。
2.显示快速按钮
{
"name": "Quick Menu Block",
"type": "menu",
"mode": "quick",
"content": {
"text": "This is a quick menu",
"buttons": [
{
"https://website.com/": "Visit Website",
"Ask Support": "Ask Support"
}
]
}
}
音频,视频和文件块
直接将视频,音频和文件拖到聊天中
{
"name": "File Block",
"type": "file",
"content": {
"text": "Download the file",
"url": "https://sample.com/doc.pdf"
}
}
url
- (必需) 文件,视频或音频链接;
text
- (可选) 描述;
位置块
从用户请求位置
{
"name": "Location Test",
"type": "location",
"content": "Please, share your location by clicking button below;Send your location",
"template": "share location",
"result": {
"save": "{{location}}"
}
}
content
- (必需) 描述;
result.save
- (必需) 将数据以json {latitude:.., longitude: ..} 的形式保存到变量中;
注意:了解变量
附件块
从用户请求图像,视频,音频或文件
{
"name": "Attachment Test",
"type": "attachment",
"mode": "image",
"content": "Please, make a photo to verify your identity",
"result": {
"save": "{{photo}}"
}
}
mode
- (可选) 可以为image,video,file,audio,如果没有提供模式,则默认为file;
轮播和列表块
绘制轮播或组件列表
{
"name": "List Test",
"type": "list",
"content": [
{
"url": "https://image.com/img1.jpg",
"title": "Component #1",
"description": "This is component #3"
},
{
"url": "https://image.com/img2.jpg",
"title": "Component #2",
"description": "This is component #3"
},
{
"url": "https://image.com/img3.jpg",
"title": "Component #3",
"description": "This is component #3",
"buttons": {
"example btn": "Example Button"
}
}
],
}
注意:某些平台可能不支持列表或轮播组件
请求块
执行自定义GET/POST请求
{
"name": "Tell a joke",
"type": "request",
"method": "GET",
"url": "http://api.icndb.com/jokes/random",
"result": {
"field": "value.joke",
"save": "{{joke}}"
},
"template": "Tell a joke;Joke;Do you know some jokes?"
}
result.field
- (可选) 从结果中读取数据;
result.save
- (可选) 将结果保存到变量中;
注意:了解变量
询问块
提问并等待用户回答
{
"name": "Ask Phone",
"type": "ask",
"content": "Can you left us your phone to contant you only in case of urgency?",
"validate": "number|min:10",
"errorMsg": "This is custom error message occurs if validation hasn't been passed",
"skip": "pause;skip",
"stop": "stop;off",
"result": {
"prompt": "yes;no"
},
"next": {
"yes": "Type Phone Block",
"no": "Ask Email Block",
"fallback": "Ask Email Block"
}
}
validate
- (可选) 验证用户输入,不保存变量并在验证未通过时重复问题。可能的值:number
(验证整数),email
(发送快速按钮用于Facebook并验证电子邮件),url
,phone
(发送快速按钮用于Telegram和Facebook),image
,file
,video
,audio
,location
(发送快速按钮用于Telegram和Facebook),confirm
(需要两次输入),size:<number>
,min:<number>
,max:<number>
(精确/最小/最大字母),numeric
(验证浮点值),digits
,non-free-input
和free-input
(对于使用文本输入栏输入的值),/^[0-9]*$/
(任何正则表达式,类似于这个);
errorMsg
- (可选) 验证错误信息;
skip
,stop
- (可选) 暂停/停止对话关键词;
result.prompt
- (可选) 显示快速按钮;
next.<user answer>
- (可选) 根据用户回答,运行下一个块('fallback' - 保留用于列表中未包含的任何回答)。
注意:规则可以用 "|" 符号组合(例如:numeric|min:10|max:12)
注意:了解更多关于结果的信息
注意:您需要在Botman网站上了解如何设置持久缓存(如Redis)
意图块
{
"name": "AlexaTest",
"provider": "alexa",
"type": "intent",
"template": "BeverageIntent",
"content": "well done; cool",
"result": {
"field": "beverage",
"save": "{{user_beverage}}"
},
"next": {
"coffee": "Coffee Card Block",
"tea": "Tea Card Block",
"default": "Repeat Question Block"
}
}
provider
- (必需) 可以是 'alexa'、'wit' 或 'dialogflow';
template
- (必需) Alexa和wit的意图名称,dialogflow的动作名称;
content
- (必需(alexa)| 可选(dialogflow)| 可选(wit)) 回答到聊天;
result.field
- (可选) 实体或槽位名称;
result.save
- (可选) 保存实体或槽位值;
next.<entity_value>
- (可选) 通过实体或槽位值触发下一个块;
注意:您应该使用Amazon Alexa控制台、wit或dialogflow控制台来运行此块;
注意:对于dialogflow v2,需要官方PHP库 - google/cloud-dialogflow;
注意:在dialogflow执行后调用块,请在dialogflow控制台中添加下一个有效负载 - {"next": "MyNextBlock"};
如果块
{
"name": "Comparison Test",
"type": "if",
"next": [
["{{var}}", "==", "1", "Block 1"],
["{{var}}", "<", "1", "Block 2"],
["{{var}}", ">", "1", "Block 3"],
]
}
例如,当 {{var}} == 1
时简单地调用 "块 1",当 {{var}} < 1
时调用 "块 2",当 {{var}} > 1
时调用 "块 3"。;
支持的运算符:==
、!=
、>
、>=
、<
、<=
方法块
简单地从您自己的策略调用方法
{
"name": "Test method",
"type": "method",
"method": "myMethod"
}
method
- (必需) 方法名称
注意:对于每个驱动程序,您应该在App\Strategies文件夹中有策略类,其中包含'myMethod'函数
namespace App\Strategies;
use BotTemplateFramework\Strategies\Strategy;
class Telegram extends Strategy {
function myMethod() {
$this->bot->reply('This is my method replies');
}
}
扩展块
简单地覆盖父块属性。当您需要制作非常相似的块但有微小变化时非常有用。
{
"name": "Oysters Extended",
"type": "extend",
"base": "Oysters Block",
"content": {
"url": "https://upload.wikimedia.org/wikipedia/commons/thumb/3/37/Oysters_p1040741.jpg/330px-Oysters_p1040741.jpg"
}
},
{
"name": "Oysters Block",
"type": "image",
"template": "Oysters",
"content": {
"url": "https://upload.wikimedia.org/wikipedia/commons/thumb/b/b0/Crassostrea_gigas_p1040848.jpg/450px-Crassostrea_gigas_p1040848.jpg"
}
}
base
- (必需) 父块名称
例如,通过覆盖 content
字段扩展 "Oysters Block"。
注意:不要扩展 intent
和 ask
块;
注意:仅扩展第一层嵌套的字段(如 type
、content
、next
,但无法仅从图像内容中扩展 url
(第二层嵌套)字段);
空闲块
简单地不做任何事情,但可以用来调用下一个块
{
"name": "Does Nothing",
"type": "idle",
"template": "call idle",
"typing": "1s",
"next": "Next Block"
}
保存块
简单地保存一些值(包括现有变量的值)到某个变量
{
"name": "Saves to Variable",
"type": "save",
"value": "123",
"variable": "{{someVar}}"
}
随机块
{
"name": "Random Block",
"type": "random",
"next": [
["20%", "Block 1"],
["30%": "Block 2"],
["40%": "Block 3"]
]
}
验证块
验证变量并在成功时执行带有 'true' 键的块
{
"name": "Validate Block",
"type": "validate",
"validate": "number|size:5",
"variable": "{{myVar}}",
"next": {
"true": "Block 1",
"false": "Block 2"
}
}
variable
- (必需) 变量名称;
validate
- (必需) 可能的值:number
(验证整数),email
(发送快速按钮用于Facebook并验证电子邮件),url
,phone
(发送快速按钮用于Telegram和Facebook),image
,file
,video
,audio
,location
(发送快速按钮用于Telegram和Facebook),size:<number>
,min:<number>
,max:<number>
(精确/最小/最大字母),numeric
(验证浮点值),digits
,non-free-input
和free-input
(对于使用文本输入栏输入的值),/^[0-9]*$/
(任何正则表达式,类似于这个);
有效负载块
向消息传递者发送有效负载
{
"name": "Test payload",
"type": "payload",
"payload": {
"text": "This is an inline keyboard example",
"reply_markup": {
"inline_keyboard": [
[
{
"text": "Button1",
"callback_data": "callback1"
},
{
"text": "Button2",
"callback_data": "callback2"
}
]
]
}
},
"drivers": "telegram"
}
payload
- (必需) 要发送的有效载荷;
drivers
- (必需) 设置精确的驱动程序非常重要,因为每个驱动程序都有一个独特的数据包
注意:学习适当信使的API文档
驱动程序
在使用这里的驱动程序之前,首先您需要为Botman安装适当的驱动程序。可用的驱动程序如下
Facebook, Telegram, Skype, Dialogflow, Alexa, Viber, Web, Chatbase, Wit
注意:由于BotMan没有附带Viber驱动程序,您需要运行
composer require adellantado/botman-viber-driver,
注意:由于BotMan没有附带Chatbase,您需要运行
composer require bhavyanshu/chatbase-php
示例
"drivers": [
{
"name": "Dialogflow",
"token": "b71dd842a2eb43434f4fg5eee55"
},
{
"name": "Web",
"token": "web"
},
{
"name": "Chatbase",
"token": "b71dd-842a-2eb4-3434-fw32e3233"
},
{
"name": "Facebook",
"app_secret": "FACEBOOK_APP_SECRET",
"token": "FACEBOOK_TOKEN",
"verification": "FACEBOOK_VERIFICATION",
"config": "true",
"events": {
"delivery": "BlockExecOnDeliveryEvent",
"read": "BlockExecOnReadEvent"
}
}
]
name
- (必需) 驱动程序名称
token
- (必需/可选) 用于Telegram、Viber、Dialogflow、Chatbase、Web(可选,默认令牌为'web')。字段:verification、token、app_secret - 用于Facebook;app_id、app_key - 用于Skype;project_id、key_path、version=2 - 用于Dialogflow v2 API。
config
- (可选) 表示字段应从env()中读取
events
- (可选) 通过事件触发阻塞。例如,在Facebook中“delivery”事件,触发名为“BlockExecOnDeliveryEvent”的阻塞。请参阅Botman中的事件。
变量
变量存储在Botman userStorage()中,所以请确保将正确的存储传递给Botman实例。
BotManFactory::create($config, null, null, new FileStorage(__DIR__));
使用变量
使用括号中的变量
{{my_variable}}
使用'result.save'字段与请求、询问、意图块一起保存变量。并且通过使用特殊的保存块。
预定义变量
- {{user.id}}- {{user.firstName}}
- {{user.lastName}}
- {{bot.name}}
- {{bot.driver}}
- {{message}}(这是用户发送的最后一条消息)
结果
有5个返回结果的块:location
、attachment
、request
、ask
、intent
对于每个,您都可以应用
"result": {
"save": "{{my_variable}}"
},
其中三个(request
、ask
、intent
)的next
字段可能会根据结果值受到影响
例如,在这个例子中,触发Type Phone Block
,然后结果是字符串值yes
,触发Ask Email Block
- 当结果是no
以及既不是yes
也不是no
时
"next": {
"yes": "Type Phone Block",
"no": "Ask Email Block",
"fallback": "Ask Email Block"
}
注意:对于intent
块,结果是实体值(Dialogflow)或插槽值(Alexa),其名称由field
字段设置
询问结果
使用prompt
字段添加快速按钮并简化用户回复,如下例所示
{
"name": "Ask Phone",
"type": "ask",
"content": "Can you left us your phone to contant you only in case of urgency?",
"result": {
"prompt": "yes;no"
},
"next": {
"yes": "Type Phone Block",
"no": "Ask Email Block",
"fallback": "Ask Email Block"
}
}
请求结果
使用field
字段快速从JSON响应中提取数据,如下所示
{
"name": "Tell a joke",
"type": "request",
"method": "GET",
"url": "http://api.icndb.com/jokes/random",
"result": {
"field": "value.joke",
"save": "{{joke}}"
},
"template": "Tell a joke;Joke;Do you know some jokes?"
}
响应看起来像这样
{
"type": "success",
"value": {
"id": 495,
"joke": "Chuck Norris doesn't needs try-catch, exceptions are too afraid to raise.",
"categories": ["nerdy"]
}
}
回退
回退可以设置为3种不同的格式
1.文本
"fallback": "This is default reply messsage"
2.Dialogflow
"fallback": {
"type": "dialogflow",
"default": "This is default reply message when no answer from Dialogflow"
}
3.块
"fallback": {
"name": "Hello Block",
"type": "block"
}
构建器
使用构建器很简单,以下是一个简单聊天机器人的示例
$template = (new Template('Beedevs Chatbot'))
->addDrivers([
new TelegramDriver('123123wefwef:wefonwewerwerwerw')
])
->addFallbackMessage('This is default message')
->addBlocks([
(new TextBlock())
->text('Hi! Welcome to beedevs chatbot')
->template([
'Hello',
'Hi',
'What\'s up',
'Good day'
])->typing(1)
->next(
$about = (new ImageBlock())
->url('https://pbs.twimg.com/profile_images/799239637684355072/SGIDpffc_400x400.jpg')
->buttons([
(new Button('Visit'))->url("https://beedevs.com")
])
->text('Beedevs is a chatbot development studio. Want to know more? Visit our website!')
->template([
'About'
])
),
$about,
(new RequestBlock())
->url('http://api.icndb.com/jokes/random')
->method('GET')
->result((new RequestResult())
->field(['value', 'joke'])
->save('{{joke}}')
)->template([
'Tell a joke',
'Joke',
'Do you know some jokes?'
])
->next(
$joke = (new TextBlock())
->text('{{joke}}')
->typing(1)
),
$joke,
(new MenuBlock())
->text('Menu')
->buttons([
(new Button('Website'))->url("https://beedevs.com"),
(new Button('About'))->callback('About')
])
->template([
'Show menu',
'Menu',
'Main menu'
]),
(new ListBlock())->items([
(new ListItem('ListItem1', 'https://static.addtoany.com/images/dracaena-cinnabari.jpg'))
->buttons([
(new Button('About'))->callback('About')
])
->description('National Park'),
(new ListItem('ListItem2', 'https://cloud.google.com/blog/big-data/2016/12/images/148114735559140/image-classification-1.png'))
->buttons([
(new Button('About'))->callback('About')
])
->description('Sunflower fields at summer time')
])->template([
'List',
'Show list'
])
]);
然后只需将您的$template
插入到引擎中,如下所示
$templateEngine = new TemplateEngine($template, $botman);
$templateEngine->listen();
// Start listening
$botman->listen();
在引擎内部,它将其转换为与您之前使用的类似JSON的数组,但使用构建器,您的功能在便利性和开发速度方面得到提升。