aws-lex-conversation 3.0.0 → 4.0.2

Sign up to get free protection for your applications and to get access to all the features.
Files changed (44) hide show
  1. checksums.yaml +4 -4
  2. data/CHANGELOG.md +42 -0
  3. data/README.md +28 -6
  4. data/lib/aws/lex/conversation.rb +9 -21
  5. data/lib/aws/lex/conversation/base.rb +13 -10
  6. data/lib/aws/lex/conversation/handler/delegate.rb +1 -3
  7. data/lib/aws/lex/conversation/handler/echo.rb +6 -4
  8. data/lib/aws/lex/conversation/response/base.rb +11 -10
  9. data/lib/aws/lex/conversation/response/close.rb +5 -11
  10. data/lib/aws/lex/conversation/response/confirm_intent.rb +4 -13
  11. data/lib/aws/lex/conversation/response/delegate.rb +4 -11
  12. data/lib/aws/lex/conversation/response/elicit_intent.rb +4 -7
  13. data/lib/aws/lex/conversation/response/elicit_slot.rb +5 -12
  14. data/lib/aws/lex/conversation/slot/elicitation.rb +6 -4
  15. data/lib/aws/lex/conversation/support/mixins/responses.rb +14 -20
  16. data/lib/aws/lex/conversation/type/base.rb +10 -4
  17. data/lib/aws/lex/conversation/type/bot.rb +3 -1
  18. data/lib/aws/lex/conversation/type/checkpoint.rb +57 -0
  19. data/lib/aws/lex/conversation/type/{confirmation_status.rb → confirmation_state.rb} +1 -1
  20. data/lib/aws/lex/conversation/type/context.rb +4 -4
  21. data/lib/aws/lex/conversation/type/{slot_detail.rb → dialog_action.rb} +4 -4
  22. data/lib/aws/lex/conversation/type/dialog_action_type.rb +3 -3
  23. data/lib/aws/lex/conversation/type/event.rb +26 -19
  24. data/lib/aws/lex/conversation/type/{output_dialog_mode.rb → input_mode.rb} +3 -2
  25. data/lib/aws/lex/conversation/type/intent.rb +14 -23
  26. data/lib/aws/lex/conversation/type/intent_confidence.rb +5 -5
  27. data/lib/aws/lex/conversation/type/interpretation.rb +23 -0
  28. data/lib/aws/lex/conversation/type/message.rb +4 -2
  29. data/lib/aws/lex/conversation/type/message/content_type.rb +2 -1
  30. data/lib/aws/lex/conversation/type/response.rb +3 -4
  31. data/lib/aws/lex/conversation/type/response_card.rb +5 -6
  32. data/lib/aws/lex/conversation/type/{sentiment_label.rb → sentiment.rb} +1 -1
  33. data/lib/aws/lex/conversation/type/sentiment_response.rb +3 -3
  34. data/lib/aws/lex/conversation/type/sentiment_score.rb +10 -20
  35. data/lib/aws/lex/conversation/type/session_attributes.rb +29 -0
  36. data/lib/aws/lex/conversation/type/session_state.rb +25 -0
  37. data/lib/aws/lex/conversation/type/slot.rb +54 -29
  38. data/lib/aws/lex/conversation/type/{slot_resolution.rb → slot_shape.rb} +4 -3
  39. data/lib/aws/lex/conversation/type/slot_value.rb +40 -0
  40. data/lib/aws/lex/conversation/version.rb +1 -1
  41. metadata +13 -12
  42. data/lib/aws/lex/conversation/type/recent_intent_summary_view.rb +0 -70
  43. data/lib/aws/lex/conversation/type/response_card/content_type.rb +0 -17
  44. data/lib/aws/lex/conversation/type/response_card/generic_attachment.rb +0 -26
@@ -8,51 +8,45 @@ module Aws
8
8
  module Responses
9
9
  def close(opts = {})
