api_ai_wrapper 1.0.0 → 1.0.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
  SHA1:
3
- metadata.gz: 469724d657925c38ac67bf0c138f213735ed032a
4
- data.tar.gz: ccc0bd55f2401a5a57766bb53fd030076a528b52
3
+ metadata.gz: bad5503f39dd701eed3c4dfd90d830632a37fd2c
4
+ data.tar.gz: 5f847be711f203214eef3ea1340011bb7f2233ec
5
5
  SHA512:
6
- metadata.gz: 3b58704d1d01e1e063e562d349d6dd2379256d52f192c5298616ff0f6a98bb2ca5644beff1fc184abc3bab00ac28c67acd4064f93de4b9c0969f8135fce5891f
7
- data.tar.gz: a941104c2cb448f049048fe366877863efff846252b3523b62a06b4c9e28e8f085b924872dddaabfe7d603f8781153f44cae6c356a72286d192477ff0c6e9771
6
+ metadata.gz: 59f828697c158ca608501b3901d39784e9a6fb86874ec5e8a464e0983490b629c037257ab29faee484d3879c28868a20adfbceefb725dab2663c1876c44bb0ec
7
+ data.tar.gz: 5507caece3003dc208f206be234c7390360985718507e8f7fbac02b4533f772601c0165e0ac17f7944d61b0590ef17047f1c0d992daf8cfe32680762d7e1f5ac
data/Gemfile.lock CHANGED
@@ -1,3 +1,9 @@
1
+ PATH
2
+ remote: .
3
+ specs:
4
+ api_ai_wrapper (1.0.3)
5
+ httpclient (~> 2.8, >= 2.8.0)
6
+
1
7
  GEM
2
8
  remote: https://rubygems.org/
3
9
  specs:
@@ -39,6 +45,7 @@ PLATFORMS
39
45
  ruby
40
46
 
41
47
  DEPENDENCIES
48
+ api_ai_wrapper!
42
49
  httpclient
43
50
  rspec
44
51
  simplecov
data/README.md CHANGED
@@ -1,2 +1,140 @@
1
- # api_ai_wrapper
1
+ # The API.AI ruby wrapper
2
2
  A simple library that let's any developer automate the training process of a Natural Language Processing Engine on API.AI, and retrieve meaning from new utterances.
