eclaircir 0.0.3
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 +7 -0
- data/.gitignore +27 -0
- data/.travis.yml +11 -0
- data/Gemfile +17 -0
- data/LICENSE +21 -0
- data/README.md +70 -0
- data/Rakefile +12 -0
- data/TODO.md +75 -0
- data/bin/console +10 -0
- data/bin/test.rb +17 -0
- data/eclaircir.gemspec +20 -0
- data/lib/eclaircir/api_models/attributes/nullable_date_time.rb +15 -0
- data/lib/eclaircir/api_models/attributes.rb +8 -0
- data/lib/eclaircir/api_models/base_model.rb +11 -0
- data/lib/eclaircir/api_models/concept.rb +12 -0
- data/lib/eclaircir/api_models/data.rb +17 -0
- data/lib/eclaircir/api_models/input.rb +22 -0
- data/lib/eclaircir/api_models/media.rb +9 -0
- data/lib/eclaircir/api_models/model.rb +29 -0
- data/lib/eclaircir/api_models/output.rb +14 -0
- data/lib/eclaircir/api_models/response.rb +16 -0
- data/lib/eclaircir/api_models/status.rb +46 -0
- data/lib/eclaircir/api_models.rb +16 -0
- data/lib/eclaircir/client/status_validator.rb +30 -0
- data/lib/eclaircir/client.rb +85 -0
- data/lib/eclaircir/configuration.rb +16 -0
- data/lib/eclaircir/constants.rb +5 -0
- data/lib/eclaircir/error.rb +27 -0
- data/lib/eclaircir/version.rb +5 -0
- data/lib/eclaircir.rb +32 -0
- data/spec/eclaircir/api_models/concept_spec.rb +32 -0
- data/spec/eclaircir/api_models/data_spec.rb +104 -0
- data/spec/eclaircir/api_models/input_spec.rb +70 -0
- data/spec/eclaircir/api_models/media_spec.rb +15 -0
- data/spec/eclaircir/api_models/model_spec.rb +109 -0
- data/spec/eclaircir/api_models/output_spec.rb +42 -0
- data/spec/eclaircir/api_models/response_spec.rb +63 -0
- data/spec/eclaircir/api_models/status_spec.rb +67 -0
- data/spec/eclaircir/client/status_validator_spec.rb +77 -0
- data/spec/eclaircir/client_spec.rb +123 -0
- data/spec/eclaircir/configuration_spec.rb +64 -0
- data/spec/eclaircir_spec.rb +55 -0
- data/spec/etc/fixtures/predict_outputs/invalid_request.json +7 -0
- data/spec/etc/fixtures/predict_outputs/success.json +58 -0
- data/spec/factories/concept.rb +8 -0
- data/spec/factories/data.rb +13 -0
- data/spec/factories/input.rb +7 -0
- data/spec/factories/media.rb +6 -0
- data/spec/factories/model.rb +9 -0
- data/spec/factories/response.rb +7 -0
- data/spec/factories/status.rb +7 -0
- data/spec/spec_helper.rb +53 -0
- metadata +122 -0
checksums.yaml
ADDED
@@ -0,0 +1,7 @@
|
|
1
|
+
---
|
2
|
+
SHA1:
|
3
|
+
metadata.gz: 82949b54ab4bb6cf95d31e2a463792c865412137
|
4
|
+
data.tar.gz: 84da4238a63460cf6c0b1d92502462586c2de59d
|
5
|
+
SHA512:
|
6
|
+
metadata.gz: 0493fe176bba3a735e5bb5b3b1b533bd617334657519d74a567215ae496f5961a0d455ea8000a49d789c3380b5c0cfc65a0e49bc66409749d37b6d0dfa632c8c
|
7
|
+
data.tar.gz: c7a7831b5afb741d095305ec90fdda0d502204525aa60e0c2b71a16e2dbbb6fc6209c0db2dd30d00a9f9dda7496b12aebc65cd26083c2fdaf98f13aa83c0c5ed
|
data/.gitignore
ADDED
@@ -0,0 +1,27 @@
|
|
1
|
+
# See http://help.github.com/ignore-files/ for more about ignoring files.
|
2
|
+
#
|
3
|
+
# If you find yourself ignoring temporary files generated by your text editor
|
4
|
+
# or operating system, you probably want to add a global ignore instead:
|
5
|
+
# git config --global core.excludesfile ~/.gitignore_global
|
6
|
+
|
7
|
+
# Ignore bundler config
|
8
|
+
/.bundle
|
9
|
+
|
10
|
+
# Ignore all logfiles and tempfiles.
|
11
|
+
/log/*.log
|
12
|
+
/tmp
|
13
|
+
/coverage
|
14
|
+
/public
|
15
|
+
/debug
|
16
|
+
/.bundle
|
17
|
+
/doc
|
18
|
+
/db/schema.rb
|
19
|
+
|
20
|
+
# Ignore dotenv config
|
21
|
+
/.env
|
22
|
+
|
23
|
+
# Ignore rspec customization
|
24
|
+
/.rspec
|
25
|
+
|
26
|
+
# Ignore Gemfile.lock as this is a gem
|
27
|
+
/Gemfile.lock
|
data/.travis.yml
ADDED
data/Gemfile
ADDED
@@ -0,0 +1,17 @@
|
|
1
|
+
source 'https://rubygems.org'
|
2
|
+
gemspec
|
3
|
+
|
4
|
+
gem 'rake'
|
5
|
+
gem 'virtus'
|
6
|
+
|
7
|
+
group :test, :development do
|
8
|
+
gem 'rspec', '~> 3.4'
|
9
|
+
gem 'rspec-its'
|
10
|
+
gem 'byebug'
|
11
|
+
gem 'dotenv'
|
12
|
+
gem 'simplecov', require: false
|
13
|
+
gem 'coveralls', require: false
|
14
|
+
gem 'factory_bot'
|
15
|
+
gem 'faker'
|
16
|
+
gem 'webmock'
|
17
|
+
end
|
data/LICENSE
ADDED
@@ -0,0 +1,21 @@
|
|
1
|
+
MIT License
|
2
|
+
|
3
|
+
Copyright (c) 2018 Karim Bogtob
|
4
|
+
|
5
|
+
Permission is hereby granted, free of charge, to any person obtaining a copy
|
6
|
+
of this software and associated documentation files (the "Software"), to deal
|
7
|
+
in the Software without restriction, including without limitation the rights
|
8
|
+
to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
|
9
|
+
copies of the Software, and to permit persons to whom the Software is
|
10
|
+
furnished to do so, subject to the following conditions:
|
11
|
+
|
12
|
+
The above copyright notice and this permission notice shall be included in all
|
13
|
+
copies or substantial portions of the Software.
|
14
|
+
|
15
|
+
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
16
|
+
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
17
|
+
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
|
18
|
+
AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
|
19
|
+
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
|
20
|
+
OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
|
21
|
+
SOFTWARE.
|
data/README.md
ADDED
@@ -0,0 +1,70 @@
|
|
1
|
+
# Eclaircir
|
2
|
+
Eclaircir is a french synonym for 'Clarify' and seemed relevant as a name for the gem.
|
3
|
+
|
4
|
+
This gem aims to be a Clarifai APIv2 wrapper that is complete, tested and covered.
|
5
|
+
|
6
|
+
[](https://travis-ci.org/kbogtob/eclaircir)
|
7
|
+
[](https://coveralls.io/github/kbogtob/eclaircir?branch=master)
|
8
|
+
|
9
|
+
## Install
|
10
|
+
|
11
|
+
```sh
|
12
|
+
gem install eclaircir
|
13
|
+
```
|
14
|
+
|
15
|
+
## Requirements
|
16
|
+
* Ruby 2.0.0 or higher
|
17
|
+
* HTTParty
|
18
|
+
* Virtus
|
19
|
+
|
20
|
+
## Examples
|
21
|
+
|
22
|
+
...
|
23
|
+
|
24
|
+
## Contributing
|
25
|
+
* Fork the project
|
26
|
+
* Run `bundle install --path .bundle`
|
27
|
+
* Run `bundle exec rake spec`
|
28
|
+
* Add tests for your feature (the TDD way!)
|
29
|
+
* Implement your feature
|
30
|
+
* Run tests again
|
31
|
+
* Commit (excluding the `Rakefile` or the `Version.rb` if you want to be merged)
|
32
|
+
* Send a pull request
|
33
|
+
|
34
|
+
## How can I help?
|
35
|
+
|
36
|
+
The Roadmap for V1 is to provide a completely usable API wrapper to do common tasks on Clarifai.
|
37
|
+
|
38
|
+
Here's an extract from the TODO:
|
39
|
+
|
40
|
+
# V1.0
|
41
|
+
- [x] Authentication
|
42
|
+
- [x] API Key Management
|
43
|
+
- [x] Authorization
|
44
|
+
- [x] Status Management
|
45
|
+
- [x] Modelization: Response
|
46
|
+
- [x] Modelization: Status
|
47
|
+
- [x] Modelization: Output
|
48
|
+
- [x] General Errors
|
49
|
+
- [x] Specific Errors
|
50
|
+
- [ ] Fully manage statuses using the statuses cheatsheet
|
51
|
+
- [x] Response Parsing
|
52
|
+
- [x] Predict
|
53
|
+
- [x] Modelization: Input
|
54
|
+
- [x] Modelization: Data
|
55
|
+
- [x] Modelization: Concept
|
56
|
+
- [x] Modelization: Model
|
57
|
+
- [x] Support URL Requests for Images
|
58
|
+
- [x] Response Parsing
|
59
|
+
- [ ] Support base 64 Requests for Images
|
60
|
+
- [ ] Support of multiple inputs (max 128)
|
61
|
+
- [ ] Modelization: Frame
|
62
|
+
- [ ] Video support
|
63
|
+
- [ ] Search
|
64
|
+
- [ ] Add Images to search index
|
65
|
+
- [ ] Search by concept
|
66
|
+
- [ ] Search by image
|
67
|
+
- [ ] Train
|
68
|
+
- [ ] Add image with concepts
|
69
|
+
- [ ] Model Creation
|
70
|
+
- [ ] Model Training
|
data/Rakefile
ADDED
data/TODO.md
ADDED
@@ -0,0 +1,75 @@
|
|
1
|
+
# V1.0
|
2
|
+
- [x] Authentication
|
3
|
+
- [x] API Key Management
|
4
|
+
- [x] Authorization
|
5
|
+
- [x] Status Management
|
6
|
+
- [x] Modelization: Response
|
7
|
+
- [x] Modelization: Status
|
8
|
+
- [x] Modelization: Output
|
9
|
+
- [x] General Errors
|
10
|
+
- [x] Specific Errors
|
11
|
+
- [ ] Fully manage statuses using the statuses cheatsheet
|
12
|
+
- [x] Response Parsing
|
13
|
+
- [x] Predict
|
14
|
+
- [x] Modelization: Input
|
15
|
+
- [x] Modelization: Data
|
16
|
+
- [x] Modelization: Concept
|
17
|
+
- [x] Modelization: Model
|
18
|
+
- [x] Support URL Requests for Images
|
19
|
+
- [x] Response Parsing
|
20
|
+
- [ ] Support base 64 Requests for Images
|
21
|
+
- [ ] Support of multiple inputs (max 128)
|
22
|
+
- [ ] Modelization: Frame
|
23
|
+
- [ ] Video support
|
24
|
+
- [ ] Search
|
25
|
+
- [ ] Add Images to search index
|
26
|
+
- [ ] Search by concept
|
27
|
+
- [ ] Search by image
|
28
|
+
- [ ] Train
|
29
|
+
- [ ] Add image with concepts
|
30
|
+
- [ ] Model Creation
|
31
|
+
- [ ] Model Training
|
32
|
+
|
33
|
+
# V2.0
|
34
|
+
- [ ] Feedback
|
35
|
+
- [ ] Modelization : Feedback Info
|
36
|
+
- [ ] Provide feedback on inputs with concepts
|
37
|
+
- [ ] Provide feedback on inputs with regions
|
38
|
+
- [ ] Provide feedback on searches
|
39
|
+
- [ ] Inputs management
|
40
|
+
- [ ] Add input with custom id
|
41
|
+
- [ ] Add input with metadata
|
42
|
+
- [ ] Add input with crop
|
43
|
+
- [ ] Get input by id
|
44
|
+
- [ ] Modelization: Status
|
45
|
+
- [ ] Get input status
|
46
|
+
- [ ] Input: Upsert concepts
|
47
|
+
- [ ] Input: Delete concepts
|
48
|
+
- [ ] Input: Bulk Upsert concepts
|
49
|
+
- [ ] Input: Bulk Delete concepts
|
50
|
+
- [ ] Delete input
|
51
|
+
- [ ] Bulk Delete input
|
52
|
+
- [ ] Clean inputs
|
53
|
+
- [ ] Models management
|
54
|
+
- [ ] Create model with concepts
|
55
|
+
- [ ] Model: Upsert concepts
|
56
|
+
- [ ] Model: Delete concepts
|
57
|
+
- [ ] Model: Update concept name
|
58
|
+
- [ ] List models
|
59
|
+
- [ ] Get model by id
|
60
|
+
- [ ] Model: List concepts
|
61
|
+
- [ ] Model: List versions
|
62
|
+
- [ ] Model: Get version by id
|
63
|
+
- [ ] Model: Get training inputs
|
64
|
+
- [ ] Model: Get training inputs by version
|
65
|
+
- [ ] Delete model
|
66
|
+
- [ ] Model: Delete version
|
67
|
+
- [ ] Clean models
|
68
|
+
- [ ] Search model
|
69
|
+
|
70
|
+
- [ ] Workflow Predict
|
71
|
+
|
72
|
+
# Experimental features
|
73
|
+
- [ ] Video splitting using ffmpeg
|
74
|
+
- [ ] For models not supporting videos
|
75
|
+
- [ ] For videos too big
|
data/bin/console
ADDED
data/bin/test.rb
ADDED
@@ -0,0 +1,17 @@
|
|
1
|
+
#!/usr/bin/env ruby
|
2
|
+
# frozen_string_literal: true
|
3
|
+
|
4
|
+
$LOAD_PATH.unshift(File.join(File.dirname(__FILE__), '..', 'lib'))
|
5
|
+
|
6
|
+
require 'eclaircir'
|
7
|
+
require 'byebug'
|
8
|
+
|
9
|
+
c = Eclaircir::Client.new(Eclaircir.configuration.api_key)
|
10
|
+
|
11
|
+
input = Eclaircir::Input.from_url('https://samples.clarifai.com/metro-north.jpg')
|
12
|
+
model = Eclaircir::Model.new(id: 'aaa03c23b3724a16a56b629203edc62c')
|
13
|
+
# response = model.predict_outputs(url: 'https://samples.clarifai.com/metro-north.jpg')
|
14
|
+
response = model.predict_outputs(input: input)
|
15
|
+
|
16
|
+
# response = c.predict_outputs(model, input)
|
17
|
+
puts response.inspect
|
data/eclaircir.gemspec
ADDED
@@ -0,0 +1,20 @@
|
|
1
|
+
# frozen_string_literal: true
|
2
|
+
# frozen_string_literal: true
|
3
|
+
|
4
|
+
require_relative 'lib/eclaircir/version'
|
5
|
+
|
6
|
+
Gem::Specification.new do |s|
|
7
|
+
s.name = 'eclaircir'
|
8
|
+
s.version = Eclaircir::VERSION
|
9
|
+
s.summary = 'Clarifai APIv2 Client'
|
10
|
+
s.description = 'Ruby Clarifai API wrapper that aims to be complete, tested and covered'
|
11
|
+
s.authors = ['Karim Bogtob']
|
12
|
+
s.email = 'kabogtob@gmail.com'
|
13
|
+
s.homepage = 'https://github.com/kbogtob/eclaircir'
|
14
|
+
s.license = 'MIT'
|
15
|
+
|
16
|
+
s.files = `git ls-files`.split("\n")
|
17
|
+
|
18
|
+
s.add_dependency 'httparty', ['~> 0.14.0']
|
19
|
+
s.add_dependency 'virtus', ['~> 1.0']
|
20
|
+
end
|
@@ -0,0 +1,15 @@
|
|
1
|
+
# frozen_string_literal: true
|
2
|
+
|
3
|
+
module Eclaircir
|
4
|
+
module Attributes
|
5
|
+
class NullableDateTime < Virtus::Attribute
|
6
|
+
def coerce(value)
|
7
|
+
if value.nil? || value.is_a?(DateTime)
|
8
|
+
value
|
9
|
+
else
|
10
|
+
DateTime.parse(value)
|
11
|
+
end
|
12
|
+
end
|
13
|
+
end
|
14
|
+
end
|
15
|
+
end
|
@@ -0,0 +1,17 @@
|
|
1
|
+
# frozen_string_literal: true
|
2
|
+
|
3
|
+
require_relative 'base_model'
|
4
|
+
|
5
|
+
module Eclaircir
|
6
|
+
class Data < BaseModel
|
7
|
+
attribute :image, Media
|
8
|
+
attribute :concepts, Array[Concept]
|
9
|
+
|
10
|
+
def to_api_hash
|
11
|
+
super.tap do |api_hash|
|
12
|
+
api_hash[:image] = image.to_api_hash if image
|
13
|
+
api_hash[:concepts] = concepts.map(&:to_api_hash) if concepts
|
14
|
+
end.compact
|
15
|
+
end
|
16
|
+
end
|
17
|
+
end
|
@@ -0,0 +1,22 @@
|
|
1
|
+
# frozen_string_literal: true
|
2
|
+
|
3
|
+
require_relative 'base_model'
|
4
|
+
|
5
|
+
module Eclaircir
|
6
|
+
class Input < BaseModel
|
7
|
+
attribute :id, String
|
8
|
+
attribute :data, Data
|
9
|
+
|
10
|
+
class << self
|
11
|
+
def from_url(url)
|
12
|
+
self.new(
|
13
|
+
data: Data.new(
|
14
|
+
image: Media.new(url: url)))
|
15
|
+
end
|
16
|
+
end
|
17
|
+
|
18
|
+
def to_api_hash
|
19
|
+
super.merge(data: data.to_api_hash).compact
|
20
|
+
end
|
21
|
+
end
|
22
|
+
end
|
@@ -0,0 +1,29 @@
|
|
1
|
+
# frozen_string_literal: true
|
2
|
+
|
3
|
+
require_relative 'base_model'
|
4
|
+
|
5
|
+
module Eclaircir
|
6
|
+
class Model < BaseModel
|
7
|
+
attribute :id, String
|
8
|
+
attribute :name, String
|
9
|
+
attribute :created_at, Attributes::NullableDateTime
|
10
|
+
attribute :app_id, String
|
11
|
+
attribute :output_info, Hash
|
12
|
+
attribute :model_version, Hash
|
13
|
+
|
14
|
+
def predict_outputs(url: nil, input: nil)
|
15
|
+
to_predict = if url
|
16
|
+
Input.from_url(url)
|
17
|
+
elsif input
|
18
|
+
input
|
19
|
+
end
|
20
|
+
|
21
|
+
if Array(to_predict).empty?
|
22
|
+
raise ArgumentError,
|
23
|
+
'one of the following keyword arguments should be provided [url, input]'
|
24
|
+
end
|
25
|
+
|
26
|
+
Eclaircir.new_client.predict_outputs(self, to_predict)
|
27
|
+
end
|
28
|
+
end
|
29
|
+
end
|
@@ -0,0 +1,14 @@
|
|
1
|
+
# frozen_string_literal: true
|
2
|
+
|
3
|
+
require_relative 'base_model'
|
4
|
+
|
5
|
+
module Eclaircir
|
6
|
+
class Output < BaseModel
|
7
|
+
attribute :id, String
|
8
|
+
attribute :status, Status
|
9
|
+
attribute :created_at, Attributes::NullableDateTime
|
10
|
+
attribute :model, Model
|
11
|
+
attribute :input, Input
|
12
|
+
attribute :data, Data
|
13
|
+
end
|
14
|
+
end
|
@@ -0,0 +1,16 @@
|
|
1
|
+
# frozen_string_literal: true
|
2
|
+
|
3
|
+
require_relative 'base_model'
|
4
|
+
|
5
|
+
module Eclaircir
|
6
|
+
class Response < BaseModel
|
7
|
+
attribute :status, Status
|
8
|
+
attribute :outputs, Array[Output]
|
9
|
+
|
10
|
+
class << self
|
11
|
+
def parse(raw_response)
|
12
|
+
self.new(raw_response)
|
13
|
+
end
|
14
|
+
end
|
15
|
+
end
|
16
|
+
end
|
@@ -0,0 +1,46 @@
|
|
1
|
+
# frozen_string_literal: true
|
2
|
+
|
3
|
+
require_relative 'base_model'
|
4
|
+
|
5
|
+
module Eclaircir
|
6
|
+
class Status < BaseModel
|
7
|
+
attribute :code, Integer
|
8
|
+
attribute :description, String
|
9
|
+
|
10
|
+
def success?
|
11
|
+
code == SUCCESS
|
12
|
+
end
|
13
|
+
|
14
|
+
def validate!
|
15
|
+
unless success?
|
16
|
+
error_class = ERRORS_MAPPINGS.fetch(code, APIError)
|
17
|
+
raise error_class, description
|
18
|
+
end
|
19
|
+
|
20
|
+
true
|
21
|
+
end
|
22
|
+
|
23
|
+
# statuses
|
24
|
+
SUCCESS = 10_000
|
25
|
+
|
26
|
+
FAILURE = 10_020
|
27
|
+
|
28
|
+
INVALID_AUTH_TOKEN = 11_001
|
29
|
+
API_KEY_NOT_FOUND = 11_009
|
30
|
+
|
31
|
+
BAD_REQUEST_FORMAT = 11_100
|
32
|
+
INVALID_REQUEST = 11_102
|
33
|
+
|
34
|
+
DUPLICATE_URL = 30_100
|
35
|
+
IMAGE_DECODING_FAILED = 30_300
|
36
|
+
|
37
|
+
ERRORS_MAPPINGS = {
|
38
|
+
INVALID_AUTH_TOKEN => InvalidAuthTokenError,
|
39
|
+
API_KEY_NOT_FOUND => ApiKeyNotFoundError,
|
40
|
+
BAD_REQUEST_FORMAT => BadRequestFormatError,
|
41
|
+
INVALID_REQUEST => InvalidRequestError,
|
42
|
+
DUPLICATE_URL => DuplicateURLError,
|
43
|
+
IMAGE_DECODING_FAILED => ImageDecodingError,
|
44
|
+
}.freeze
|
45
|
+
end
|
46
|
+
end
|
@@ -0,0 +1,16 @@
|
|
1
|
+
# frozen_string_literal: true
|
2
|
+
|
3
|
+
module Eclaircir
|
4
|
+
|
5
|
+
end
|
6
|
+
|
7
|
+
require_relative 'api_models/attributes'
|
8
|
+
|
9
|
+
require_relative 'api_models/concept'
|
10
|
+
require_relative 'api_models/status'
|
11
|
+
require_relative 'api_models/media'
|
12
|
+
require_relative 'api_models/data'
|
13
|
+
require_relative 'api_models/model'
|
14
|
+
require_relative 'api_models/input'
|
15
|
+
require_relative 'api_models/output'
|
16
|
+
require_relative 'api_models/response'
|
@@ -0,0 +1,30 @@
|
|
1
|
+
# frozen_string_literal: true
|
2
|
+
|
3
|
+
module Eclaircir
|
4
|
+
class Client
|
5
|
+
class StatusValidator
|
6
|
+
def initialize(response)
|
7
|
+
@response = response
|
8
|
+
end
|
9
|
+
|
10
|
+
def validate!
|
11
|
+
return true if main_status.success?
|
12
|
+
|
13
|
+
sub_statuses.each(&:validate!)
|
14
|
+
|
15
|
+
main_status.validate!
|
16
|
+
end
|
17
|
+
|
18
|
+
protected
|
19
|
+
attr_reader :response
|
20
|
+
|
21
|
+
def main_status
|
22
|
+
response.status
|
23
|
+
end
|
24
|
+
|
25
|
+
def sub_statuses
|
26
|
+
response.outputs.map(&:status)
|
27
|
+
end
|
28
|
+
end
|
29
|
+
end
|
30
|
+
end
|
@@ -0,0 +1,85 @@
|
|
1
|
+
# frozen_string_literal: true
|
2
|
+
|
3
|
+
module Eclaircir
|
4
|
+
class Client
|
5
|
+
include HTTParty
|
6
|
+
|
7
|
+
base_uri(Eclaircir::API_ENDPOINT)
|
8
|
+
format :json
|
9
|
+
headers 'Content-Type' => 'application/json', 'Accept' => 'application/json'
|
10
|
+
|
11
|
+
def initialize(api_key)
|
12
|
+
@api_key = api_key
|
13
|
+
end
|
14
|
+
|
15
|
+
def models(options = {})
|
16
|
+
get('/models', query: options)
|
17
|
+
end
|
18
|
+
|
19
|
+
def predict_outputs(model, inputs)
|
20
|
+
with_response_parsing do
|
21
|
+
validate post("/models/#{model.id}/outputs", body: {
|
22
|
+
inputs: Array(inputs).map(&:to_api_hash)
|
23
|
+
}.to_json)
|
24
|
+
end
|
25
|
+
end
|
26
|
+
|
27
|
+
protected
|
28
|
+
attr_reader :api_key
|
29
|
+
|
30
|
+
def authorization_headers
|
31
|
+
@authorization_headers ||= {
|
32
|
+
'Authorization' => "Key #{api_key}"
|
33
|
+
}
|
34
|
+
end
|
35
|
+
|
36
|
+
def get(path, query: nil)
|
37
|
+
self.class.get(path,
|
38
|
+
headers: authorization_headers,
|
39
|
+
query: query)
|
40
|
+
end
|
41
|
+
|
42
|
+
def post(path, query: nil, body: nil)
|
43
|
+
self.class.post(path,
|
44
|
+
headers: authorization_headers,
|
45
|
+
query: query,
|
46
|
+
body: body)
|
47
|
+
end
|
48
|
+
|
49
|
+
def patch(path, query: nil, body: nil)
|
50
|
+
self.class.patch(path,
|
51
|
+
headers: authorization_headers,
|
52
|
+
query: query,
|
53
|
+
body: body)
|
54
|
+
end
|
55
|
+
|
56
|
+
def delete(path, query: nil, body: nil)
|
57
|
+
self.class.delete(path,
|
58
|
+
headers: authorization_headers,
|
59
|
+
query: query,
|
60
|
+
body: body)
|
61
|
+
end
|
62
|
+
|
63
|
+
def with_response_parsing
|
64
|
+
Eclaircir::Response.parse(yield).tap do |response|
|
65
|
+
StatusValidator.new(response).validate!
|
66
|
+
end
|
67
|
+
end
|
68
|
+
|
69
|
+
def validate(response)
|
70
|
+
case response.code
|
71
|
+
when 200..399
|
72
|
+
response.parsed_response
|
73
|
+
else
|
74
|
+
raise_status_error(response.parsed_response)
|
75
|
+
end
|
76
|
+
end
|
77
|
+
|
78
|
+
def raise_status_error(raw_response)
|
79
|
+
status = raw_response['status']
|
80
|
+
raise APIError, status['description']
|
81
|
+
end
|
82
|
+
end
|
83
|
+
end
|
84
|
+
|
85
|
+
require_relative 'client/status_validator'
|
@@ -0,0 +1,16 @@
|
|
1
|
+
# frozen_string_literal: true
|
2
|
+
|
3
|
+
module Eclaircir
|
4
|
+
class Configuration
|
5
|
+
def initialize(
|
6
|
+
env: ENV,
|
7
|
+
api_key: nil)
|
8
|
+
@api_key = api_key || env['CLARIFIER_API_KEY']
|
9
|
+
end
|
10
|
+
|
11
|
+
attr_accessor :api_key
|
12
|
+
|
13
|
+
protected
|
14
|
+
attr_reader :env
|
15
|
+
end
|
16
|
+
end
|