nlu_adapter 0.1.2 → 0.1.4

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
  SHA256:
3
- metadata.gz: 4833a2510ae848ce4e45ece07476dc4d0a6601b8f9ca951dc1c3e08e723f0d08
4
- data.tar.gz: 3d6f981287bc3c2aaece9044404b1095a4f09784c6bf4370112d494aec4c40c3
3
+ metadata.gz: 7499fe30c4727e84ae33be8b0e3905d921942daa4b74cac9105105e473107160
4
+ data.tar.gz: 2cdb76a1ba9593b53d80d5f32b3be140c38d629e376c9abbd6893ff1ae1669d6
5
5
  SHA512:
6
- metadata.gz: 86a985870ee3db4355df44ec4e7b13a8572585aa8af646774229b0a3771353b0c996de5efbec75b44e599dd97276ee7cb1a8c7903ec2832c1f802489451502ca
7
- data.tar.gz: d7ff110b0c12613882648e666bf3147fe935657ba42fa313c67a207f33f290070758b699a5a5b6c7020dc436683902c0ebc1e7bd434b892beed7c37d25ffdc37
6
+ metadata.gz: d0f35e5f09313ba18410c8ccf9d07ae4ea4ecb6cb217cf348e0cfccb8af0600e01262911e0890a706360b0c650ad9a9f395cf86273af9fa541065dec0098f854
7
+ data.tar.gz: 1d350b886b3154d973a5aef113cd505311ecc544037f7250f2f7a5da0b1691e6e87b7c9b91ed6c51fd116527c7207a1c78585705944cc0c566067007fdc7d606
@@ -0,0 +1 @@
1
+ Gemfile.lock
@@ -0,0 +1,8 @@
1
+ --protected
2
+ --no-private
3
+ -
4
+ CHANGELOG.md
5
+ CODE_OF_CONDUCT.md
6
+ LICENSE
7
+ docs/dialogflow.md
8
+ docs/lex.md
@@ -1,3 +1,15 @@
1
+ 0.1.4
2
+ ---
3
+ * Fixed a bad push
4
+
5
+ 0.1.3
6
+ ---
7
+ * New functionalities:
8
+ * bulk_parse - parse multiple texts
9
+ * parse_test - test multiple texts & intents and get the resuts in json/csv/ruby hash formats
10
+ * parse_test_report - gives a test report summary with metrics: accuracy, confusion_matrix, class wise precision, recall and total
11
+ * More documentation
12
+
1
13
  0.1.2 (31/Dec/2018)
2
14
  ---
3
15
  * fixed lib path error
data/README.md CHANGED
@@ -23,9 +23,21 @@ Or install it yourself as:
23
23
 
24
24
  Check [documentation](docs) for usage.
25
25
 