10
10
  params = {
11
- active_contexts: lex.active_contexts,
12
- recent_intent_summary_view: pending_checkpoints,
13
- session_attributes: lex.session_attributes
11
+ session_state: lex.session_state,
12
+ request_attributes: lex.request_attributes
14
13
  }.merge(opts)
15
14
  Response::Close.new(params).to_lex
16
15
  end
17
16
 
18
17
  def confirm_intent(opts = {})
19
18
  params = {
20
- active_contexts: lex.active_contexts,
21
- intent_name: lex.current_intent.name,
22
- recent_intent_summary_view: pending_checkpoints,
23
- session_attributes: lex.session_attributes,
24
- slots: lex.current_intent.slots
19
+ session_state: lex.session_state,
20
+ request_attributes: lex.request_attributes,
21
+ intent: lex.current_intent
25
22
  }.merge(opts)
23
+ lex.session_state.intent = params.fetch(:intent)
26
24
  Response::ConfirmIntent.new(params).to_lex
27
25
  end
28
26
 
29
27
  def delegate(opts = {})
30
28
  params = {
31
- active_contexts: lex.active_contexts,
32
- recent_intent_summary_view: pending_checkpoints,
33
- session_attributes: lex.session_attributes,
34
- slots: lex.current_intent.slots
29
+ session_state: lex.session_state,
30
+ request_attributes: lex.request_attributes
35
31
  }.merge(opts)
36
32
  Response::Delegate.new(params).to_lex
37
33
  end
38
34
 
39
35
  def elicit_intent(opts = {})
40
36
  params = {
41
- active_contexts: lex.active_contexts,
42
- recent_intent_summary_view: pending_checkpoints,
43
- session_attributes: lex.session_attributes
37
+ session_state: lex.session_state,
38
+ request_attributes: lex.request_attributes
44
39
  }.merge(opts)
45
40
  Response::ElicitIntent.new(params).to_lex
46
41
  end
47
42
 
48
43
  def elicit_slot(opts = {})
49
44
  params = {
50
- active_contexts: lex.active_contexts,
51
- intent_name: lex.current_intent.name,
52
- recent_intent_summary_view: pending_checkpoints,
53
- session_attributes: lex.session_attributes,
54
- slots: lex.current_intent.slots
45
+ session_state: lex.session_state,
46
+ request_attributes: lex.request_attributes,
47
+ intent: lex.current_intent
55
48
  }.merge(opts)
49
+ lex.session_state.intent = params.fetch(:intent)
56
50
  Response::ElicitSlot.new(params).to_lex
57
51
  end
58
52
  end
@@ -26,10 +26,11 @@ module Aws
26
26
  end
27
27
 
28
28
  def to_lex
29
- self.class.attributes.each_with_object({}) do |attribute, hash|
30
- value = transform_to_lex(instance_variable_get("@#{attribute}"))
29
+ output = self.class.attributes.each_with_object({}) do |attribute, hash|
30
+ value = transform_to_lex(public_send(attribute))
31
31
  hash[self.class.mapping.fetch(attribute)] = value
32
32
  end
33
+ output.compact
33
34
  end
34
35
 
35
36
  private
@@ -37,8 +38,13 @@ module Aws
37
38
  def transform_to_lex(value)
38
39
  case value
39
40
  when Hash
40
- value.each_with_object({}) do |(key, val), hash|
41
- hash[key.to_sym] = transform_to_lex(val)
41
+ if value.respond_to?(:to_lex)
42
+ value.to_lex
43
+ else
44
+ output = value.each_with_object({}) do |(key, val), hash|
45
+ hash[key.to_sym] = transform_to_lex(val)
46
+ end
47
+ output.compact
42
48
  end
43
49
  when Array
44
50
  value.map { |v| transform_to_lex(v) }
@@ -7,8 +7,10 @@ module Aws
7
7
  class Bot
8
8
  include Base
9
9
 