3
+
4
+ # To install
5
+ Directly from a bash console
6
+
7
+ ```ruby
8
+ gem install api_ai_wrapper
9
+ ```
10
+
11
+ Or in your Gemfile
12
+ ```ruby
13
+ gem "api_ai_wrapper"
14
+ ```
15
+
16
+
17
+ The only gem dependency is `http_client` to manage HTTP calls to API.AI.
18
+
19
+ # To start things up
20
+ The gem is centered around the ApiAiWrapper::Engine model that will be the gateway to all the gem's available endpoints. To make such calls, just instantiate an Engine with the correct developer and client tokens (for training and meaning retrieval) like so (in an initializer for instance) :
21
+
22
+ ```ruby
23
+ $engine = ApiAiWrapper::Engine.new({
24
+ developer_token: "YOUR DEVELOPER TOKEN",
25
+ client_token: "YOUR CLIENT TOKEN"
26
+ })
27
+ ```
28
+
29
+ That's for the basic usage, if you want complete control over your API.AI engine initialization, you might do :
30
+
31
+ ```ruby
32
+ $engine = ApiAiWrapper::Engine.new({
33
+ developer_token: "YOUR DEVELOPER TOKEN",
34
+ client_token: "YOUR CLIENT TOKEN",
35
+ client_timeout: HTTPCLIENT TIMEOUT IN SECONDS (defaults to 50000),
36
+ locale: "YOUR ENGINE REQUIRED LOCALE" (defaults to "en"),
37
+ version: "YOUR PREFERRED API.AI VERSION" (defaults to "20150910")
38
+ })
39
+ ```
40
+
41
+ Because we use HTTPClient for calls, you can override the client_timeout attribute to pick your prefered timeout. As a default, it is set to 50000 seconds.
42
+
43
+ # To actually use the gem
44
+ The API.AI API (that's a mouthful) offers two modes : the Training mode and the Query mode.
45
+
46
+ ## Training Mode
47
+ Included in this gem are all endpoints available in API.AI around [entities](https://api.ai/docs/reference/agent/entities) and [intents](https://api.ai/docs/reference/agent/intents).
48
+
49
+ To use them, initializing an engine with the code above (`developer_token` is required) gives you access to an `IntentTrainer` and `EntityTrainer` instances that serve as proxy to call the corresponding endpoints. For example, assuming `$engine` has been initialized, fetching all entities on a given engine can be done as follows :
50
+
51
+ ```ruby
52
+ entity_trainer = $engine.entity_trainer
53
+ entities = entity_trainer.get_entities
54
+ ```
55
+
56
+ Posting a new intent can be as easy as that :
57
+
58
+ ```ruby
59
+ intent_trainer = $engine.intent_trainer
60
+ intent_trainer.post_intent({
61
+ name: "some-name",
62
+ user_says_data: [
63
+ {
64
+ data: [
65
+ {
66
+ text: "A sample "
67
+ },
68
+ {
69
+ text: "utterance",
70
+ alias: "object",
71
+ meta: "@object"
72
+ },
73
+ {
74
+ text: " for you"
75
+ }
76
+ ],
77
+ isTemplate: false,
78
+ count: 0
79
+ },
80
+ {
81
+ data: ...
82
+ }
83
+ ]
84
+ })
85
+ ```
86
+
87
+ ### Endpoints list
88
+
89
+ All available methods/endpoints are listed in the tables below
90
+
91
+ #### IntentTrainer
92
+
93
+ Use these methods on `intent_trainer = $engine.intent_trainer`
94
+
95
+ Name | Arguments | Description
96
+ --- | --- | ---
97
+ *get_intents* | none | Retrieves a list of all intents for the agent.
98
+ *get_intent* | `intent_id` | Retrieves the specified intent.
99
+ *post_intent* | `name`, `user_says_data`, `options` | Creates a new intent (options is a hash containing additional info about an intent specified in API.AI documentation).
100
+ *put_intent* | `intent_id`, `options` | Updates the specified intent. (options is a hash containing intent fields to modify)
101
+ *delete_intent* | `intent_id` | Deletes the specified entity.
102
+
103
+ #### EntityTrainer
104
+
105
+ Use these methods on `entity_trainer = $engine.entity_trainer`
106
+
107
+ Name | Arguments | Description
108
+ --- | --- | ---
109
+ *get_entities* | none | Retrieves a list of all entities for the agent.
110
+ *get_entity* | `entity_id` | Retrieves the specified entity.
111
+ *post_entity* | `name`, `entries` | Creates a new entity.
112
+ *post_entity_entries* | `entity_id`, `entries` | Adds an array of entity entries to the specified entity.
113
+ *put_entity* | `entity_id`, `options` | Creates or updates multiple entities. (options is a hash containing entity fields to modify)
114
+ *put_entity_entries* | `entity_id`, `entries` | Updates an array of entity entries in the specified entity.
115
+ *delete_entity* | `entity_id` | Deletes the specified entity.
116
+ *delete_entity_entries* | `entity_id`, `entries` | Deletes an array of entity entries from the specified entity.
117
+
118
+ ## Query mode
119
+ After your API.AI engine is properly trained, you can retrieve meaning (intents and entities) from a novel utterance via the `query` endpoint.
120
+
121
+ To use is, initializing an engine with the code above (`client_token` is required) gives you access to a `MeaningExtractor` instance that serves as proxy to call the `query` endpoint. Assuming `$engine` has been initialized, extracting the meaning from a sentence can be done as follows :
122
+
123
+ ```ruby
124
+ meaning_extractor = $engine.meaning_extractor
125
+ meaning_extractor.post_query("A sample utterance")
126
+ ```
127
+
128
+ This call will return a JSON parsed hash with the utterance meaning returned by API.AI
129
+
130
+ Name | Arguments | Description
131
+ --- | --- | ---
132
+ *post_query* | `query`, `options` | Takes natural language text and information, returns intent and entity information. (options is a hash containing additional info about an intent specified in API.AI documentation).
133
+
134
+ # Errors
135
+ `ApiAiWrapper::Errors::Engine::MissingTokens` error is returned when an `ApiAiWrapper::Engine` is instantiated without any token.
136
+
137
+ `ApiAiWrapper::Errors::Engine::MissingToken` errors are returned when a call is made to `entity_trainer`, `intent_trainer` or `meaning_extractor` but the appropriate token (either `developer_token` or `client_token`) has not been defined in the Engine.
138
+
139
+ `ApiAiWrapper::Errors::Engine::ApiError` error is returned whenever something goes wrong during a request to API.AI. The error contains a `error.message`, `error.code` and `error.status` identical to the ones returned by API.AI for full transparency.
140
+
@@ -1,6 +1,6 @@
1
1
  Gem::Specification.new do |s|
2
2
  s.name = 'api_ai_wrapper'
3
- s.version = '1.0.0'
3
+ s.version = '1.0.4'
4
4
  s.date = '2017-08-04'
5
5
  s.summary = "An API.AI Ruby Wrapper"
6
6
  s.description = "A simple ruby library that let's any developer automate the training process of a Natural Language Processing Engine on API.AI, and retrieve meaning from new utterances."
@@ -1,6 +1,7 @@
1
1
  module ApiAiWrapper::Components
2
2
 
3
3
  class Component
4
+
4
5
  attr_accessor :engine
5
6
 
6
7
  # We define http_verb methods get/post/put/delete to add correct headers and parse result automatically
@@ -20,16 +21,20 @@ module ApiAiWrapper::Components
20
21
  # Throws an error if the call is not successful
21
22
  # Returns response if no error is returned
22
23
  def handle_response(response_body)
23
- response = response_body.deep_symbolize_keys
24
- response_status = response[:status]
25
- response_code = response_status[:code]
26
24
 
27
- if response_code != 200
28
- raise ApiAiWrapper::Errors::Engine::ApiError.new(response_status[:errorDetails], response_code, response_status[:errorType])
25
+ if response_body.is_a?(Hash) && response_body.has_key?("status")
26
+ response_body = response_body.deep_symbolize_keys
27
+ response_status = response_body[:status]
28
+ response_code = response_status[:code]
29
+
30
+ if response_code != 200
31
+ raise ApiAiWrapper::Errors::Engine::ApiError.new(response_status[:errorDetails], response_code, response_status[:errorType])
32
+ end
29
33
  end
30
34
 
31
- response
35
+ response_body
32
36
  end
37
+
33
38
  end
34
39
 
35
40
  end
@@ -1,3 +1,4 @@
1
+ # Hash Override taken from Rails
1
2
  class Hash
2
3
 
3
4
  def transform_keys
@@ -1,3 +1,4 @@
1
+ # Object Override taken from Rails
1
2
  class Object
2
3
  def blank?
3
4
  respond_to?(:empty?) ? empty? : !self
@@ -1,3 +1,4 @@
1
+ # String Override taken from Rails
1
2
  class String
2
3
 
3
4
  def demodulize
@@ -7,23 +7,17 @@ module ApiAiWrapper::Trainers
7
7
  # https://api.ai/docs/reference/agent/intents#get_intents
8
8
  # Fetches all intents for a given token
9
9
  def get_intents
10
- set_headers
11
10
  endpoint_url = URI.join(self.engine.base_url, "intents?v=#{self.engine.version}")
12
11
 
13
- res = self.engine.client.get(endpoint_url, {}, self.engine.headers)
14
-
15
- JSON.parse(res.body)
12
+ self.get(endpoint_url, {})
16
13
  end
17
14
 
18
15
  # https://api.ai/docs/reference/agent/intents#get_intentsiid
19
16
  # Retrieves intent info
20
17
  def get_intent(iid)
21
- set_headers
22
18
  endpoint_url = URI.join(self.engine.base_url, "intents/#{iid}?v=#{self.engine.version}")
23
19
 
24
- res = self.engine.client.get(endpoint_url, {}, self.engine.headers)
25
-
26
- JSON.parse(res.body)
20
+ self.get(endpoint_url, {})
27
21
  end
28
22
 
29
23
  # https://api.ai/docs/reference/agent/intents#post_intents
@@ -33,7 +27,6 @@ module ApiAiWrapper::Trainers
33
27
  # - templates
34
28
  # - responses
35
29
  def post_intent(name, user_says_data, options = {})
36
- set_headers
37
30
  body = options.merge({
38
31
  name: name,
39
32
  auto: true, # ML activated
@@ -41,31 +34,23 @@ module ApiAiWrapper::Trainers
41
34
  })
42
35
  endpoint_url = URI.join(self.engine.base_url, "intents?v=#{self.engine.version}")
43
36
 
44
- res = self.engine.client.post(endpoint_url, body.to_json, self.engine.headers)
45
-
46
- JSON.parse(res.body)
37
+ self.post(endpoint_url, body.to_json)
47
38
  end
48
39
 
49
40
  # https://api.ai/docs/reference/agent/intents#put_intentsiid
50
41
  # Update an intent
51
42
  def put_intent(iid, options = {})
52
- set_headers
53
43
  endpoint_url = URI.join(self.engine.base_url, "intents/#{iid}?v=#{self.engine.version}")
54
44
 
55
- res = self.engine.client.put(endpoint_url, options.to_json, self.engine.headers)
56
-
57
- JSON.parse(res.body)
45
+ self.put(endpoint_url, options.to_json)
58
46
  end
59
47
 
60
48
  # https://api.ai/docs/reference/agent/entities#delete_entitieseid
61
49
  # Delete an intent
62
50
  def delete_intent(iid)
63
- set_headers
64
51
  endpoint_url = URI.join(self.engine.base_url, "intents/#{iid}?v=#{self.engine.version}")
65
52
 
66
- res = self.engine.client.delete(endpoint_url, {}, self.engine.headers)
67
-
68
- JSON.parse(res.body)
53
+ self.delete(endpoint_url, {})
69
54
  end
70
55
 
71
56
  end
@@ -57,11 +57,27 @@ RSpec.describe ApiAiWrapper::Components::Component do
57
57
  end
58
58
 
59
59
  describe "#handle_response(response)" do
60
- context "when API.AI call is successful (code is 200)" do
61
- it "should return JSON parsed response" do
62
- response = { "status" => { "code" => 200, "errorType" => "success" } }
60
+ context "when API.AI call is successful" do
61
+ context "from a GET request" do
62
+ it "should return JSON parsed array for a list GET" do
63
+ response = [{ "object-column" => "object-value" }]
64
+
65
+ expect(component.send(:handle_response, response)).to eq(response)
66
+ end
67
+
68
+ it "should return JSON parsed object for an instance GET" do
69
+ response = { "object-column" => "object-value" }
70
+
71
+ expect(component.send(:handle_response, response)).to eq(response)
72
+ end
73
+ end
74
+
75
+ context "from a POST/PUT/DELETE request" do
76
+ it "should return JSON parsed response" do
77
+ response = { "status" => { "code" => 200, "errorType" => "success" } }
63
78
 
64
- expect(component.send(:handle_response, response)).to eq(response.deep_symbolize_keys)
79
+ expect(component.send(:handle_response, response)).to eq(response.deep_symbolize_keys)
80
+ end
65
81
  end
66
82
  end
67
83
 
metadata CHANGED
@@ -1,7 +1,7 @@
1
1
  --- !ruby/object:Gem::Specification
2
2
  name: api_ai_wrapper
3
3
  version: !ruby/object:Gem::Version
4
- version: 1.0.0
4
+ version: 1.0.4
5
5
  platform: ruby
6
6
  authors:
7
7
  - Vincent Gabou