alexa_generator 0.1.2 → 0.2.0

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.
checksums.yaml CHANGED
@@ -1,7 +1,7 @@
1
1
  ---
2
2
  SHA1:
3
- metadata.gz: 4805b19d31381011f755d8270dc535a64bb75879
4
- data.tar.gz: c0360ca35a27e1c95432681ba41c670c361e3606
3
+ metadata.gz: 5e8ba24c9e6ca19a170be8d4e925ac95e89511e2
4
+ data.tar.gz: 48408c740b0ec858c3159824f2ea190a9ff487df
5
5
  SHA512:
6
- metadata.gz: 3a760ba8c02c4f78922b4e42e4f93b6795c5f4b7a0d506b6ac67231df366194b1ba0320f4dd17e6089ff13dd58994ed089aee42f9834013acb6f66683c35b67a
7
- data.tar.gz: b50e3df34f7742573f1c2c49cacbe96aa96a54f358d56dc4098ae8991f0d6284ad389bfcb347fad5e88c61aa43038e2286153b1b2221384200fae7bb37c301eb
6
+ metadata.gz: 7048fadeedc9213ce2f34823c7a12257ea7092b32a3b1b691f175ea6d5cd374b927cff87907811871e75260c8066390fa83c9acf96283f2caee05edfeca53d7d
7
+ data.tar.gz: 4f94f8409c5e413a44f71b5ba2d1b5a6386bf4c8622c1b32d83b566a501f6779180ca947075980b0a88d8ac5b30eb2b6a35d68766f1331c6575a2c994f5cf3bb
@@ -1,4 +1,7 @@
1
1
  module AlexaGenerator
2
2
  class AlexaSyntaxError < StandardError
3
3
  end
4
+
5
+ class InvalidIntentError < StandardError
6
+ end
4
7
  end
@@ -3,6 +3,31 @@ require 'alexa_generator/sample_utterance_template'
3
3
 
4
4
  module AlexaGenerator
5
5
  class Intent
6
+
7
+ module AmazonIntentType
8
+ VALUES = [
9
+ CANCEL = :"AMAZON.CancelIntent",
10
+ HELP = :"AMAZON.HelpIntent",
11
+ LOOP_OFF = :"AMAZON.LoopOffIntent",
12
+ LOOP_ON = :"AMAZON.LoopOnIntent",
13
+ NEXT = :"AMAZON.NextIntent",
14
+ NO = :"AMAZON.NoIntent",
15
+ PAUSE = :"AMAZON.PauseIntent",
16
+ PREVIOUS = :"AMAZON.PreviousIntent",
17
+ REPEAT = :"AMAZON.RepeatIntent",
18
+ RESUME = :"AMAZON.ResumeIntent",
19
+ SHUFFLE_OFF = :"AMAZON.ShuffleOffIntent",
20
+ SHUFFLE_ON = :"AMAZON.ShuffleOnIntent",
21
+ START_OVER = :"AMAZON.StartOverIntent",
22
+ STOP = :"AMAZON.StopIntent",
23
+ YES = :"AMAZON.YesIntent"
24
+ ]
25
+
26
+ def self.amazon_intent?(val)
27
+ VALUES.include?(val.to_sym)
28
+ end
29
+ end
30
+
6
31
  attr_reader :name, :slots
7
32
 
8
33
  class Builder
@@ -16,6 +41,11 @@ module AlexaGenerator
16
41
  end
17
42
 
18
43
  def add_slot(name, type, &block)
44
+ if AmazonIntentType.amazon_intent?(@name)
45
+ raise AlexaGenerator::InvalidIntentError,
46
+ "Amazon intents don't support slots. Tried to add a slot to intent of type: #{type}"
47
+ end
48
+
19
49
  builder = Slot.build(name, type, &block)
20
50
 
21
51
  slot_bindings = builder.bindings.map { |x| SlotBinding.new(name, x) }
@@ -41,10 +71,14 @@ module AlexaGenerator
41
71
  @name = name
42
72
  @slots = slots
43
73
  end
74
+
75
+ def amazon_intent?
76
+ AmazonIntentType.amazon_intent?(@name)
77
+ end
44
78
 
45
79
  def self.build(name, &block)
46
80
  builder = Builder.new(name)
47
- block.call(builder)
81
+ block.call(builder) if block
48
82
  builder
49
83
  end
50
84
  end
@@ -45,29 +45,35 @@ module AlexaGenerator
45
45
  end
