Botml é uma linguagem de marcação declarativa e poderosa para projetar chatbots modernos (também conhecidos como bots de conversação).
Qualquer pessoa (desenvolvedores e não desenvolvedores) pode usá-lo para criar e ensinar bots como se comportar . Defina o comportamento do seu chatbot usando a formatação certa e inicie a conversa rapidamente. Veja você mesmo: um bot de calculadora escrito em apenas duas linhas.
Este projeto usa nó e npm. Vá verificá-los se você não os tiver instalados localmente.
$ npm i -g botml
Isso instalará o pacote do nó botml
e o cliente bot
.
Opcionalmente, se você usar o Atom como editor, você pode instalar o realce de sintaxe com o pacote language-botml
.
Execute o cli:
$ bot
ou use-o em seu código:
const Botml = require ( 'botml/lib/botml' )
const bot = new Botml ( 'alice.bot' )
bot . start ( )
ou até mesmo carregá-lo estaticamente no seu navegador:
< script src =' https://unpkg.com/botml ' > </ script >
< script >
const bot = new Botml ( )
// either load an URI:
// bot.load('https://raw.githubusercontent.com/codename-co/botml/master/examples/hello.bot')
// or load the script directly:
bot . parse ( '> *n< yes?n' )
bot . start ( )
bot . send ( 'hey' )
</ script >
Os recursos existentes são de dois tipos: recursos básicos que atendem às necessidades básicas de um bot e recursos avançados que permitem recursos de conversação mais ricos.
Recursos básicos:
Recursos avançados:
O formato visa alcançar o máximo usando o mínimo. Com o conjunto certo e mínimo de convenções, pode ser muito poderoso.
A sintaxe geral segue 3 convenções importantes :
O arquivo .bot
mais básico seria:
! BOTML 1
> Hello
< Hello human!
A linha de especificação é necessária para informar ao Botml que ele pode carregar o arquivo.
Esta deve ser a primeira linha de qualquer arquivo .bot
.
! BOTML 1
O 1
representa a versão atual do formato.
Os comentários podem ajudar a tornar seu arquivo .bot
mais claro.
Eles podem ser usados como blocos independentes ou inseridos em blocos acionáveis.
Eles não podem ser usados em linha.
# COMMENT
Os diálogos são o conceito central de qualquer bot. Ele define como o humano e o bot podem interagir.
Um diálogo deve começar com uma linha >
, que define quais frases podem ativar o bot para responder.
Deve haver uma ou várias <
linhas depois que definam as respostas do bot.
Pode haver várias idas e vindas repetindo esta sequência dentro do mesmo bloco.
> MESSAGE
< MESSAGE
Exemplo:
> Hi
< Hello there. Who are you?
> *
< Nice to meet you.
Respostas aleatórias em diálogos fazem o bot parecer menos rígido. Ao responder a um humano, o bot escolhe aleatoriamente os candidatos a resposta. Apenas um dos vários candidatos de resposta pode ser escolhido pelo bot.
> MESSAGE
< REPLY CANDIDATE #1
< REPLY CANDIDATE #2
Exemplo:
> Hello
< Hi there
< Howdy?
As listas são úteis para reunir noções semelhantes ou alternativas.
Uma lista deve começar com uma linha =
, que define o nome da lista.
Deve ter pelo menos um item de lista, mas pode ter mais. Cada item da lista começa com o símbolo -
.
= LIST_NAME
- LIST_ITEM
- LIST_ITEM
Um item de lista pode fazer referência a outra lista.
= LIST_NAME
- LIST_ITEM
- [ANOTHER_LIST]
Ele pode ser referenciado em uma linha >
para referenciar múltiplas variantes de um padrão de entrada.
Ele pode ser referenciado em uma linha <
para referenciar aleatoriamente um dos itens da lista como resposta.
Ele pode ser referenciado em um ?
linha (prompt) para fazer referência a várias opções predefinidas.
A referência a uma lista é feita colocando o nome da lista entre colchetes: [LIST_NAME]
.
Exemplo:
= citrus
- oranges
- lemons
- grapefruits
= random_fruit
- apples
- apricots
- bananas
- [citrus]
> I like [random_fruit]
< Oh. I prefer [random_fruit].
# which is the equivalent to:
# > I like apples
# > I like apricots
# > I like bananas
# > I like oranges
# > I like lemons
# > I like grapefruits
# < Oh. I prefer apples
# < Oh. I prefer apricots
# < Oh. I prefer bananas
# < Oh. I prefer oranges
# < Oh. I prefer lemons
# < Oh. I prefer grapefruits
#
# > I like [random_fruit]
# < Oh. I prefer [random_fruit].
As listas também podem ser usadas em prompts.
Os prompts são respostas rápidas predefinidas em reação a uma situação específica.
Eles devem ser colocados após uma linha <
, no final de um diálogo.
Eles devem referenciar uma lista para acessar todas as respostas rápidas.
O número de respostas rápidas deve ser mínimo.
= LIST_NAME
- LIST_ITEM
- LIST_ITEM
? [LIST_NAME]
Exemplo:
= pizza_types
- Peperroni
- Margherita
- Hawaiian
> I need a pizza
< What kind of pizza?
? [pizza_types]
Os serviços podem aproveitar endpoints de APIs externas.
Um serviço deve ser declarado em seu próprio bloco começando com o sinal @
. Consiste em um nome e um endpoint de API formatado em JSON (por http ou https).
Ele pode (e na maioria das vezes deve ) aceitar um parâmetro usando o sinal $
em seu terminal.
@ SERVICE_NAME ENDPOINT
Pode ser consumido dentro de um diálogo.
Quando o ENDPOINT possuir o sinal $
, ele deverá aceitar um parâmetro cujo valor substituirá o sinal $
.
O resultado da chamada de serviço pode ser filtrado usando um OUTPUT opcional. É um seletor cujo formato é /(.w)+/
.
@ SERVICE_NAME( PARAMETER )[ OUTPUT ]
Exemplo:
@ geo_domain http://freegeoip.net/json/$
> Where is *{domain}
@ geo_domain($domain).city
< It is running from $.
Scripts podem ser usados para avaliar código.
A linguagem do código depende da linguagem usada do analisador usado. O analisador botml
está em Javascript, portanto, o código Javascript pode ser usado.
Deve estar embutido nos diálogos envoltos em ```.
Ele pode acessar variáveis nomeadas:
context.variables.get('price')
$price
Exemplo:
> It will cost you #{price} USD
< `$price / 1000`k USD is a lot!
Variáveis são a forma de detectar, formatar, armazenar e reutilizar informações significativas.
Uma variável pode ser capturada dentro de uma linha >
(diálogo).
Deve ser textual ( $
), numérico ( #
) ou alfanumérico ( *
).
Pode ser usado em <
linhas.
> My name is *{name}
< Nice to meet you, $name
> I am #{age} years old
< Seems that you are $age
O formato da variável é ${VARIABLE_NAME}
(com seus equivalentes numéricos e alfanuméricos). Mas para facilitar o uso, o formato $VARIABLE_NAME
também pode ser usado para variáveis textuais e numéricas.
Uma variável especial $
sempre se refere ao último valor correspondente de um diálogo ou ao resultado da linha anterior (o resultado de um consumo de serviço, por exemplo).
Expressões regulares podem ser usadas em >
linhas para ter mais controle sobre o que detectar.
Uma expressão regular deve ser encapsulada em /
e não pode ser misturada com expressões básicas.
> /^I (?:.+s)?(w+) (?:.+s)?(it|this)/
< Cool bro.
Na verdade, a biblioteca XRegExp é usada nos bastidores, dando acesso às principais capturas nomeadas, comentários embutidos e modificadores de modo.
Os fluxos de trabalho de diálogo são um superconjunto dos diálogos clássicos.
Um fluxo de trabalho pode ser usado para determinar um fluxo preciso de conversa.
Deve começar com uma linha ~
, que define o nome da lista.
Apenas um fluxo de trabalho pode começar com um diálogo <
. Esse fluxo de trabalho será ativado e usado por padrão quando o usuário se conectar ao bot.
# grocery shopping
> I want to buy *{items}
< How many $items?
> #{count} $items
> #{count}
< There you go.
Ramificações condicionais são instruções que direcionam o bot para outra parte do diálogo com base nas condições de teste.
As ramificações condicionais começam com ---
e ouvem todas as informações digitadas e depois testam-nas com todos os casos. Cada caso sendo separado por ---
:
---
> first input case
< first reply
---
> second input case
< second reply
---
> last input case
< last reply
As ramificações condicionais funcionam muito bem com outro recurso chamado checkpoint .
Um ponto de verificação é um marcador ~ CHECKPOINT_NAME
no fluxo de trabalho, que facilita o retorno a ele em um estágio posterior da caixa de diálogo atual. Pode ser referido com ~ [CHECKPOINT_NAME]
, que redireciona o fluxo para a marca do ponto de verificação:
~ ask_howdy
< Hello stranger.
~ checkpoint_name
< How are you?
> meh
< So you feel bad huh
~ [checkpoint_name]
# Example of workflow working:
# < Hello stranger.
# < How are you?
# > meh
# < So you feel bad huh
# < How are you?
# > ...
Tanto os pontos de verificação quanto as listas tornam o trabalho com ramificações condicionais algo realmente interessante:
= mood
- good
- meh
- great
- ok
= exceptions
- fantastic
- better than ever
~ ask_howdy
< hello stranger.
~ listen_howdy
< how are you?
? [mood]
---
> meh
< So you feel bad huh
~ [listen_howdy]
---
> good
< Oh, it is not bad ;)
~ [rechecker]
---
> [exceptions]
< Seems you really cool guy!
---
> ok
< Hmm, just ok? Okay then...
---
> great
< Nice! Let's continue then...
~ rechecker
< Maybe it is more than good?
> excellent
< Much better!
Também é possível usar o sinal "diferente" !
na ramificação condicional :
= mood
- [bad_mood]
- [good_mood]
= bad_mood
- meh
- bad
= good_mood
- great
- ok
~ ask_howdy
< hello stranger.
~ listen_howdy
< how are you?
? [mood]
---
> ![mood]
< I asked you how you are ; please let's start over with another answer?
~ [listen_howdy]
---
> [good_mood]
< Oh, it is awesome ;)
---
> [bad_mood]
< Hmm... bye then...
A ramificação condicional também funciona bem com scripts, desde que um valor seja retornado. Se um script retornar o valor true
, o branch correspondente será ativado. Se todos os testes forem false
a ramificação condicional irá ignorar todas as ramificações e continuar com o fluxo de trabalho atual:
~ ask_for_email
> start email workflow
~ listen_email
< Your email please?
> *{email}
---
` !/^.+@.+..+/.test('$email')
< This email $email seems not legit!
~ [listen_email]
---
< Cool. We'll reach you over at $email
Os gatilhos são uma forma de o bot ser integrado a outro programa.
Existem dois tipos de eventos: eventos padrão e eventos personalizados.
Os eventos padrão são os seguintes:
'start'
'patterns:set'
com dois parâmetros String: nome e valor do padrão'match'
com dois parâmetros String: rótulo, padrão'current-dialogue-start'
com um parâmetro String: dialogLabel'reply'
com um parâmetro String: mensagem'smart-replies'
com um parâmetro Array: respostas'current-dialogue-end'
com um parâmetro String: dialogLabel'variable:set'
com dois parâmetros String: nome e valor da variável'quit'
'*'
captura todos os eventos padrão e personalizadosEventos personalizados podem ser acionados em diálogos.
Um evento personalizado deve ter um nome.
Pode ter parâmetros. Os parâmetros podem contar com variáveis nomeadas.
@ trigger( 'EVENT_NAME' [, PARAMETER] )
Exemplo:
> hello
< hi
@ trigger('said_hi')
Em seguida, lide com o evento 'said_hi' no seu código de acordo com suas necessidades:
bot . on ( 'said_hi' , ( ) => console . log ( 'The bot said hi' ) ) ;
TokensRegex é uma estrutura para definir padrões avançados baseados em processamento de linguagem natural a priori, como entidades nomeadas e marcação de partes do discurso.
> ([ner: PERSON]+) /was|is/ /an?/ []{0,3} /painter|artist/
< An accomplished artist you say.
Este recurso é habilitado por meio da integração de código. Veja um exemplo.
A PNL pode ser habilitada por meio da integração de código. Veja um exemplo.
Veja o diretório examples/
.
Inicie os testes de unidade com:
npm test
npm run autotest # this is for continuous testing
Use a CLI para testar scripts botml no console:
node lib/cli.js
node lib/cli.js examples/echo.bot # load script from a local file
debug=true node lib/cli.js # add logging verbosity
No modo CLI, alguns comandos especiais também podem ajudar na depuração:
Sinta-se à vontade para mergulhar! Abra um problema ou envie PRs.
Botml é licenciado pelo MIT.