Class: BotFramework::Dialogs::EntityRecognizer

Inherits:
Object
  • Object
show all
Defined in:
lib/bot_framework/dialogs/entity_recognizer.rb

Constant Summary collapse

DATE_REGEX =
/^\d{4}-\d{2}-\d{2}/i
YES_REGEX =
/^(1|y|yes|yep|sure|ok|true)(\W|$)/i
NO_REGX =
/^(2|n|no|nope|not|false)(\W|$)/i
NUMBER_REGEX =
/[+-]?(?:\d+\.?\d*|\d*\.?\d+)/
ORDINAL_WORDS_REGEX =
/first|second|third|fourth|fifth|sixth|seventh|eigth|ninth|tenth/

Class Method Summary collapse

Instance Method Summary collapse

Constructor Details

#initialize(*args) ⇒ EntityRecognizer

Returns a new instance of EntityRecognizer.



10
# File 'lib/bot_framework/dialogs/entity_recognizer.rb', line 10

def initialize(*args); end

Class Method Details

.expand_choices(choices) ⇒ Object



112
113
114
115
116
117
118
119
120
# File 'lib/bot_framework/dialogs/entity_recognizer.rb', line 112

def self.expand_choices(choices)
  case choices
  when nil then []
  when Array then choices.map(&:to_s)
  when Hash then choices.keys.map(&:to_s)
  when String then choices.split('|')
  else [choices.to_s]
  end
end

.find_all_entities(entities, type) ⇒ Object



17
18
19
# File 'lib/bot_framework/dialogs/entity_recognizer.rb', line 17

def self.find_all_entities(entities, type)
  entities.find_all { |entity| entity[:type] == type }
end

.find_all_matches(choices, utterance, threshold = 0.6) ⇒ Object



88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
# File 'lib/bot_framework/dialogs/entity_recognizer.rb', line 88

def self.find_all_matches(choices, utterance, threshold = 0.6)
  matches = []
  utterance = utterance.strip.downcase
  tokens = utterance.split

  expand_choices(choices).each_with_index do |choice, index|
    score = 0.0
    value = choice.strip.downcase
    if value.include?(utterance)
      score = utterance.size.to_f / value.size
    elsif utterance.include? value
      score = [0.5 + (value.size.to_f / utterance.size), 0.9].min
    else
      matched = ''
      tokens.each { |token| matched += token if value.include? token }
      score = matched.size / value.size
    end
    if score > threshold
      matches.push(index: index, entity: choice, score: score)
    end
  end
  matches
end

.find_best_match(choices, utterance, threshhold = 0.6) ⇒ Object



83
84
85
86
# File 'lib/bot_framework/dialogs/entity_recognizer.rb', line 83

def self.find_best_match(choices, utterance, threshhold = 0.6)
  matches = find_all_matches(choices, utterance, threshhold)
  matches.max { |entry| entry[:score] }
end

.find_entity(entities, type) ⇒ Object



12
13
14
15
# File 'lib/bot_framework/dialogs/entity_recognizer.rb', line 12

def self.find_entity(entities, type)
  # raise ArgumentError unless entities.is_a? Hash
  entities.find { |entity| entity[:type] == type }
end

.parse_boolean(utterance) ⇒ Object



74
75
76
77
78
79
80
81
# File 'lib/bot_framework/dialogs/entity_recognizer.rb', line 74

def self.parse_boolean(utterance)
  utterance.strip!
  if YES_REGEX =~ utterance
    true
  elsif NO_REGX =~ utterance
    false
  end
end

.parse_number(entities) ⇒ Object



60
61
62
63
64
65
66
67
68
69
70
71
72
# File 'lib/bot_framework/dialogs/entity_recognizer.rb', line 60

def self.parse_number(entities)
  entity = nil
  entity = if entities.is_a? String
             { type: 'text', entity: entities.strip }
           else
             find_entity(entities, 'builtin.number')
           end

  if entity
    match = NUMBER_REGEX.match(entity[:entity])
    return match[0] if match
  end
end

.parse_time(entities) ⇒ Object



21
22
23
24
# File 'lib/bot_framework/dialogs/entity_recognizer.rb', line 21

def self.parse_time(entities)
  entities = [EntityRecognizer.recognize_time(entities)] if entities.is_a? String
  EntityRecognizer.resolve_time(entities)
end

.recognize_time(utterance, reference_date = {}) ⇒ Object



47
48
49
50
51
52
53
54
55
56
57
58
# File 'lib/bot_framework/dialogs/entity_recognizer.rb', line 47

def self.recognize_time(utterance, reference_date = {})
  time = Chronic.parse(utterance, reference_date)
  return false unless time
  {
    type: 'chronic.time',
    entity: time.to_s,
    resolution: {
      resolution_type: 'chronic.time',
      time: time
    }
  }
end

.resolve_time(entities) ⇒ Object



26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
# File 'lib/bot_framework/dialogs/entity_recognizer.rb', line 26

def self.resolve_time(entities)
  now = DateTime.now
  resolved_date = nil
  time = nil
  entities.each do |entity|
    next unless entity[:resolution]
    case entity[:resolution][:resolution_type] || entity[:type]
    when 'builtin.datetime'
    when 'builtin.datetime.date'
    when 'builtin.datetime.time'
      time = entity[:resolution][:time]
    when 'chronic.time'
      duration = entity
      time = entity[:resolution][:time]
      resolved_date = duration[:resolution][:time]
    end
  end
  date = now if !resolved_date && (date || time)
  time
end