46
46
 
47
47
  def intent_schema
48
- {
49
- intents: @intents.values.map do |intent|
50
- {
51
- intent: intent.name,
52
- slots: intent.slots.map do |slot|
53
- {
54
- name: slot.name,
55
- type: slot.type
56
- }
57
- end
58
- }
59
- end
60
- }
48
+ intents = []
49
+
50
+ @intents.values.each do |intent|
51
+ slots = []
52
+
53
+ intent.slots.each do |slot|
54
+ slots << {name: slot.name, type: slot.type}
55
+ end
56
+
57
+ intents << {intent: intent.name, slots: slots}
58
+ end
59
+
60
+ { intents: intents }
61
61
  end
62
62
 
63
63
  def sample_utterances(intent_name)
64
64
  templates = @utterance_templates[intent_name] || []
65
+ slot_types = collect_slot_types
65
66
  utterances = Set.new
66
67
 
67
68
  templates.each do |template|
68
69
  # Consider only the slots that are referenced in this template
69
70
  relevant_slots = template.referenced_slots
70
71
 
72
+ # Amazon wants only the LITERAL ones
73
+ relevant_slots.select! do |s|
74
+ AlexaGenerator::Slot::SlotType.literal?(slot_types[s.to_sym])
75
+ end
76
+
71
77
  # Compute all possible value bindings for the relevant slots
72
78
  slot_values = relevant_slots.
73
79
  # Extract value bindings for each slot
@@ -106,6 +112,16 @@ module AlexaGenerator
106
112
  end
107
113
  end
108
114
 
115
+ def collect_slot_types
116
+ out = {}
117
+ @intents.values.each do |intent|
118
+ intent.slots.map do |slot|
119
+ out[slot.name.to_sym] = slot.type.to_s
120
+ end
121
+ end
122
+ out
123
+ end
124
+
109
125
  def self.build(&block)
110
126
  builder = Builder.new
111
127
  block.call(builder)
@@ -1,11 +1,15 @@
1
1
  module AlexaGenerator
2
2
  class Slot
3
3
  module SlotType
4
- LITERAL = :LITERAL
5
- NUMBER = :NUMBER
6
- DATE = :DATE
7
- TIME = :TIME
8
- DURATION = :DURATION
4
+ LITERAL = :"AMAZON.LITERAL"
5
+ NUMBER = :"AMAZON.NUMBER"
6
+ DATE = :"AMAZON.DATE"
7
+ TIME = :"AMAZON.TIME"
8
+ DURATION = :"AMAZON.DURATION"
9
+
10
+ def self.literal?(value)
11
+ [:LITERAL, LITERAL].include?(value.to_sym)
12
+ end
9
13
  end
10
14
 
11
15
  class Builder
@@ -1,3 +1,3 @@
1
1
  module AlexaGenerator
2
- VERSION = '0.1.2'
2
+ VERSION = '0.2.0'
3
3
  end
@@ -1,3 +1,3 @@
1
1
  require 'alexa_generator/interaction_model'
2
- require 'alexa_generator/alexa_syntax_error'
2
+ require 'alexa_generator/errors'
3
3
  require 'alexa_generator/version'
@@ -33,5 +33,13 @@ describe AlexaGenerator::Slot do
33
33
  expect(intent.slots.count).to eq(1)
34
34
  expect(intent.slots.first.name).to eq(:SlotOne)
35
35
  end
36
+
37
+ it 'should whine when trying to add a slot to an Amazon intent' do
38
+ AlexaGenerator::Intent.build(AlexaGenerator::Intent::AmazonIntentType::CANCEL) do |intent|
39
+ expect {
40
+ intent.add_slot(:SlotOne, AlexaGenerator::Slot::SlotType::LITERAL)
41
+ }.to raise_error(AlexaGenerator::InvalidIntentError)
42
+ end
43
+ end
36
44
  end
37
45
  end
@@ -43,6 +43,56 @@ describe AlexaGenerator::InteractionModel do
43
43
  })
44
44
  end
45
45
 