10
+ required :alias_id
11
+ required :id
12
+ required :locale_id
10
13
  required :name
11
- required :alias
12
14
  required :version
13
15
  end
14
16
  end
@@ -0,0 +1,57 @@
1
+ # frozen_string_literal: true
2
+
3
+ module Aws
4
+ module Lex
5
+ class Conversation
6
+ module Type
7
+ class Checkpoint
8
+ include Base
9
+
10
+ required :dialog_action_type
11
+ required :intent
12
+
13
+ optional :label
14
+ optional :fulfillment_state
15
+ optional :slot_to_elicit
16
+
17
+ coerce(
18
+ intent: Intent,
19
+ dialog_action_type: DialogActionType,
20
+ fulfillment_state: FulfillmentState
21
+ )
22
+
23
+ # rubocop:disable Metrics/MethodLength
24
+ def restore(conversation, opts = {})
25
+ case dialog_action_type.raw
26
+ when 'Close'
27
+ conversation.close(
28
+ fulfillment_state: opts.fetch(:fulfillment_state) { fulfillment_state },
29
+ messages: opts.fetch(:messages)
30
+ )
31
+ when 'ConfirmIntent'
32
+ conversation.confirm_intent(
33
+ intent: intent,
34
+ messages: opts.fetch(:messages)
35
+ )
36
+ when 'Delegate'
37
+ conversation.delegate
38
+ when 'ElicitIntent'
39
+ conversation.elicit_intent(
40
+ messages: opts.fetch(:messages)
41
+ )
42
+ when 'ElicitSlot'
43
+ conversation.elicit_slot(
44
+ intent: intent,
45
+ messages: opts.fetch(:messages),
46
+ slot_to_elicit: slot_to_elicit
47
+ )
48
+ else
49
+ raise ArgumentError, "invalid DialogActionType: `#{dialog_action_type.raw}`"
50
+ end
51
+ end
52
+ # rubocop:enable Metrics/MethodLength
53
+ end
54
+ end
55
+ end
56
+ end
57
+ end
@@ -4,7 +4,7 @@ module Aws
4
4
  module Lex
5
5
  class Conversation
6
6
  module Type
7
- class ConfirmationStatus
7
+ class ConfirmationState
8
8
  include Enumeration
9
9
 
10
10
  enumeration('None')
@@ -7,13 +7,13 @@ module Aws
7
7
  class Context
8
8
  include Base
9
9
 
10
- required :time_to_live
10
+ required :context_attributes
11
11
  required :name
12
- required :parameters
12
+ required :time_to_live
13
13
 
14
14
  coerce(
15
- time_to_live: TimeToLive,
16
- parameters: symbolize_hash!
15
+ context_attributes: symbolize_hash!,
16
+ time_to_live: TimeToLive
17
17
  )
18
18
  end
19
19
  end
@@ -4,14 +4,14 @@ module Aws
4
4
  module Lex
5
5
  class Conversation
6
6
  module Type
7
- class SlotDetail
7
+ class DialogAction
8
8
  include Base
9
9
 
10
- required :resolutions
11
- required :original_value
10
+ optional :slot_to_elicit
11
+ required :type
12
12
 
13
13
  coerce(
14
- resolutions: Array[SlotResolution]
14
+ type: DialogActionType
15
15
  )
16
16
  end
17
17
  end
@@ -7,11 +7,11 @@ module Aws
7
7
  class DialogActionType
8
8
  include Enumeration
9
9
 
10
- enumeration('ElicitIntent')
11
- enumeration('ElicitSlot')
10
+ enumeration('Close')
12
11
  enumeration('ConfirmIntent')
13
12
  enumeration('Delegate')
14
- enumeration('Close')
13
+ enumeration('ElicitIntent')
14
+ enumeration('ElicitSlot')
15
15
  end
16
16
  end
17
17
  end
@@ -7,36 +7,43 @@ module Aws
7
7
  class Event
