eclaircir 0.0.3
Sign up to get free protection for your applications and to get access to all the features.
- 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
|
+
[![Build Status](https://travis-ci.org/kbogtob/eclaircir.svg?branch=master)](https://travis-ci.org/kbogtob/eclaircir)
|
7
|
+
[![Coverage Status](https://coveralls.io/repos/github/kbogtob/eclaircir/badge.svg?branch=master)](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
|