46
+ it 'should allow built in intents' do
47
+ iface = AlexaGenerator::InteractionModel.build do |iface|
48
+ iface.add_intent(AlexaGenerator::Intent::AmazonIntentType::CANCEL)
49
+ end
50
+
51
+ expect(iface).to be_an_instance_of(AlexaGenerator::InteractionModel)
52
+ expect(iface.intent_schema).to eq(
53
+ {
54
+ intents: [
55
+ {
56
+ intent: :"AMAZON.CancelIntent",
57
+ slots: []
58
+ }
59
+ ]
60
+ })
61
+ end
62
+
63
+ it 'should combine custom and built in intents' do
64
+ iface = AlexaGenerator::InteractionModel.build do |iface|
65
+ iface.add_intent(AlexaGenerator::Intent::AmazonIntentType::CANCEL)
66
+ iface.add_intent(:IntentOne) do |intent|
67
+ intent.add_slot(:SlotOne, AlexaGenerator::Slot::SlotType::LITERAL) do |slot|
68
+ slot.add_binding('value1')
69
+ end
70
+
71
+ intent.add_utterance_template('test {SlotOne} test')
72
+ end
73
+ end
74
+
75
+ expect(iface).to be_an_instance_of(AlexaGenerator::InteractionModel)
76
+ expect(iface.intent_schema).to eq(
77
+ {
78
+ intents: [
79
+ {
80
+ intent: :"AMAZON.CancelIntent",
81
+ slots: []
82
+ },
83
+ {
84
+ intent: :IntentOne,
85
+ slots: [
86
+ {
87
+ name: :SlotOne,
88
+ type: AlexaGenerator::Slot::SlotType::LITERAL
89
+ }
90
+ ]
91
+ }
92
+ ]
93
+ })
94
+ end
95
+
46
96
  it 'should produce bound utterances' do
47
97
  iface = AlexaGenerator::InteractionModel.build do |iface|
48
98
  iface.add_intent(:MyIntent) do |intent|
@@ -67,15 +117,10 @@ describe AlexaGenerator::InteractionModel do
67
117
 
68
118
  actual = iface.sample_utterances(:MyIntent)
69
119
 
70
- expect(actual.count).to eq(8)
71
- expect(actual).to include('MyIntent Alexa, please {fix my motorcycle|SlotOne} {one|SlotTwo} at {noon|SlotThree}')
72
- expect(actual).to include('MyIntent Alexa, please {fix my motorcycle|SlotOne} {two|SlotTwo} at {noon|SlotThree}')
73
- expect(actual).to include('MyIntent Alexa, please {make me a sandwich|SlotOne} {one|SlotTwo} at {noon|SlotThree}')
74
- expect(actual).to include('MyIntent Alexa, please {make me a sandwich|SlotOne} {two|SlotTwo} at {noon|SlotThree}')
75
- expect(actual).to include('MyIntent Alexa, please {fix my motorcycle|SlotOne} {one|SlotTwo} at {6 a.m.|SlotThree}')
76
- expect(actual).to include('MyIntent Alexa, please {fix my motorcycle|SlotOne} {two|SlotTwo} at {6 a.m.|SlotThree}')
77
- expect(actual).to include('MyIntent Alexa, please {make me a sandwich|SlotOne} {one|SlotTwo} at {6 a.m.|SlotThree}')
78
- expect(actual).to include('MyIntent Alexa, please {make me a sandwich|SlotOne} {two|SlotTwo} at {6 a.m.|SlotThree}')
120
+ # only the literal ones get examples
121
+ expect(actual.count).to eq(2)
122
+ expect(actual).to include('MyIntent Alexa, please {fix my motorcycle|SlotOne} {SlotTwo} at {SlotThree}')
123
+ expect(actual).to include('MyIntent Alexa, please {make me a sandwich|SlotOne} {SlotTwo} at {SlotThree}')
79
124
  end
80
125
  end
81
126
 
@@ -144,15 +189,10 @@ describe AlexaGenerator::InteractionModel do
144
189
  it 'should produce bound utterances' do
145
190
  actual = AlexaGenerator::InteractionModel.new(intents, utterance_templates, slot_bindings).sample_utterances(:MyIntent)
146
191
 