8
8
  include Base
9
9
 
10
- required :active_contexts, default: -> { [] }
11
- required :alternative_intents, default: -> { [] }
12
- required :current_intent
13
10
  required :bot
14
- required :user_id
15
- required :input_transcript
11
+ required :input_mode
12
+ required :input_transcript, default: -> { '' }
13
+ required :interpretations
16
14
  required :invocation_source
17
- required :output_dialog_mode
18
15
  required :message_version
19
- required :session_attributes
20
- required :recent_intent_summary_view, default: -> { [] }
21
- optional :request_attributes
22
- optional :sentiment_response
23
- optional :kendra_response
16
+ required :request_attributes, default: -> { {} }
17
+ required :response_content_type
18
+ required :session_id
19
+ required :session_state
20
+
21
+ computed_property :current_intent, ->(instance) do
22
+ instance.session_state.intent.tap do |intent|
23
+ intent.nlu_confidence = instance.interpretations.find { |i| i.intent.name == intent.name }.nlu_confidence
24
+ end
25
+ end
24
26
 
25
27
  computed_property :intents, ->(instance) do
26
- [instance.current_intent] | instance.alternative_intents
28
+ instance.interpretations.map(&:intent).tap do |intents|
29
+ intents.map do |intent|
30
+ intent.nlu_confidence = instance.interpretations.find { |i| i.intent.name == intent.name }.nlu_confidence
31
+ end
32
+ end
33
+ end
34
+
35
+ computed_property :alternate_intents, ->(instance) do
36
+ instance.intents.reject { |intent| intent.name == instance.current_intent.name }
27
37
  end
28
38
 
29
39
  coerce(
30
- active_contexts: Array[Context],
31
- alternative_intents: Array[Intent],
32
- current_intent: Intent,
33
40
  bot: Bot,
41
+ input_mode: InputMode,
42
+ interpretations: Array[Interpretation],
34
43
  invocation_source: InvocationSource,
35
- output_dialog_mode: OutputDialogMode,
36
- session_attributes: symbolize_hash!,
37
44
  request_attributes: symbolize_hash!,
38
- recent_intent_summary_view: Array[RecentIntentSummaryView],
39
- sentiment_response: SentimentResponse
45
+ response_content_type: Message::ContentType,
46
+ session_state: SessionState
40
47
  )
41
48
  end
42
49
  end
@@ -4,10 +4,11 @@ module Aws
4
4
  module Lex
5
5
  class Conversation
6
6
  module Type
7
- class OutputDialogMode
7
+ class InputMode
8
8
  include Enumeration
9
9
 
10
- enumeration('Voice')
10
+ enumeration('DTMF')
11
+ enumeration('Speech')
11
12
  enumeration('Text')
12
13
  end
13
14
  end
@@ -7,46 +7,37 @@ module Aws
7
7
  class Intent
8
8
  include Base
9
9
 
10
+ required :confirmation_state
11
+ optional :kendra_response
10
12
  required :name
11
13
  required :raw_slots, from: :slots, virtual: true
12
- required :slot_details
13
- required :confirmation_status
14
- optional :nlu_intent_confidence_score
14
+ required :state
15
+ optional :originating_request_id
16
+ optional :nlu_confidence
15
17
 
16
18
  computed_property :slots, ->(instance) do
17
19
  # any keys indexed without a value will return an empty Slot instance
18
20
  default_hash = Hash.new do |_hash, key|
19
- Slot.new(active: false, name: key.to_sym, value: nil, current_intent: instance)
21
+ Slot.shrink_wrap(active: false, name: key.to_sym, value: nil, shape: 'Scalar')
20
22
  end
21
23
 
22
24
  instance.raw_slots.each_with_object(default_hash) do |(key, value), hash|