26
- ## Supported NLU services
27
- 1. [Aws Lex](https://aws.amazon.com/lex/)
28
- 2. [Google Dialogflow](https://dialogflow.com/)
26
+ ## NLU Adapter support matrix
27
+
28
+ C: Create, R: Get, U: Update, D: Delete
29
+
30
+ NLU Service | Intent | Intet Collection | Intent identification
31
+ ----------- | ------ | ---------------- | ---------------------
32
+ [Aws Lex](https://aws.amazon.com/lex/) ([doc](docs/lex.md)) | C,R,U | C,R,U | Yes
33
+ [Google Dialogflow](https://dialogflow.com/) ([doc](docs/dialogflow.md)) | C,R,U | To-Do | Yes
34
+
35
+ ## Classification metrics
36
+ ### Supported intent classification metrics
37
+ * Accuracy
38
+ * Confusion Matrix
39
+ * Precision (per Class)
40
+ * Recall (per Class)
29
41
 
30
42
  ## Development
31
43
 
@@ -35,7 +47,7 @@ To install this gem onto your local machine, run `bundle exec rake install`. To
35
47
 
36
48
  ## Contributing
37
49
 
38
- Bug reports and pull requests are welcome on GitHub at https://github.com/technopreneurG/nlu_adapter. This project is intended to be a safe, welcoming space for collaboration, and contributors are expected to adhere to the [Contributor Covenant](http://contributor-covenant.org) code of conduct.
50
+ Bug reports and pull requests are welcome on GitHub at https://github.com/technopreneurG/nlu_adapter_ruby. This project is intended to be a safe, welcoming space for collaboration, and contributors are expected to adhere to the [Contributor Covenant](http://contributor-covenant.org) code of conduct.
39
51
 
40
52
  ## License
41
53
 
@@ -3,6 +3,8 @@ require "nlu_adapter/version"
3
3
  module NluAdapter
4
4
  autoload :NluAdapterIntent, 'nlu_adapter/intent'
5
5
  autoload :NluAdapterIntentCollection, 'nlu_adapter/intent_collection'
6
+ autoload :ParseHelper, 'nlu_adapter/parse_helper'
7
+ autoload :Metrics, 'nlu_adapter/metrics'
6
8
  module Adapters
7
9
  autoload :Lex, 'nlu_adapter/lex'
8
10
  autoload :Dialogflow, 'nlu_adapter/dialogflow'
@@ -2,21 +2,37 @@ require "google/cloud/dialogflow"
2
2
 
3
3
  module NluAdapter
4
4
  module Adapters
5
+ # Dialogflow wrapper class
6
+ #
5
7
  class Dialogflow
8
+ include ParseHelper
9
+
10
+ # Constructor
6
11
  def initialize(options = {})
7
12
  @project_id = options[:project_id]
8
13
  @session_id = options[:session_id]
9
14
  end
10
15
 
11
- def parse(text, language_code = 'en')
16
+ # Understand a given text
17
+ #
18
+ # @param text [String] a text to parse using the NLU provider
19
+ # @return [Json] return the identified intent name
20
+ #
21
+ def parse(text)
12
22
  sessions_client = Google::Cloud::Dialogflow::Sessions.new(version: :v2)
13
23
  formatted_session = Google::Cloud::Dialogflow::V2::SessionsClient.session_path(@project_id, @session_id)
24
+ language_code = 'en'
14
25
  query_input = Google::Cloud::Dialogflow::V2::QueryInput.new({text: {language_code: language_code, text: text}})
15
26
  response = sessions_client.detect_intent(formatted_session, query_input)
16
27
 
17
28
  return { intent_name: response.query_result.intent.display_name }
18
29
  end
19
30
 
31
+ # Get an instance of Intent, if it exists else nil
32
+ #
33
+ # @param name [String] name of the intent
34
+ # @return [Intent] intent object
35
+ #
20
36
  def get_intent(name)
21
37
  intents_client = Google::Cloud::Dialogflow::Intents.new(version: :v2)
22
38
  formatted_parent = Google::Cloud::Dialogflow::V2::IntentsClient.project_agent_path(@project_id)
@@ -31,6 +47,12 @@ module NluAdapter
31
47
  return nil
32
48
  end
33
49
 
50
+ # Get a new instance of Intent
51
+ #
52
+ # @param name [String] name of the intent
53
+ # @param utterences [Array] phrases for training
54
+ # @return [Intent] Intent object
55
+ #
34
56
  def new_intent(name, utterences = [])
35
57
  i = get_intent(name)
36
58
 
@@ -40,6 +62,13 @@ module NluAdapter
40
62
  return i
41
63
  end
42
64
 
65
+ # Given an Intent object, create/update it in Dialogflow
66
+ #
67
+ # @param intent [Intent] Intent object
68
+ # @return [Intent] Intent object
69
+ #
70
+ # @todo convert response -> Intent
71
+ #
43
72
  def create_intent(intent)
44
73
  intents_client = Google::Cloud::Dialogflow::Intents.new(version: :v2)
45
74
  formatted_parent = Google::Cloud::Dialogflow::V2::IntentsClient.project_agent_path(@project_id)
@@ -55,25 +84,39 @@ module NluAdapter
55
84
  end
56
85
  end
57
86
 
87
+ # Not implemented
88
+ # @todo check back
89
+ #
58
90
  def get_intent_collection(name)
59
91
  end
60
92
 
93
+ # Not implemented
94
+ # @todo check back
95
+ #
61
96
  def new_intent_collection(name, intents)
62
97
  end
63
98
 
99
+ # Not implemented
100
+ # @todo check back
101
+ #
64
102
  def create_intent_collection(collection)
65
103
  end
66
104
 
105
+ # Class represents Intent in an IntentCollection
67
106
  class Intent
68
107
  include NluAdapterIntent
69
108
  attr_accessor :id
70
109
 
110
+ # Constructor
71
111
  def initialize(options = {})
72
112
  @name = options[:name] #DF.intent.display_name
73
113
  @id = options[:id] #DF.intent.name
74
114
  @utterences = options[:utterences]
75
115
  end
76
116
 
117
+ # Convert self to Hash
118
+ # @return [Hash] ruby hash
119
+ #
77
120
  def to_h
78
121
  training_phrases = []
79
122
  @utterences.each do |u|
@@ -87,21 +130,32 @@ module NluAdapter
87
130
  }
88
131
  end
89
132
 
133
+ # convert self to json
134
+ # @return [json] json
135
+ #
90
136
  def to_json
91
137
  to_h.to_json
92
138
  end
93
139
 
94
140
  end
95
141
 
142
+ # Class represents a collection of Intents
96
143
  class IntentCollection
97
144
  include NluAdapterIntentCollection
98
145
 
146
+ # Constructor
99
147
  def initialize(options = {})
100
148
  end
101
149
 
150
+ # Convert self to Hash
151
+ # @return [Hash] ruby hash
152
+ #
102
153
  def to_h
103
154
  end
104
155
 
156
+ # convert self to json
157
+ # @return [json] json
158
+ #
105
159
  def to_json
106
160
  end
107
161
  end
@@ -1,9 +1,12 @@
1
1
  require 'json'
2
2
 
3
- #Class represents Intent in an IntentCollection
3
+ # Class represents Intent in an IntentCollection
4
4
  module NluAdapterIntent
5
5
  attr_accessor :name, :utterences
6
6
 
7
+ # Convert self to Hash
8
+ # @return [Hash] ruby hash
9
+ #
7
10
  def to_h
8
11
  {
9
12
  :name => @name,
@@ -11,6 +14,9 @@ module NluAdapterIntent
11
14
  }
12
15
  end
13
16
 
17
+ # Convert self to Json
18
+ # @return [Json] json
19
+ #
14
20
  def to_json
15
21
  to_h.to_json
16
22
  end
@@ -1,14 +1,18 @@
1
1
  require 'json'
2
2
 
3
- #Class represents a collection of Intents
3
+ # Class represents a collection of Intents
4
4
  module NluAdapterIntentCollection
5
5
  attr_accessor :name, :intents
6
6
 
7
+ # Constructor
7
8
  def initialize(name, intents)
8
9
  @name = name
9
10
  @intents = intents
10
11
  end
11
12
 
13
+ # Convert self to Hash
14
+ # @return [Hash] ruby hash
15
+ #
12
16
  def to_h
13
17
  {
14
18
  :name => @name,
@@ -16,6 +20,9 @@ module NluAdapterIntentCollection
16
20
  }
17
21
  end
18
22
 
23
+ # Convert self to Json
24
+ # @return [Json] json
25
+ #
19
26
  def to_json
20
27
  to_h.to_json
21
28
  end
@@ -1,11 +1,13 @@
1
-
2
1
  require 'aws-sdk-lex'
3
2
  require 'aws-sdk-lexmodelbuildingservice'
4
3
 
5
4
  module NluAdapter
6
5
  module Adapters
6
+ # AWS Lex wrapper class
7
7
  class Lex
8
+ include ParseHelper
8
9
 
10
+ # Constructor
9
11
  def initialize(options = {})
10
12
  #creds & region from config/env
11
13
  @bot_name = options[:bot_name]
@@ -15,7 +17,11 @@ module NluAdapter
15
17
  @lexm_client = Aws::LexModelBuildingService::Client.new()
16
18
  end
17
19
 
18
- #understand a given text
20
+ # Understand a given text
21
+ #
22
+ # @param text [String] a text to parse using the NLU provider
23
+ # @return [Json] return the identified intent name
24
+ #
19
25
  def parse(text)
20
26
  intent_name = nil
21
27
  begin
@@ -39,7 +45,12 @@ module NluAdapter
39
45
  return { intent_name: intent_name }
40
46
  end
41
47
 
42
- #get an instance of Intent, if it exists
48
+ # Get an instance of Intent, if it exists else nil
49
+ #
50
+ # @param name [String] name of the intent
51
+ # @param version [String] version of the intent
52
+ # @return [Intent] intent object
53
+ #
43
54
  def get_intent(name, version = nil)
44
55
  version = '$LATEST'
45
56
 
@@ -53,7 +64,12 @@ module NluAdapter
53
64
  return nil
54
65
  end
55
66
 
56
- #get a new instance of Intent
67
+ # Get a new instance of Intent
68
+ #
69
+ # @param name [String] name of the intent
70
+ # @param utterences [Array] phrases for training
71
+ # @return [Intent] Intent object
72
+ #
57
73
  def new_intent(name, utterences= [])
58
74
  #check for existing intent, and get checksum
59
75
 
@@ -65,12 +81,20 @@ module NluAdapter
65
81
  return i
66
82
  end
67
83
 
68
- #given an Intent object, create it in Lex
84
+ # Given an Intent object, create/update it in Lex
85
+ #
86
+ # @param intent [Intent] Intent object
87
+ # @return [Intent] Intent object
88
+ #
89
+ # @todo convert response -> Intent
90
+ #
69
91
  def create_intent(intent)
70
92
  resp = @lexm_client.put_intent(intent.to_h)
71
93
  end
72
94
 
73
- #get an instance of IntentCollection, if it exists
95
+ # Get an instance of IntentCollection, if it exists
96
+ # @param name [String] intent collection name
97
+ # @param version [String] version
74
98
  def get_intent_collection(name, version = nil)
75
99
  version = '$LATEST'
76
100
  begin
@@ -83,7 +107,9 @@ module NluAdapter
83
107
  return nil
84
108
  end
85
109
 
86
- #get a new instance of Intent
110
+ # Get a new instance of Intent
111
+ # @param name [String] intent collection name
112
+ # @param intents [Array<Intent>] array of intent objects
87
113
  def new_intent_collection(name, intents)
88
114
  ic = get_intent_collection(name)
89
115
 
@@ -93,7 +119,10 @@ module NluAdapter
93
119
  return ic
94
120
  end
95
121
 
96
- #given an IntentCollection object, create it in Lex
122
+ # Given an IntentCollection object, create it in Lex
123
+ #
124
+ # @param collection [IntentCollection] the Bot to be created
125
+ #
97
126
  def create_intent_collection(collection)
98
127
  #create/update intents
99
128
  collection.intents.each do |i|
@@ -103,15 +132,20 @@ module NluAdapter
103
132
  resp = @lexm_client.put_bot(collection.to_h)
104
133
  end
105
134
 
106
- #Classes
135
+ # Class represents Intent in an IntentCollection
107
136
  class Intent
108
137
  include NluAdapterIntent
138
+
139
+ # Constructor
109
140
  def initialize(options = {})
110
141
  @name = options[:name]
111
142
  @version = options[:version]
112
143
  @checksum = options[:checksum]
113
144
  end
114
145
 
146
+ # Convert self to Hash
147
+ # @return [Hash] ruby hash
148
+ #
115
149
  def to_h
116
150
  {
117
151
  name: @name,
@@ -123,22 +157,29 @@ module NluAdapter
123
157
  }
124
158
  end
125
159
 
160
+ # convert self to Json
161
+ # @return [json] json
162
+ #
126
163
  def to_json
127
164
  to_h.to_json
128
165
  end
129
166
  end
130
167
 
131
- #Classes
168
+ # Class represents a collection of Intents
132
169
  class IntentCollection
133
170
  include NluAdapterIntentCollection
134
171
  attr_accessor :extra
135
172
 
173
+ # Constructor
136
174
  def initialize(options = {})
137
175
  @name = options[:name]
138
176
  @checksum = options[:checksum]
139
177
  @intents = options[:intents]
140
178
  end
141
179
 
180
+ # Convert self to Hash
181
+ # @return [Hash] ruby hash
182
+ #
142
183
  def to_h
143
184
  intents = []
144
185
  @intents.each do |i|
@@ -183,6 +224,9 @@ module NluAdapter
183
224
  }
184
225
  end
185
226
 
227
+ # Convert self to Json
228
+ # @return [Json] json
229
+ #
186
230
  def to_json
187
231
  to_h.to_json
188
232
  end
@@ -0,0 +1,178 @@
1
+ require 'matrix'
2
+
3
+ module NluAdapter
4
+
5
+ # A utility class to calculate classification matrics
6
+ # @see https://scikit-learn.org/stable/modules/model_evaluation.html#classification-metrics
7
+ #
8
+ class Metrics
9
+
10
+ # Constructor
11
+ # @param actual [Array] an array of actual results (true values)
12
+ # @param predicted [Array] an array of predicted results (predicted values)
13
+ # @param class_labels [Array] an array of class_labels for the results,
14
+ # this is required if actual & predicted values are numeric
15
+ #
16
+ def initialize(actual, predicted, class_labels = [])
17
+ @actual = actual
18
+ @predicted = predicted
19
+ @class_labels = class_labels
20
+
21
+ @actual.map!{ |a| a.is_a?(String)? a.intern : a }
22
+ @predicted.map!{ |p| p.is_a?(String)? p.intern : p }
23
+ @class_labels.map!{ |l| l.is_a?(String)? l.intern : l }
24
+ end
25
+
26
+ # Caclulate the accuracy
27
+ # @return [Float] accuracy
28
+ # @see https://en.wikipedia.org/wiki/Accuracy_and_precision
29
+ #
30
+ def accuracy
31
+ if @actual.size != @predicted.size
32
+ #todo: throw error
33
+ puts "actual & predicted array are not of same size"
34
+ return
35
+ end
36
+
37
+ total = @actual.size
38
+ correct = 0
39
+ @actual.each_with_index do |v, i|
40
+ correct+=1 if @predicted[i] == v
41
+ end
42
+ (correct.fdiv(total) * 100).round(4)
43
+ end
44
+
45
+ # Get the confusion matrix
46
+ # @return [Matrix] confusion matrix
47
+ # @see https://en.wikipedia.org/wiki/Confusion_matrix
48
+ #
49
+ def confusion_matrix
50
+ class_labels = @class_labels
51
+ actual = @actual
52
+ predicted = @predicted
53
+
54
+ #if no class_labels, convert to numeric values, and extract the class_labels
55
+ if @class_labels.empty?
56
+ class_labels = (@actual + @predicted).sort.uniq.sort
57
+ class_labels.map!{|c| c.intern}
58
+ @actual.each_with_index do |v, i|
59
+ actual[i] = class_labels.index(v)
60
+ end
61
+
62
+ @predicted.each_with_index do |v, i|
63
+ predicted[i] = class_labels.index(v)
64
+ end
65
+ else
66
+ #check if any string passed in actual/predicted
67
+ i = actual.select { |a| a.is_a?(Symbol) }.size
68
+ j = predicted.select { |p| p.is_a?(Symbol) }.size
69
+
70
+ if i > 0 || j > 0
71
+ #todo: fix it OR throw error
72
+ puts "actual, predicted & class_labels array having string values not implemented yet"
73
+ return
74
+
75
+ end
76
+ end
77
+
78
+ m = Matrix.zero(class_labels.size)
79
+
80
+ @class_totals = Hash[class_labels.collect { |c| [c, 0] }]
81
+ actual.each_with_index do |vi, i|
82
+ vj = predicted[i]
83
+ m[vi, vj] = m[vi, vj] + 1
84
+ @class_totals[class_labels[vi]] += 1
85
+ end
86
+
87
+ @class_labels = class_labels
88
+ @actual = actual
89
+ @predicted = predicted
90
+
91
+ @m = m
92
+ return m
93
+ end
94
+
95
+ # Get totals of actual values per class
96
+ # @return [Hash] Hash of class totals
97
+ #
98
+ def class_totals
99
+ return @class_totals
100
+ end
101
+
102
+ # Get total positives
103
+ # @param class_name [String] class name
104
+ # @return [Integer] total positive value for class_name
105
+ #
106
+ def tp(class_name)
107
+ i = @class_labels.index(class_name.intern)
108
+ return nil if i == nil || @m == nil || @m.empty?
109
+ tp = @m[i, i]
110
+ return tp
111
+ end
112
+
113
+ # Get false positive
114
+ # @param class_name [String] class name
115
+ # @return [Integer] false positive value for class_name
116
+ #
117
+ def fp(class_name)
118
+ i = @class_labels.index(class_name.intern)
119
+ return nil if i == nil || @m == nil || @m.empty?
120
+ fp = @m.column(i).sum - tp(class_name)
121
+ return fp
122
+ end
123
+
124
+ # Get false negative
125
+ # @param class_name [String] class name
126
+ # @return [Integer] false negative value for class_name
127
+ #
128
+ def fn(class_name)
129
+ i = @class_labels.index(class_name.intern)
130
+ return nil if i == nil || @m == nil || @m.empty?
131
+ fn = @m.row(i).sum - tp(class_name)
132
+ return fn
133
+ end
134
+
135
+ # Get the precision for given class
136
+ # @param class_name [String] class name
137
+ # @return [Float] precision rounded off to 4 decimal places
138
+ #
139
+ def precision(class_name)
140
+ confusion_matrix if !@m
141
+ return 0.00 if tp(class_name) == 0
142
+ precision = tp(class_name).fdiv((tp(class_name) + fp(class_name))).round(4)
143
+ return precision
144
+ end
145
+
146
+ # Get the recall for given class
147
+ # @param class_name [String] class name
148
+ # @return [Float] recall rounded off to 4 decimal places
149
+ #
150
+ def recall(class_name)
151
+ confusion_matrix if !@m
152
+ return 0.00 if tp(class_name) == 0
153
+ recall = tp(class_name).fdiv((tp(class_name) + fn(class_name))).round(4)
154
+
155
+ return recall
156
+ end
157
+
158
+ # Generate classification report
159
+ # @return [Hash] precision, recall and totals for each class name as key
160
+ #
161
+ def classification_report
162
+ confusion_matrix if !@m
163
+ report = {}
164
+ @class_labels.each do |label|
165
+ report[label] = {
166
+ precision: precision(label),
167
+ recall: recall(label),
168
+ class_total: class_totals[label]
169
+ }
170
+ end
171
+
172
+ return report
173
+ end
174
+
175
+ #todo: f1-score
176
+ end
177
+ end
178
+
@@ -0,0 +1,100 @@
1
+ require 'csv'
2
+ require 'json'
3
+
4
+ #helper functions to parse text and match intent
5
+ module NluAdapter
6
+ module ParseHelper
7
+ # parse multiple texts
8
+ #
9
+ # Example input/output
10
+ # texts:
11
+ # ["book me a hotel, please", "book a hotel"]
12
+ # result:
13
+ # {"book me a hotel, please"=>"BookHotel", "book a hotel"=>"BookHotel"}
14
+ #
15
+ # @param [Array<String>] texts An array of texts to be parsed
16
+ # @return [Hash] return a hash of "text" => "result"
17
+ # @todo parallize
18
+ def bulk_parse(texts)
19
+ result = {}
20
+ texts.each do |text|
21
+ resp = parse(text)
22
+ result[text] = resp[:intent_name]
23
+ end
24
+ result
25
+ end
26
+
27
+ # run the parse tests with test_data and generate test_results in supported format
28
+ #
29
+ # Example input/output
30
+ # test_data
31
+ # {"BookHotel":["please book a hotel"],"intent1":["book me a hotel, please","book a hotel"]}
32
+ # test_results
33
+ # json:
34
+ # [{"text":"book me a hotel, please","expected":"intent1","got":"BookHotel"},{"text":"book a hotel","expected":"intent1","got":"BookHotel"},{"text":"please book a hotel","expected":"BookHotel","got":"BookHotel"}]
35
+ # csv:
36
+ # "book me a hotel, please",intent1,BookHotel
37
+ # book a hotel,intent1,BookHotel
38
+ # please book a hotel,BookHotel,BookHotel
39
+ # hash:
40
+ # [{:text=>"book me a hotel, please", :expected=>"intent1", :got=>"BookHotel"}, {:text=>"book a hotel", :expected=>"intent1", :got=>"BookHotel"}, {:text=>"please book a hotel", :expected=>"BookHotel", :got=>"BookHotel"}]
41
+ #
42
+ # @param test_data [Json]: Test data in specified format
43
+ # @param output_format [Symbol] supported formats :csv, :json or :hash
44
+ # @return [test_results]: output the test results in expected format
45
+ #
46
+ def parse_test(test_data, output_format = :hash)
47
+ test_results = []
48
+ test_data.each do |intent_name, texts|
49
+ resp = bulk_parse(texts)
50
+ texts.each do |t|
51
+ test_results << {text: t, expected: intent_name, got: resp[t]}
52
+ end
53
+ end
54
+
55
+ case output_format
56
+ when :json
57
+ return test_results.to_json
58
+ when :csv
59
+ return to_csv(test_results)
60
+ when :hash
61
+ return test_results
62
+ else
63
+ puts 'Warning: valid format not specified'
64
+ return test_results
65
+ end
66
+
67
+ end
68
+
69
+
70
+ # run the parse tests with test_data and generate test report
71
+ #
72
+ # @param test_data [Json]: Test data in specified format
73
+ # @return [test_report]: generate a test report
74
+ # @todo F1-Score
75
+ #
76
+ def parse_test_report(test_data)
77
+ test_results = parse_test(test_data)
78
+ expected = []
79
+ got = []
80
+ test_results.each do |result|
81
+ expected << result[:expected]
82
+ got << result[:got]
83
+ end
84
+
85
+ m = Metrics.new(expected, got)
86
+
87
+ return {accuracy: m.accuracy, confusion_matrix: m.confusion_matrix, classification_report: m.classification_report}
88
+ end
89
+
90
+ private
91
+ def to_csv(test_results)
92
+ csv_string = CSV.generate do |csv|
93
+ test_results.each do |result|
94
+ csv << result.values
95
+ end
96
+ end
97
+ csv_string
98
+ end
99
+ end
100
+ end
@@ -1,3 +1,3 @@
1
1
  module NluAdapter
2
- VERSION = "0.1.2"
2
+ VERSION = "0.1.4"
3
3
  end
@@ -6,7 +6,7 @@ require "nlu_adapter/version"
6
6
  Gem::Specification.new do |spec|
7
7
  spec.name = "nlu_adapter"
8
8
  spec.version = NluAdapter::VERSION
9
- spec.authors = ["Girish"]
9
+ spec.authors = ["Girish Nair"]
10
10
  spec.email = ["getgirish@gmail.com"]
11
11
 
12
12
  spec.summary = %q{NLU Adapter - An adapter for various NLU web services}
@@ -41,10 +41,12 @@ Gem::Specification.new do |spec|
41
41
  spec.add_development_dependency "rspec", "~> 3.8"
42
42
 
43
43
  #Official AWS Ruby gem for Amazon Lex Runtime Service. This gem is part of the AWS SDK for Ruby.
44
- spec.add_dependency('aws-sdk-lex', '1.9')
45
- spec.add_dependency('aws-sdk-lexmodelbuildingservice', '1.12')
44
+ spec.add_dependency('aws-sdk-lex', '~> 1.9')
45
+ spec.add_dependency('aws-sdk-lexmodelbuildingservice', '~> 1.12')
46
46
 
47
47
  #google-cloud-dialogflow is the official library for Dialogflow API.
48
- spec.add_dependency('google-cloud-dialogflow', '0.2.3')
48
+ spec.add_dependency('google-cloud-dialogflow', '~> 0.2.3')
49
49
 
50
+ #An implementation of Matrix and Vector classes.
51
+ spec.add_dependency('matrix', '~> 0.1.0')
50
52
  end
metadata CHANGED
@@ -1,14 +1,14 @@
1
1
  --- !ruby/object:Gem::Specification
2
2
  name: nlu_adapter
3
3
  version: !ruby/object:Gem::Version
4
- version: 0.1.2
4
+ version: 0.1.4
5
5
  platform: ruby
6
6
  authors:
7
- - Girish
7
+ - Girish Nair
8
8
  autorequire:
9
9
  bindir: exe
10
10
  cert_chain: []
11
- date: 2018-12-30 00:00:00.000000000 Z
11
+ date: 2019-01-18 00:00:00.000000000 Z
12
12
  dependencies:
13
13
  - !ruby/object:Gem::Dependency
14
14
  name: bundler
@@ -56,44 +56,58 @@ dependencies:
56
56
  name: aws-sdk-lex
57
57
  requirement: !ruby/object:Gem::Requirement
58
58
  requirements:
59
- - - '='
59
+ - - "~>"
60
60
  - !ruby/object:Gem::Version
61
61
  version: '1.9'
62
62
  type: :runtime
63
63
  prerelease: false
64
64
  version_requirements: !ruby/object:Gem::Requirement
65
65
  requirements:
66
- - - '='
66
+ - - "~>"
67
67
  - !ruby/object:Gem::Version
68
68
  version: '1.9'
69
69
  - !ruby/object:Gem::Dependency
70
70
  name: aws-sdk-lexmodelbuildingservice
71
71
  requirement: !ruby/object:Gem::Requirement
72
72
  requirements:
73
- - - '='
73
+ - - "~>"
74
74
  - !ruby/object:Gem::Version
75
75
  version: '1.12'
76
76
  type: :runtime
77
77
  prerelease: false
78
78
  version_requirements: !ruby/object:Gem::Requirement
79
79
  requirements:
80
- - - '='
80
+ - - "~>"
81
81
  - !ruby/object:Gem::Version
82
82
  version: '1.12'
83
83
  - !ruby/object:Gem::Dependency
84
84
  name: google-cloud-dialogflow
85
85
  requirement: !ruby/object:Gem::Requirement
86
86
  requirements:
87
- - - '='
87
+ - - "~>"
88
88
  - !ruby/object:Gem::Version
89
89
  version: 0.2.3
90
90
  type: :runtime
91
91
  prerelease: false
92
92
  version_requirements: !ruby/object:Gem::Requirement
93
93
  requirements:
94
- - - '='
94
+ - - "~>"
95
95
  - !ruby/object:Gem::Version
96
96
  version: 0.2.3
97
+ - !ruby/object:Gem::Dependency
98
+ name: matrix
99
+ requirement: !ruby/object:Gem::Requirement
100
+ requirements:
101
+ - - "~>"
102
+ - !ruby/object:Gem::Version
103
+ version: 0.1.0
104
+ type: :runtime
105
+ prerelease: false
106
+ version_requirements: !ruby/object:Gem::Requirement
107
+ requirements:
108
+ - - "~>"
109
+ - !ruby/object:Gem::Version
110
+ version: 0.1.0
97
111
  description: An adapter for various NLU web services like Aws Lex, Google Dialogflow
98
112
  etc.
99
113
  email:
@@ -102,12 +116,13 @@ executables: []
102
116
  extensions: []
103
117
  extra_rdoc_files: []
104
118
  files:
119
+ - ".gitignore"
105
120
  - ".rspec"
121
+ - ".yardopts"
106
122
  - CHANGELOG.md
107
123
  - CODE_OF_CONDUCT.md
108
124
  - Dockerfile
109
125
  - Gemfile
110
- - Gemfile.lock
111
126
  - LICENSE
112
127
  - README.md
113
128
  - Rakefile
@@ -121,6 +136,8 @@ files:
121
136
  - lib/nlu_adapter/intent.rb
122
137
  - lib/nlu_adapter/intent_collection.rb
123
138
  - lib/nlu_adapter/lex.rb
139
+ - lib/nlu_adapter/metrics.rb
140
+ - lib/nlu_adapter/parse_helper.rb
124
141
  - lib/nlu_adapter/version.rb
125
142
  - nlu_adapter.gemspec
126
143
  homepage: https://rubygems.org/gems/nlu_adapter
@@ -1,94 +0,0 @@
1
- PATH
2
- remote: .
3
- specs:
4
- nlu_adapter (0.1.2)
5
- aws-sdk-lex (= 1.9)
6
- aws-sdk-lexmodelbuildingservice (= 1.12)
7
- google-cloud-dialogflow (= 0.2.3)
8
-
9
- GEM
10
- remote: https://rubygems.org/
11
- specs:
12
- addressable (2.5.2)
13
- public_suffix (>= 2.0.2, < 4.0)
14
- aws-eventstream (1.0.1)
15
- aws-partitions (1.127.0)
16
- aws-sdk-core (3.44.1)
17
- aws-eventstream (~> 1.0)
18
- aws-partitions (~> 1.0)
19
- aws-sigv4 (~> 1.0)
20
- jmespath (~> 1.0)
21
- aws-sdk-lex (1.9.0)
22
- aws-sdk-core (~> 3, >= 3.39.0)
23
- aws-sigv4 (~> 1.0)
24
- aws-sdk-lexmodelbuildingservice (1.12.0)
25
- aws-sdk-core (~> 3, >= 3.39.0)
26
- aws-sigv4 (~> 1.0)
27
- aws-sigv4 (1.0.3)
28
- diff-lcs (1.3)
29
- faraday (0.15.4)
30
- multipart-post (>= 1.2, < 3)
31
- google-cloud-dialogflow (0.2.3)
32
- google-gax (~> 1.3)
33
- google-gax (1.4.0)
34
- google-protobuf (~> 3.2)
35
- googleapis-common-protos (>= 1.3.5, < 2.0)
36
- googleauth (~> 0.6.2)
37
- grpc (>= 1.7.2, < 2.0)
38
- rly (~> 0.2.3)
39
- google-protobuf (3.6.1)
40
- googleapis-common-protos (1.3.7)
41
- google-protobuf (~> 3.0)
42
- googleapis-common-protos-types (~> 1.0)
43
- grpc (~> 1.0)
44
- googleapis-common-protos-types (1.0.2)
45
- google-protobuf (~> 3.0)
46
- googleauth (0.6.7)
47
- faraday (~> 0.12)
48
- jwt (>= 1.4, < 3.0)
49
- memoist (~> 0.16)
50
- multi_json (~> 1.11)
51
- os (>= 0.9, < 2.0)
52
- signet (~> 0.7)
53
- grpc (1.17.1)
54
- google-protobuf (~> 3.1)
55
- googleapis-common-protos-types (~> 1.0.0)
56
- jmespath (1.4.0)
57
- jwt (2.1.0)
58
- memoist (0.16.0)
59
- multi_json (1.13.1)
60
- multipart-post (2.0.0)
61
- os (1.0.0)
62
- public_suffix (3.0.3)
63
- rake (12.3.2)
64
- rly (0.2.3)
65
- rspec (3.8.0)
66
- rspec-core (~> 3.8.0)
67
- rspec-expectations (~> 3.8.0)
68
- rspec-mocks (~> 3.8.0)
69
- rspec-core (3.8.0)
70
- rspec-support (~> 3.8.0)
71
- rspec-expectations (3.8.2)
72
- diff-lcs (>= 1.2.0, < 2.0)
73
- rspec-support (~> 3.8.0)
74
- rspec-mocks (3.8.0)
75
- diff-lcs (>= 1.2.0, < 2.0)
76
- rspec-support (~> 3.8.0)
77
- rspec-support (3.8.0)
78
- signet (0.11.0)
79
- addressable (~> 2.3)
80
- faraday (~> 0.9)
81
- jwt (>= 1.5, < 3.0)
82
- multi_json (~> 1.10)
83
-
84
- PLATFORMS
85
- ruby
86
-
87
- DEPENDENCIES
88
- bundler (~> 1.16)
89
- nlu_adapter!
90
- rake (~> 12.0)
91
- rspec (~> 3.8)
92
-
93
- BUNDLED WITH
94
- 1.16.6