147
- expect(actual.count).to eq(8)
148
- expect(actual).to include('MyIntent Alexa, please {fix my motorcycle|SlotOne} {one|SlotTwo} at {noon|SlotThree}')
149
- expect(actual).to include('MyIntent Alexa, please {fix my motorcycle|SlotOne} {two|SlotTwo} at {noon|SlotThree}')
150
- expect(actual).to include('MyIntent Alexa, please {make me a sandwich|SlotOne} {one|SlotTwo} at {noon|SlotThree}')
151
- expect(actual).to include('MyIntent Alexa, please {make me a sandwich|SlotOne} {two|SlotTwo} at {noon|SlotThree}')
152
- expect(actual).to include('MyIntent Alexa, please {fix my motorcycle|SlotOne} {one|SlotTwo} at {6 a.m.|SlotThree}')
153
- expect(actual).to include('MyIntent Alexa, please {fix my motorcycle|SlotOne} {two|SlotTwo} at {6 a.m.|SlotThree}')
154
- expect(actual).to include('MyIntent Alexa, please {make me a sandwich|SlotOne} {one|SlotTwo} at {6 a.m.|SlotThree}')
155
- expect(actual).to include('MyIntent Alexa, please {make me a sandwich|SlotOne} {two|SlotTwo} at {6 a.m.|SlotThree}')
192
+ # only the literal ones get examples
193
+ expect(actual.count).to eq(2)
194
+ expect(actual).to include('MyIntent Alexa, please {fix my motorcycle|SlotOne} {SlotTwo} at {SlotThree}')
195
+ expect(actual).to include('MyIntent Alexa, please {make me a sandwich|SlotOne} {SlotTwo} at {SlotThree}')
156
196
  end
157
197
  end
158
198
  end
metadata CHANGED
@@ -1,41 +1,41 @@
1
1
  --- !ruby/object:Gem::Specification
2
2
  name: alexa_generator
3
3
  version: !ruby/object:Gem::Version
4
- version: 0.1.2
4
+ version: 0.2.0
5
5
  platform: ruby
6
6
  authors:
7
7
  - Christopher Mullins
8
8
  autorequire:
9
9
  bindir: bin
10
10
  cert_chain: []
11
- date: 2015-07-21 00:00:00.000000000 Z
11
+ date: 2016-12-20 00:00:00.000000000 Z
12
12
  dependencies:
13
13
  - !ruby/object:Gem::Dependency
14
14
  name: rspec
15
15
  requirement: !ruby/object:Gem::Requirement
16
16
  requirements:
17
- - - '>='
17
+ - - ">="
18
18
  - !ruby/object:Gem::Version
19
19
  version: 3.0.0
20
20
  type: :development
21
21
  prerelease: false
22
22
  version_requirements: !ruby/object:Gem::Requirement
23
23
  requirements:
24
- - - '>='
24
+ - - ">="
25
25
  - !ruby/object:Gem::Version
26
26
  version: 3.0.0
27
27
  - !ruby/object:Gem::Dependency
28
28
  name: rake
29
29
  requirement: !ruby/object:Gem::Requirement
30
30
  requirements:
31
- - - '>='
31
+ - - ">="
32
32
  - !ruby/object:Gem::Version
33
33
  version: '0'
34
34
  type: :development
35
35
  prerelease: false
36
36
  version_requirements: !ruby/object:Gem::Requirement
37
37
  requirements:
38
- - - '>='
38
+ - - ">="
39
39
  - !ruby/object:Gem::Version
40
40
  version: '0'
41
41
  description:
@@ -44,14 +44,14 @@ executables: []
44
44
  extensions: []
45
45
  extra_rdoc_files: []
46
46
  files:
47
- - .gitignore
47
+ - ".gitignore"
48
48
  - Gemfile
49
49
  - LICENSE
50
50
  - README.md
51
51
  - Rakefile
52
52
  - alexa_generator.gemspec
53
53
  - lib/alexa_generator.rb
54
- - lib/alexa_generator/alexa_syntax_error.rb
54
+ - lib/alexa_generator/errors.rb
55
55
  - lib/alexa_generator/intent.rb
56
56
  - lib/alexa_generator/intent_schema.rb
57
57
  - lib/alexa_generator/interaction_model.rb
@@ -73,17 +73,17 @@ require_paths:
73
73
  - lib
74
74
  required_ruby_version: !ruby/object:Gem::Requirement
75
75
  requirements:
76
- - - '>='
76
+ - - ">="
77
77
  - !ruby/object:Gem::Version
78
78
  version: '0'
79
79
  required_rubygems_version: !ruby/object:Gem::Requirement
80
80
  requirements:
81
- - - '>='
81
+ - - ">="
82
82
  - !ruby/object:Gem::Version
83
83
  version: '0'
84
84
  requirements: []
85
85
  rubyforge_project:
86
- rubygems_version: 2.0.14
86
+ rubygems_version: 2.5.1
87
87
  signing_key:
88
88
  specification_version: 4
89
89
  summary: Generates voice interfaces for Alexa apps based on templates.