25
+ normalized = value&.transform_keys(&:to_sym) || { shape: 'Scalar' }
23
26
  hash[key.to_sym] = Slot.shrink_wrap(
24
27
  active: true,
25
28
  name: key,
26
- value: value,
27
- # pass a reference to the parent down to the slot so that each slot
28
- # instance can view a broader scope such as slot_details/resolutions
29
- current_intent: instance
29
+ shape: normalized[:shape],
30
+ value: normalized[:value],
31
+ values: normalized[:values]
30
32
  )
31
33
  end
32
34
  end
33
35
 
34
- class << self
35
- def slot_details!
36
- ->(val) do
37
- val
38
- .compact
39
- .each_with_object({}) do |(key, value), hash|
40
- hash[key.to_sym] = SlotDetail.shrink_wrap(value)
41
- end
42
- end
43
- end
44
- end
45
-
46
36
  coerce(
47
- slot_details: slot_details!,
48
- confirmation_status: ConfirmationStatus,
49
- nlu_intent_confidence_score: float!(nilable: true)
37
+ raw_slots: symbolize_hash!,
38
+ slots: Array[Slot],
39
+ confirmation_state: ConfirmationState,
40
+ nlu_confidence: float!(nilable: true)
50
41
  )
51
42
  end
52
43
  end
@@ -28,9 +28,9 @@ module Aws
28
28
  def candidates(threshold: standard_deviation)
29
29
  intents = event.intents.select do |intent|
30
30
  diff = event.current_intent
31
- .nlu_intent_confidence_score
31
+ .nlu_confidence
32
32
  .to_f
33
- .-(intent.nlu_intent_confidence_score.to_f)
33
+ .-(intent.nlu_confidence.to_f)
34
34
  .abs
35
35
 
36
36
  diff <= threshold
@@ -38,7 +38,7 @@ module Aws
38
38
 
39
39
  # sort descending
40
40
  intents.sort do |a, b|
41
- b.nlu_intent_confidence_score.to_f <=> a.nlu_intent_confidence_score.to_f
41
+ b.nlu_confidence.to_f <=> a.nlu_confidence.to_f
42
42
  end
43
43
  end
44
44
 
@@ -58,13 +58,13 @@ module Aws
58
58
  private
59
59
 
60
60
  def calculate_mean
61
- sum = event.intents.sum { |i| i.nlu_intent_confidence_score.to_f }
61
+ sum = event.intents.sum { |i| i.nlu_confidence.to_f }
62
62
  sum / event.intents.size
63
63
  end
64
64
 
65
65
  def calculate_standard_deviation
66
66
  normalized = event.intents.map do |intent|
67
- (intent.nlu_intent_confidence_score.to_f - mean) ** 2
67
+ (intent.nlu_confidence.to_f - mean) ** 2
68
68
  end
69
69
  normalized_mean = normalized.sum / normalized.size
70
70
  Math.sqrt(normalized_mean)
@@ -0,0 +1,23 @@
1
+ # frozen_string_literal: true
2
+
3
+ module Aws
4
+ module Lex
5
+ class Conversation
6
+ module Type
7
+ class Interpretation
8
+ include Base
9
+
10
+ required :intent
11
+ optional :nlu_confidence
12
+ optional :sentiment_response
13
+
14
+ coerce(
15
+ intent: Intent,
16
+ nlu_confidence: float!(nilable: true),
17
+ sentiment_response: SentimentResponse
18
+ )
19
+ end
20
+ end
21
+ end
22
+ end
23
+ end
@@ -7,11 +7,13 @@ module Aws
7
7
  class Message
8
8
  include Base
9
9
 
10
- optional :content_type, default: 'PlainText'
10
+ required :content_type, default: -> { 'PlainText' }
11
11
  required :content
12
+ optional :image_response_card
12
13
 
13
14
  coerce(
14
- content_type: Message::ContentType
15
+ content_type: Message::ContentType,
16
+ image_response_card: Aws::Lex::Conversation::Type::ResponseCard
15
17
  )
16
18
  end
17
19
  end