Instruções de uso¶
Essa seção apresenta as informações básicas de como utilizar templates com o CPqD Texto Fala em uma aplicação. Detalhes sobre as classes da API pública em C/C++ podem ser consultados acessando a seção Interface de Programação e a em Java na seção Interface de Programação.
O que é um template¶
No nosso contexto, consideramos um template um padrão de texto, utilizado por aplicações, nas quais há pequenas variações em alguns trechos, como nomes, endereços, por exemplo.
Para que a aplicação não precise sempre enviar esse mesmo padrão, com pequenas variações, foi criado um mecanismo de template estendendo o SSML. Essa extensão consiste em adicionar tags especiais no SSML, cujo conteúdo são instruções em linguagem de programação. Através dessa tag especial é possível introduzir lógica de programação que afeta a saída SSML gerada, bem como introduzir o uso de variáveis.
O preenchimento do template requer um conjunto de dados de entrada, que serão fornecidos através de mensagens. Uma mensagem é um documento em JSON contendo conjuntos de pares chave-valor. Uma única mensagem pode fazer uso de vários templates.
As mensagens contém apenas os dados a serem utilizados no template. Definições sobre como as informações devem ser verbalizadas estão contidas no template (e.g. através da tag say-as
).
Com o template preenchido e as variáveis definidas, o API pública do CPqD Texto Fala irá processar essas informações e gerar um SSML que deverá ser utilizado na síntese.
Linguagem do template¶
Definindo o template¶
A linguagem que descreve os templates é uma extensão do SSML. Nessa extensão é introduzida a tag de script, aberta com <%
e fechada com %>
. O conteúdo dessa tag consiste em construções de programação em linguagem própria. Todo conteúdo que esteja fora dessas tags será emitido sem qualquer alteração.
Um template é definido na abertura do marcador speak
e finalizado no fechamento do mesmo marcador. Se houver mais de um speak definido, um erro será retornado.
Exemplo
<speak> <% if (NumeroBA not empty) then %> Número bê á: <say-as interpret-as="spell"> <%= NumeroBA %> </say-as> <break time="1000ms"/> <% else %> Número bê á não fornecido <% skipOrderInfo = true %> <% end %> </speak>
O nome do template pode ser indicado de duas formas:
- Parâmetro específico na API do TTS ou
- Nome do arquivo em disco.
Mais detalhes podem ser consultados na seção API do CPqD Texto Fala.
Variáveis¶
O script do template utiliza tipagem forte (cada variável tem um tipo definido) e dinâmica (os tipos são definidos durante a execução). As variáveis são declaradas implicitamente na primeira atribuição, o que também define seu tipo. A partir do momento, em que uma variável foi declarada, seu tipo não pode ser alterado.
Variáveis possuem o escopo global, seu nome é sensível à caixa e deve ser composto por uma letra seguida de letras, números ou sublinhas.
Os tipos válidos são:
- Lógico (booleano): true ou false;
- Numérico: qualquer valor numérico decimal, inteiro ou ponto-flutuante;
- Textual: sequência de caracteres entre aspas duplas.
Exemplo
<%
// cria a variável do tipo booleana
skipOrderInfo = true
// cria uma string
name = "Sebastiano"
// variáveis não podem mudar de tipo
name = 56.33 // ERRO!
print(name)
%>
Campos¶
Os campos tem um funcionamento similar ao das variáveis, porém seus valores não podem ser alterados.
Exemplo
Supondo a mensagem:
[
{
"template": "modelo1",
"fields": [
{"id": "Nome", "value": "Sebastiano"}
]
}
]
Um template poderia conter:
<%
print(Nome) // imprime 'Sebastiano'
value = Nome // cria variável com o conteúdo de Nome
print(value) // imprime 'Sebastiano'
%>
Operadores¶
Os operadores têm um funcionamento similar aos operadores de linguagens de programação. E foram limitados conforme abaixo.
Operadores condicionais:
- not: operador de negação que deve ser utilizado entre parênteses
- !=
- ==
- >=
- <=
- >
- <
- empty: operador utilizado em conjunto com o operador not. Exemplo: not empty
- exist: operador que verifica se um campo existe. Ele deve ser utilizado entre parênteses
- and
- or
Operadores aritméticos:
- +
- -
- *
- /
Operadores de atribuição:
- =
- +=
Exemplo
Supondo a mensagem:
[ { "template": "modelo1", "fields": [ {"id": "Nome", "value": "Sebastiano"} ] } ]
Um template poderia conter:
<%
print(Nome) // imprime 'Sebastiano'
value = Nome + "Silva" // variável = Sebastiano Silvia
print(value) // imprime 'Sebastiano Silvia'
%>
Função print¶
Existe apenas a função print no template que insere na saída exatamente o texto definido. O parâmetro da função aceita qualquer tipo: string, numérico, booleano, variáveis e campos.
Exemplo
// insere o texto “Número bê á: <say-as interpret-as='spell'>” na saida
print("Número bê á: <say-as interpret-as='spell'>")
Callback¶
Em determinados momentos, o usuário pode invocar uma função interna da sua aplicação que retorna uma string tratada de uma maneira diferente. Essa chamada pode ser feita via callback definida da seguinte maneira:
<say-as interpret-as = "none" callback="<nome da função>"> texto </say-as>
Exemplo
<say-as interpret-as = "none" callback="trataTelefone"> 1937055828 </say-as>
A chamada da função trataTelefone, irá tratar o texto 1937055828 e irá retornar um texto alterado de acordo com a função da aplicação.
Spell¶
Para utilizar a normalização do spell juntamente com uma callback, o usuário pode utilizar o atributo spell na tag say-as em conjunto com o atributo callback.
Ao utilizar em conjunto, primeiramente o processamento da callback é realizado e no texto retornado será aplicado o spell, de acordo com a opção escolhida(soletrar tudo, somente números ou somente as letras).
Exemplo
<say-as interpret-as="spell" format="number" callback="TrataBA">
<%= NumeroBA %>
</say-as>
Soletra os números após a formatação do campo NumeroBA chamado na callback TrataBA.
Construção condicional¶
Permite executar uma ou mais construções mediante uma condição. Deve possuir uma cláusula if e opcionalmente as cláusulas elseif e else.
<% if ( <expressão> ) then %>
...
<% elseif ( <expressão> ) then %>
...
<% else %>
...
<% end %>
Exemplo
<% // verifica se a variável "NumeroBA" não é vazia
if (NumeroBA not empty) then %>
Número bê á: <say-as interpret-as="spell"> <%= NumeroBA %>
</say-as> <break time="1000ms"/>
<% else %>
Número bê á não fornecido <% skipOrderInfo = true %>
<% end %>
Comentário¶
Comentários são permitidos no template, através do marcador <!-- >
ou dentro do código com o marcador //
.
Não será permitido comentário dentro do marcador <%=
.
Exemplo
<!-- análise do count -->
<% //condicional que verifica se o contador não é vazio
if (count != 0) then %>
...
Exemplo de template¶
<speak>
O cliente possui <%= NUMERO_PROJETOS %> ativos. Com as seguintes descrições:
<% if (ID_PROJETO != "") then %>
Número do projeto: <say-as interpret-as="none" callback="TrataProjeto"> <%= ID_PROJETO_CRE %> </say-as>. <break time="1000ms"/>
<% end %>
<% if (NUMERO_TELEFONE != "") then %>
Número do telefone: <say-as interpret-as="spell"> <%= NUMERO_TELEFONE %> </say-as>. <break time="1000ms"/>
<% end %>
<% if (exist(TIPO_LOGRAD) and (TIPO_LOGRAD == "AV")) then %>
Endereço: Avenida <break time="500ms"/>
<% elseif (exist(TIPO_LOGRAD) and (TIPO_LOGRAD == "R")) then %>
Endereço: Rua <break time="500ms"/>
<% elseif (((exist(TIPO_LOGRAD) and (TIPO_LOGRAD != "AV")) and (exist(TIPO_LOGRAD) and (TIPO_LOGRAD != "R"))) and (exist(TIPO_LOGRAD) and (TIPO_LOGRAD != ""))) then %>
Endereço: <%= TIPO_LOGRAD_ATENDIMENTO %> <break time="500ms"/>
<% end %>
...
</speak>
Mensagem¶
O preenchimento do template requer um conjunto de dados de entrada, que serão fornecidos através de mensagens. Uma mensagem é um documento JSON
contendo conjuntos de pares chave-valor. Uma única mensagem pode fazer uso de vários templates.
As mensagens contém apenas os dados a serem utilizados no template. Definições sobre como as informações devem ser verbalizadas estão contidas no template (e.g. através da tag say-as
).
Definindo uma mensagem¶
A mensagem é composta pelo nome do template e por campos.
Uma única mensagem pode fazer uso de vários templates criando diferentes grupos.
O nome do template é o identificador do template carregado na biblioteca CPqD Texto Fala.
Os campos são definidos com elementos fields. Obrigatoriamente, é preciso informar os atributos id e value, que indicam o nome e o valor do campo, respectivamente. Existe ainda o atributo opcional type que permite definir o tipo de dado utilizado como valor: number, string ou boolean. Por padrão todos os valores são considerados como sendo do tipo string. Definir o tipo de dado do valor possibilita fazer comparações utilizando o tipo adequado (e.g. informar que o campo é numérico para poder utilizar os operadores < e > em comparações).
Os nomes dos campos e templates seguem as mesmas regras definidas para nomes de variáveis.
A saída SSML gerada para uma mensagem consiste no processamento dos grupos, na ordem em que aparecem. Para cada grupo na mensagem, o mecanismo irá processar o template especificado com os campos definidos no grupo. O SSML resultante é a concatenação dos resultados parciais para cada grupo. É importante destacar que a ordem dos campos dentro de um grupo é irrelevante para o processamento de um template (a ordem segue o preenchimento do template), porém a ordem dos grupos vai determinar a ordem na qual os templates serão processados para gerar a saída.
Exemplo
[
{
"template": "Template1",
"fields": [
{"id": "ID_PROJETO", "value": "124310452202068"},
{"id": "NUMERO_TELEFONE", "value": "36985257", "type": "number"}
]
},
{
"template": "Template2",
"fields": [
{"id": "Nome", "value": "Sebastiano"},
{"id": "Endereco", "value": "R. Alberto Sapo, 99, Campinas"}
]
}
]
Exemplo de uso¶
Após os conceitos apresentados acima, iremos exemplificar passo a passo a utilização do template.
Utilizando template sem callback:
Criar um template: Arquivo de teste Template1.txt
<speak> O cliente possui <%= NUMERO_PROJETOS %> ativos. Com as seguintes descrições: <% if (ID_PROJETO != "") then %> Número do projeto: <say-as interpret-as="spell" format="number"> <%= ID_PROJETO_CRE %> </say-as>. <break time="1000ms"/> <% end %> <% if (NUMERO_TELEFONE != "") then %> Número do telefone: <say-as interpret-as="spell"> <%= NUMERO_TELEFONE %> </say-as>. <break time="1000ms"/> <% end %> </speak>
Criar uma mensagem: Arquivo de teste mensagem.txt
[ { "template": "Template1", "fields": [ {"id": "ID_PROJETO", "value": "124310452202068"}, {"id": "NUMERO_TELEFONE", "value": "36985257", "type": "number"} ] }
Carregar um template:
Processar uma mensagem:
string message = main_loadInputFile("message.txt"); TTS_ProcessMessage(message.c_str(), TEMPLATE_MESSAGE_DONT_CHECK, &output);
String message = loadInputFile("message.txt"); String ssml = engine.processMessage(message, 0);
Passo opcional: validar o resultado do processamento da mensagem.
Utilizar o texto da mensagem processada:
TTS_TextToSpeech(handle, output);
session.textToSpeech(ssml);
Descarregar um template:
TTS_UnloadTemplate("Template1.txt");
engine.unloadTemplate("Template1.txt");
Utilizando template com callback:
Criar um template com callback: Arquivo de teste Template2.txt
<speak> O cliente possui <%= NUMERO_PROJETOS %> ativos. Com as seguintes descrições: <% if (ID_PROJETO != "") then %> Número do projeto: <say-as interpret-as="none" callback="TrataProjeto"> <%= ID_PROJETO_CRE %> </say-as>. <break time="1000ms"/> <% end %> <% if (NUMERO_TELEFONE != "") then %> Número do telefone: <say-as interpret-as="spell"> <%= NUMERO_TELEFONE %> </say-as>. <break time="1000ms"/> <% end %> </speak>
Criar uma mensagem: Arquivo de teste mensagem.txt
[ { "template": "Template2", "fields": [ {"id": "ID_PROJETO", "value": "148596"}, {"id": "NUMERO_TELEFONE", "value": "35896652", "type": "number"} ] }
Criar uma callback:
void userCallback( void* context, const char *input, TTS_INTERPRET_OUTPUT_CALLBACK *output, void *data ) { string out = input; out += " esse texto"; output(context, out.c_str()); }
public static class MyCallback extends InterpretedListener { MyCallback(boolean normalize, Object data) { super("TrataProjeto", normalize, data); } @Override public String callback(String input, Object data) { return input + " meu teste"; } }
Registrar uma callback:
TTS_RegisterInterpretation("TrataProjeto", userCallback, NULL, true);
registerInterpretation em Java
MyCallback myCallback = new MyCallback(true, null); engine.registerInterpretation( myCallback);
Carregar um template:
TTS_LoadTemplate("Template2.txt");
engine.loadTemplate("Template2.txt");
Processar uma mensagem:
string message = main_loadInputFile("message.txt"); TTS_ProcessMessage(message.c_str(), TEMPLATE_MESSAGE_DONT_CHECK, &output);
String message = loadInputFile("message.txt"); String ssml = engine.processMessage(message, 0);
Passo opcional: validar o resultado do processamento da mensagem.
Utilizar o texto da mensagem processada:
TTS_TextToSpeech(handle, output);
session.textToSpeech(ssml);
Descarregar um template:
TTS_UnloadTemplate("Template2.txt");
engine.unloadTemplate("Template2.txt");
Nota
Os exemplos completos do uso do template estão disponíveis no GitHub em C (https://github.com/CPqD/tts-examples-c) e Java (https://github.com/CPqD/tts-sdk-java.)