adhearsion-asr 0.1.0

Sign up to get free protection for your applications and to get access to all the features.
checksums.yaml ADDED
@@ -0,0 +1,7 @@
1
+ ---
2
+ SHA1:
3
+ metadata.gz: c04b1a33ab083f07c27fcb249b183b1261fd24ff
4
+ data.tar.gz: 30b74b8f7774084d0ba658b207330ba6070ea19e
5
+ SHA512:
6
+ metadata.gz: 812e7c4fceaed9eccf44d9443ad42341b9f4c7bcc7b7b7a35b21e68813c316b7427de465fe01a42dbbc98474853bf0c9ef65e502a21c526e62b0a1d7c77cb3e9
7
+ data.tar.gz: ca1aff66a38dc817b8929ed2229323736aedcb86c2d32778e8ed7832b0d5fb4baf31b2bb2a74a92b288df40d77dca35a77f9b04af9580aec5cde016648e7b6f6
data/.gitignore ADDED
@@ -0,0 +1,21 @@
1
+ # Gem related stuff
2
+ *.gem
3
+ /pkg
4
+ /.bundle
5
+ /Gemfile.lock
6
+ /vendor
7
+
8
+ # RBX stuff
9
+ /.rbx/
10
+
11
+ # Editor temp/backup files
12
+ *~
13
+ .*.sw?
14
+
15
+ # General
16
+ /nbproject
17
+ .DS_Store
18
+ /.rvmrc
19
+ /.yardoc
20
+ /doc
21
+ /tmp
data/.rspec ADDED
@@ -0,0 +1,3 @@
1
+ --format documentation
2
+ --colour
3
+ --tty
data/.travis.yml ADDED
@@ -0,0 +1,13 @@
1
+ language: ruby
2
+ rvm:
3
+ - 1.9.2
4
+ - 1.9.3
5
+ - 2.0.0
6
+ - jruby-19mode
7
+ - rbx-19mode
8
+ - ruby-head
9
+ matrix:
10
+ allow_failures:
11
+ - rvm: jruby-19mode
12
+ notifications:
13
+ irc: "irc.freenode.org#adhearsion"
data/CHANGELOG.md ADDED
@@ -0,0 +1,7 @@
1
+ # [develop](https://github.com/adhearsion/adhearsion-asr)
2
+
3
+ # [v0.1.0](https://github.com/adhearsion/adhearsion-asr/compare/6216ddb0a8b8c0ac5d1731ec154fe6d6abfea692...0.1.0) - [2013-05-07](https://rubygems.org/gems/adhearsion-asr/versions/0.1.0)
4
+ * Feature: #ask and #menu from Adhearsion core
5
+ * Mostly API compatible, with some very minor differences
6
+ * Use Rayo Prompt component
7
+ * Support for arbitrary grammars (ASR) in #ask
data/Gemfile ADDED
@@ -0,0 +1,6 @@
1
+ source "https://rubygems.org"
2
+
3
+ gemspec
4
+
5
+ gem 'adhearsion', github: 'adhearsion', branch: 'feature/rayo_prompt'
6
+ gem 'punchblock', github: 'adhearsion/punchblock', branch: 'feature/new_rayo'
data/Guardfile ADDED
@@ -0,0 +1,5 @@
1
+ guard 'rspec', :cli => '--format documentation' do
2
+ watch(%r{^spec/.+_spec\.rb$})
3
+ watch(%r{^lib/(.+)\.rb$}) { |m| "spec/#{m[1]}_spec.rb" }
4
+ watch('spec/spec_helper.rb') { "spec/" }
5
+ end
data/LICENSE.txt ADDED
@@ -0,0 +1,20 @@
1
+ Copyright (C) 2013 Adhearsion Foundation Inc
2
+
3
+ Permission is hereby granted, free of charge, to any person obtaining
4
+ a copy of this software and associated documentation files (the
5
+ "Software"), to deal in the Software without restriction, including
6
+ without limitation the rights to use, copy, modify, merge, publish,
7
+ distribute, sublicense, and/or sell copies of the Software, and to
8
+ permit persons to whom the Software is furnished to do so, subject to
9
+ the following conditions:
10
+
11
+ The above copyright notice and this permission notice shall be
12
+ included in all copies or substantial portions of the Software.
13
+
14
+ THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
15
+ EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
16
+ MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
17
+ NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE
18
+ LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION
19
+ OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION
20
+ WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
data/README.md ADDED
@@ -0,0 +1,172 @@
1
+ # adhearsion-asr
2
+
3
+ Adds speech recognition support to Adhearsion as a plugin. Overrides `CallController#ask` and `#menu` to pass all recognition responsibility to the recognizer instead of invoking it multiple times.
4
+
5
+ ## Features
6
+
7
+ * #ask API from Adhearsion core supporting digit limits, terminators, timeouts, inline grammars and grammar references
8
+ * #menu API from Adhearsion core supporting DTMF input and recognition failure
9
+
10
+ ## Install
11
+
12
+ Add the following entries to your Adhearsion application's Gemfile:
13
+
14
+ ```ruby
15
+ gem 'adhearsion-asr'
16
+ gem 'adhearsion', github: 'adhearsion', branch: 'feature/rayo_prompt'
17
+ gem 'punchblock', github: 'adhearsion/punchblock', branch: 'feature/new_rayo'
18
+ ```
19
+
20
+ The dependencies on Adhearsion and Punchblock from git are temporary and are required because this plugin uses functionality that is unreleased in those gems (mostly changes to keep up to date with the Rayo specification; they will be released once the Rayo specification has been advanced to Draft by the XSF).
21
+
22
+ Be sure to check out the plugin config by running `rake config:show` and adjust to your requirements.
23
+
24
+ ## Examples
25
+
26
+ ### Simple collection of 5 DTMF digits
27
+
28
+ ```ruby
29
+ class MyController < Adhearsion::CallController
30
+ include AdhearsionASR::ControllerMethods
31
+
32
+ def run
33
+ result = ask limit: 5
34
+ case result.status
35
+ when :match
36
+ speak "You entered #{result.response}"
37
+ when :noinput
38
+ speak "Hellooo? Anyone there?"
39
+ when :nomatch
40
+ speak "That doesn't make sense."
41
+ end
42
+ end
43
+ end
44
+ ```
45
+
46
+ ### Collecting an arbitrary number of digits until '#' is received:
47
+
48
+ ```ruby
49
+ class MyController < Adhearsion::CallController
50
+ include AdhearsionASR::ControllerMethods
51
+
52
+ def run
53
+ result = ask terminator: '#'
54
+ case result.status
55
+ when :match
56
+ speak "You entered #{result.response}"
57
+ when :noinput
58
+ speak "Hellooo? Anyone there?"
59
+ when :nomatch
60
+ speak "That doesn't make sense."
61
+ end
62
+ end
63
+ end
64
+ ```
65
+
66
+ ### Collecting input from an inline speech grammar
67
+
68
+ ```ruby
69
+ class MyController < Adhearsion::CallController
70
+ include AdhearsionASR::ControllerMethods
71
+
72
+ def run
73
+ grammar = RubySpeech::GRXML.draw root: 'main', language: 'en-us', mode: :voice do
74
+ rule id: 'main', scope: 'public' do
75
+ one_of do
76
+ item { 'yes' }
77
+ item { 'no' }
78
+ end
79
+ end
80
+ end
81
+
82
+ result = ask grammar: grammar, input_options: { mode: :speech }
83
+ case result.status
84
+ when :match
85
+ speak "You said #{result.response}"
86
+ when :noinput
87
+ speak "Hellooo? Anyone there?"
88
+ when :nomatch
89
+ speak "That doesn't make sense."
90
+ end
91
+ end
92
+ end
93
+ ```
94
+
95
+ ### Collecting input from a speech grammar by URL
96
+
97
+ ```ruby
98
+ class MyController < Adhearsion::CallController
99
+ include AdhearsionASR::ControllerMethods
100
+
101
+ def run
102
+ result = ask grammar_url: 'http://example.com/mygrammar.grxml', input_options: { mode: :speech }
103
+ case result.status
104
+ when :match
105
+ speak "You said #{result.response}"
106
+ when :noinput
107
+ speak "Hellooo? Anyone there?"
108
+ when :nomatch
109
+ speak "That doesn't make sense."
110
+ end
111
+ end
112
+ end
113
+ ```
114
+
115
+ ### Executing a DTMF menu
116
+
117
+ ```ruby
118
+ class MyController < Adhearsion::CallController
119
+ def run
120
+ answer
121
+ menu "Where can we take you today?", timeout: 8.seconds, tries: 3 do
122
+ match 1, BooController
123
+ match '2', MyOtherController
124
+ match(3, 4) { pass YetAnotherController }
125
+ match 5, FooController
126
+ match 6..10 do |dialed|
127
+ say_dialed dialed
128
+ end
129
+
130
+ timeout { do_this_on_timeout }
131
+
132
+ invalid do
133
+ invoke InvalidController
134
+ end
135
+
136
+ failure do
137
+ speak 'Goodbye'
138
+ hangup
139
+ end
140
+ end
141
+
142
+ speak "This code gets executed unless #pass is used"
143
+ end
144
+
145
+ def say_dialed(dialed)
146
+ speak "#{dialed} was dialed"
147
+ end
148
+
149
+ def do_this_on_timeout
150
+ speak 'Timeout'
151
+ end
152
+ end
153
+ ```
154
+
155
+ Check out the [API documentation](http://rdoc.info/gems/adhearsion-asr/frames) for more details.
156
+
157
+ ## Links:
158
+ * [Source](https://github.com/adhearsion/adhearsion-asr)
159
+ * [Documentation](http://rdoc.info/gems/adhearsion-asr/frames)
160
+ * [Bug Tracker](https://github.com/adhearsion/adhearsion-asr/issues)
161
+
162
+ ## Author
163
+
164
+ [Ben Langfeld](https://github.com/benlangfeld)
165
+
166
+ ### Contributions
167
+
168
+ Adhearsion has a set of [contribution guidelines](https://github.com/adhearsion/adhearsion/wiki/Contributing) which help to smooth the contribution process.
169
+
170
+ ### Copyright
171
+
172
+ Copyright (c) 2013 Adhearsion Foundation Inc. MIT LICENSE (see LICENSE for details).
data/Rakefile ADDED
@@ -0,0 +1,6 @@
1
+ require "bundler/gem_tasks"
2
+
3
+ require 'rspec/core/rake_task'
4
+ RSpec::Core::RakeTask.new :spec
5
+
6
+ task default: :spec
@@ -0,0 +1,28 @@
1
+ # -*- encoding: utf-8 -*-
2
+ $:.push File.expand_path("../lib", __FILE__)
3
+ require "adhearsion-asr/version"
4
+
5
+ Gem::Specification.new do |s|
6
+ s.name = "adhearsion-asr"
7
+ s.version = AdhearsionASR::VERSION
8
+ s.authors = ["Ben Langfeld"]
9
+ s.email = ["ben@langfeld.me"]
10
+ s.homepage = "https://github.com/adhearsion/adhearsion-asr"
11
+ s.summary = %q{Adds speech recognition support to Adhearsion as a plugin}
12
+ s.description = %q{Adds speech recognition support to Adhearsion as a plugin}
13
+
14
+ s.rubyforge_project = "adhearsion-asr"
15
+
16
+ s.files = `git ls-files`.split("\n")
17
+ s.test_files = `git ls-files -- {test,spec,features}/*`.split("\n")
18
+ s.require_paths = ["lib"]
19
+
20
+ s.add_runtime_dependency %q<adhearsion>, ["~> 2.1"]
21
+ s.add_runtime_dependency %q<ruby_speech>, ["~> 2.1"]
22
+
23
+ s.add_development_dependency %q<bundler>, ["~> 1.0"]
24
+ s.add_development_dependency %q<rspec>, ["~> 2.5"]
25
+ s.add_development_dependency %q<rake>, [">= 0"]
26
+ s.add_development_dependency %q<guard-rspec>
27
+ s.add_development_dependency %q<rb-fsevent>, ['~> 0.9']
28
+ end
@@ -0,0 +1,38 @@
1
+ module AdhearsionASR
2
+ class AskGrammarBuilder
3
+ def initialize(options)
4
+ @options = options
5
+ end
6
+
7
+ def grammars
8
+ @grammars ||= build_grammars
9
+ end
10
+
11
+ private
12
+
13
+ def build_grammars
14
+ grammars = []
15
+
16
+ grammars.concat [@options[:grammar]].flatten.compact.map { |val| {value: val} } if @options[:grammar]
17
+ grammars.concat [@options[:grammar_url]].flatten.compact.map { |val| {url: val} } if @options[:grammar_url]
18
+
19
+ if grammars.empty?
20
+ limit = @options[:limit]
21
+ grammar = RubySpeech::GRXML.draw mode: :dtmf, root: 'digits' do
22
+ rule id: 'digits', scope: 'public' do
23
+ item repeat: "0-#{limit}" do
24
+ one_of do
25
+ 0.upto(9) { |d| item { d.to_s } }
26
+ item { "#" }
27
+ item { "*" }
28
+ end
29
+ end
30
+ end
31
+ end
32
+ grammars << {value: grammar}
33
+ end
34
+
35
+ grammars
36
+ end
37
+ end
38
+ end
@@ -0,0 +1,112 @@
1
+ require 'adhearsion-asr/ask_grammar_builder'
2
+ require 'adhearsion-asr/prompt_builder'
3
+ require 'adhearsion-asr/menu_builder'
4
+
5
+ module AdhearsionASR
6
+ module ControllerMethods
7
+
8
+ #
9
+ # Prompts for input, handling playback of prompts, DTMF grammar construction, and execution
10
+ #
11
+ # @example A basic DTMF digit collection:
12
+ # ask "Welcome, ", "/opt/sounds/menu-prompt.mp3",
13
+ # timeout: 10, terminator: '#', limit: 3
14
+ #
15
+ # The first arguments will be a list of sounds to play, as accepted by #play, including strings for TTS, Date and Time objects, and file paths.
16
+ # :timeout, :terminator and :limit options may be specified to automatically construct a grammar, or grammars may be manually specified.
17
+ #
18
+ # @param [Object, Array<Object>] args A list of outputs to play, as accepted by #play
19
+ # @param [Hash] options Options to modify the grammar
20
+ # @option options [Boolean] :interruptible If the prompt should be interruptible or not. Defaults to true
21
+ # @option options [Integer] :limit Digit limit (causes collection to cease after a specified number of digits have been collected)
22
+ # @option options [Integer] :timeout Timeout in seconds before the first and between each input digit
23
+ # @option options [String] :terminator Digit to terminate input
24
+ # @option options [RubySpeech::GRXML::Grammar, Array<RubySpeech::GRXML::Grammar>] :grammar One of a collection of grammars to execute
25
+ # @option options [String, Array<String>] :grammar_url One of a collection of URLs for grammars to execute
26
+ # @option options [Hash] :input_options A hash of options passed directly to the Punchblock Input constructor
27
+ # @option options [Hash] :output_options A hash of options passed directly to the Punchblock Output constructor
28
+ #
29
+ # @return [Result] a result object from which the details of the response may be established
30
+ #
31
+ # @see Output#play
32
+ # @see Punchblock::Component::Input.new
33
+ # @see Punchblock::Component::Output.new
34
+ #
35
+ def ask(*args)
36
+ options = args.last.kind_of?(Hash) ? args.pop : {}
37
+ prompts = args.flatten
38
+
39
+ options[:grammar] || options[:grammar_url] || options[:limit] || options[:terminator] || raise(ArgumentError, "You must specify at least one of limit, terminator or grammar")
40
+
41
+ output_document = output_formatter.ssml_for_collection(prompts)
42
+ grammars = AskGrammarBuilder.new(options).grammars
43
+
44
+ PromptBuilder.new(output_document, grammars, options).execute self
45
+ end
46
+
47
+ # Creates and manages a multiple choice menu driven by DTMF, handling playback of prompts,
48
+ # invalid input, retries and timeouts, and final failures.
49
+ #
50
+ # @example A complete example of the method is as follows:
51
+ # menu "Welcome, ", "/opt/sounds/menu-prompt.mp3", tries: 2, timeout: 10 do
52
+ # match 1, OperatorController
53
+ #
54
+ # match 10..19 do
55
+ # pass DirectController
56
+ # end
57
+ #
58
+ # match 5, 6, 9 do |exten|
59
+ # play "The #{exten} extension is currently not active"
60
+ # end
61
+ #
62
+ # match '7', OfficeController
63
+ #
64
+ # invalid { play "Please choose a valid extension" }
65
+ # timeout { play "Input timed out, try again." }
66
+ # failure { pass OperatorController }
67
+ # end
68
+ #
69
+ # The first arguments will be a list of sounds to play, as accepted by #play, including strings for TTS, Date and Time objects, and file paths.
70
+ # :tries and :timeout options respectively specify the number of tries before going into failure, and the timeout in seconds allowed on each digit input.
71
+ # The most important part is the following block, which specifies how the menu will be constructed and handled.
72
+ #
73
+ # #match handles connecting an input pattern to a payload.
74
+ # The pattern can be one or more of: an integer, a Range, a string, an Array of the possible single types.
75
+ # Input is matched against patterns, and the first exact match has it's payload executed.
76
+ # Matched input is passed in to the associated block, or to the controller through #options.
77
+ #
78
+ # Allowed payloads are the name of a controller class, in which case it is executed through its #run method, or a block, which is executed in the context of the current controller.
79
+ #
80
+ # #invalid has its associated block executed when the input does not possibly match any pattern.
81
+ # #timeout's block is run when timeout expires before receiving any input
82
+ # #failure runs its block when the maximum number of tries is reached without an input match.
83
+ #
84
+ # Execution of the current context resumes after #menu finishes. If you wish to jump to an entirely different controller, use #pass.
85
+ # Menu will return :failed if failure was reached, or :done if a match was executed.
86
+ #
87
+ # @param [Object] args A list of outputs to play, as accepted by #play
88
+ # @param [Hash] options Options to use for the menu
89
+ # @option options [Integer] :tries Number of tries allowed before failure
90
+ # @option options [Integer] :timeout Timeout in seconds before the first and between each input digit
91
+ # @option options [Boolean] :interruptible If the prompt should be interruptible or not. Defaults to true
92
+ # @option options [Hash] :input_options A hash of options passed directly to the Punchblock Input constructor
93
+ # @option options [Hash] :output_options A hash of options passed directly to the Punchblock Output constructor
94
+ #
95
+ # @return [Result] a result object from which the details of the response may be established
96
+ #
97
+ # @see Output#play
98
+ # @see CallController#pass
99
+ #
100
+ def menu(*args, &block)
101
+ raise ArgumentError, "You must specify a block to build the menu" unless block
102
+ options = args.last.kind_of?(Hash) ? args.pop : {}
103
+ prompts = args.flatten
104
+
105
+ menu_builder = MenuBuilder.new(options, &block)
106
+
107
+ output_document = output_formatter.ssml_for_collection(prompts)
108
+
109
+ menu_builder.execute output_document, self
110
+ end
111
+ end
112
+ end
@@ -0,0 +1,122 @@
1
+ require 'adhearsion-asr/prompt_builder'
2
+
3
+ module AdhearsionASR
4
+ class MenuBuilder
5
+ def initialize(options, &block)
6
+ @options = options
7
+ @matchers = []
8
+ @callbacks = {}
9
+ build(&block)
10
+ end
11
+
12
+ def match(*args, &block)
13
+ payload = block || args.pop
14
+
15
+ @matchers << Matcher.new(payload, args)
16
+ end
17
+
18
+ def invalid(&block)
19
+ register_user_supplied_callback :nomatch, &block
20
+ end
21
+
22
+ def timeout(&block)
23
+ register_user_supplied_callback :noinput, &block
24
+ end
25
+
26
+ def failure(&block)
27
+ register_user_supplied_callback :failure, &block
28
+ end
29
+
30
+ def execute(output_document, controller)
31
+ catch :match do
32
+ (@options[:tries] || 1).times do
33
+ result = PromptBuilder.new(output_document, grammars, @options).execute(controller)
34
+ process_result result
35
+ end
36
+ execute_hook :failure
37
+ end
38
+ end
39
+
40
+ private
41
+
42
+ def grammars
43
+ @grammar ||= [{value: build_grammar}]
44
+ end
45
+
46
+ def process_result(result)
47
+ if result.status == :match
48
+ handle_match result
49
+ else
50
+ execute_hook result.status
51
+ end
52
+ end
53
+
54
+ def register_user_supplied_callback(name, &block)
55
+ @callbacks[name] = block
56
+ end
57
+
58
+ def execute_hook(hook_name)
59
+ callback = @callbacks[hook_name]
60
+ return unless callback
61
+ @context.instance_exec(&callback)
62
+ end
63
+
64
+ def handle_match(result)
65
+ match = @matchers[result.interpretation.to_i]
66
+ match.dispatch @context, result.response
67
+ throw :match
68
+ end
69
+
70
+ def build(&block)
71
+ @context = eval "self", block.binding
72
+ instance_eval(&block)
73
+ end
74
+
75
+ def build_grammar
76
+ raise ArgumentError, "You must specify one or more matches." if @matchers.count < 1
77
+ matchers = @matchers
78
+
79
+ RubySpeech::GRXML.draw mode: :dtmf, root: 'options', tag_format: 'semantics/1.0-literals' do
80
+ rule id: 'options', scope: 'public' do
81
+ item do
82
+ one_of do
83
+ matchers.each_with_index do |matcher, index|
84
+ item do
85
+ tag { index.to_s }
86
+ matcher.apply_to_grammar self
87
+ end
88
+ end
89
+ end
90
+ end
91
+ end
92
+ end
93
+ end
94
+
95
+ Matcher = Struct.new(:payload, :keys) do
96
+ def dispatch(controller, response)
97
+ if payload.is_a?(Proc)
98
+ controller.instance_exec response, &payload
99
+ else
100
+ controller.invoke payload, extension: response
101
+ end
102
+ end
103
+
104
+ def apply_to_grammar(grammar)
105
+ possible_options = calculate_possible_options
106
+ if possible_options.count > 1
107
+ grammar.one_of do
108
+ possible_options.each do |key|
109
+ item { key.to_s }
110
+ end
111
+ end
112
+ else
113
+ keys.first.to_s
114
+ end
115
+ end
116
+
117
+ def calculate_possible_options
118
+ keys.map { |key| key.respond_to?(:to_a) ? key.to_a : key }.flatten
119
+ end
120
+ end
121
+ end
122
+ end
@@ -0,0 +1,11 @@
1
+ module AdhearsionASR
2
+ class Plugin < Adhearsion::Plugin
3
+ config :adhearsion_asr do
4
+ min_confidence 0.5, desc: 'The default minimum confidence level used for all recognizer invocations.', transform: Proc.new { |v| v.to_f }
5
+ timeout 5, desc: 'The default timeout (in seconds) used for all recognizer invocations.', transform: Proc.new { |v| v.to_i }
6
+ recognizer nil, desc: 'The default recognizer used for all input. Set nil to use platform default.'
7
+ input_language 'en-US', desc: 'The default language set on generated grammars. Set nil to use platform default.'
8
+ renderer nil, desc: 'The default renderer used for all output. Set nil to use platform default.'
9
+ end
10
+ end
11
+ end
@@ -0,0 +1,54 @@
1
+ require 'adhearsion-asr/result'
2
+
3
+ module AdhearsionASR
4
+ class PromptBuilder
5
+ def initialize(output_document, grammars, options)
6
+ output_options = {
7
+ render_document: {value: output_document},
8
+ renderer: Plugin.config.renderer
9
+ }.merge(options[:output_options] || {})
10
+
11
+ input_options = {
12
+ mode: :dtmf,
13
+ initial_timeout: (options[:timeout] || Plugin.config.timeout) * 1000,
14
+ inter_digit_timeout: (options[:timeout] || Plugin.config.timeout) * 1000,
15
+ max_silence: (options[:timeout] || Plugin.config.timeout) * 1000,
16
+ min_confidence: Plugin.config.min_confidence,
17
+ grammars: grammars,
18
+ recognizer: Plugin.config.recognizer,
19
+ language: Plugin.config.input_language,
20
+ terminator: options[:terminator]
21
+ }.merge(options[:input_options] || {})
22
+
23
+ @prompt = Punchblock::Component::Prompt.new output_options, input_options, barge_in: options.has_key?(:interruptible) ? options[:interruptible] : true
24
+ end
25
+
26
+ def execute(controller)
27
+ controller.execute_component_and_await_completion @prompt
28
+
29
+ result @prompt.complete_event.reason
30
+ end
31
+
32
+ private
33
+
34
+ def result(reason)
35
+ Result.new.tap do |result|
36
+ case reason
37
+ when proc { |r| r.respond_to? :nlsml }
38
+ result.status = :match
39
+ result.confidence = reason.confidence
40
+ result.response = reason.utterance
41
+ result.interpretation = reason.interpretation
42
+ result.nlsml = reason.nlsml
43
+ when Punchblock::Event::Complete::Error
44
+ raise Error, reason.details
45
+ when Punchblock::Event::Complete::Reason
46
+ result.status = reason.name
47
+ else
48
+ raise "Unknown completion reason received: #{reason}"
49
+ end
50
+ logger.debug "Ask completed with result #{result.inspect}"
51
+ end
52
+ end
53
+ end
54
+ end
@@ -0,0 +1,11 @@
1
+ module AdhearsionASR
2
+ Result = Struct.new(:status, :confidence, :response, :interpretation, :nlsml) do
3
+ def to_s
4
+ response
5
+ end
6
+
7
+ def inspect
8
+ "#<#{self.class} status=#{status.inspect}, confidence=#{confidence.inspect}, response=#{response.inspect}, interpretation=#{interpretation.inspect}, nlsml=#{nlsml.inspect}>"
9
+ end
10
+ end
11
+ end
@@ -0,0 +1,3 @@
1
+ module AdhearsionASR
2
+ VERSION = "0.1.0"
3
+ end
@@ -0,0 +1,7 @@
1
+ module AdhearsionASR
2
+ Error = Class.new Adhearsion::Error
3
+ end
4
+
5
+ require "adhearsion-asr/version"
6
+ require "adhearsion-asr/plugin"
7
+ require "adhearsion-asr/controller_methods"