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 +4 -4
- data/Gemfile.lock +7 -0
- data/README.md +139 -1
- data/api_ai_wrapper.gemspec +1 -1
- data/lib/api_ai_wrapper/components/component.rb +11 -6
- data/lib/api_ai_wrapper/extensions/hash.rb +1 -0
- data/lib/api_ai_wrapper/extensions/object.rb +1 -0
- data/lib/api_ai_wrapper/extensions/string.rb +1 -0
- data/lib/api_ai_wrapper/trainers/intent_trainer.rb +5 -20
- data/spec/api_ai_wrapper/components/component_spec.rb +20 -4
- metadata +1 -1
checksums.yaml
CHANGED
@@ -1,7 +1,7 @@
|
|
1
1
|
---
|
2
2
|
SHA1:
|
3
|
-
metadata.gz:
|
4
|
-
data.tar.gz:
|
3
|
+
metadata.gz: bad5503f39dd701eed3c4dfd90d830632a37fd2c
|
4
|
+
data.tar.gz: 5f847be711f203214eef3ea1340011bb7f2233ec
|
5
5
|
SHA512:
|
6
|
-
metadata.gz:
|
7
|
-
data.tar.gz:
|
6
|
+
metadata.gz: 59f828697c158ca608501b3901d39784e9a6fb86874ec5e8a464e0983490b629c037257ab29faee484d3879c28868a20adfbceefb725dab2663c1876c44bb0ec
|
7
|
+
data.tar.gz: 5507caece3003dc208f206be234c7390360985718507e8f7fbac02b4533f772601c0165e0ac17f7944d61b0590ef17047f1c0d992daf8cfe32680762d7e1f5ac
|
data/Gemfile.lock
CHANGED
data/README.md
CHANGED
@@ -1,2 +1,140 @@
|
|
1
|
-
#
|
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
|
+
|
data/api_ai_wrapper.gemspec
CHANGED
@@ -1,6 +1,6 @@
|
|
1
1
|
Gem::Specification.new do |s|
|
2
2
|
s.name = 'api_ai_wrapper'
|
3
|
-
s.version = '1.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
|
28
|
-
|
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
|
-
|
35
|
+
response_body
|
32
36
|
end
|
37
|
+
|
33
38
|
end
|
34
39
|
|
35
40
|
end
|
@@ -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
|
-
|
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
|
-
|
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
|
-
|
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
|
-
|
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
|
-
|
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
|
61
|
-
|
62
|
-
|
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
|
-
|
79
|
+
expect(component.send(:handle_response, response)).to eq(response.deep_symbolize_keys)
|
80
|
+
end
|
65
81
|
end
|
66
82
|
end
|
67
83
|
|