mindee 5.4.0 → 5.6.0
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 +4 -4
- data/.betterleaks.toml +15 -0
- data/.editorconfig +1 -1
- data/CHANGELOG.md +14 -0
- data/CONTRIBUTING.md +88 -0
- data/bin/mindee.rb +4 -1
- data/bin/v1/products.rb +0 -6
- data/bin/v2/parser.rb +40 -45
- data/bin/v2/search_commands.rb +100 -0
- data/lib/mindee/v1/client.rb +1 -75
- data/lib/mindee/v1/http.rb +0 -1
- data/lib/mindee/v1/product.rb +0 -3
- data/lib/mindee/v2/client.rb +62 -36
- data/lib/mindee/v2/client_options/base_product_parameters.rb +162 -0
- data/lib/mindee/v2/client_options/base_search_parameters.rb +51 -0
- data/lib/mindee/v2/client_options.rb +4 -0
- data/lib/mindee/v2/http/mindee_api_v2.rb +59 -78
- data/lib/mindee/v2/parsing/search/base_search_response.rb +47 -0
- data/lib/mindee/v2/parsing/search/model_webhook.rb +3 -3
- data/lib/mindee/v2/parsing/search/pagination_metadata.rb +1 -1
- data/lib/mindee/v2/parsing/search/search_models.rb +2 -1
- data/lib/mindee/v2/parsing/search/search_rag_document.rb +60 -0
- data/lib/mindee/v2/parsing/search/search_rag_documents.rb +39 -0
- data/lib/mindee/v2/parsing/search/search_response.rb +2 -29
- data/lib/mindee/v2/parsing/search.rb +5 -1
- data/lib/mindee/v2/product/base_product.rb +2 -2
- data/lib/mindee/v2/product/classification/classification_classifier.rb +5 -5
- data/lib/mindee/v2/product/classification/params/classification_parameters.rb +1 -1
- data/lib/mindee/v2/product/crop/crop_item.rb +5 -5
- data/lib/mindee/v2/product/crop/params/crop_parameters.rb +1 -1
- data/lib/mindee/v2/product/extraction/params/extraction_parameters.rb +2 -2
- data/lib/mindee/v2/product/ocr/params/ocr_parameters.rb +1 -1
- data/lib/mindee/v2/product/split/params/split_parameters.rb +1 -1
- data/lib/mindee/v2/product/split/split_range.rb +5 -5
- data/lib/mindee/v2/search/models/model_search_parameters.rb +54 -0
- data/lib/mindee/v2/search/models/model_search_response.rb +28 -0
- data/lib/mindee/v2/search/rag_documents/rag_document_search_parameters.rb +52 -0
- data/lib/mindee/v2/search/rag_documents/rag_document_search_response.rb +28 -0
- data/lib/mindee/v2/search.rb +6 -0
- data/lib/mindee/v2.rb +2 -0
- data/lib/mindee/version.rb +1 -1
- data/mindee.gemspec +1 -1
- data/prek.toml +45 -0
- data/sig/custom/net_http.rbs +1 -1
- data/sig/mindee/v1/client.rbs +1 -15
- data/sig/mindee/v2/client.rbs +11 -4
- data/sig/mindee/v2/client_options/base_product_parameters.rbs +41 -0
- data/sig/mindee/v2/client_options/base_search_parameters.rbs +19 -0
- data/sig/mindee/v2/http/mindee_api_v2.rbs +19 -15
- data/sig/mindee/v2/parsing/search/base_search_response.rbs +19 -0
- data/sig/mindee/v2/parsing/search/search_rag_document.rbs +23 -0
- data/sig/mindee/v2/parsing/search/search_rag_documents.rbs +16 -0
- data/sig/mindee/v2/parsing/search/search_response.rbs +4 -9
- data/sig/mindee/v2/product/base_product.rbs +3 -3
- data/sig/mindee/v2/product/classification/classification_classifier.rbs +1 -1
- data/sig/mindee/v2/product/classification/params/classification_parameters/classification_parameters.rbs +1 -1
- data/sig/mindee/v2/product/crop/crop_item.rbs +1 -1
- data/sig/mindee/v2/product/crop/params/crop_parameters/crop_parameters.rbs +1 -1
- data/sig/mindee/v2/product/extraction/params/extraction_parameters.rbs +1 -1
- data/sig/mindee/v2/product/ocr/params/ocr_parameters/ocr_parameters.rbs +1 -1
- data/sig/mindee/v2/product/split/params/split_parameters/split_parameters.rbs +1 -1
- data/sig/mindee/v2/product/split/split_range.rbs +1 -1
- data/sig/mindee/v2/search/models/model_search_parameters.rbs +22 -0
- data/sig/mindee/v2/search/models/model_search_response.rbs +17 -0
- data/sig/mindee/v2/search/rag_documents/rag_document_search_parameters.rbs +22 -0
- data/sig/mindee/v2/search/rag_documents/rag_document_search_response.rbs +17 -0
- metadata +28 -32
- data/.pre-commit-config.yaml +0 -36
- data/docs/code_samples/bank_account_details_v1.txt +0 -24
- data/docs/code_samples/barcode_reader_v1.txt +0 -24
- data/docs/code_samples/idcard_fr_v1.txt +0 -24
- data/docs/code_samples/workflow_execution.txt +0 -28
- data/lib/mindee/input/base_parameters.rb +0 -156
- data/lib/mindee/v1/http/workflow_endpoint.rb +0 -93
- data/lib/mindee/v1/product/barcode_reader/barcode_reader_v1.rb +0 -47
- data/lib/mindee/v1/product/barcode_reader/barcode_reader_v1_document.rb +0 -47
- data/lib/mindee/v1/product/barcode_reader/barcode_reader_v1_page.rb +0 -38
- data/lib/mindee/v1/product/fr/bank_account_details/bank_account_details_v1.rb +0 -49
- data/lib/mindee/v1/product/fr/bank_account_details/bank_account_details_v1_document.rb +0 -49
- data/lib/mindee/v1/product/fr/bank_account_details/bank_account_details_v1_page.rb +0 -40
- data/lib/mindee/v1/product/fr/id_card/id_card_v1.rb +0 -49
- data/lib/mindee/v1/product/fr/id_card/id_card_v1_document.rb +0 -106
- data/lib/mindee/v1/product/fr/id_card/id_card_v1_page.rb +0 -57
- data/sig/mindee/input/base_parameters.rbs +0 -36
- data/sig/mindee/v1/http/workflow_endpoint.rbs +0 -22
- data/sig/mindee/v1/product/barcode_reader/barcode_reader_v1.rbs +0 -13
- data/sig/mindee/v1/product/barcode_reader/barcode_reader_v1_document.rbs +0 -16
- data/sig/mindee/v1/product/barcode_reader/barcode_reader_v1_page.rbs +0 -17
- data/sig/mindee/v1/product/fr/bank_account_details/bank_account_details_v1.rbs +0 -15
- data/sig/mindee/v1/product/fr/bank_account_details/bank_account_details_v1_document.rbs +0 -19
- data/sig/mindee/v1/product/fr/bank_account_details/bank_account_details_v1_page.rbs +0 -19
- data/sig/mindee/v1/product/fr/id_card/id_card_v1.rbs +0 -15
- data/sig/mindee/v1/product/fr/id_card/id_card_v1_document.rbs +0 -26
- data/sig/mindee/v1/product/fr/id_card/id_card_v1_page.rbs +0 -20
data/lib/mindee/v2/client.rb
CHANGED
|
@@ -18,26 +18,11 @@ module Mindee
|
|
|
18
18
|
@mindee_api = Mindee::V2::HTTP::MindeeApiV2.new(api_key: api_key)
|
|
19
19
|
end
|
|
20
20
|
|
|
21
|
-
#
|
|
22
|
-
# @param product [Class<Mindee::V2::Product::BaseProduct>] The return class.
|
|
23
|
-
# @param resource [String] ID of the inference or URL to the result.
|
|
24
|
-
# @return [Mindee::V2::Parsing::BaseResponse]
|
|
25
|
-
def get_result(product, resource)
|
|
26
|
-
@mindee_api.req_get_result(product, resource)
|
|
27
|
-
end
|
|
28
|
-
|
|
29
|
-
# Retrieves an inference from a given queue or URL to the job.
|
|
30
|
-
# @param job_id [String] ID of the job.
|
|
31
|
-
# @return [Mindee::V2::Parsing::JobResponse]
|
|
32
|
-
def get_job(job_id)
|
|
33
|
-
@mindee_api.req_get_job(job_id)
|
|
34
|
-
end
|
|
35
|
-
|
|
36
|
-
# Enqueue a document for async parsing.
|
|
21
|
+
# Send a file to the asynchronous processing queue for inference.
|
|
37
22
|
# @param product [Class<Mindee::V2::Product::BaseProduct>] The return class.
|
|
38
23
|
# @param input_source [Mindee::Input::Source::LocalInputSource, Mindee::Input::Source::URLInputSource]
|
|
39
24
|
# The source of the input document (local file or URL).
|
|
40
|
-
# @param params [Hash,
|
|
25
|
+
# @param params [Hash, ClientOptions::BaseProductParameters] Parameters for the inference.
|
|
41
26
|
# @return [Mindee::V2::Parsing::JobResponse]
|
|
42
27
|
def enqueue(
|
|
43
28
|
product,
|
|
@@ -48,19 +33,51 @@ module Mindee
|
|
|
48
33
|
normalized_params.validate_async_params
|
|
49
34
|
logger.debug("Enqueueing document to model '#{normalized_params.model_id}'.")
|
|
50
35
|
|
|
51
|
-
@mindee_api.
|
|
36
|
+
@mindee_api.req_post_product_enqueue(input_source, normalized_params)
|
|
37
|
+
end
|
|
38
|
+
|
|
39
|
+
# Get the status of an inference that was previously enqueued.
|
|
40
|
+
# Can be used for polling.
|
|
41
|
+
# @param url [String] HTTPS URL to the job.
|
|
42
|
+
# @return [Mindee::V2::Parsing::JobResponse]
|
|
43
|
+
def get_job_by_url(url)
|
|
44
|
+
@mindee_api.req_get_job_by_url(url)
|
|
45
|
+
end
|
|
46
|
+
|
|
47
|
+
# Get the result of an inference that was previously enqueued.
|
|
48
|
+
# @param product [Class<Mindee::V2::Product::BaseProduct>] The return class.
|
|
49
|
+
# @param url [String] HTTPS URL to the result.
|
|
50
|
+
# @return [Mindee::V2::Parsing::BaseResponse]
|
|
51
|
+
def get_result_by_url(product, url)
|
|
52
|
+
@mindee_api.req_get_result_by_url(product, url)
|
|
53
|
+
end
|
|
54
|
+
|
|
55
|
+
# Get the result of an inference that was previously enqueued.
|
|
56
|
+
# Prefer using `get_result_by_url` using the result URL returned by the Job.
|
|
57
|
+
# @param product [Class<Mindee::V2::Product::BaseProduct>] The return class.
|
|
58
|
+
# @param resource [String] ID of the inference or URL to the result.
|
|
59
|
+
# @return [Mindee::V2::Parsing::BaseResponse]
|
|
60
|
+
def get_result(product, resource)
|
|
61
|
+
@mindee_api.req_get_result_by_id(product, resource)
|
|
52
62
|
end
|
|
53
63
|
|
|
54
|
-
#
|
|
55
|
-
#
|
|
64
|
+
# Get the status of an inference that was previously enqueued.
|
|
65
|
+
# Prefer using `get_job_by_url` with the polling URL returned by enqueue.
|
|
66
|
+
# @param job_id [String] ID of the job.
|
|
67
|
+
# @return [Mindee::V2::Parsing::JobResponse]
|
|
68
|
+
def get_job(job_id)
|
|
69
|
+
@mindee_api.req_get_job_by_id(job_id)
|
|
70
|
+
end
|
|
71
|
+
|
|
72
|
+
# Send a file to the inference queue and return the results when complete.
|
|
56
73
|
# @param product [Class<Mindee::V2::Product::BaseProduct>] The return class.
|
|
57
74
|
# @param input_source [Mindee::Input::Source::LocalInputSource, Mindee::Input::Source::URLInputSource]
|
|
58
75
|
# The source of the input document (local file or URL).
|
|
59
|
-
# @param params [Hash,
|
|
76
|
+
# @param params [Hash, ClientOptions::BaseProductParameters] Parameters for the inference.
|
|
60
77
|
# @param polling_options [Hash, PollingOptions, nil] Parameters for polling.
|
|
61
78
|
# @param cancellation_token [Mindee::HTTP::CancellationToken, nil] Token for cancellation.
|
|
62
79
|
# @return [Parsing::BaseResponse]
|
|
63
|
-
# rubocop:disable Metrics/CyclomaticComplexity, Metrics/PerceivedComplexity
|
|
80
|
+
# rubocop:disable-next Metrics/CyclomaticComplexity, Metrics/PerceivedComplexity, Metrics/AbcSize
|
|
64
81
|
def enqueue_and_get_result(
|
|
65
82
|
product,
|
|
66
83
|
input_source,
|
|
@@ -84,29 +101,31 @@ module Mindee
|
|
|
84
101
|
|
|
85
102
|
sleep(normalized_params.polling_options.initial_delay_sec)
|
|
86
103
|
retry_counter = 1
|
|
87
|
-
|
|
104
|
+
polling_url = enqueue_response.job.polling_url
|
|
105
|
+
|
|
106
|
+
job_response = get_job_by_url(polling_url)
|
|
88
107
|
|
|
89
108
|
while retry_counter < normalized_params.polling_options.max_retries
|
|
90
|
-
if
|
|
109
|
+
if job_response.job.status == 'Failed'
|
|
91
110
|
break
|
|
92
|
-
elsif !
|
|
93
|
-
return
|
|
111
|
+
elsif !job_response.job.result_url.nil?
|
|
112
|
+
return get_result_by_url(product, job_response.job.result_url)
|
|
94
113
|
end
|
|
95
114
|
|
|
96
115
|
logger.debug(
|
|
97
116
|
"Successfully enqueued inference with job id: #{job_id}.\n" \
|
|
98
117
|
"Attempt n°#{retry_counter}/#{normalized_params.polling_options.max_retries}.\n" \
|
|
99
|
-
"Job status: #{
|
|
118
|
+
"Job status: #{job_response.job.status}."
|
|
100
119
|
)
|
|
101
120
|
|
|
102
121
|
raise Mindee::Error::MindeeError, 'Enqueueing of the document was canceled.' if cancellation_token&.canceled?
|
|
103
122
|
|
|
104
123
|
sleep(normalized_params.polling_options.delay_sec)
|
|
105
|
-
|
|
124
|
+
job_response = get_job_by_url(polling_url)
|
|
106
125
|
retry_counter += 1
|
|
107
126
|
end
|
|
108
127
|
|
|
109
|
-
error =
|
|
128
|
+
error = job_response.job.error
|
|
110
129
|
unless error.nil?
|
|
111
130
|
err_to_raise = Mindee::Error::MindeeHTTPErrorV2.new(error)
|
|
112
131
|
# NOTE: purposefully decoupled from the line above, otherwise rubocop thinks `error` is a `message` param.
|
|
@@ -117,14 +136,21 @@ module Mindee
|
|
|
117
136
|
raise Mindee::Error::MindeeError,
|
|
118
137
|
"Asynchronous parsing request timed out after #{sec_count} seconds"
|
|
119
138
|
end
|
|
120
|
-
# rubocop:enable Metrics/CyclomaticComplexity, Metrics/PerceivedComplexity
|
|
121
139
|
|
|
122
|
-
#
|
|
123
|
-
# @param
|
|
124
|
-
# @
|
|
125
|
-
|
|
140
|
+
# Search for resources matching the given criteria.
|
|
141
|
+
# @param params [ClientOptions::BaseSearchParameters] Search parameters.
|
|
142
|
+
# @return [Mindee::V2::Parsing::Search::BaseSearchResponse] A search response containing the matching resources.
|
|
143
|
+
def search(params)
|
|
144
|
+
@mindee_api.req_get_search(params)
|
|
145
|
+
end
|
|
146
|
+
|
|
147
|
+
# Returns a list of models matching a criteria for the given API key.
|
|
148
|
+
# @deprecated Use {#search} instead.
|
|
149
|
+
# @param model_name [String, nil] Name filter.
|
|
150
|
+
# @param model_type [String, nil] Model type filter.
|
|
151
|
+
# @return [Mindee::V2::Search::Models::ModelSearchResponse]
|
|
126
152
|
def search_models(model_name, model_type)
|
|
127
|
-
|
|
153
|
+
search(Search::Models::ModelSearchParameters.new(name: model_name, model_type: model_type))
|
|
128
154
|
end
|
|
129
155
|
|
|
130
156
|
private
|
|
@@ -136,7 +162,7 @@ module Mindee
|
|
|
136
162
|
def normalize_parameters(param_class, params, polling_options: nil)
|
|
137
163
|
if params.is_a?(Hash)
|
|
138
164
|
params[:polling_options] = polling_options if polling_options
|
|
139
|
-
elsif params.is_a?(Mindee::
|
|
165
|
+
elsif params.is_a?(Mindee::V2::ClientOptions::BaseProductParameters) && !polling_options.nil?
|
|
140
166
|
params.polling_options = polling_options
|
|
141
167
|
end
|
|
142
168
|
return param_class.from_hash(params: params) if params.is_a?(Hash)
|
|
@@ -0,0 +1,162 @@
|
|
|
1
|
+
# frozen_string_literal: true
|
|
2
|
+
|
|
3
|
+
module Mindee
|
|
4
|
+
module V2
|
|
5
|
+
module ClientOptions
|
|
6
|
+
# Base class for parameters accepted by all V2 endpoints.
|
|
7
|
+
class BaseProductParameters
|
|
8
|
+
# @return [String] Model ID to use for the inference. Required.
|
|
9
|
+
attr_reader :model_id
|
|
10
|
+
|
|
11
|
+
# @return [String, nil] Optional: a free-form string to tag the request with your own identifier.
|
|
12
|
+
# For example, an internal document ID, reference number, or database key.
|
|
13
|
+
# If set, it will be included in the job and result responses.
|
|
14
|
+
attr_reader :file_alias
|
|
15
|
+
|
|
16
|
+
# @return [Array<String>, nil] Webhook IDs to call after all processing is finished.
|
|
17
|
+
# If empty, no webhooks will be used.
|
|
18
|
+
attr_reader :webhook_ids
|
|
19
|
+
|
|
20
|
+
# @return [Input::PollingOptions] Options for polling. Set only if having timeout issues.
|
|
21
|
+
attr_reader :polling_options
|
|
22
|
+
|
|
23
|
+
# @return [Boolean, nil] Whether to close the file after parsing.
|
|
24
|
+
attr_reader :close_file
|
|
25
|
+
|
|
26
|
+
# @param [String] model_id ID of the model
|
|
27
|
+
# @param [String, nil] file_alias File alias, if applicable.
|
|
28
|
+
# @param [Array<String>, nil] webhook_ids List of webhook IDs to propagate the API response to.
|
|
29
|
+
# @param [Hash, Input::PollingOptions, nil] polling_options Options for polling. Set only if having timeout
|
|
30
|
+
# issues.
|
|
31
|
+
# @param [Boolean, nil] close_file Whether to close the file after parsing.
|
|
32
|
+
def initialize(
|
|
33
|
+
model_id,
|
|
34
|
+
file_alias: nil,
|
|
35
|
+
webhook_ids: nil,
|
|
36
|
+
polling_options: nil,
|
|
37
|
+
close_file: true
|
|
38
|
+
)
|
|
39
|
+
raise Error::MindeeInputError, 'Model ID is required.' if model_id.nil? || model_id.empty?
|
|
40
|
+
|
|
41
|
+
@model_id = model_id
|
|
42
|
+
@file_alias = file_alias
|
|
43
|
+
@webhook_ids = webhook_ids || []
|
|
44
|
+
@polling_options = get_clean_polling_options(polling_options)
|
|
45
|
+
@close_file = close_file.nil? || close_file
|
|
46
|
+
end
|
|
47
|
+
|
|
48
|
+
# Sets polling options after normalizing hash inputs.
|
|
49
|
+
# @param [Hash, Input::PollingOptions, nil] polling_options
|
|
50
|
+
# @return [Input::PollingOptions]
|
|
51
|
+
def polling_options=(polling_options)
|
|
52
|
+
@polling_options = get_clean_polling_options(polling_options)
|
|
53
|
+
end
|
|
54
|
+
|
|
55
|
+
# @return [String] Slug for the endpoint.
|
|
56
|
+
def self.slug
|
|
57
|
+
if self == BaseProductParameters
|
|
58
|
+
raise NotImplementedError, 'Cannot access `slug` directly on the BaseProductParameters class.'
|
|
59
|
+
end
|
|
60
|
+
|
|
61
|
+
''
|
|
62
|
+
end
|
|
63
|
+
|
|
64
|
+
# @return [String] Slug for the endpoint.
|
|
65
|
+
def slug
|
|
66
|
+
self.class.slug
|
|
67
|
+
end
|
|
68
|
+
|
|
69
|
+
# Load from a hash
|
|
70
|
+
# @param [Hash] params Parameters to provide as a hash.
|
|
71
|
+
# @return [BaseProductParameters]
|
|
72
|
+
def self.from_hash(params: {})
|
|
73
|
+
load_from_hash(params: params)
|
|
74
|
+
new(
|
|
75
|
+
params[:model_id],
|
|
76
|
+
file_alias: params[:file_alias],
|
|
77
|
+
webhook_ids: params[:webhook_ids],
|
|
78
|
+
polling_options: params[:polling_options],
|
|
79
|
+
close_file: params[:close_file]
|
|
80
|
+
)
|
|
81
|
+
end
|
|
82
|
+
|
|
83
|
+
# Loads a prediction from a Hash.
|
|
84
|
+
# @param [Hash] params Parameters to provide as a hash.
|
|
85
|
+
# @return [Hash]
|
|
86
|
+
def self.load_from_hash(params: {})
|
|
87
|
+
params.transform_keys!(&:to_sym)
|
|
88
|
+
|
|
89
|
+
if params.empty? || params[:model_id].nil? || params[:model_id].empty?
|
|
90
|
+
raise Error::MindeeInputError, 'Model ID is required.'
|
|
91
|
+
end
|
|
92
|
+
|
|
93
|
+
polling_options_input = params.fetch(:page_options, Input::PollingOptions.new)
|
|
94
|
+
if polling_options_input.is_a?(Hash)
|
|
95
|
+
polling_options_input = polling_options_input.transform_keys(&:to_sym)
|
|
96
|
+
Input::PollingOptions.new(
|
|
97
|
+
initial_delay_sec: polling_options_input.fetch(:initial_delay_sec, 2.0),
|
|
98
|
+
delay_sec: polling_options_input.fetch(:delay_sec, 1.5),
|
|
99
|
+
max_retries: polling_options_input.fetch(:max_retries, 80)
|
|
100
|
+
)
|
|
101
|
+
end
|
|
102
|
+
params
|
|
103
|
+
end
|
|
104
|
+
|
|
105
|
+
# Appends base form data to the provided array.
|
|
106
|
+
# @param [Array] form_data Array of form fields
|
|
107
|
+
# @return [Array]
|
|
108
|
+
def append_form_data(form_data)
|
|
109
|
+
form_data.push(['alias', @file_alias]) if @file_alias
|
|
110
|
+
webhook_ids = @webhook_ids || []
|
|
111
|
+
form_data.push(['webhook_ids', webhook_ids.join(',')]) unless @webhook_ids.nil? || webhook_ids.empty?
|
|
112
|
+
form_data
|
|
113
|
+
end
|
|
114
|
+
|
|
115
|
+
# Validates the parameters for async auto-polling
|
|
116
|
+
def validate_async_params
|
|
117
|
+
min_delay_sec = 1
|
|
118
|
+
min_initial_delay_sec = 1
|
|
119
|
+
min_retries = 2
|
|
120
|
+
|
|
121
|
+
if @polling_options.delay_sec < min_delay_sec
|
|
122
|
+
raise ArgumentError,
|
|
123
|
+
"Cannot set auto-poll delay to less than #{min_delay_sec} second(s)"
|
|
124
|
+
end
|
|
125
|
+
if @polling_options.initial_delay_sec < min_initial_delay_sec
|
|
126
|
+
raise ArgumentError,
|
|
127
|
+
"Cannot set initial parsing delay to less than #{min_initial_delay_sec} second(s)"
|
|
128
|
+
end
|
|
129
|
+
return unless @polling_options.max_retries < min_retries
|
|
130
|
+
|
|
131
|
+
raise ArgumentError,
|
|
132
|
+
"Cannot set auto-poll retries to less than #{min_retries}"
|
|
133
|
+
end
|
|
134
|
+
|
|
135
|
+
private
|
|
136
|
+
|
|
137
|
+
# Cleans a proper polling options object potentially from a hash.
|
|
138
|
+
# @param [Hash, Input::PollingOptions, nil] polling_options Polling options.
|
|
139
|
+
# @return [Input::PollingOptions] Valid polling options object.
|
|
140
|
+
def get_clean_polling_options(polling_options)
|
|
141
|
+
return Input::PollingOptions.new if polling_options.is_a?(Input::PollingOptions)
|
|
142
|
+
|
|
143
|
+
if polling_options.is_a?(Hash)
|
|
144
|
+
polling_options = polling_options.transform_keys(&:to_sym)
|
|
145
|
+
output_polling_options = Input::PollingOptions.new(
|
|
146
|
+
initial_delay_sec: polling_options.fetch(:initial_delay_sec, 2.0),
|
|
147
|
+
delay_sec: polling_options.fetch(:delay_sec, 1.5),
|
|
148
|
+
max_retries: polling_options.fetch(:max_retries, 80)
|
|
149
|
+
)
|
|
150
|
+
else
|
|
151
|
+
output_polling_options = if polling_options.is_a?(Input::PollingOptions)
|
|
152
|
+
polling_options || Input::PollingOptions.new
|
|
153
|
+
else
|
|
154
|
+
Input::PollingOptions.new
|
|
155
|
+
end
|
|
156
|
+
end
|
|
157
|
+
output_polling_options
|
|
158
|
+
end
|
|
159
|
+
end
|
|
160
|
+
end
|
|
161
|
+
end
|
|
162
|
+
end
|
|
@@ -0,0 +1,51 @@
|
|
|
1
|
+
# frozen_string_literal: true
|
|
2
|
+
|
|
3
|
+
module Mindee
|
|
4
|
+
module V2
|
|
5
|
+
module ClientOptions
|
|
6
|
+
# Base parameters for searches.
|
|
7
|
+
class BaseSearchParameters
|
|
8
|
+
# @return [Integer, nil] 1-based page index.
|
|
9
|
+
attr_reader :page
|
|
10
|
+
# @return [Integer, nil] Number of items per page.
|
|
11
|
+
attr_reader :per_page
|
|
12
|
+
|
|
13
|
+
# @param page [Integer, nil] 1-based page index.
|
|
14
|
+
# @param per_page [Integer, nil] Number of items per page.
|
|
15
|
+
def initialize(page: nil, per_page: nil)
|
|
16
|
+
@page = page
|
|
17
|
+
@per_page = per_page
|
|
18
|
+
end
|
|
19
|
+
|
|
20
|
+
# Gets the request parameters for the search request.
|
|
21
|
+
# @return [Hash{String => String, Array<String>}]
|
|
22
|
+
def request_parameters
|
|
23
|
+
params = {} # : Hash[String, String | Array[String]]
|
|
24
|
+
params['page'] = @page.to_s unless @page.nil?
|
|
25
|
+
params['per_page'] = @per_page.to_s unless @per_page.nil?
|
|
26
|
+
params
|
|
27
|
+
end
|
|
28
|
+
|
|
29
|
+
# @return [String] Slug of searchable resources.
|
|
30
|
+
def self.slug
|
|
31
|
+
raise NotImplementedError, 'Subclasses must implement the `slug` class method'
|
|
32
|
+
end
|
|
33
|
+
|
|
34
|
+
# @return [String] Slug of searchable resources.
|
|
35
|
+
def slug
|
|
36
|
+
self.class.slug
|
|
37
|
+
end
|
|
38
|
+
|
|
39
|
+
# @return [Class<Mindee::V2::Parsing::Search::BaseSearchResponse>] Response class for the search.
|
|
40
|
+
def self.response_class
|
|
41
|
+
raise NotImplementedError, 'Subclasses must implement the `response_class` class method'
|
|
42
|
+
end
|
|
43
|
+
|
|
44
|
+
# @return [Class<Mindee::V2::Parsing::Search::BaseSearchResponse>] Response class for the search.
|
|
45
|
+
def response_class
|
|
46
|
+
self.class.response_class
|
|
47
|
+
end
|
|
48
|
+
end
|
|
49
|
+
end
|
|
50
|
+
end
|
|
51
|
+
end
|
|
@@ -17,13 +17,13 @@ module Mindee
|
|
|
17
17
|
@settings = ApiV2Settings.new(api_key: api_key)
|
|
18
18
|
end
|
|
19
19
|
|
|
20
|
-
#
|
|
20
|
+
# Send a file to the asynchronous processing queue for inference processing.
|
|
21
21
|
#
|
|
22
22
|
# @param input_source [Input::Source::LocalInputSource, Input::Source::URLInputSource]
|
|
23
|
-
# @param params [
|
|
23
|
+
# @param params [ClientOptions::BaseProductParameters]
|
|
24
24
|
# @return [Mindee::V2::Parsing::JobResponse]
|
|
25
25
|
# @raise [Mindee::Error::MindeeHttpErrorV2]
|
|
26
|
-
def
|
|
26
|
+
def req_post_product_enqueue(input_source, params)
|
|
27
27
|
@settings.check_api_key
|
|
28
28
|
response = enqueue(
|
|
29
29
|
input_source,
|
|
@@ -33,52 +33,53 @@ module Mindee
|
|
|
33
33
|
end
|
|
34
34
|
|
|
35
35
|
# Retrieves a result from a given queue.
|
|
36
|
-
# @param product [Class<Mindee::V2::Product::BaseProduct>]
|
|
37
|
-
# @param
|
|
36
|
+
# @param product [Class<Mindee::V2::Product::BaseProduct>]
|
|
37
|
+
# @param inference_id [String] ID of the inference or URL to the result.
|
|
38
38
|
# @return [Mindee::V2::Parsing::BaseResponse]
|
|
39
|
-
def
|
|
40
|
-
|
|
41
|
-
|
|
42
|
-
@settings.check_api_key
|
|
43
|
-
response = result_req_get(
|
|
44
|
-
resource,
|
|
45
|
-
product
|
|
46
|
-
)
|
|
47
|
-
product.response_type.new(process_response(response))
|
|
39
|
+
def req_get_result_by_id(product, inference_id)
|
|
40
|
+
req_get_result_by_url(product, "#{@settings.base_url}/v2/products/#{product.slug}/results/#{inference_id}")
|
|
48
41
|
end
|
|
49
42
|
|
|
50
43
|
# Retrieves a queued job.
|
|
51
44
|
#
|
|
52
45
|
# @param job_id [String] ID of the job or URL to the job.
|
|
53
46
|
# @return [Mindee::V2::Parsing::JobResponse]
|
|
54
|
-
def
|
|
47
|
+
def req_get_job_by_id(job_id)
|
|
48
|
+
req_get_job_by_url("#{@settings.base_url}/v2/jobs/#{job_id}")
|
|
49
|
+
end
|
|
50
|
+
|
|
51
|
+
# Retrieves a queued job from its polling URL.
|
|
52
|
+
#
|
|
53
|
+
# @param url [String] HTTPS URL to the job.
|
|
54
|
+
# @return [Mindee::V2::Parsing::JobResponse]
|
|
55
|
+
def req_get_job_by_url(url)
|
|
56
|
+
validate_https_url!(url)
|
|
55
57
|
@settings.check_api_key
|
|
56
|
-
response = poll(
|
|
58
|
+
response = poll(url)
|
|
57
59
|
Mindee::V2::Parsing::JobResponse.new(process_response(response))
|
|
58
60
|
end
|
|
59
61
|
|
|
60
|
-
# Retrieves a
|
|
61
|
-
#
|
|
62
|
-
# @param
|
|
63
|
-
# @
|
|
64
|
-
|
|
65
|
-
|
|
66
|
-
|
|
62
|
+
# Retrieves a result from its URL.
|
|
63
|
+
#
|
|
64
|
+
# @param product [Class<Mindee::V2::Product::BaseProduct>]
|
|
65
|
+
# @param url [String] HTTPS URL to the result.
|
|
66
|
+
# @return [Mindee::V2::Parsing::BaseResponse]
|
|
67
|
+
def req_get_result_by_url(product, url)
|
|
68
|
+
validate_https_url!(url)
|
|
69
|
+
@settings.check_api_key
|
|
70
|
+
response = poll(url)
|
|
71
|
+
product.response_type.new(process_response(response))
|
|
67
72
|
end
|
|
68
73
|
|
|
69
|
-
|
|
70
|
-
|
|
71
|
-
#
|
|
72
|
-
#
|
|
73
|
-
|
|
74
|
-
|
|
75
|
-
|
|
76
|
-
url = "#{@settings.base_url}/v2/search/models"
|
|
77
|
-
uri = URI(url)
|
|
74
|
+
# Retrieves a list of resources with the given criteria.
|
|
75
|
+
# @param params [ClientOptions::BaseSearchParameters] Search parameters.
|
|
76
|
+
# @return [Mindee::V2::Parsing::Search::BaseSearchResponse] A search response containing the matching
|
|
77
|
+
# resources.
|
|
78
|
+
def req_get_search(params)
|
|
79
|
+
@settings.check_api_key
|
|
80
|
+
uri = URI("#{@settings.base_url}/v2/search/#{params.slug}")
|
|
78
81
|
|
|
79
|
-
query_params =
|
|
80
|
-
query_params[:name] = model_name if model_name
|
|
81
|
-
query_params[:model_type] = model_type if model_type
|
|
82
|
+
query_params = params.request_parameters
|
|
82
83
|
uri.query = URI.encode_www_form(query_params) unless query_params.empty?
|
|
83
84
|
|
|
84
85
|
headers = {
|
|
@@ -86,43 +87,27 @@ module Mindee
|
|
|
86
87
|
'User-Agent' => @settings.user_agent,
|
|
87
88
|
}
|
|
88
89
|
req = Net::HTTP::Get.new(uri, headers)
|
|
89
|
-
req['Transfer-Encoding'] = 'chunked'
|
|
90
90
|
|
|
91
|
-
Net::HTTP.start(uri.hostname, uri.port,
|
|
92
|
-
|
|
91
|
+
response = Net::HTTP.start(uri.hostname, uri.port,
|
|
92
|
+
use_ssl: true,
|
|
93
|
+
open_timeout: @settings.request_timeout,
|
|
94
|
+
read_timeout: @settings.request_timeout) do |http|
|
|
95
|
+
http.request(req)
|
|
93
96
|
end
|
|
94
|
-
|
|
97
|
+
params.response_class.new(process_response(response))
|
|
95
98
|
end
|
|
96
99
|
|
|
97
|
-
|
|
98
|
-
# @return [Boolean]
|
|
99
|
-
def uri?(resource)
|
|
100
|
-
uri = URI.parse(resource)
|
|
101
|
-
throw Mindee::Error::MindeeError, 'HTTP is not supported.' if uri.scheme == 'http'
|
|
102
|
-
uri.scheme == 'https'
|
|
103
|
-
rescue URI::BadURIError, URI::InvalidURIError
|
|
104
|
-
false
|
|
105
|
-
end
|
|
106
|
-
|
|
107
|
-
# Retrieves a queued job.
|
|
108
|
-
#
|
|
109
|
-
# @param url [String]
|
|
110
|
-
# @return [Mindee::V2::Parsing::JobResponse]
|
|
111
|
-
def req_get_job_url(url)
|
|
112
|
-
@settings.check_api_key
|
|
113
|
-
response = poll(url)
|
|
114
|
-
Mindee::V2::Parsing::JobResponse.new(process_response(response))
|
|
115
|
-
end
|
|
100
|
+
private
|
|
116
101
|
|
|
117
|
-
#
|
|
102
|
+
# Validates that a URL uses HTTPS and includes a host.
|
|
118
103
|
#
|
|
119
|
-
# @param result_class [Class<Mindee::V2::Parsing::BaseResponse>]
|
|
120
104
|
# @param url [String]
|
|
121
|
-
# @return [
|
|
122
|
-
def
|
|
123
|
-
|
|
124
|
-
|
|
125
|
-
|
|
105
|
+
# @return [void]
|
|
106
|
+
def validate_https_url!(url)
|
|
107
|
+
uri = URI.parse(url)
|
|
108
|
+
raise Mindee::Error::MindeeError, "Invalid URL: #{url}" unless uri.scheme == 'https' && !uri.host.to_s.empty?
|
|
109
|
+
rescue URI::BadURIError, URI::InvalidURIError
|
|
110
|
+
raise Mindee::Error::MindeeError, "Invalid URL: #{url}"
|
|
126
111
|
end
|
|
127
112
|
|
|
128
113
|
# Converts an HTTP response to a parsed response object.
|
|
@@ -155,23 +140,16 @@ module Mindee
|
|
|
155
140
|
'User-Agent' => @settings.user_agent,
|
|
156
141
|
}
|
|
157
142
|
req = Net::HTTP::Get.new(uri, headers)
|
|
158
|
-
req['Transfer-Encoding'] = 'chunked'
|
|
159
143
|
|
|
160
|
-
Net::HTTP.start(uri.hostname, uri.port,
|
|
144
|
+
Net::HTTP.start(uri.hostname, uri.port,
|
|
145
|
+
use_ssl: true,
|
|
146
|
+
open_timeout: @settings.request_timeout,
|
|
147
|
+
read_timeout: @settings.request_timeout) do |http|
|
|
161
148
|
return http.request(req)
|
|
162
149
|
end
|
|
163
150
|
raise Mindee::Error::MindeeError, 'Could not resolve server response.'
|
|
164
151
|
end
|
|
165
152
|
|
|
166
|
-
# Polls the API for the result of an inference.
|
|
167
|
-
#
|
|
168
|
-
# @param queue_id [String] ID of the queue.
|
|
169
|
-
# @param product [Class<Mindee::V2::Product::BaseProduct>] The return class.
|
|
170
|
-
# @return [Net::HTTPResponse]
|
|
171
|
-
def result_req_get(queue_id, product)
|
|
172
|
-
poll("#{@settings.base_url}/v2/products/#{product.slug}/results/#{queue_id}")
|
|
173
|
-
end
|
|
174
|
-
|
|
175
153
|
# Handle parameters for the enqueue form
|
|
176
154
|
# @param form_data [Array] Array of form fields
|
|
177
155
|
# @param params [V2::Product::Extraction::Params::ExtractionParameters] Inference options.
|
|
@@ -191,7 +169,7 @@ module Mindee
|
|
|
191
169
|
end
|
|
192
170
|
|
|
193
171
|
# @param input_source [Mindee::Input::Source::LocalInputSource, Mindee::Input::Source::URLInputSource]
|
|
194
|
-
# @param params [
|
|
172
|
+
# @param params [ClientOptions::BaseProductParameters] Inference options.
|
|
195
173
|
# @return [Net::HTTPResponse, nil]
|
|
196
174
|
def enqueue(input_source, params)
|
|
197
175
|
uri = URI("#{@settings.base_url}/v2/products/#{params.slug}/enqueue")
|
|
@@ -218,7 +196,10 @@ module Mindee
|
|
|
218
196
|
req.set_form(form_data, 'multipart/form-data')
|
|
219
197
|
req['Transfer-Encoding'] = 'chunked'
|
|
220
198
|
|
|
221
|
-
Net::HTTP.start(uri.hostname, uri.port,
|
|
199
|
+
Net::HTTP.start(uri.hostname, uri.port,
|
|
200
|
+
use_ssl: true,
|
|
201
|
+
open_timeout: @settings.request_timeout,
|
|
202
|
+
read_timeout: @settings.request_timeout) do |http|
|
|
222
203
|
return http.request(req)
|
|
223
204
|
end
|
|
224
205
|
raise Mindee::Error::MindeeError, 'Could not resolve server response.'
|
|
@@ -0,0 +1,47 @@
|
|
|
1
|
+
# frozen_string_literal: true
|
|
2
|
+
|
|
3
|
+
module Mindee
|
|
4
|
+
module V2
|
|
5
|
+
module Parsing
|
|
6
|
+
module Search
|
|
7
|
+
# Base class for search responses.
|
|
8
|
+
class BaseSearchResponse < CommonResponse
|
|
9
|
+
# Pagination metadata.
|
|
10
|
+
# @return [Mindee::V2::Parsing::Search::PaginationMetadata]
|
|
11
|
+
attr_reader :pagination
|
|
12
|
+
|
|
13
|
+
# @param http_response [Hash] The parsed JSON payload from the API.
|
|
14
|
+
def initialize(http_response)
|
|
15
|
+
super
|
|
16
|
+
|
|
17
|
+
@pagination = PaginationMetadata.new(http_response['pagination'])
|
|
18
|
+
end
|
|
19
|
+
|
|
20
|
+
# Lines composing the response-specific body (header + items).
|
|
21
|
+
# @return [Array<String>]
|
|
22
|
+
def body_lines
|
|
23
|
+
raise NotImplementedError, 'body_lines must be implemented in subclasses'
|
|
24
|
+
end
|
|
25
|
+
|
|
26
|
+
# Pagination metadata (Obsolete).
|
|
27
|
+
# @deprecated Use {#pagination} instead.
|
|
28
|
+
# @return [Mindee::V2::Parsing::Search::PaginationMetadata]
|
|
29
|
+
def pagination_metadata
|
|
30
|
+
pagination
|
|
31
|
+
end
|
|
32
|
+
|
|
33
|
+
# String representation of the search response.
|
|
34
|
+
# @return [String]
|
|
35
|
+
def to_s
|
|
36
|
+
lines = body_lines
|
|
37
|
+
lines.push('Pagination Metadata')
|
|
38
|
+
lines.push('###################')
|
|
39
|
+
lines.push(@pagination.to_s)
|
|
40
|
+
|
|
41
|
+
lines.join("\n")
|
|
42
|
+
end
|
|
43
|
+
end
|
|
44
|
+
end
|
|
45
|
+
end
|
|
46
|
+
end
|
|
47
|
+
end
|
|
@@ -4,7 +4,7 @@ module Mindee
|
|
|
4
4
|
module V2
|
|
5
5
|
module Parsing
|
|
6
6
|
module Search
|
|
7
|
-
#
|
|
7
|
+
# Information about a model's webhook.
|
|
8
8
|
class ModelWebhook
|
|
9
9
|
# @return [String] ID of the webhook.
|
|
10
10
|
attr_reader :id
|
|
@@ -15,14 +15,14 @@ module Mindee
|
|
|
15
15
|
# @return [String] URL of the webhook.
|
|
16
16
|
attr_reader :url
|
|
17
17
|
|
|
18
|
-
# @param payload [Hash] The parsed JSON payload mapping to the
|
|
18
|
+
# @param payload [Hash] The parsed JSON payload mapping to the webhook.
|
|
19
19
|
def initialize(payload)
|
|
20
20
|
@id = payload['id']
|
|
21
21
|
@name = payload['name']
|
|
22
22
|
@url = payload['url']
|
|
23
23
|
end
|
|
24
24
|
|
|
25
|
-
# String representation of the
|
|
25
|
+
# String representation of the webhook.
|
|
26
26
|
# @return [String]
|
|
27
27
|
def to_s
|
|
28
28
|
[
|
|
@@ -4,7 +4,7 @@ module Mindee
|
|
|
4
4
|
module V2
|
|
5
5
|
module Parsing
|
|
6
6
|
module Search
|
|
7
|
-
# Pagination
|
|
7
|
+
# Pagination metadata associated with searches.
|
|
8
8
|
class PaginationMetadata
|
|
9
9
|
# @return [Integer] Number of items per page.
|
|
10
10
|
attr_reader :per_page
|