aws-lex-conversation 2.1.0 → 4.0.1

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.
Files changed (44) hide show
  1. checksums.yaml +4 -4
  2. data/CHANGELOG.md +38 -0
  3. data/README.md +28 -6
  4. data/lib/aws/lex/conversation.rb +38 -1
  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 +25 -18
  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 +20 -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 +63 -20
  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 -11
  42. data/lib/aws/lex/conversation/type/recent_intent_summary_view.rb +0 -29
  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
@@ -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
11
+ required :input_mode
15
12
  required :input_transcript
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
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,40 +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
- instance.raw_slots.each_with_object({}) do |(key, value), hash|
19
+ # any keys indexed without a value will return an empty Slot instance
20
+ default_hash = Hash.new do |_hash, key|
21
+ Slot.shrink_wrap(active: false, name: key.to_sym, value: nil, shape: 'Scalar')
22
+ end
23
+
24
+ instance.raw_slots.each_with_object(default_hash) do |(key, value), hash|
25
+ normalized = value&.transform_keys(&:to_sym) || { shape: 'Scalar' }
18
26
  hash[key.to_sym] = Slot.shrink_wrap(
27
+ active: true,
19
28
  name: key,
20
- value: value,
21
- # pass a reference to the parent down to the slot so that each slot
22
- # instance can view a broader scope such as slot_details/resolutions
23
- current_intent: instance
29
+ shape: normalized[:shape],
30
+ value: normalized[:value],
31
+ values: normalized[:values]
24
32
  )
25
33
  end
26
34
  end
27
35
 
28
- class << self
29
- def slot_details!
30
- ->(val) do
31
- val
32
- .compact
33
- .each_with_object({}) do |(key, value), hash|
34
- hash[key.to_sym] = SlotDetail.shrink_wrap(value)
35
- end
36
- end
37
- end
38
- end
39
-
40
36
  coerce(
41
- slot_details: slot_details!,
42
- confirmation_status: ConfirmationStatus,
43
- 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)
44
41
  )
45
42
  end
46
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
@@ -8,9 +8,10 @@ module Aws
8
8
  class ContentType
9
9
  include Enumeration
10
10
 
11
+ enumeration('CustomPayload')
12
+ enumeration('ImageResponseCard')
11
13
  enumeration('PlainText')
12
14
  enumeration('SSML')
13
- enumeration('CustomPayload')
14
15
  end
15
16
  end
16
17
  end
@@ -7,10 +7,9 @@ module Aws
7
7
  class Response
8
8
  include Base
9
9
 
10
- required :dialog_action
11
- optional :session_attributes
12
- optional :recent_intent_summary_view
13
- optional :active_contexts
10
+ required :session_state
11
+ required :messages
12
+ required :request_attributes
14
13
  end
15
14
  end
16
15
  end
@@ -7,14 +7,13 @@ module Aws
7
7
  class ResponseCard
8
8
  include Base
9
9
 
10
- optional :version
11
- optional :content_type, default: 'application/vnd.amazonaws.card.generic'
12
- required :generic_attachments
10
+ required :title
11
+ required :buttons, default: -> { [] }
12
+ optional :sub_title
13
+ optional :image_url
13
14
 
14
15
  coerce(
15
- version: integer!,
16
- content_type: ResponseCard::ContentType,
17
- generic_attachments: Array[GenericAttachment]
16
+ buttons: Array[ResponseCard::Button]
18
17
  )
19
18
  end
20
19
  end
@@ -4,7 +4,7 @@ module Aws
4
4
  module Lex
5
5
  class Conversation
6
6
  module Type
7
- class SentimentLabel
7
+ class Sentiment
8
8
  include Enumeration
9
9
 
10
10
  enumeration('POSITIVE')
@@ -7,12 +7,12 @@ module Aws
7
7
  class SentimentResponse
8
8
  include Base
9
9
 
10
- required :sentiment_label
10
+ required :sentiment
11
11
  required :sentiment_score
12
12
 
13
13
  coerce(
14
- sentiment_label: SentimentLabel,
15
- sentiment_score: ->(v) { SentimentScore.parse_string(v) }
14
+ sentiment_label: Sentiment,
15
+ sentiment_score: SentimentScore
16
16
  )
17
17
  end
18
18
  end