Skip to content

Commit

Permalink
Added options for grammars (#25)
Browse files Browse the repository at this point in the history
Added options for grammars
Added grammar class
Added grammar-related exceptions
Updated command line test
Updated README
Updated conan version
  • Loading branch information
vylion authored Mar 26, 2024
1 parent 59df4e3 commit 11ee5e1
Show file tree
Hide file tree
Showing 13 changed files with 161 additions and 17 deletions.
2 changes: 1 addition & 1 deletion .github/workflows/ci.yml
Original file line number Diff line number Diff line change
Expand Up @@ -13,7 +13,7 @@ jobs:
with:
python-version: 3.7
- name: Install Conan
run: pip install conan==1.54.0 && conan --version
run: pip install conan==1.60.0 && conan --version
- name: Create Build Folder
run: mkdir build
- name: Install CMake
Expand Down
3 changes: 2 additions & 1 deletion .gitignore
Original file line number Diff line number Diff line change
Expand Up @@ -5,4 +5,5 @@ debug
.cmake
*.wav
*.token
cmake-*
cmake-*
env/
16 changes: 16 additions & 0 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -257,6 +257,22 @@ This argument is required, stating a path to a .wav audio in 8kHz or 16kHz sampl

> **THIS FEATURE IS STILL IN DEVELOPMENT, PLEASE USE THE GENERIC TOPIC FOR ALL REQUESTS OR AN ERROR WILL BE GIVEN.**
#### Grammar

There are three options available to provide a grammar:

```
-I, --inline-grammar arg
-G, --grammar-uri arg
-C, --compiled-grammar arg
```

- The inline grammar option expects a grammar passed inline as a string.
- The grammar URI option expects a URI, either pointing to a built-in grammar or to a grammar that is being hosted externally.
- The compiled grammar expects a filename of the compiled grammar binary.

> **THIS FEATURE IS STILL IN DEVELOPMENT, PLEASE ONLY USE THE GRAMMAR URI OPTION WITH BUILTIN GRAMMARS, OR AN ERROR WILL BE GIVEN.**
#### Language

```
Expand Down
12 changes: 7 additions & 5 deletions headers/Configuration.h
Original file line number Diff line number Diff line change
@@ -1,11 +1,10 @@
#ifndef VERBIO_ASRTESTCONFIGURATION_H
#define VERBIO_ASRTESTCONFIGURATION_H


#include <memory>
#include <string>
#include <vector>

#include "Grammar.h"

class Configuration {
public:
Expand All @@ -19,6 +18,8 @@ class Configuration {

std::string getAudioPath() const;

bool hasTopic() const;

std::string getTopic() const;

std::string getHost() const;
Expand All @@ -27,7 +28,9 @@ class Configuration {

std::string getTokenPath() const;

std::string getGrammarPath() const;
bool hasGrammar() const;

Grammar getGrammar() const;

uint32_t getSampleRate() const;

Expand All @@ -53,7 +56,7 @@ class Configuration {

std::string language;
std::string topic;
std::string grammarPath;
Grammar grammar;
std::string audioPath;
std::string host;
std::string tokenPath;
Expand All @@ -71,5 +74,4 @@ class Configuration {

};


#endif
35 changes: 35 additions & 0 deletions headers/Grammar.h
Original file line number Diff line number Diff line change
@@ -0,0 +1,35 @@
#ifndef SPEECHCENTER_GRAMMAR_H
#define SPEECHCENTER_GRAMMAR_H

#include <string>
#include <vector>

enum GrammarType {
NONE,
INLINE,
URI,
COMPILED
};

class Grammar {
public:
Grammar();

Grammar(const GrammarType type, const std::string content);

~Grammar();

GrammarType getType() const;

std::string getContent() const;

std::vector<char> getCompiledBytes() const;

private:
GrammarType type;
std::string content;
std::vector<char> compiledBytes;
};


#endif//SPEECHCENTER_GRAMMAR_H
2 changes: 2 additions & 0 deletions headers/RecognitionClient.h
Original file line number Diff line number Diff line change
Expand Up @@ -37,6 +37,8 @@ class RecognitionClient {

std::unique_ptr<RecognitionResource> buildRecognitionResource();

GrammarResource* buildGrammarResource(const Grammar &grammar);

std::unique_ptr<RecognitionParameters> buildRecognitionParameters();

static std::unique_ptr<PCM> buildPCM(const uint32_t &sampleRate);
Expand Down
5 changes: 5 additions & 0 deletions headers/gRpcExceptions.h
Original file line number Diff line number Diff line change
Expand Up @@ -30,6 +30,11 @@ class UnknownTopicModel : public GrpcException {
explicit UnknownTopicModel(const std::string &topic);
};

class UnknownGrammarModel : public GrpcException {
public:
explicit UnknownGrammarModel(const std::string &grammar);
};

class UnsupportedSampleRate : public GrpcException {
public:
explicit UnsupportedSampleRate(const std::string &sampleRate);
Expand Down
1 change: 1 addition & 0 deletions src/CMakeLists.txt
Original file line number Diff line number Diff line change
Expand Up @@ -6,6 +6,7 @@ add_library(speech-center-client STATIC
RecognitionClient.cpp
Configuration.cpp
Audio.cpp
Grammar.cpp
SpeechCenterCredentials.cpp)

target_link_libraries(speech-center-client PUBLIC
Expand Down
41 changes: 33 additions & 8 deletions src/Configuration.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -5,7 +5,7 @@
#include <cxxopts.hpp>


Configuration::Configuration() : host("us.speechcenter.verbio.com"), topic("generic"), language("en-US"),
Configuration::Configuration() : host("us.speechcenter.verbio.com"), language("en-US"),
sampleRate(8000) {}

Configuration::Configuration(int argc, char **argv) : Configuration() {
Expand All @@ -15,16 +15,19 @@ Configuration::Configuration(int argc, char **argv) : Configuration() {
Configuration::~Configuration() = default;

void Configuration::parse(int argc, char **argv) {
std::string grammarInline, grammarUri, grammarCompiled;

cxxopts::Options options(argv[0], "Verbio Technlogies S.L. - Speech Center client example");
options.set_width(180).allow_unrecognised_options().add_options()
("a,audio",
"Path to a .wav audio in 8kHz or 16kHz sampling rate and PCM16 encoding to use for the recognition",
cxxopts::value(audioPath), "file")
//("g,grammar", "Path to the Grammar ABNF file to use for the recognition", cxxopts::value(grammarPath), "file")
("I,inline-grammar", "ABNF Grammar to use for the recognition passed as a string", cxxopts::value(grammarInline), "string")
("G,grammar-uri", "Grammar URI to use for the recognition (builtin or externally served)", cxxopts::value(grammarUri), "uri")
("C,compiled-grammar", "Path to the compiled grammar file to use for the recognition", cxxopts::value(grammarCompiled), "file")
("T,topic",
"Topic to use for the recognition when a grammar is not provided. Must be GENERIC | BANKING | TELCO | INSURANCE",
cxxopts::value(topic)->default_value(topic))
cxxopts::value(topic))
("l,language",
"Language to use for the recognition: en-US, en-GB, pt-BR, es, es-419, tr, ja, fr, fr-CA, de, it",
cxxopts::value(language)->default_value(language))
Expand All @@ -48,9 +51,22 @@ void Configuration::parse(int argc, char **argv) {
std::cout << options.help();
exit(0);
}
if ((parsedOptions.count("t") == 0) == (parsedOptions.count("g") == 0))
if (1 != (parsedOptions.count("T") + parsedOptions.count("G") + parsedOptions.count("I") + parsedOptions.count("C")))
throw GrpcException("Topic and grammar options are mutually exclusive and at least one is needed.");

if (parsedOptions.count("G") == 1) {
grammar = Grammar(URI, grammarUri);
}
else if(parsedOptions.count("I") == 1) {
grammar = Grammar(INLINE, grammarInline);
}
else if (parsedOptions.count("C") == 1) {
grammar = Grammar(COMPILED, grammarCompiled);
}
else {
grammar = Grammar();
}

validate_configuration_values();
}

Expand All @@ -70,8 +86,16 @@ std::string Configuration::getTokenPath() const {
return tokenPath;
}

std::string Configuration::getGrammarPath() const {
return grammarPath;
bool Configuration::hasGrammar() const {
return grammar.getType() != GrammarType::NONE;
}

Grammar Configuration::getGrammar() const {
return grammar;
}

bool Configuration::hasTopic() const {
return !topic.empty();
}

std::string Configuration::getTopic() const {
Expand Down Expand Up @@ -113,10 +137,11 @@ std::string Configuration::getClientSecret() const {
void Configuration::validate_configuration_values() {

if(sampleRate != 8000 and sampleRate != 16000) {
throw std::runtime_error("Unsupported parameter value. Allowed values sample rate: 8000 1600");
throw std::runtime_error("Unsupported parameter value. Allowed values sample rate: 8000 16000");
}

validate_string_value("topic", topic, allowedTopicValues);
if (hasTopic())
validate_string_value("topic", topic, allowedTopicValues);
validate_string_value("language", language, allowedLanguageValues);
validate_string_value("asr version", asrVersion, allowedAsrVersionValues);
}
Expand Down
28 changes: 28 additions & 0 deletions src/Grammar.cpp
Original file line number Diff line number Diff line change
@@ -0,0 +1,28 @@
#include "Grammar.h"
#include <fstream>

Grammar::Grammar() : type{NONE}, content{} {}

Grammar::Grammar(const GrammarType type, const std::string content) : type(type), content(content) {
if (type == COMPILED) {
std::ifstream input(content, std::ios::binary);
compiledBytes = std::vector<char> (
(std::istreambuf_iterator<char>(input)),
(std::istreambuf_iterator<char>()));
input.close();
}
}

Grammar::~Grammar() = default;

GrammarType Grammar::getType() const {
return type;
}

std::string Grammar::getContent() const {
return content;
}

std::vector<char> Grammar::getCompiledBytes() const {
return compiledBytes;
}
29 changes: 28 additions & 1 deletion src/RecognitionClient.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -235,7 +235,10 @@ RecognitionClient::buildRecognitionResource() {
std::unique_ptr<RecognitionResource> resource(
new RecognitionResource());

resource->set_topic(convertTopic(configuration.getTopic()));
if (configuration.hasTopic())
resource->set_topic(convertTopic(configuration.getTopic()));
else if (configuration.hasGrammar())
resource->set_allocated_grammar(buildGrammarResource(configuration.getGrammar()));
return resource;
}

Expand Down Expand Up @@ -264,6 +267,30 @@ RecognitionClient::convertTopic(const std::string &topicName) {
return topicIter->second;
}

GrammarResource*
RecognitionClient::buildGrammarResource(const Grammar &grammar) {
GrammarResource* resource = new GrammarResource();
std::vector<char> bytes;

switch (grammar.getType()) {
case GrammarType::INLINE:
resource->set_inline_grammar(grammar.getContent());
break;
case GrammarType::URI:
resource->set_grammar_uri(grammar.getContent());
break;
case GrammarType::COMPILED:
bytes = grammar.getCompiledBytes();
resource->set_compiled_grammar(bytes.data(), bytes.size());
break;
default:
ERROR("Unsupported grammar: {}", grammar.getContent());
throw UnknownGrammarModel(grammar.getContent());
}

return resource;
}

RecognitionConfig_AsrVersion RecognitionClient::buildAsrVersion() {
static const std::unordered_map<
std::string, ::RecognitionConfig_AsrVersion>
Expand Down
2 changes: 2 additions & 0 deletions src/gRpcExceptions.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -6,6 +6,8 @@ CallbackNotImplemented::CallbackNotImplemented() : GrpcException("Callback is no

UnknownTopicModel::UnknownTopicModel(const std::string &topic) : GrpcException("Unknown topic: " + topic) {}

UnknownGrammarModel::UnknownGrammarModel(const std::string &grammar) : GrpcException("Unknown grammar: " + grammar) {}

UnsupportedSampleRate::UnsupportedSampleRate(const std::string &sampleRate) : GrpcException(
"Unsupported sample rate: " + sampleRate) {}

Expand Down
2 changes: 1 addition & 1 deletion test/test_commandLine.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -6,5 +6,5 @@

TEST(CommandLine, happy_path) {
int argc = 8;
const char* argv[] = {"cli_client", "-a", "file.wav", "-b", "file.bnf", "-l pt-BR", "-T", "file.token"};
const char* argv[] = {"cli_client", "-a", "file.wav", "-b", "file.bnf", "-l pt-BR", "-t", "file.token", "-T", "GENERIC"};
}

0 comments on commit 11ee5e1

Please sign in to comment.