ruby_speech 2.1.0-java
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- data/.gitignore +12 -0
- data/.rspec +3 -0
- data/.travis.yml +17 -0
- data/CHANGELOG.md +144 -0
- data/Gemfile +3 -0
- data/Guardfile +9 -0
- data/LICENSE.md +20 -0
- data/README.md +314 -0
- data/Rakefile +34 -0
- data/assets/grammar-core.xsd +317 -0
- data/assets/grammar.xsd +37 -0
- data/assets/synthesis-core.xsd +445 -0
- data/assets/synthesis.xsd +63 -0
- data/assets/xml.xsd +287 -0
- data/ext/ruby_speech/RubySpeechGRXMLMatcher.java +64 -0
- data/ext/ruby_speech/RubySpeechService.java +23 -0
- data/ext/ruby_speech/extconf.rb +7 -0
- data/ext/ruby_speech/ruby_speech.c +97 -0
- data/lib/ruby_speech/generic_element.rb +169 -0
- data/lib/ruby_speech/grxml/element.rb +29 -0
- data/lib/ruby_speech/grxml/grammar.rb +189 -0
- data/lib/ruby_speech/grxml/item.rb +144 -0
- data/lib/ruby_speech/grxml/match.rb +16 -0
- data/lib/ruby_speech/grxml/matcher.rb +126 -0
- data/lib/ruby_speech/grxml/max_match.rb +6 -0
- data/lib/ruby_speech/grxml/no_match.rb +10 -0
- data/lib/ruby_speech/grxml/one_of.rb +31 -0
- data/lib/ruby_speech/grxml/potential_match.rb +10 -0
- data/lib/ruby_speech/grxml/rule.rb +73 -0
- data/lib/ruby_speech/grxml/ruleref.rb +69 -0
- data/lib/ruby_speech/grxml/tag.rb +29 -0
- data/lib/ruby_speech/grxml/token.rb +31 -0
- data/lib/ruby_speech/grxml.rb +39 -0
- data/lib/ruby_speech/nlsml/builder.rb +34 -0
- data/lib/ruby_speech/nlsml/document.rb +120 -0
- data/lib/ruby_speech/nlsml.rb +18 -0
- data/lib/ruby_speech/ruby_speech.jar +0 -0
- data/lib/ruby_speech/ssml/audio.rb +47 -0
- data/lib/ruby_speech/ssml/break.rb +62 -0
- data/lib/ruby_speech/ssml/desc.rb +24 -0
- data/lib/ruby_speech/ssml/element.rb +23 -0
- data/lib/ruby_speech/ssml/emphasis.rb +44 -0
- data/lib/ruby_speech/ssml/mark.rb +43 -0
- data/lib/ruby_speech/ssml/p.rb +25 -0
- data/lib/ruby_speech/ssml/phoneme.rb +72 -0
- data/lib/ruby_speech/ssml/prosody.rb +172 -0
- data/lib/ruby_speech/ssml/s.rb +25 -0
- data/lib/ruby_speech/ssml/say_as.rb +100 -0
- data/lib/ruby_speech/ssml/speak.rb +27 -0
- data/lib/ruby_speech/ssml/sub.rb +42 -0
- data/lib/ruby_speech/ssml/voice.rb +108 -0
- data/lib/ruby_speech/ssml.rb +39 -0
- data/lib/ruby_speech/version.rb +3 -0
- data/lib/ruby_speech/xml/language.rb +13 -0
- data/lib/ruby_speech/xml.rb +11 -0
- data/lib/ruby_speech.rb +36 -0
- data/ruby_speech.gemspec +42 -0
- data/spec/ruby_speech/grxml/grammar_spec.rb +341 -0
- data/spec/ruby_speech/grxml/item_spec.rb +192 -0
- data/spec/ruby_speech/grxml/match_spec.rb +15 -0
- data/spec/ruby_speech/grxml/matcher_spec.rb +688 -0
- data/spec/ruby_speech/grxml/max_match_spec.rb +17 -0
- data/spec/ruby_speech/grxml/no_match_spec.rb +17 -0
- data/spec/ruby_speech/grxml/one_of_spec.rb +49 -0
- data/spec/ruby_speech/grxml/potential_match_spec.rb +17 -0
- data/spec/ruby_speech/grxml/rule_spec.rb +125 -0
- data/spec/ruby_speech/grxml/ruleref_spec.rb +55 -0
- data/spec/ruby_speech/grxml/tag_spec.rb +41 -0
- data/spec/ruby_speech/grxml/token_spec.rb +62 -0
- data/spec/ruby_speech/grxml_spec.rb +339 -0
- data/spec/ruby_speech/nlsml_spec.rb +353 -0
- data/spec/ruby_speech/ssml/audio_spec.rb +121 -0
- data/spec/ruby_speech/ssml/break_spec.rb +100 -0
- data/spec/ruby_speech/ssml/desc_spec.rb +57 -0
- data/spec/ruby_speech/ssml/emphasis_spec.rb +110 -0
- data/spec/ruby_speech/ssml/mark_spec.rb +53 -0
- data/spec/ruby_speech/ssml/p_spec.rb +96 -0
- data/spec/ruby_speech/ssml/phoneme_spec.rb +65 -0
- data/spec/ruby_speech/ssml/prosody_spec.rb +309 -0
- data/spec/ruby_speech/ssml/s_spec.rb +92 -0
- data/spec/ruby_speech/ssml/say_as_spec.rb +71 -0
- data/spec/ruby_speech/ssml/speak_spec.rb +166 -0
- data/spec/ruby_speech/ssml/sub_spec.rb +57 -0
- data/spec/ruby_speech/ssml/voice_spec.rb +200 -0
- data/spec/ruby_speech/ssml_spec.rb +285 -0
- data/spec/ruby_speech_spec.rb +124 -0
- data/spec/spec_helper.rb +21 -0
- data/spec/support/match_examples.rb +43 -0
- data/spec/support/matchers.rb +46 -0
- metadata +405 -0
|
@@ -0,0 +1,339 @@
|
|
|
1
|
+
require 'spec_helper'
|
|
2
|
+
|
|
3
|
+
module RubySpeech
|
|
4
|
+
describe GRXML do
|
|
5
|
+
describe "#draw" do
|
|
6
|
+
it "should create a GRXML document" do
|
|
7
|
+
GRXML.draw.should == GRXML::Grammar.new
|
|
8
|
+
end
|
|
9
|
+
|
|
10
|
+
context "with a root rule name specified but not found" do
|
|
11
|
+
it "should raise an error" do
|
|
12
|
+
lambda do
|
|
13
|
+
GRXML.draw :root => 'foo' do
|
|
14
|
+
rule :id => 'bar' do
|
|
15
|
+
'6'
|
|
16
|
+
end
|
|
17
|
+
end
|
|
18
|
+
end.should raise_error(InvalidChildError, "A GRXML document must have a rule matching the root rule name")
|
|
19
|
+
end
|
|
20
|
+
end
|
|
21
|
+
|
|
22
|
+
# TODO: Maybe GRXML#draw should create a Rule to pass the string
|
|
23
|
+
describe "when the return value of the block is a string" do
|
|
24
|
+
it "should be inserted into the document" do
|
|
25
|
+
lambda { GRXML.draw { "Hello Fred" }}.should raise_error(InvalidChildError, "A Grammar can only accept Rule and Tag as children")
|
|
26
|
+
end
|
|
27
|
+
end
|
|
28
|
+
|
|
29
|
+
it "should allow other GRXML elements to be inserted in the document" do
|
|
30
|
+
doc = GRXML.draw(:mode => :voice, :root => 'main') { rule :id => :main, :content => "Hello Fred" }
|
|
31
|
+
|
|
32
|
+
expected_doc = GRXML::Grammar.new(:mode => :voice, :root => 'main')
|
|
33
|
+
rule = GRXML::Rule.new(:id => "main")
|
|
34
|
+
rule << "Hello Fred"
|
|
35
|
+
expected_doc << rule
|
|
36
|
+
doc.should == expected_doc
|
|
37
|
+
end
|
|
38
|
+
|
|
39
|
+
it "should allow accessing methods defined outside the block" do
|
|
40
|
+
def foo
|
|
41
|
+
'bar'
|
|
42
|
+
end
|
|
43
|
+
|
|
44
|
+
doc = GRXML.draw do
|
|
45
|
+
rule :id => foo
|
|
46
|
+
end
|
|
47
|
+
|
|
48
|
+
expected_doc = GRXML::Grammar.new
|
|
49
|
+
rule = GRXML::Rule.new(:id => foo)
|
|
50
|
+
expected_doc << rule
|
|
51
|
+
doc.should == expected_doc
|
|
52
|
+
end
|
|
53
|
+
|
|
54
|
+
it "should raise error if given an empty rule" do
|
|
55
|
+
pending 'Reject empty rules -- http://www.w3.org/TR/2002/CR-speech-grammar-20020626/#S3.1 http://www.w3.org/Voice/2003/srgs-ir/test/rule-no-empty.grxml'
|
|
56
|
+
lambda { GRXML.draw { rule :id => 'main' }}.should raise_error
|
|
57
|
+
end
|
|
58
|
+
|
|
59
|
+
it "should allow nested block return values" do
|
|
60
|
+
doc = RubySpeech::GRXML.draw do
|
|
61
|
+
rule :scope => 'public', :id => :main do
|
|
62
|
+
"Hello Fred"
|
|
63
|
+
end
|
|
64
|
+
end
|
|
65
|
+
expected_doc = GRXML::Grammar.new
|
|
66
|
+
expected_doc << GRXML::Rule.new(:scope => :public, :id => :main, :content => "Hello Fred")
|
|
67
|
+
doc.should == expected_doc
|
|
68
|
+
end
|
|
69
|
+
|
|
70
|
+
it "should allow nested GRXML elements" do
|
|
71
|
+
doc = RubySpeech::GRXML.draw do
|
|
72
|
+
rule :id => :main, :scope => 'public' do
|
|
73
|
+
string "Hello Fred. I like ninjas and pirates"
|
|
74
|
+
one_of do
|
|
75
|
+
item :content => "ninja"
|
|
76
|
+
item :content => "pirate"
|
|
77
|
+
end
|
|
78
|
+
end
|
|
79
|
+
end
|
|
80
|
+
rule = GRXML::Rule.new(:id => :main, :scope => 'public', :content => "Hello Fred. I like ninjas and pirates")
|
|
81
|
+
oneof = GRXML::OneOf.new
|
|
82
|
+
oneof << GRXML::Item.new(:content => "ninja")
|
|
83
|
+
oneof << GRXML::Item.new(:content => "pirate")
|
|
84
|
+
rule << oneof
|
|
85
|
+
expected_doc = GRXML::Grammar.new
|
|
86
|
+
expected_doc << rule
|
|
87
|
+
doc.should == expected_doc
|
|
88
|
+
end
|
|
89
|
+
|
|
90
|
+
# TODO: maybe turn a rule embedded in anthoer rule into a ruleref??
|
|
91
|
+
describe "embedding" do
|
|
92
|
+
context "GRXML documents" do
|
|
93
|
+
let :doc1 do
|
|
94
|
+
RubySpeech::GRXML.draw :mode => :dtmf, :root => 'digits' do
|
|
95
|
+
rule :id => :digits do
|
|
96
|
+
one_of do
|
|
97
|
+
item { "1" }
|
|
98
|
+
item { "2" }
|
|
99
|
+
end
|
|
100
|
+
end
|
|
101
|
+
end
|
|
102
|
+
end
|
|
103
|
+
|
|
104
|
+
let :doc2 do
|
|
105
|
+
doc = doc1
|
|
106
|
+
RubySpeech::GRXML.draw :mode => :dtmf do
|
|
107
|
+
embed doc
|
|
108
|
+
rule :id => :main do
|
|
109
|
+
"Hello Fred"
|
|
110
|
+
end
|
|
111
|
+
end
|
|
112
|
+
end
|
|
113
|
+
|
|
114
|
+
let :expected_doc do
|
|
115
|
+
RubySpeech::GRXML.draw :mode => :dtmf do
|
|
116
|
+
rule :id => :digits do
|
|
117
|
+
one_of do
|
|
118
|
+
item :content => "1"
|
|
119
|
+
item :content => "2"
|
|
120
|
+
end
|
|
121
|
+
end
|
|
122
|
+
rule :id => :main, :content => 'Hello Fred'
|
|
123
|
+
end
|
|
124
|
+
end
|
|
125
|
+
|
|
126
|
+
it "should embed the document" do
|
|
127
|
+
doc2.should == expected_doc
|
|
128
|
+
end
|
|
129
|
+
|
|
130
|
+
context "of different modes (dtmf in voice or vice-versa)" do
|
|
131
|
+
let :voice_doc do
|
|
132
|
+
GRXML.draw :mode => :voice do
|
|
133
|
+
embed dtmf_doc
|
|
134
|
+
end
|
|
135
|
+
end
|
|
136
|
+
|
|
137
|
+
let :dtmf_doc do
|
|
138
|
+
GRXML.draw :mode => :dtmf do
|
|
139
|
+
rule do
|
|
140
|
+
'6'
|
|
141
|
+
end
|
|
142
|
+
end
|
|
143
|
+
end
|
|
144
|
+
|
|
145
|
+
it "should raise an exception" do
|
|
146
|
+
lambda { voice_doc }.should raise_error(InvalidChildError, "Embedded grammars must have the same mode")
|
|
147
|
+
end
|
|
148
|
+
end
|
|
149
|
+
end
|
|
150
|
+
|
|
151
|
+
it "GRXML elements" do
|
|
152
|
+
element = GRXML::Item.new :content => "HELLO?"
|
|
153
|
+
|
|
154
|
+
doc = RubySpeech::GRXML.draw do
|
|
155
|
+
rule :id => :main, :scope => 'public' do
|
|
156
|
+
embed element
|
|
157
|
+
end
|
|
158
|
+
end
|
|
159
|
+
|
|
160
|
+
expected_doc = RubySpeech::GRXML.draw do
|
|
161
|
+
rule :id => :main, :scope => 'public' do
|
|
162
|
+
item do
|
|
163
|
+
"HELLO?"
|
|
164
|
+
end
|
|
165
|
+
end
|
|
166
|
+
end
|
|
167
|
+
|
|
168
|
+
doc.should == expected_doc
|
|
169
|
+
end
|
|
170
|
+
|
|
171
|
+
it "strings" do
|
|
172
|
+
string = "How now, brown cow?"
|
|
173
|
+
|
|
174
|
+
doc = RubySpeech::GRXML.draw do
|
|
175
|
+
rule :id => :main, :scope => 'public' do
|
|
176
|
+
embed string
|
|
177
|
+
end
|
|
178
|
+
end
|
|
179
|
+
|
|
180
|
+
expected_doc = RubySpeech::GRXML.draw do
|
|
181
|
+
rule :id => :main, :scope => 'public' do
|
|
182
|
+
string "How now, brown cow?"
|
|
183
|
+
end
|
|
184
|
+
end
|
|
185
|
+
|
|
186
|
+
doc.should == expected_doc
|
|
187
|
+
end
|
|
188
|
+
end
|
|
189
|
+
|
|
190
|
+
it "should properly escape string input" do
|
|
191
|
+
doc = RubySpeech::GRXML.draw do
|
|
192
|
+
rule { string "I <3 nachos." }
|
|
193
|
+
rule { "I <3 nachos." }
|
|
194
|
+
rule { 'I <3 nachos.' }
|
|
195
|
+
end
|
|
196
|
+
expected_doc = GRXML::Grammar.new
|
|
197
|
+
3.times do
|
|
198
|
+
expected_doc << GRXML::Rule.new(:native_content => "I <3 nachos.")
|
|
199
|
+
end
|
|
200
|
+
doc.should == expected_doc
|
|
201
|
+
end
|
|
202
|
+
|
|
203
|
+
# TODO: verfify rule is in document if named in a ruleref
|
|
204
|
+
# TODO: ruleref must have named rule id
|
|
205
|
+
|
|
206
|
+
it "should allow all permutations of possible nested GRXML elements" do
|
|
207
|
+
doc = RubySpeech::GRXML.draw do
|
|
208
|
+
rule :id => "hello" do
|
|
209
|
+
string "HELLO?"
|
|
210
|
+
item :weight => 2.5
|
|
211
|
+
one_of do
|
|
212
|
+
item { "1" }
|
|
213
|
+
item { "2" }
|
|
214
|
+
end
|
|
215
|
+
ruleref :uri => '#test'
|
|
216
|
+
item { "last" }
|
|
217
|
+
end
|
|
218
|
+
rule :id => "test" do
|
|
219
|
+
string "TESTING"
|
|
220
|
+
end
|
|
221
|
+
rule :id => :hello2 do
|
|
222
|
+
item :weight => 5.5 do
|
|
223
|
+
"hello"
|
|
224
|
+
end
|
|
225
|
+
string "H...E...L...L...O?"
|
|
226
|
+
token { "test token" }
|
|
227
|
+
tag { }
|
|
228
|
+
item { "" }
|
|
229
|
+
one_of { item { "single item" } }
|
|
230
|
+
end
|
|
231
|
+
end
|
|
232
|
+
expected_doc = GRXML::Grammar.new
|
|
233
|
+
rule = GRXML::Rule.new(:id => "hello", :content => "HELLO?")
|
|
234
|
+
rule << GRXML::Item.new(:weight => 2.5)
|
|
235
|
+
oneof = GRXML::OneOf.new
|
|
236
|
+
1.upto(2) { |d| oneof << GRXML::Item.new(:content => d.to_s) }
|
|
237
|
+
rule << oneof
|
|
238
|
+
rule << GRXML::Ruleref.new(:uri => '#test')
|
|
239
|
+
rule << GRXML::Item.new(:content => "last")
|
|
240
|
+
expected_doc << rule
|
|
241
|
+
|
|
242
|
+
rule = GRXML::Rule.new(:id => "test", :content => "TESTING")
|
|
243
|
+
expected_doc << rule
|
|
244
|
+
|
|
245
|
+
rule = GRXML::Rule.new(:id => "hello2")
|
|
246
|
+
rule << GRXML::Item.new(:weight => 5.5, :content => "hello")
|
|
247
|
+
rule << "H...E...L...L...O?"
|
|
248
|
+
rule << GRXML::Token.new(:content => "test token")
|
|
249
|
+
rule << GRXML::Tag.new
|
|
250
|
+
rule << GRXML::Item.new
|
|
251
|
+
oneof = GRXML::OneOf.new
|
|
252
|
+
oneof << GRXML::Item.new(:content => "single item")
|
|
253
|
+
rule << oneof
|
|
254
|
+
expected_doc << rule
|
|
255
|
+
doc.should == expected_doc
|
|
256
|
+
end
|
|
257
|
+
|
|
258
|
+
describe "importing nested tags" do
|
|
259
|
+
let(:item) { GRXML::Item.new(:weight => 1.5, :content => "Are you a pirate or ninja?") }
|
|
260
|
+
let(:string) { "Hello Fred. I like pirates and ninjas " }
|
|
261
|
+
let :rule do
|
|
262
|
+
GRXML::Rule.new(:id => :main, :scope => 'public', :content => string).tap do |rule|
|
|
263
|
+
rule << item
|
|
264
|
+
end
|
|
265
|
+
end
|
|
266
|
+
|
|
267
|
+
let :document do
|
|
268
|
+
GRXML::Grammar.new.tap { |doc| doc << rule }.to_s
|
|
269
|
+
end
|
|
270
|
+
|
|
271
|
+
let(:import) { GRXML.import document }
|
|
272
|
+
|
|
273
|
+
subject { import }
|
|
274
|
+
|
|
275
|
+
it "should work" do
|
|
276
|
+
lambda { subject }.should_not raise_error
|
|
277
|
+
end
|
|
278
|
+
|
|
279
|
+
it { should be_a GRXML::Grammar }
|
|
280
|
+
|
|
281
|
+
its(:children) { should == [rule] }
|
|
282
|
+
|
|
283
|
+
describe "rule" do
|
|
284
|
+
subject { import.children.first }
|
|
285
|
+
its(:children) { should == [string,item] }
|
|
286
|
+
end
|
|
287
|
+
end
|
|
288
|
+
|
|
289
|
+
it "should allow finding direct children of a particular type, matching certain attributes" do
|
|
290
|
+
item = GRXML::Item.new
|
|
291
|
+
item1 = GRXML::Item.new :weight => 0.5
|
|
292
|
+
item11 = GRXML::Item.new :weight => 0.5
|
|
293
|
+
item1 << item11
|
|
294
|
+
item << item1
|
|
295
|
+
item2 = GRXML::Item.new :weight => 0.7
|
|
296
|
+
item << item2
|
|
297
|
+
tag = GRXML::Tag.new
|
|
298
|
+
item << tag
|
|
299
|
+
|
|
300
|
+
item.children(:item, :weight => 0.5).should == [item1]
|
|
301
|
+
end
|
|
302
|
+
|
|
303
|
+
it "should be able to traverse up the tree" do
|
|
304
|
+
grammar = GRXML.draw do
|
|
305
|
+
rule :id => 'one' do
|
|
306
|
+
item do
|
|
307
|
+
'foobar'
|
|
308
|
+
end
|
|
309
|
+
end
|
|
310
|
+
end
|
|
311
|
+
|
|
312
|
+
rule = grammar.children.first
|
|
313
|
+
rule.parent.should == grammar
|
|
314
|
+
|
|
315
|
+
item = rule.children.first
|
|
316
|
+
item.parent.should == rule
|
|
317
|
+
|
|
318
|
+
text = item.nokogiri_children.first
|
|
319
|
+
text.parent.should == item
|
|
320
|
+
end
|
|
321
|
+
end # draw
|
|
322
|
+
|
|
323
|
+
describe "manually created documents" do
|
|
324
|
+
it "should be able to traverse up the tree" do
|
|
325
|
+
grammar = GRXML::Grammar.new
|
|
326
|
+
rule = GRXML::Rule.new :id => 'one'
|
|
327
|
+
item = GRXML::Item.new
|
|
328
|
+
text = Nokogiri::XML::Text.new 'foobar', grammar.document
|
|
329
|
+
item << text
|
|
330
|
+
rule << item
|
|
331
|
+
grammar << rule
|
|
332
|
+
|
|
333
|
+
text.parent.should == item
|
|
334
|
+
item.parent.should == rule
|
|
335
|
+
rule.parent.should == grammar
|
|
336
|
+
end
|
|
337
|
+
end
|
|
338
|
+
end # GRXML
|
|
339
|
+
end # RubySpeech
|
|
@@ -0,0 +1,353 @@
|
|
|
1
|
+
require 'spec_helper'
|
|
2
|
+
|
|
3
|
+
describe RubySpeech::NLSML do
|
|
4
|
+
let :example_document do
|
|
5
|
+
'''
|
|
6
|
+
<result xmlns="http://www.ietf.org/xml/ns/mrcpv2" grammar="http://flight">
|
|
7
|
+
<interpretation confidence="0.6">
|
|
8
|
+
<input mode="speech">I want to go to Pittsburgh</input>
|
|
9
|
+
<instance>
|
|
10
|
+
<airline>
|
|
11
|
+
<to_city>Pittsburgh</to_city>
|
|
12
|
+
</airline>
|
|
13
|
+
</instance>
|
|
14
|
+
</interpretation>
|
|
15
|
+
<interpretation confidence="0.4">
|
|
16
|
+
<input>I want to go to Stockholm</input>
|
|
17
|
+
<instance>
|
|
18
|
+
<airline>
|
|
19
|
+
<to_city>Stockholm</to_city>
|
|
20
|
+
</airline>
|
|
21
|
+
</instance>
|
|
22
|
+
</interpretation>
|
|
23
|
+
</result>
|
|
24
|
+
'''
|
|
25
|
+
end
|
|
26
|
+
|
|
27
|
+
describe 'drawing a document' do
|
|
28
|
+
let :expected_document do
|
|
29
|
+
Nokogiri::XML(example_document, nil, nil, Nokogiri::XML::ParseOptions::NOBLANKS).to_xml
|
|
30
|
+
end
|
|
31
|
+
|
|
32
|
+
it "should allow building a document" do
|
|
33
|
+
document = RubySpeech::NLSML.draw(grammar: 'http://flight') do
|
|
34
|
+
interpretation confidence: 0.6 do
|
|
35
|
+
input "I want to go to Pittsburgh", mode: :speech
|
|
36
|
+
|
|
37
|
+
instance do
|
|
38
|
+
airline do
|
|
39
|
+
to_city 'Pittsburgh'
|
|
40
|
+
end
|
|
41
|
+
end
|
|
42
|
+
end
|
|
43
|
+
|
|
44
|
+
interpretation confidence: 0.4 do
|
|
45
|
+
input "I want to go to Stockholm"
|
|
46
|
+
|
|
47
|
+
instance do
|
|
48
|
+
airline do
|
|
49
|
+
to_city "Stockholm"
|
|
50
|
+
end
|
|
51
|
+
end
|
|
52
|
+
end
|
|
53
|
+
end
|
|
54
|
+
|
|
55
|
+
document.to_xml.should == expected_document
|
|
56
|
+
end
|
|
57
|
+
|
|
58
|
+
context "with a string instance" do
|
|
59
|
+
let :example_document do
|
|
60
|
+
'''
|
|
61
|
+
<result xmlns="http://www.ietf.org/xml/ns/mrcpv2" grammar="http://flight">
|
|
62
|
+
<interpretation confidence="0.6">
|
|
63
|
+
<input mode="speech">I want to go to Pittsburgh</input>
|
|
64
|
+
<instance>I want to go to Pittsburgh</instance>
|
|
65
|
+
</interpretation>
|
|
66
|
+
</result>
|
|
67
|
+
'''
|
|
68
|
+
end
|
|
69
|
+
|
|
70
|
+
it "should allow building a document" do
|
|
71
|
+
document = RubySpeech::NLSML.draw(grammar: 'http://flight') do
|
|
72
|
+
interpretation confidence: 0.6 do
|
|
73
|
+
input "I want to go to Pittsburgh", mode: :speech
|
|
74
|
+
|
|
75
|
+
instance "I want to go to Pittsburgh"
|
|
76
|
+
end
|
|
77
|
+
end
|
|
78
|
+
|
|
79
|
+
document.to_xml.should == expected_document
|
|
80
|
+
end
|
|
81
|
+
end
|
|
82
|
+
end
|
|
83
|
+
|
|
84
|
+
describe "parsing a document" do
|
|
85
|
+
subject do
|
|
86
|
+
RubySpeech.parse example_document
|
|
87
|
+
end
|
|
88
|
+
|
|
89
|
+
let(:empty_result) { '<result xmlns="http://www.ietf.org/xml/ns/mrcpv2"/>' }
|
|
90
|
+
|
|
91
|
+
its(:grammar) { should == 'http://flight' }
|
|
92
|
+
|
|
93
|
+
it { should be_match }
|
|
94
|
+
|
|
95
|
+
let(:expected_best_interpretation) do
|
|
96
|
+
{
|
|
97
|
+
confidence: 0.6,
|
|
98
|
+
input: { mode: :speech, content: 'I want to go to Pittsburgh' },
|
|
99
|
+
instance: { airline: { to_city: 'Pittsburgh' } },
|
|
100
|
+
instances: [{ airline: { to_city: 'Pittsburgh' } }]
|
|
101
|
+
}
|
|
102
|
+
end
|
|
103
|
+
|
|
104
|
+
let(:expected_interpretations) do
|
|
105
|
+
[
|
|
106
|
+
expected_best_interpretation,
|
|
107
|
+
{
|
|
108
|
+
confidence: 0.4,
|
|
109
|
+
input: { content: 'I want to go to Stockholm' },
|
|
110
|
+
instance: { airline: { to_city: 'Stockholm' } },
|
|
111
|
+
instances: [{ airline: { to_city: 'Stockholm' } }]
|
|
112
|
+
}
|
|
113
|
+
]
|
|
114
|
+
end
|
|
115
|
+
|
|
116
|
+
its(:interpretations) { should == expected_interpretations }
|
|
117
|
+
its(:best_interpretation) { should == expected_best_interpretation }
|
|
118
|
+
|
|
119
|
+
it "should be equal if the XML is the same" do
|
|
120
|
+
subject.should be == RubySpeech.parse(example_document)
|
|
121
|
+
end
|
|
122
|
+
|
|
123
|
+
it "should not be equal if the XML is different" do
|
|
124
|
+
subject.should_not be == RubySpeech.parse(empty_result)
|
|
125
|
+
end
|
|
126
|
+
|
|
127
|
+
context "with an interpretation that has no instance" do
|
|
128
|
+
let :example_document do
|
|
129
|
+
'''
|
|
130
|
+
<result xmlns="http://www.ietf.org/xml/ns/mrcpv2" grammar="http://flight">
|
|
131
|
+
<interpretation confidence="0.6">
|
|
132
|
+
<input mode="speech">I want to go to Pittsburgh</input>
|
|
133
|
+
</interpretation>
|
|
134
|
+
<interpretation confidence="0.4">
|
|
135
|
+
<input>I want to go to Stockholm</input>
|
|
136
|
+
</interpretation>
|
|
137
|
+
</result>
|
|
138
|
+
'''
|
|
139
|
+
end
|
|
140
|
+
|
|
141
|
+
let(:expected_best_interpretation) do
|
|
142
|
+
{
|
|
143
|
+
confidence: 0.6,
|
|
144
|
+
input: { mode: :speech, content: 'I want to go to Pittsburgh' },
|
|
145
|
+
instance: nil,
|
|
146
|
+
instances: []
|
|
147
|
+
}
|
|
148
|
+
end
|
|
149
|
+
|
|
150
|
+
let(:expected_interpretations) do
|
|
151
|
+
[
|
|
152
|
+
expected_best_interpretation,
|
|
153
|
+
{
|
|
154
|
+
confidence: 0.4,
|
|
155
|
+
input: { content: 'I want to go to Stockholm' },
|
|
156
|
+
instance: nil,
|
|
157
|
+
instances: []
|
|
158
|
+
}
|
|
159
|
+
]
|
|
160
|
+
end
|
|
161
|
+
|
|
162
|
+
its(:interpretations) { should == expected_interpretations }
|
|
163
|
+
its(:best_interpretation) { should == expected_best_interpretation }
|
|
164
|
+
end
|
|
165
|
+
|
|
166
|
+
context "with a string instance" do
|
|
167
|
+
let :example_document do
|
|
168
|
+
'''
|
|
169
|
+
<result xmlns="http://www.ietf.org/xml/ns/mrcpv2" grammar="http://flight">
|
|
170
|
+
<interpretation confidence="0.6">
|
|
171
|
+
<input mode="speech">I want to go to Pittsburgh</input>
|
|
172
|
+
<instance>I want to go to Pittsburgh</instance>
|
|
173
|
+
</interpretation>
|
|
174
|
+
</result>
|
|
175
|
+
'''
|
|
176
|
+
end
|
|
177
|
+
|
|
178
|
+
let(:expected_best_interpretation) do
|
|
179
|
+
{
|
|
180
|
+
confidence: 0.6,
|
|
181
|
+
input: { mode: :speech, content: 'I want to go to Pittsburgh' },
|
|
182
|
+
instance: 'I want to go to Pittsburgh',
|
|
183
|
+
instances: ['I want to go to Pittsburgh']
|
|
184
|
+
}
|
|
185
|
+
end
|
|
186
|
+
|
|
187
|
+
let(:expected_interpretations) do
|
|
188
|
+
[expected_best_interpretation]
|
|
189
|
+
end
|
|
190
|
+
|
|
191
|
+
its(:interpretations) { should == expected_interpretations }
|
|
192
|
+
its(:best_interpretation) { should == expected_best_interpretation }
|
|
193
|
+
end
|
|
194
|
+
|
|
195
|
+
context "without any interpretations" do
|
|
196
|
+
subject do
|
|
197
|
+
RubySpeech.parse empty_result
|
|
198
|
+
end
|
|
199
|
+
|
|
200
|
+
it { should_not be_match }
|
|
201
|
+
end
|
|
202
|
+
|
|
203
|
+
context "with interpretations out of confidence order" do
|
|
204
|
+
let :example_document do
|
|
205
|
+
'''
|
|
206
|
+
<result xmlns="http://www.ietf.org/xml/ns/mrcpv2" grammar="http://flight">
|
|
207
|
+
<interpretation confidence="0.4">
|
|
208
|
+
<input>I want to go to Stockholm</input>
|
|
209
|
+
<instance>
|
|
210
|
+
<airline>
|
|
211
|
+
<to_city>Stockholm</to_city>
|
|
212
|
+
</airline>
|
|
213
|
+
</instance>
|
|
214
|
+
</interpretation>
|
|
215
|
+
<interpretation confidence="0.6">
|
|
216
|
+
<input mode="speech">I want to go to Pittsburgh</input>
|
|
217
|
+
<instance>
|
|
218
|
+
<airline>
|
|
219
|
+
<to_city>Pittsburgh</to_city>
|
|
220
|
+
</airline>
|
|
221
|
+
</instance>
|
|
222
|
+
</interpretation>
|
|
223
|
+
</result>
|
|
224
|
+
'''
|
|
225
|
+
end
|
|
226
|
+
|
|
227
|
+
its(:interpretations) { should == expected_interpretations }
|
|
228
|
+
its(:best_interpretation) { should == expected_best_interpretation }
|
|
229
|
+
end
|
|
230
|
+
|
|
231
|
+
context "with multiple instances for a single interpretation" do
|
|
232
|
+
let :example_document do
|
|
233
|
+
'''
|
|
234
|
+
<result xmlns="http://www.ietf.org/xml/ns/mrcpv2" grammar="http://flight">
|
|
235
|
+
<interpretation confidence="1">
|
|
236
|
+
<input mode="speech">I want to go to Boston</input>
|
|
237
|
+
<instance>
|
|
238
|
+
<airline>
|
|
239
|
+
<to_city>Boston, MA</to_city>
|
|
240
|
+
</airline>
|
|
241
|
+
</instance>
|
|
242
|
+
<instance>
|
|
243
|
+
<airline>
|
|
244
|
+
<to_city>Boston, UK</to_city>
|
|
245
|
+
</airline>
|
|
246
|
+
</instance>
|
|
247
|
+
</interpretation>
|
|
248
|
+
</result>
|
|
249
|
+
'''
|
|
250
|
+
end
|
|
251
|
+
|
|
252
|
+
let(:expected_interpretation) do
|
|
253
|
+
{
|
|
254
|
+
confidence: 1.0,
|
|
255
|
+
input: { content: 'I want to go to Boston', mode: :speech },
|
|
256
|
+
instance: { airline: { to_city: 'Boston, MA' } },
|
|
257
|
+
instances: [
|
|
258
|
+
{ airline: { to_city: 'Boston, MA' } },
|
|
259
|
+
{ airline: { to_city: 'Boston, UK' } }
|
|
260
|
+
]
|
|
261
|
+
}
|
|
262
|
+
end
|
|
263
|
+
|
|
264
|
+
its(:interpretations) { should == [expected_interpretation] }
|
|
265
|
+
its(:best_interpretation) { should == expected_interpretation }
|
|
266
|
+
end
|
|
267
|
+
|
|
268
|
+
context "with no namespace" do
|
|
269
|
+
let :example_document do
|
|
270
|
+
'''
|
|
271
|
+
<result grammar="http://flight">
|
|
272
|
+
<interpretation confidence="0.6">
|
|
273
|
+
<input mode="speech">I want to go to Pittsburgh</input>
|
|
274
|
+
<instance>
|
|
275
|
+
<airline>
|
|
276
|
+
<to_city>Pittsburgh</to_city>
|
|
277
|
+
</airline>
|
|
278
|
+
</instance>
|
|
279
|
+
</interpretation>
|
|
280
|
+
<interpretation confidence="0.4">
|
|
281
|
+
<input>I want to go to Stockholm</input>
|
|
282
|
+
<instance>
|
|
283
|
+
<airline>
|
|
284
|
+
<to_city>Stockholm</to_city>
|
|
285
|
+
</airline>
|
|
286
|
+
</instance>
|
|
287
|
+
</interpretation>
|
|
288
|
+
</result>
|
|
289
|
+
'''
|
|
290
|
+
end
|
|
291
|
+
|
|
292
|
+
its(:interpretations) { should == expected_interpretations }
|
|
293
|
+
its(:best_interpretation) { should == expected_best_interpretation }
|
|
294
|
+
end
|
|
295
|
+
|
|
296
|
+
context "with a single interpretation with a nomatch input" do
|
|
297
|
+
let :example_document do
|
|
298
|
+
'''
|
|
299
|
+
<result xmlns="http://www.ietf.org/xml/ns/mrcpv2" grammar="http://flight">
|
|
300
|
+
<interpretation>
|
|
301
|
+
<input>
|
|
302
|
+
<nomatch/>
|
|
303
|
+
</input>
|
|
304
|
+
</interpretation>
|
|
305
|
+
</result>
|
|
306
|
+
'''
|
|
307
|
+
end
|
|
308
|
+
|
|
309
|
+
it { should_not be_match }
|
|
310
|
+
end
|
|
311
|
+
|
|
312
|
+
context "with multiple interpretations where one is a nomatch input" do
|
|
313
|
+
let :example_document do
|
|
314
|
+
'''
|
|
315
|
+
<result xmlns="http://www.ietf.org/xml/ns/mrcpv2" grammar="http://flight">
|
|
316
|
+
<interpretation confidence="0.6">
|
|
317
|
+
<input mode="speech">I want to go to Pittsburgh</input>
|
|
318
|
+
<instance>
|
|
319
|
+
<airline>
|
|
320
|
+
<to_city>Pittsburgh</to_city>
|
|
321
|
+
</airline>
|
|
322
|
+
</instance>
|
|
323
|
+
</interpretation>
|
|
324
|
+
<interpretation>
|
|
325
|
+
<input>
|
|
326
|
+
<nomatch/>
|
|
327
|
+
</input>
|
|
328
|
+
</interpretation>
|
|
329
|
+
</result>
|
|
330
|
+
'''
|
|
331
|
+
end
|
|
332
|
+
|
|
333
|
+
it { should be_match }
|
|
334
|
+
end
|
|
335
|
+
|
|
336
|
+
context "with a single interpretation with a noinput" do
|
|
337
|
+
let :example_document do
|
|
338
|
+
'''
|
|
339
|
+
<result xmlns="http://www.ietf.org/xml/ns/mrcpv2" grammar="http://flight">
|
|
340
|
+
<interpretation>
|
|
341
|
+
<input>
|
|
342
|
+
<noinput/>
|
|
343
|
+
</input>
|
|
344
|
+
</interpretation>
|
|
345
|
+
</result>
|
|
346
|
+
'''
|
|
347
|
+
end
|
|
348
|
+
|
|
349
|
+
it { should_not be_match }
|
|
350
|
+
it { should be_noinput }
|
|
351
|
+
end
|
|
352
|
+
end
|
|
353
|
+
end
|