nlu_adapter 0.1.2 → 0.1.4

Sign up to get free protection for your applications and to get access to all the features.
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